Files
tryton/purchase.py
T

233 lines
7.8 KiB
Python
Raw Normal View History

2014-12-02 12:56:03 +01:00
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import fields, ModelView, Workflow
from trytond.pyson import Eval
2013-04-05 00:17:18 +02:00
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.tools import grouped_slice
__all__ = ['PurchaseRequest', 'PurchaseConfig', 'Purchase', 'PurchaseLine',
'ProductSupplier', 'CreatePurchase', 'PurchaseHandleShipmentException']
__metaclass__ = PoolMeta
class PurchaseRequest:
__name__ = 'purchase.request'
customer = fields.Many2One('party.party', 'Customer', readonly=True,
states={
'invisible': ~Eval('customer'),
})
delivery_address = fields.Many2One('party.address', 'Delivery Address',
domain=[('party', '=', Eval('customer'))],
states={
'invisible': ~Eval('customer'),
'readonly': Eval('state') != 'draft',
},
depends=['customer', 'state'])
class PurchaseConfig:
__name__ = 'purchase.configuration'
purchase_drop_location = fields.Property(
fields.Many2One('stock.location', 'Purchase Drop Location',
domain=[('type', '=', 'drop')]))
class Purchase:
__name__ = 'purchase.purchase'
customer = fields.Many2One('party.party', 'Customer', readonly=True,
states={
'invisible': ~Eval('customer'),
2014-01-26 14:29:36 +01:00
})
delivery_address = fields.Many2One('party.address', 'Delivery Address',
domain=[('party', '=', Eval('customer'))],
states={
'readonly': Eval('state') != 'draft',
'invisible': ~Eval('customer'),
},
depends=['state', 'customer'])
drop_shipments = fields.Function(fields.One2Many('stock.shipment.drop',
None, 'Drop Shipments',
states={
'invisible': ~Eval('customer'),
},
depends=['customer']),
'get_drop_shipments')
drop_location = fields.Many2One('stock.location', 'Drop Location',
domain=[('type', '=', 'drop')],
states={
'invisible': ~Eval('customer', False),
'required': Eval('customer', False),
},
depends=['customer'])
@classmethod
def __setup__(cls):
super(Purchase, cls).__setup__()
cls._error_messages.update({
'delivery_address_required': ('A delivery address must be '
'defined for quotation of purchase "%s".'),
})
@staticmethod
def default_drop_location():
pool = Pool()
PurchaseConfig = pool.get('purchase.configuration')
config = PurchaseConfig(1)
return config.purchase_drop_location.id
2014-01-26 14:29:36 +01:00
@fields.depends('customer', 'delivery_address')
def on_change_customer(self):
2014-10-29 20:40:23 +01:00
self.delivery_address = None
if self.customer:
2014-10-29 20:40:23 +01:00
self.delivery_address = self.customer.address_get(type='delivery')
def get_drop_shipments(self, name):
2013-04-05 00:17:18 +02:00
DropShipment = Pool().get('stock.shipment.drop')
return list(set(m.shipment.id for l in self.lines for m in l.moves
if isinstance(m.shipment, DropShipment)))
def check_for_quotation(self):
super(Purchase, self).check_for_quotation()
if self.customer and not self.delivery_address:
self.raise_user_error('delivery_address_required', self.rec_name)
def create_move(self, move_type):
pool = Pool()
DropShipment = pool.get('stock.shipment.drop')
moves = super(Purchase, self).create_move(move_type)
if moves and self.customer and move_type == 'in':
drop_shipment = self.create_drop_shipment()
drop_shipment.supplier_moves = moves
drop_shipment.save()
DropShipment.wait([drop_shipment])
return moves
def create_drop_shipment(self):
pool = Pool()
DropShipment = pool.get('stock.shipment.drop')
return DropShipment(
company=self.company,
supplier=self.party,
contact_address=self.party.address_get(),
customer=self.customer,
delivery_address=self.delivery_address,
)
@classmethod
@ModelView.button
@Workflow.transition('cancel')
def cancel(cls, purchases):
pool = Pool()
SaleLine = pool.get('sale.line')
Move = pool.get('stock.move')
super(Purchase, cls).cancel(purchases)
sale_lines = []
for sub_purchases in grouped_slice(purchases):
sale_lines += SaleLine.search([
('purchase_request.purchase_line.purchase', 'in',
[p.id for p in sub_purchases]),
])
Move.cancel([m for sl in sale_lines for m in sl.moves
if m.state != 'done' and m.from_location.type == 'drop'])
class PurchaseLine:
__name__ = 'purchase.line'
def get_to_location(self, name):
result = super(PurchaseLine, self).get_to_location(name)
if self.purchase.customer:
return self.purchase.drop_location.id
return result
def get_move(self):
move = super(PurchaseLine, self).get_move()
if move and self.purchase.customer:
move.cost_price = move.unit_price
return move
class ProductSupplier:
__name__ = 'purchase.product_supplier'
drop_shipment = fields.Boolean('Drop Shipment',
states={
'invisible': ~Eval('_parent_product', {}).get('supply_on_sale',
False),
})
class CreatePurchase:
__name__ = 'purchase.request.create_purchase'
@classmethod
def _group_purchase_key(cls, requests, request):
result = super(CreatePurchase, cls)._group_purchase_key(requests,
request)
result += (
('customer', request.customer.id if request.customer else None),
('delivery_address', request.delivery_address.id
if request.delivery_address else None),
)
return result
class PurchaseHandleShipmentException:
__name__ = 'purchase.handle.shipment.exception'
def transition_handle(self):
pool = Pool()
Sale = pool.get('sale.sale')
SaleLine = pool.get('sale.line')
Purchase = pool.get('purchase.purchase')
PurchaseRequest = pool.get('purchase.request')
Move = pool.get('stock.move')
super(PurchaseHandleShipmentException, self).transition_handle()
sales = set()
moves = set()
to_recreate = set(self.ask.recreate_moves)
domain_moves = set(self.ask.domain_moves)
purchase = Purchase(Transaction().context['active_id'])
requests = []
for sub_lines in grouped_slice([pl.id for pl in purchase.lines]):
requests += PurchaseRequest.search([
('purchase_line', 'in', list(sub_lines)),
])
pline2request = {r.purchase_line: r for r in requests}
request2sline = {}
for sub_requests in grouped_slice(requests):
sale_lines = SaleLine.search([
('purchase_request', 'in', [r.id for r in sub_requests]),
])
request2sline.update({sl.purchase_request: sl
for sl in sale_lines})
for line in purchase.lines:
if not set(line.moves) & domain_moves:
continue
if not any(m in to_recreate for m in line.moves):
sale_line = request2sline[pline2request[line]]
moves.update({m for m in sale_line.moves
if (m.state != 'done'
and m.from_location.type == 'drop')})
sales.add(sale_line.sale)
if moves:
Move.cancel(list(moves))
if sales:
Sale.process(list(sales))
return 'end'