diff --git a/modules/purchase_trade/lot.py b/modules/purchase_trade/lot.py
index 18144da..97e1cd8 100755
--- a/modules/purchase_trade/lot.py
+++ b/modules/purchase_trade/lot.py
@@ -2958,11 +2958,9 @@ class LotShipping(Wizard):
'lot.shipping.start',
'purchase_trade.shipping_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
- Button("New shipment & link", 'create_shipment', 'tryton-add'),
Button("Link", 'shipping', 'tryton-ok', default=True),
])
- create_shipment = StateTransition()
shipping = StateTransition()
def transition_start(self):
@@ -2986,25 +2984,21 @@ class LotShipping(Wizard):
def _record_id(record):
return record.id if record else None
- def _unique_supplier(self):
- suppliers = {}
- for record in self.records:
- supplier = getattr(record, 'r_supplier', None)
- if supplier:
- suppliers[supplier.id] = supplier
- if len(suppliers) == 1:
- return next(iter(suppliers.values()))
- if not suppliers:
- raise UserError("Supplier is required to create a shipment.")
- raise UserError(
- "Please select lots with the same supplier to create a shipment.")
+ def _selected_shipment(self):
+ if self.ship.shipment == 'in':
+ return self.ship.shipment_in
+ if self.ship.shipment == 'out':
+ return self.ship.shipment_out
+ if self.ship.shipment == 'int':
+ return self.ship.shipment_internal
def _shipment_in_create_values(self):
if self.ship.shipment != 'in':
raise UserError("Shipment creation is only available for Shipment In.")
- supplier = self._unique_supplier()
+ if not self.ship.shipment_supplier:
+ raise UserError("Shipment supplier is required.")
values = {
- 'supplier': self._record_id(supplier),
+ 'supplier': self._record_id(self.ship.shipment_supplier),
}
if self.ship.planned_from_location:
values['from_location'] = self.ship.planned_from_location.id
@@ -3012,13 +3006,10 @@ class LotShipping(Wizard):
values['to_location'] = self.ship.planned_to_location.id
return values
- def transition_create_shipment(self):
+ def _create_shipment_in(self):
ShipmentIn = Pool().get('stock.shipment.in')
- if self.ship.shipment_in:
- return self.transition_shipping()
shipment, = ShipmentIn.create([self._shipment_in_create_values()])
self.ship.shipment_in = shipment
- return self.transition_shipping()
def transition_shipping(self):
Lot = Pool().get('lot.lot')
@@ -3027,6 +3018,11 @@ class LotShipping(Wizard):
affected_lines = []
if not self.ship.shipment:
pass
+ if self.ship.create_new_shipment and self._selected_shipment():
+ raise UserError(
+ "Choose either an existing shipment or create a new shipment.")
+ if self.ship.create_new_shipment:
+ self._create_shipment_in()
with Lot.skip_quantity_consistency():
for r in self.records:
if r.r_lot_shipment_in:
@@ -3041,15 +3037,15 @@ class LotShipping(Wizard):
shipped_quantity = Decimal(str(r.r_lot_matched)).quantize(Decimal("0.00001"))
if self.ship.shipment == 'in':
if not self.ship.shipment_in:
- UserError("Shipment not known!")
+ raise UserError("Shipment not known!")
shipment_origin = 'stock.shipment.in,'+str(self.ship.shipment_in.id)
elif self.ship.shipment == 'out':
if not self.ship.shipment_out:
- UserError("Shipment not known!")
+ raise UserError("Shipment not known!")
shipment_origin = 'stock.shipment.out,'+str(self.ship.shipment_out.id)
elif self.ship.shipment == 'int':
if not self.ship.shipment_internal:
- UserError("Shipment not known!")
+ raise UserError("Shipment not known!")
shipment_origin = 'stock.shipment.internal,'+str(self.ship.shipment_internal.id)
if r.id < 10000000 :
l = Lot(r.id)
@@ -3137,6 +3133,16 @@ class LotShippingStart(ModelView):
shipment_in = fields.Many2One('stock.shipment.in',"Shipment In", states={'invisible': (Eval('shipment') != 'in')})
shipment_out = fields.Many2One('stock.shipment.out',"Shipment Out", states={'invisible': (Eval('shipment') != 'out')})
shipment_internal = fields.Many2One('stock.shipment.internal',"Shipment Internal", states={'invisible': (Eval('shipment') != 'int')})
+ create_new_shipment = fields.Boolean(
+ "Create a new shipment",
+ states={'invisible': Eval('shipment') != 'in'})
+ shipment_supplier = fields.Many2One(
+ 'party.party', "Shipment supplier",
+ states={
+ 'invisible': ~Bool(Eval('create_new_shipment')),
+ 'required': Bool(Eval('create_new_shipment')),
+ },
+ depends=['create_new_shipment'])
planned_from_location = fields.Many2One(
'stock.location', "Planned From", readonly=True)
planned_to_location = fields.Many2One(
@@ -3152,6 +3158,10 @@ class LotShippingStart(ModelView):
def default_shipment(cls):
return 'in'
+ @classmethod
+ def default_create_new_shipment(cls):
+ return False
+
class LotPlanTransport(Wizard):
"Plan lot to transport"
diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py
index 7109e2f..56d5f0d 100644
--- a/modules/purchase_trade/tests/test_module.py
+++ b/modules/purchase_trade/tests/test_module.py
@@ -219,27 +219,33 @@ class PurchaseTradeTestCase(ModuleTestCase):
'planned_to_location': 20,
})
- def test_lot_shipping_create_shipment_links_planned_locations(self):
- 'link to transport creates shipment in and links planned locations'
+ def test_lot_shipping_link_creates_shipment_from_dialog_supplier(self):
+ 'link to transport creates shipment in from dialog supplier'
wizard = lot_module.LotShipping()
supplier = Mock(id=30)
created_shipment = Mock(id=40)
ShipmentIn = Mock()
ShipmentIn.create.return_value = [created_shipment]
- wizard.records = [Mock(r_supplier=supplier)]
+ wizard.records = []
wizard.ship = Mock(
shipment='in',
shipment_in=None,
+ shipment_out=None,
+ shipment_internal=None,
+ create_new_shipment=True,
+ shipment_supplier=supplier,
planned_from_location=Mock(id=10),
planned_to_location=Mock(id=20),
)
- with patch('trytond.modules.purchase_trade.lot.Pool') as PoolMock:
- PoolMock.return_value.get.return_value = ShipmentIn
- with patch.object(
- wizard, 'transition_shipping', return_value='end'
- ) as transition_shipping:
- state = wizard.transition_create_shipment()
+ Lot = Mock()
+ Lot.skip_quantity_consistency.return_value.__enter__ = Mock()
+ Lot.skip_quantity_consistency.return_value.__exit__ = Mock()
+ pool = Mock()
+ pool.get.side_effect = [Lot, Mock(), Mock(), ShipmentIn]
+ with patch('trytond.modules.purchase_trade.lot.Pool',
+ return_value=pool):
+ state = wizard.transition_shipping()
self.assertEqual(state, 'end')
ShipmentIn.create.assert_called_once_with([{
@@ -248,7 +254,22 @@ class PurchaseTradeTestCase(ModuleTestCase):
'to_location': 20,
}])
self.assertEqual(wizard.ship.shipment_in, created_shipment)
- transition_shipping.assert_called_once_with()
+ Lot.assert_lines_quantity_consistency.assert_called_once_with([])
+
+ def test_lot_shipping_rejects_existing_and_new_shipment(self):
+ 'link to transport rejects choosing existing shipment and create new'
+ wizard = lot_module.LotShipping()
+ wizard.ship = Mock(
+ shipment='in',
+ shipment_in=Mock(id=40),
+ shipment_out=None,
+ shipment_internal=None,
+ create_new_shipment=True,
+ shipment_supplier=Mock(id=30),
+ )
+
+ with self.assertRaises(UserError):
+ wizard.transition_shipping()
@with_transaction()
def test_get_mtm_applies_component_ratio_as_percentage(self):
diff --git a/modules/purchase_trade/view/lot_shipping_start_form.xml b/modules/purchase_trade/view/lot_shipping_start_form.xml
index 33da66f..7361edb 100755
--- a/modules/purchase_trade/view/lot_shipping_start_form.xml
+++ b/modules/purchase_trade/view/lot_shipping_start_form.xml
@@ -4,6 +4,10 @@
+
+
+
+