165 lines
5.6 KiB
Python
165 lines
5.6 KiB
Python
# 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 import backend
|
|
from trytond.model import ModelSQL, ValueMixin, fields
|
|
from trytond.pyson import Eval
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.transaction import Transaction
|
|
from trytond.tools.multivalue import migrate_property
|
|
|
|
from trytond.modules.sale.sale import (
|
|
get_shipments_returns, search_shipments_returns)
|
|
|
|
__all__ = ['SaleConfig', 'SaleConfigSaleDropLocation', 'Sale', 'SaleLine']
|
|
sale_drop_location = fields.Many2One(
|
|
'stock.location', "Sale Drop Location", domain=[('type', '=', 'drop')])
|
|
|
|
|
|
class SaleConfig(metaclass=PoolMeta):
|
|
__name__ = 'sale.configuration'
|
|
|
|
sale_drop_location = fields.MultiValue(sale_drop_location)
|
|
|
|
@classmethod
|
|
def default_sale_drop_location(cls, **pattern):
|
|
return cls.multivalue_model(
|
|
'sale_drop_location').default_sale_drop_location()
|
|
|
|
|
|
class SaleConfigSaleDropLocation(ModelSQL, ValueMixin):
|
|
"Sale Configuration Sale Drop Location"
|
|
__name__ = 'sale.configuration.sale_drop_location'
|
|
sale_drop_location = sale_drop_location
|
|
|
|
@classmethod
|
|
def __register__(cls, module_name):
|
|
TableHandler = backend.get('TableHandler')
|
|
exist = TableHandler.table_exist(cls._table)
|
|
|
|
super(SaleConfigSaleDropLocation, cls).__register__(
|
|
module_name)
|
|
|
|
if not exist:
|
|
cls._migrate_property([], [], [])
|
|
|
|
@classmethod
|
|
def _migrate_property(cls, field_names, value_names, fields):
|
|
field_names.append('sale_drop_location')
|
|
value_names.append('sale_drop_location')
|
|
migrate_property(
|
|
'sale.configuration', field_names, cls, value_names,
|
|
fields=fields)
|
|
|
|
@classmethod
|
|
def default_sale_drop_location(cls):
|
|
pool = Pool()
|
|
ModelData = pool.get('ir.model.data')
|
|
try:
|
|
return ModelData.get_id(
|
|
'sale_supply_drop_shipment', 'location_drop')
|
|
except KeyError:
|
|
return None
|
|
|
|
|
|
class Sale(metaclass=PoolMeta):
|
|
__name__ = 'sale.sale'
|
|
|
|
drop_shipments = fields.Function(fields.One2Many('stock.shipment.drop',
|
|
None, 'Drop Shipments',
|
|
states={
|
|
'invisible': ~Eval('drop_shipments'),
|
|
}),
|
|
'get_drop_shipments', searcher='search_drop_shipments')
|
|
drop_location = fields.Many2One('stock.location', 'Drop Location',
|
|
domain=[('type', '=', 'drop')])
|
|
|
|
@staticmethod
|
|
def default_drop_location():
|
|
pool = Pool()
|
|
Config = pool.get('sale.configuration')
|
|
|
|
config = Config(1)
|
|
if config.sale_drop_location:
|
|
return config.sale_drop_location.id
|
|
|
|
get_drop_shipments = get_shipments_returns('stock.shipment.drop')
|
|
search_drop_shipments = search_shipments_returns('stock.shipment.drop')
|
|
|
|
def create_shipment(self, shipment_type):
|
|
shipments = super(Sale, self).create_shipment(shipment_type)
|
|
if shipment_type == 'out':
|
|
with Transaction().set_context(_drop_shipment=True):
|
|
self.create_drop_shipment_moves()
|
|
return shipments
|
|
|
|
def create_drop_shipment_moves(self):
|
|
pool = Pool()
|
|
Move = pool.get('stock.move')
|
|
|
|
moves = []
|
|
for line in self.lines:
|
|
moves += line.get_drop_moves()
|
|
Move.save(moves)
|
|
|
|
|
|
class SaleLine(metaclass=PoolMeta):
|
|
__name__ = 'sale.line'
|
|
|
|
@property
|
|
def supply_on_sale(self):
|
|
supply_on_sale = super(SaleLine, self).supply_on_sale
|
|
return (supply_on_sale
|
|
or (self.moves and all(m.from_location.type == 'drop'
|
|
for m in self.moves)))
|
|
|
|
@property
|
|
def supply_on_sale_drop_move(self):
|
|
"Return True if the sale line can have drop move"
|
|
if not self.supply_on_sale:
|
|
return False
|
|
if self.purchase_request and not self.purchase_request.customer:
|
|
return False
|
|
if self.purchase_request_state == 'cancel':
|
|
return False
|
|
if self.purchase_request:
|
|
purchase_line = self.purchase_request.purchase_line
|
|
if purchase_line and purchase_line.move_done:
|
|
return False
|
|
return True
|
|
|
|
def get_move(self, shipment_type):
|
|
result = super(SaleLine, self).get_move(shipment_type)
|
|
if (shipment_type == 'out'
|
|
and not Transaction().context.get('_drop_shipment')):
|
|
if self.supply_on_sale_drop_move:
|
|
return
|
|
return result
|
|
|
|
def get_purchase_request(self):
|
|
request = super(SaleLine, self).get_purchase_request()
|
|
if request and request.party:
|
|
drop_shipment = False
|
|
if self.product and self.product.type in ('goods', 'assets'):
|
|
# FIXME this doesn't ensure to find always the right
|
|
# product_supplier
|
|
for product_supplier in self.product.product_suppliers:
|
|
if product_supplier.party == request.party:
|
|
drop_shipment = product_supplier.drop_shipment
|
|
break
|
|
if drop_shipment:
|
|
request.customer = self.sale.party
|
|
request.delivery_address = self.sale.shipment_address
|
|
return request
|
|
|
|
def get_drop_moves(self):
|
|
if (self.type != 'line'
|
|
or not self.product):
|
|
return []
|
|
moves = []
|
|
if self.supply_on_sale_drop_move:
|
|
move = self.get_move('out')
|
|
if move is not None:
|
|
move.from_location = self.sale.drop_location
|
|
moves.append(move)
|
|
return moves
|