Unify shipment assignation scheduled jobs
The order shipments are assigned is important as it determines which order will be done or not. So we must try to assign all the shipments and productions following a defined order. Closes #13027
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# 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.pool import PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class Cron(metaclass=PoolMeta):
|
||||
@@ -12,5 +13,16 @@ class Cron(metaclass=PoolMeta):
|
||||
cls.method.selection.extend([
|
||||
('production|set_cost_from_moves', "Set Cost from Moves"),
|
||||
('production|reschedule', "Reschedule Productions"),
|
||||
('production|assign_cron', "Assign Productions"),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table = cls.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 7.0: replace assign_cron
|
||||
cursor.execute(*table.update(
|
||||
[table.method], ['ir.cron|stock_shipment_assign_try'],
|
||||
where=table.method == 'production|assign_cron'))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Unify shipment assignation scheduled jobs
|
||||
* Fill shipment number only in waiting state
|
||||
* Manage assignation for customer shipment with same picking and output location
|
||||
* Add pblc argument to assign_try
|
||||
|
||||
+37
-5
@@ -1,6 +1,13 @@
|
||||
# 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.pool import PoolMeta
|
||||
|
||||
from itertools import groupby
|
||||
from operator import attrgetter
|
||||
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .shipment import ShipmentAssignMixin
|
||||
|
||||
|
||||
class Cron(metaclass=PoolMeta):
|
||||
@@ -18,8 +25,33 @@ class Cron(metaclass=PoolMeta):
|
||||
"Reschedule Supplier Return Shipments"),
|
||||
('stock.shipment.internal|reschedule',
|
||||
"Reschedule Internal Shipments"),
|
||||
('stock.shipment.out|assign_cron',
|
||||
"Assign Customer Shipments"),
|
||||
('stock.shipment.internal|assign_cron',
|
||||
"Assign Internal Shipments"),
|
||||
('ir.cron|stock_shipment_assign_try', "Assign Shipments"),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table = cls.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 7.0: replace assign_cron
|
||||
cursor.execute(*table.update(
|
||||
[table.method], ['ir.cron|stock_shipment_assign_try'],
|
||||
where=table.method.in_([
|
||||
'stock.shipment.out|assign_cron',
|
||||
'stock.shipment.internal|assign_cron',
|
||||
])))
|
||||
|
||||
@classmethod
|
||||
def stock_shipment_assign_try(cls):
|
||||
pool = Pool()
|
||||
records = []
|
||||
for _, kls in pool.iterobject():
|
||||
if issubclass(kls, ShipmentAssignMixin):
|
||||
records.extend(kls.to_assign())
|
||||
|
||||
records.sort(key=attrgetter('assign_order_key'))
|
||||
|
||||
for kls, records in groupby(records, key=attrgetter('__class__')):
|
||||
kls.assign_try(list(records))
|
||||
|
||||
@@ -210,9 +210,12 @@ class ShipmentAssignMixin(ShipmentMixin):
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def assign_cron(cls):
|
||||
shipments = cls.search(cls._get_assign_domain())
|
||||
cls.assign_try(shipments)
|
||||
def to_assign(cls):
|
||||
return cls.search(cls._get_assign_domain())
|
||||
|
||||
@property
|
||||
def assign_order_key(self):
|
||||
return (self.planned_date, self.create_date)
|
||||
|
||||
def get_partially_assigned(self, name):
|
||||
return (self.state != 'assigned'
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
==========================
|
||||
Stock Shipment Cron Assign
|
||||
==========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> UoM = Model.get('product.uom')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create a product::
|
||||
|
||||
>>> unit, = UoM.find([('name', '=', "Unit")])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.type = 'goods'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Get locations::
|
||||
|
||||
>>> storage_loc, = Location.find([('code', '=', "STO")])
|
||||
>>> supplier_loc, = Location.find([('code', '=', "SUP")])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')], limit=1)
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 5
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Create different shipments with different planned dates::
|
||||
|
||||
>>> shipment_int_1 = ShipmentInternal()
|
||||
>>> shipment_int_1.planned_date = today
|
||||
>>> shipment_int_1.from_location = storage_loc
|
||||
>>> shipment_int_1.to_location = lost_loc
|
||||
>>> move = shipment_int_1.moves.new()
|
||||
>>> move.from_location = shipment_int_1.from_location
|
||||
>>> move.to_location = shipment_int_1.to_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> shipment_int_1.click('wait')
|
||||
>>> shipment_int_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_1 = ShipmentOut()
|
||||
>>> shipment_out_1.planned_date = today
|
||||
>>> shipment_out_1.customer = customer
|
||||
>>> move = shipment_out_1.outgoing_moves.new()
|
||||
>>> move.from_location = shipment_out_1.warehouse_output
|
||||
>>> move.to_location = shipment_out_1.customer_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_out_1.click('wait')
|
||||
>>> shipment_out_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_int_2, = shipment_int_1.duplicate()
|
||||
>>> shipment_int_2.click('wait')
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_2, = shipment_out_1.duplicate()
|
||||
>>> shipment_out_2.click('wait')
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
|
||||
Run assignation cron::
|
||||
|
||||
>>> cron = Cron(method='ir.cron|stock_shipment_assign_try')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'days'
|
||||
>>> cron.click('run_once')
|
||||
|
||||
Check assignations::
|
||||
|
||||
>>> shipment_int_1.reload()
|
||||
>>> shipment_int_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_out_1.reload()
|
||||
>>> shipment_out_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_int_2.reload()
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
>>> shipment_int_2.partially_assigned
|
||||
True
|
||||
|
||||
>>> shipment_out_2.reload()
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
>>> shipment_out_2.partially_assigned
|
||||
False
|
||||
Reference in New Issue
Block a user