Lot virtual packing update
This commit is contained in:
@@ -1127,6 +1127,15 @@ class CoffeeLineMixin:
|
||||
'Package weight', digits=(16, 5))
|
||||
coffee_packing_weight_unit = fields.Many2One(
|
||||
'product.uom', 'Package weight unit')
|
||||
coffee_packing_unit = fields.Many2One(
|
||||
'product.uom', 'Package unit',
|
||||
domain=[
|
||||
('category', '=', Eval('coffee_packing_category')),
|
||||
],
|
||||
depends=['coffee_packing_category'])
|
||||
coffee_packing_category = fields.Function(
|
||||
fields.Many2One('product.uom.category', 'Packing Category'),
|
||||
'on_change_with_coffee_packing_category')
|
||||
coffee_packing_description = fields.Char('Packing description')
|
||||
coffee_market_reference = fields.Many2One(
|
||||
'price.price', 'Market reference')
|
||||
@@ -1142,6 +1151,13 @@ class CoffeeLineMixin:
|
||||
def on_change_with_active_coffee_compatibility(self, name=None):
|
||||
return self.get_active_coffee_compatibility(name)
|
||||
|
||||
@fields.depends()
|
||||
def on_change_with_coffee_packing_category(self, name=None):
|
||||
UnitCategory = Pool().get('product.uom.category')
|
||||
packing = UnitCategory.search([('name', '=', 'Packing')], limit=1)
|
||||
if packing:
|
||||
return packing[0]
|
||||
|
||||
def _coffee_attributes_name(self):
|
||||
values = []
|
||||
for field_name, selection in self._coffee_attribute_name_fields:
|
||||
|
||||
@@ -2882,6 +2882,27 @@ class Line(metaclass=PoolMeta):
|
||||
def _should_regenerate_valuation(cls, values):
|
||||
return bool(cls._valuation_regeneration_fields() & set(values))
|
||||
|
||||
@classmethod
|
||||
def _sync_virtual_lot_packing(cls, line):
|
||||
Lot = Pool().get('lot.lot')
|
||||
if not getattr(line, 'lots', None):
|
||||
line = cls(line.id)
|
||||
virtual_lots = [
|
||||
lot for lot in (line.lots or [])
|
||||
if getattr(lot, 'lot_type', None) == 'virtual']
|
||||
if not virtual_lots:
|
||||
return
|
||||
lot = virtual_lots[0]
|
||||
packing_count = getattr(line, 'coffee_packing_count', None)
|
||||
packing_unit = getattr(line, 'coffee_packing_unit', None)
|
||||
lot_unit_id = getattr(lot.lot_unit, 'id', lot.lot_unit)
|
||||
packing_unit_id = getattr(packing_unit, 'id', packing_unit)
|
||||
if lot.lot_qt == packing_count and lot_unit_id == packing_unit_id:
|
||||
return
|
||||
lot.lot_qt = packing_count
|
||||
lot.lot_unit = packing_unit
|
||||
Lot.save([lot])
|
||||
|
||||
@classmethod
|
||||
def write(cls, *args):
|
||||
actions = iter(args)
|
||||
@@ -3104,17 +3125,18 @@ class Line(metaclass=PoolMeta):
|
||||
if Decimal(str(line.quantity_theorical or 0)) > 0:
|
||||
Lot.save([lot])
|
||||
#check if fees need to be updated
|
||||
if line.fees:
|
||||
for fee in line.fees:
|
||||
fl_check = FeeLots.search([('fee','=',fee.id),('lot','=',lot.id),('line','=',line.id)])
|
||||
if not fl_check:
|
||||
fl = FeeLots()
|
||||
if line.fees:
|
||||
for fee in line.fees:
|
||||
fl_check = FeeLots.search([('fee','=',fee.id),('lot','=',lot.id),('line','=',line.id)])
|
||||
if not fl_check:
|
||||
fl = FeeLots()
|
||||
fl.fee = fee.id
|
||||
fl.lot = lot.id
|
||||
fl.line = line.id
|
||||
FeeLots.save([fl])
|
||||
|
||||
if line.fee_:
|
||||
fl.line = line.id
|
||||
FeeLots.save([fl])
|
||||
cls._sync_virtual_lot_packing(line)
|
||||
|
||||
if line.fee_:
|
||||
if not line.fee_.purchase:
|
||||
Fee = Pool().get('fee.fee')
|
||||
f = Fee(line.fee_)
|
||||
|
||||
@@ -3002,6 +3002,27 @@ class SaleLine(metaclass=PoolMeta):
|
||||
default.setdefault('quantity_theorical', None)
|
||||
default.setdefault('price_pricing', None)
|
||||
return super().copy(lines, default=default)
|
||||
|
||||
@classmethod
|
||||
def _sync_virtual_lot_packing(cls, line):
|
||||
Lot = Pool().get('lot.lot')
|
||||
if not getattr(line, 'lots', None):
|
||||
line = cls(line.id)
|
||||
virtual_lots = [
|
||||
lot for lot in (line.lots or [])
|
||||
if getattr(lot, 'lot_type', None) == 'virtual']
|
||||
if not virtual_lots:
|
||||
return
|
||||
lot = virtual_lots[0]
|
||||
packing_count = getattr(line, 'coffee_packing_count', None)
|
||||
packing_unit = getattr(line, 'coffee_packing_unit', None)
|
||||
lot_unit_id = getattr(lot.lot_unit, 'id', lot.lot_unit)
|
||||
packing_unit_id = getattr(packing_unit, 'id', packing_unit)
|
||||
if lot.lot_qt == packing_count and lot_unit_id == packing_unit_id:
|
||||
return
|
||||
lot.lot_qt = packing_count
|
||||
lot.lot_unit = packing_unit
|
||||
Lot.save([lot])
|
||||
|
||||
@classmethod
|
||||
def validate(cls, salelines):
|
||||
@@ -3061,6 +3082,7 @@ class SaleLine(metaclass=PoolMeta):
|
||||
fl.lot = lot.id
|
||||
fl.sale_line = line.id
|
||||
FeeLots.save([fl])
|
||||
cls._sync_virtual_lot_packing(line)
|
||||
|
||||
#generate valuation for purchase and sale
|
||||
LotQt = Pool().get('lot.qt')
|
||||
|
||||
@@ -210,6 +210,62 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
self.assertEqual(
|
||||
line.get_coffee_quality_status(), 'approved')
|
||||
|
||||
def test_purchase_line_syncs_packing_to_virtual_lot(self):
|
||||
'purchase line packing updates the existing virtual lot'
|
||||
package_unit = Mock(id=60)
|
||||
lot = Mock(lot_type='virtual', lot_qt=None, lot_unit=None)
|
||||
line = Mock(
|
||||
lots=[lot],
|
||||
coffee_packing_count=440,
|
||||
coffee_packing_unit=package_unit)
|
||||
lot_model = Mock()
|
||||
pool = Mock()
|
||||
pool.get.return_value = lot_model
|
||||
|
||||
with patch.object(purchase_module, 'Pool', return_value=pool):
|
||||
purchase_module.Line._sync_virtual_lot_packing(line)
|
||||
|
||||
self.assertEqual(lot.lot_qt, 440)
|
||||
self.assertEqual(lot.lot_unit, package_unit)
|
||||
lot_model.save.assert_called_once_with([lot])
|
||||
|
||||
def test_sale_line_syncs_packing_to_virtual_lot(self):
|
||||
'sale line packing updates the existing virtual lot'
|
||||
package_unit = Mock(id=90)
|
||||
old_unit = Mock(id=60)
|
||||
lot = Mock(lot_type='virtual', lot_qt=440, lot_unit=old_unit)
|
||||
line = Mock(
|
||||
lots=[lot],
|
||||
coffee_packing_count=300,
|
||||
coffee_packing_unit=package_unit)
|
||||
lot_model = Mock()
|
||||
pool = Mock()
|
||||
pool.get.return_value = lot_model
|
||||
|
||||
with patch.object(sale_module, 'Pool', return_value=pool):
|
||||
sale_module.SaleLine._sync_virtual_lot_packing(line)
|
||||
|
||||
self.assertEqual(lot.lot_qt, 300)
|
||||
self.assertEqual(lot.lot_unit, package_unit)
|
||||
lot_model.save.assert_called_once_with([lot])
|
||||
|
||||
def test_purchase_line_does_not_resave_aligned_virtual_lot_packing(self):
|
||||
'aligned purchase packing does not resave the virtual lot'
|
||||
package_unit = Mock(id=60)
|
||||
lot = Mock(lot_type='virtual', lot_qt=440, lot_unit=Mock(id=60))
|
||||
line = Mock(
|
||||
lots=[lot],
|
||||
coffee_packing_count=440,
|
||||
coffee_packing_unit=package_unit)
|
||||
lot_model = Mock()
|
||||
pool = Mock()
|
||||
pool.get.return_value = lot_model
|
||||
|
||||
with patch.object(purchase_module, 'Pool', return_value=pool):
|
||||
purchase_module.Line._sync_virtual_lot_packing(line)
|
||||
|
||||
lot_model.save.assert_not_called()
|
||||
|
||||
def test_itsa_book_year_suffix_uses_april_fiscal_start(self):
|
||||
'ITSA book year changes on April 1st'
|
||||
self.assertEqual(
|
||||
|
||||
@@ -45,12 +45,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
col_widths="min-content,1fr,min-content,1fr">
|
||||
<label name="coffee_packing_count"/>
|
||||
<field name="coffee_packing_count" width="120" xexpand="0" xfill="0"/>
|
||||
<label name="coffee_packing_unit_weight"/>
|
||||
<field name="coffee_packing_unit_weight" width="120" xexpand="0" xfill="0"/>
|
||||
<label name="coffee_packing_weight_unit"/>
|
||||
<field name="coffee_packing_weight_unit"/>
|
||||
<label name="coffee_packing_unit"/>
|
||||
<field name="coffee_packing_unit"/>
|
||||
<label name="coffee_packing_description"/>
|
||||
<field name="coffee_packing_description"/>
|
||||
<field name="coffee_packing_category" invisible="1" colspan="4"/>
|
||||
</group>
|
||||
<group id="tolerances" string="Tolerances & Inheritance"
|
||||
colspan="1" col="4" panel="card" icon="tryton-switch"
|
||||
|
||||
@@ -42,12 +42,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
col_widths="min-content,1fr,min-content,1fr">
|
||||
<label name="coffee_packing_count"/>
|
||||
<field name="coffee_packing_count" width="120" xexpand="0" xfill="0"/>
|
||||
<label name="coffee_packing_unit_weight"/>
|
||||
<field name="coffee_packing_unit_weight" width="120" xexpand="0" xfill="0"/>
|
||||
<label name="coffee_packing_weight_unit"/>
|
||||
<field name="coffee_packing_weight_unit"/>
|
||||
<label name="coffee_packing_unit"/>
|
||||
<field name="coffee_packing_unit"/>
|
||||
<label name="coffee_packing_description"/>
|
||||
<field name="coffee_packing_description"/>
|
||||
<field name="coffee_packing_category" invisible="1" colspan="4"/>
|
||||
</group>
|
||||
<group id="tolerances" string="Tolerances & Inheritance"
|
||||
colspan="1" col="4" panel="card" icon="tryton-switch"
|
||||
|
||||
Reference in New Issue
Block a user