diff --git a/issue11745.diff b/issue11745.diff new file mode 100644 index 0000000..268bb22 --- /dev/null +++ b/issue11745.diff @@ -0,0 +1,276 @@ +diff --git a/tryton/modules/stock/location.py b/tryton/modules/stock/location.py +index 4c7e4d5..f1a790f 100644 +--- a/tryton/modules/stock/location.py ++++ b/tryton/modules/stock/location.py +@@ -811,12 +832,14 @@ class LocationLeadTime(sequence_ordered(), ModelSQL, ModelView, MatchMixin): + ondelete='CASCADE', + domain=[ + ('type', '=', 'warehouse'), +- ]) ++ ('id', '!=', Eval('warehouse_to', -1)), ++ ], depends=['warehouse_to']) + warehouse_to = fields.Many2One('stock.location', 'Warehouse To', + ondelete='CASCADE', + domain=[ + ('type', '=', 'warehouse'), +- ]) ++ ('id', '!=', Eval('warehouse_from', -1)), ++ ], depends=['warehouse_from']) + lead_time = fields.TimeDelta('Lead Time', + help="The time it takes to move stock between the warehouses.") + +diff --git a/tryton/modules/stock/shipment.py b/tryton/modules/stock/shipment.py +index 9067c31..ae467d3 100644 +--- a/tryton/modules/stock/shipment.py ++++ b/tryton/modules/stock/shipment.py +@@ -2264,11 +2264,15 @@ class ShipmentInternal(ShipmentAssignMixin, Workflow, ModelSQL, ModelView): + def default_company(): + return Transaction().context.get('company') + +- @fields.depends('planned_date', 'planned_start_date', 'company') ++ @fields.depends('from_location', 'to_location', 'company') + def on_change_with_transit_location(self, name=None): + pool = Pool() + Config = pool.get('stock.configuration') +- if self.planned_date != self.planned_start_date: ++ if (self.from_location ++ and self.to_location ++ and self.from_location.warehouse != self.to_location.warehouse ++ and self.from_location.warehouse ++ and self.to_location.warehouse): + return Config(1).get_multivalue( + 'shipment_internal_transit', + company=self.company.id if self.company else None).id +@@ -2278,11 +2282,14 @@ class ShipmentInternal(ShipmentAssignMixin, Workflow, ModelSQL, ModelView): + if self.from_location and self.from_location.warehouse: + return self.from_location.warehouse.id + +- @fields.depends('planned_date', 'from_location', 'to_location') ++ @fields.depends( ++ 'planned_date', 'from_location', 'to_location', ++ methods=['on_change_with_transit_location']) + def on_change_with_planned_start_date(self, pattern=None): + pool = Pool() + LocationLeadTime = pool.get('stock.location.lead_time') +- if self.planned_date: ++ transit_location = self.on_change_with_transit_location() ++ if self.planned_date and transit_location: + if pattern is None: + pattern = {} + pattern.setdefault('warehouse_from', + +diff --git a/tryton/modules/stock/tests/scenario_stock_shipment_internal.rst b/tryton/modules/stock/tests/scenario_stock_shipment_internal.rst +index 311d8f3..fe8e262 100644 +--- a/tryton/modules/stock/tests/scenario_stock_shipment_internal.rst ++++ b/tryton/modules/stock/tests/scenario_stock_shipment_internal.rst +@@ -43,7 +43,8 @@ Get stock locations:: + >>> Location = Model.get('stock.location') + >>> lost_found_loc, = Location.find([('type', '=', 'lost_found')]) + >>> storage_loc, = Location.find([('code', '=', 'STO')]) +- >>> internal_loc = Location(name='Internal', type='storage') ++ >>> internal_loc = Location( ++ ... name="Internal", type='storage', parent=storage_loc.parent) + >>> internal_loc.save() + + Create stock user:: +@@ -116,7 +117,7 @@ Create Internal Shipment from lost_found location:: + >>> lost_found_shipment.state + 'done' + +-Check that now whe can finish the older shipment:: ++Check that now we can finish the older shipment:: + + >>> shipment.click('assign_try') + True +@@ -130,72 +131,6 @@ Check that now whe can finish the older shipment:: + >>> shipment.done_by == employee + True + +-Add lead time inside the warehouse:: +- +- >>> set_user(1) +- >>> LeadTime = Model.get('stock.location.lead_time') +- >>> lead_time = LeadTime() +- >>> lead_time.warehouse_from = internal_loc.warehouse +- >>> lead_time.warehouse_to = storage_loc.warehouse +- >>> lead_time.lead_time = datetime.timedelta(1) +- >>> lead_time.save() +- +-Create Internal Shipment with lead time:: +- +- >>> set_user(stock_user) +- >>> shipment = Shipment() +- >>> shipment.planned_date = tomorrow +- >>> shipment.from_location = internal_loc +- >>> shipment.to_location = storage_loc +- >>> shipment.planned_start_date == today +- True +- >>> move = shipment.moves.new() +- >>> move.product = product +- >>> move.quantity = 2 +- >>> move.from_location = internal_loc +- >>> move.to_location = storage_loc +- >>> shipment.click('wait') +- >>> len(shipment.moves) +- 2 +- >>> outgoing_move, = shipment.outgoing_moves +- >>> outgoing_move.quantity +- 2.0 +- >>> outgoing_move.from_location == internal_loc +- True +- >>> outgoing_move.to_location == shipment.transit_location +- True +- >>> outgoing_move.planned_date == today +- True +- >>> incoming_move, = shipment.incoming_moves +- >>> incoming_move.quantity +- 2.0 +- >>> incoming_move.from_location == shipment.transit_location +- True +- >>> incoming_move.to_location == storage_loc +- True +- >>> incoming_move.planned_date == tomorrow +- True +- +- >>> outgoing_move.quantity = 1 +- >>> outgoing_move.save() +- +- >>> shipment.click('assign_try') +- True +- >>> shipment.effective_start_date = yesterday +- >>> shipment.click('ship') +- >>> incoming_move, = shipment.incoming_moves +- >>> incoming_move.quantity +- 1.0 +- >>> shipment.outgoing_moves[0].state +- 'done' +- >>> shipment.outgoing_moves[0].effective_date == yesterday +- True +- >>> shipment.click('done') +- >>> shipment.incoming_moves[0].state +- 'done' +- >>> shipment.incoming_moves[0].effective_date == today +- True +- + Duplicate Internal Shipment:: + + >>> shipment_copy, = shipment.duplicate() + +diff --git a/tryton/modules/stock/tests/scenario_stock_shipment_internal_transit.rst b/tryton/modules/stock/tests/scenario_stock_shipment_internal_transit.rst +new file mode 100644 +index 0000000..37cd081 +--- /dev/null ++++ b/tryton/modules/stock/tests/scenario_stock_shipment_internal_transit.rst +@@ -0,0 +1,112 @@ ++============================================= ++Stock Shipment Internal with Transit Scenario ++============================================= ++ ++Imports:: ++ ++ >>> import datetime as dt ++ >>> from decimal import Decimal ++ ++ >>> from proteus import Model, Wizard ++ >>> from trytond.tests.tools import activate_modules ++ >>> from trytond.modules.company.tests.tools import ( ++ ... create_company, get_company) ++ ++ >>> today = dt.date.today() ++ >>> yesterday = today - dt.timedelta(days=1) ++ >>> tomorrow = today + dt.timedelta(days=1) ++ ++Activate modules:: ++ ++ >>> config = activate_modules('stock') ++ ++ >>> ProductTemplate = Model.get('product.template') ++ >>> ProductUom = Model.get('product.uom') ++ >>> Shipment = Model.get('stock.shipment.internal') ++ ++Create company:: ++ ++ >>> _ = create_company() ++ >>> company = get_company() ++ ++Create product:: ++ ++ >>> unit, = ProductUom.find([('name', '=', 'Unit')]) ++ >>> template = ProductTemplate() ++ >>> template.name = "Product" ++ >>> template.default_uom = unit ++ >>> template.type = 'goods' ++ >>> template.list_price = Decimal('20') ++ >>> template.save() ++ >>> product, = template.products ++ ++Get stock locations:: ++ ++ >>> Location = Model.get('stock.location') ++ >>> warehouse1, = Location.find([('type', '=', 'warehouse')]) ++ >>> warehouse2, = warehouse1.duplicate() ++ ++Add lead time between warehouses:: ++ ++ >>> LeadTime = Model.get('stock.location.lead_time') ++ >>> lead_time = LeadTime() ++ >>> lead_time.warehouse_from = warehouse1 ++ >>> lead_time.warehouse_to = warehouse2 ++ >>> lead_time.lead_time = dt.timedelta(1) ++ >>> lead_time.save() ++ ++Create Internal Shipment with lead time:: ++ ++ >>> shipment = Shipment() ++ >>> shipment.planned_date = tomorrow ++ >>> shipment.from_location = warehouse1.storage_location ++ >>> shipment.to_location = warehouse2.storage_location ++ >>> bool(shipment.transit_location) ++ True ++ >>> shipment.planned_start_date == today ++ True ++ >>> move = shipment.moves.new() ++ >>> move.product = product ++ >>> move.quantity = 2 ++ >>> move.from_location = shipment.from_location ++ >>> move.to_location = shipment.to_location ++ >>> shipment.click('wait') ++ >>> len(shipment.moves) ++ 2 ++ >>> outgoing_move, = shipment.outgoing_moves ++ >>> outgoing_move.quantity ++ 2.0 ++ >>> outgoing_move.from_location == shipment.from_location ++ True ++ >>> outgoing_move.to_location == shipment.transit_location ++ True ++ >>> outgoing_move.planned_date == today ++ True ++ >>> incoming_move, = shipment.incoming_moves ++ >>> incoming_move.quantity ++ 2.0 ++ >>> incoming_move.from_location == shipment.transit_location ++ True ++ >>> incoming_move.to_location == shipment.to_location ++ True ++ >>> incoming_move.planned_date == tomorrow ++ True ++ ++ >>> outgoing_move.quantity = 1 ++ >>> outgoing_move.save() ++ ++ >>> shipment.click('assign_force') ++ >>> shipment.effective_start_date = yesterday ++ >>> shipment.click('ship') ++ >>> incoming_move, = shipment.incoming_moves ++ >>> incoming_move.quantity ++ 1.0 ++ >>> shipment.outgoing_moves[0].state ++ 'done' ++ >>> shipment.outgoing_moves[0].effective_date == yesterday ++ True ++ >>> shipment.click('done') ++ >>> shipment.incoming_moves[0].state ++ 'done' ++ >>> shipment.incoming_moves[0].effective_date == today ++ True diff --git a/series b/series index ec6bf12..b5c0229 100644 --- a/series +++ b/series @@ -86,3 +86,5 @@ issue12414.diff # [stock_lot_sled] Check expiration lot in case Shelf Life Time issue12315.diff # [stock_product_location] Make production entry move from_location configurable merge_request581.diff # [account] Post cancelled, grouped, rescheduled and delegated moves + +issue11745.diff # [stock] Moves of internal shipment are not valid when switching between transit and no transit