ICT bug padding + template
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
,PC_LO/baron,PC_LO,28.05.2026 13:23,file:///C:/Users/baron/AppData/Roaming/LibreOffice/4;
|
|
||||||
@@ -230,12 +230,13 @@ def register():
|
|||||||
Pool.register(
|
Pool.register(
|
||||||
account.PhysicalTradeIFRS,
|
account.PhysicalTradeIFRS,
|
||||||
module='purchase_trade', type_='model')
|
module='purchase_trade', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
configuration.AccountConfiguration,
|
configuration.AccountConfiguration,
|
||||||
configuration.AccountConfigurationDefaultAccount,
|
configuration.AccountConfigurationDefaultAccount,
|
||||||
invoice.InvoicePaddingReport,
|
invoice.InvoiceLineLotWeight,
|
||||||
invoice.InvoicePaddingContext,
|
invoice.InvoicePaddingReport,
|
||||||
module='purchase_trade', type_='model')
|
invoice.InvoicePaddingContext,
|
||||||
|
module='purchase_trade', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
invoice.Invoice,
|
invoice.Invoice,
|
||||||
invoice.InvoiceLine,
|
invoice.InvoiceLine,
|
||||||
|
|||||||
@@ -444,6 +444,9 @@ class Fee(ModelSQL,ModelView):
|
|||||||
return sum(quantities)
|
return sum(quantities)
|
||||||
|
|
||||||
def sync_quantity_from_lots(self):
|
def sync_quantity_from_lots(self):
|
||||||
|
if self.mode == 'ppack' and self.auto_calculation:
|
||||||
|
self.assert_quantity_consistency()
|
||||||
|
return
|
||||||
quantity = self._get_effective_fee_lots_quantity()
|
quantity = self._get_effective_fee_lots_quantity()
|
||||||
if quantity is None:
|
if quantity is None:
|
||||||
self.assert_quantity_consistency()
|
self.assert_quantity_consistency()
|
||||||
|
|||||||
@@ -17,13 +17,106 @@ from trytond.modules.purchase.purchase import (
|
|||||||
PurchaseReport as BasePurchaseReport)
|
PurchaseReport as BasePurchaseReport)
|
||||||
|
|
||||||
|
|
||||||
|
class InvoiceLineLotWeight(ModelSQL, ModelView):
|
||||||
|
"Invoice Line Lot Weight"
|
||||||
|
__name__ = 'account.invoice.line.lot.weight'
|
||||||
|
|
||||||
|
invoice_line = fields.Many2One(
|
||||||
|
'account.invoice.line', "Invoice Line", required=True,
|
||||||
|
ondelete='CASCADE')
|
||||||
|
lot = fields.Many2One('lot.lot', "Lot", required=True, ondelete='CASCADE')
|
||||||
|
lot_qt_hist = fields.Many2One('lot.qt.hist', "Quantity History")
|
||||||
|
quantity_type = fields.Many2One('lot.qt.type', "Quantity Type")
|
||||||
|
net_quantity = fields.Numeric("Net Weight", digits=(1, 5), required=True)
|
||||||
|
gross_quantity = fields.Numeric(
|
||||||
|
"Gross Weight", digits=(1, 5), required=True)
|
||||||
|
unit = fields.Many2One('product.uom', "Unit")
|
||||||
|
lot_qt = fields.Integer("Packing Quantity")
|
||||||
|
lot_unit = fields.Many2One('product.uom', "Packing Unit")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_lot_hist_entry(cls, lot):
|
||||||
|
state = getattr(lot, 'lot_state', None)
|
||||||
|
state_id = getattr(state, 'id', None)
|
||||||
|
hist = list(getattr(lot, 'lot_hist', []) or [])
|
||||||
|
if state_id is not None:
|
||||||
|
for entry in hist:
|
||||||
|
quantity_type = getattr(entry, 'quantity_type', None)
|
||||||
|
if getattr(quantity_type, 'id', None) == state_id:
|
||||||
|
return entry
|
||||||
|
if len(hist) == 1:
|
||||||
|
return hist[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_lot_weights(cls, lot):
|
||||||
|
hist = cls._get_lot_hist_entry(lot)
|
||||||
|
if hist:
|
||||||
|
net = Decimal(str(getattr(hist, 'quantity', 0) or 0))
|
||||||
|
gross = Decimal(str(
|
||||||
|
getattr(hist, 'gross_quantity', None)
|
||||||
|
if getattr(hist, 'gross_quantity', None) not in (None, '')
|
||||||
|
else net))
|
||||||
|
return hist, net, gross
|
||||||
|
if hasattr(lot, 'get_hist_quantity'):
|
||||||
|
net, gross = lot.get_hist_quantity()
|
||||||
|
net = Decimal(str(net or 0))
|
||||||
|
gross = Decimal(str(gross if gross not in (None, '') else net))
|
||||||
|
return None, net, gross
|
||||||
|
net = Decimal(str(getattr(lot, 'lot_quantity', 0) or 0))
|
||||||
|
gross = Decimal(str(
|
||||||
|
getattr(lot, 'lot_gross_quantity', None)
|
||||||
|
if getattr(lot, 'lot_gross_quantity', None) not in (None, '')
|
||||||
|
else net))
|
||||||
|
return None, net, gross
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_for_invoice_line(cls, line, lot):
|
||||||
|
if not getattr(line, 'id', None) or not getattr(lot, 'id', None):
|
||||||
|
return
|
||||||
|
existing = cls.search([
|
||||||
|
('invoice_line', '=', line.id),
|
||||||
|
('lot', '=', lot.id),
|
||||||
|
])
|
||||||
|
if existing:
|
||||||
|
cls.delete(existing)
|
||||||
|
hist, net, gross = cls._get_lot_weights(lot)
|
||||||
|
snapshot = cls()
|
||||||
|
snapshot.invoice_line = line
|
||||||
|
snapshot.lot = lot
|
||||||
|
snapshot.lot_qt_hist = hist
|
||||||
|
snapshot.quantity_type = (
|
||||||
|
getattr(hist, 'quantity_type', None)
|
||||||
|
or getattr(lot, 'lot_state', None))
|
||||||
|
snapshot.net_quantity = net
|
||||||
|
snapshot.gross_quantity = gross
|
||||||
|
snapshot.unit = (
|
||||||
|
getattr(lot, 'lot_unit_line', None)
|
||||||
|
or getattr(lot, 'lot_unit', None)
|
||||||
|
or getattr(line, 'unit', None))
|
||||||
|
snapshot.lot_qt = getattr(lot, 'lot_qt', None)
|
||||||
|
snapshot.lot_unit = getattr(lot, 'lot_unit', None)
|
||||||
|
cls.save([snapshot])
|
||||||
|
|
||||||
|
|
||||||
class Invoice(metaclass=PoolMeta):
|
class Invoice(metaclass=PoolMeta):
|
||||||
__name__ = 'account.invoice'
|
__name__ = 'account.invoice'
|
||||||
|
|
||||||
def do_lot_invoicing(self):
|
def do_lot_invoicing(self):
|
||||||
super().do_lot_invoicing()
|
super().do_lot_invoicing()
|
||||||
|
self._create_lot_weight_snapshots()
|
||||||
self._create_sale_padding_moves()
|
self._create_sale_padding_moves()
|
||||||
|
|
||||||
|
def _create_lot_weight_snapshots(self):
|
||||||
|
Snapshot = Pool().get('account.invoice.line.lot.weight')
|
||||||
|
Lot = Pool().get('lot.lot')
|
||||||
|
for line in self._get_report_invoice_lines():
|
||||||
|
if (getattr(line, 'description', None) != 'Pro forma'
|
||||||
|
or Decimal(str(getattr(line, 'quantity', 0) or 0)) <= 0
|
||||||
|
or not getattr(line, 'lot', None)):
|
||||||
|
continue
|
||||||
|
Snapshot.create_for_invoice_line(line, Lot(line.lot.id))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _post(cls, invoices):
|
def _post(cls, invoices):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
@@ -292,6 +385,20 @@ class Invoice(metaclass=PoolMeta):
|
|||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
def _get_report_invoice_line_weights(self, line):
|
def _get_report_invoice_line_weights(self, line):
|
||||||
|
snapshots = self._get_report_invoice_line_weight_snapshots(line)
|
||||||
|
if snapshots:
|
||||||
|
sign = self._get_report_line_sign(line)
|
||||||
|
net_total = sum(
|
||||||
|
Decimal(str(snapshot.net_quantity or 0))
|
||||||
|
for snapshot in snapshots)
|
||||||
|
gross_total = sum(
|
||||||
|
Decimal(str(snapshot.gross_quantity or 0))
|
||||||
|
for snapshot in snapshots)
|
||||||
|
unit = self._get_report_invoice_line_unit(line)
|
||||||
|
padding = self._get_report_invoice_line_padding(line, unit)
|
||||||
|
net_total += padding
|
||||||
|
gross_total += padding
|
||||||
|
return net_total * sign, gross_total * sign
|
||||||
lots = self._get_report_preferred_lots(line)
|
lots = self._get_report_preferred_lots(line)
|
||||||
if lots and self._report_invoice_line_reuses_lot(line):
|
if lots and self._report_invoice_line_reuses_lot(line):
|
||||||
quantity = self._get_report_invoice_line_quantity_from_line(line)
|
quantity = self._get_report_invoice_line_quantity_from_line(line)
|
||||||
@@ -311,6 +418,33 @@ class Invoice(metaclass=PoolMeta):
|
|||||||
quantity = Decimal(str(getattr(line, 'quantity', 0) or 0))
|
quantity = Decimal(str(getattr(line, 'quantity', 0) or 0))
|
||||||
return quantity, quantity
|
return quantity, quantity
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_report_invoice_line_weight_snapshots(line):
|
||||||
|
snapshots = getattr(line, 'lot_weight_snapshots', None)
|
||||||
|
if snapshots and isinstance(snapshots, (list, tuple)):
|
||||||
|
return list(snapshots)
|
||||||
|
line_id = getattr(line, 'id', None)
|
||||||
|
if not isinstance(line_id, int):
|
||||||
|
return []
|
||||||
|
Snapshot = Pool().get('account.invoice.line.lot.weight')
|
||||||
|
return Snapshot.search([('invoice_line', '=', line_id)])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_report_invoice_line_padding(cls, line, to_unit):
|
||||||
|
if getattr(line, 'description', None) != 'Pro forma':
|
||||||
|
return Decimal(0)
|
||||||
|
invoice_type = getattr(line, 'invoice_type', None)
|
||||||
|
invoice = getattr(line, 'invoice', None)
|
||||||
|
if invoice_type != 'out' and getattr(invoice, 'type', None) != 'out':
|
||||||
|
return Decimal(0)
|
||||||
|
lot = getattr(line, 'lot', None)
|
||||||
|
padding = Decimal(str(
|
||||||
|
getattr(lot, 'sale_invoice_padding', 0) or 0))
|
||||||
|
if not padding:
|
||||||
|
return Decimal(0)
|
||||||
|
return cls._convert_report_quantity(
|
||||||
|
padding, getattr(line, 'unit', None), to_unit)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_report_line_lot_keys(line):
|
def _get_report_line_lot_keys(line):
|
||||||
keys = []
|
keys = []
|
||||||
@@ -416,6 +550,9 @@ class Invoice(metaclass=PoolMeta):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_report_invoice_line_unit(line):
|
def _get_report_invoice_line_unit(line):
|
||||||
|
snapshots = Invoice._get_report_invoice_line_weight_snapshots(line)
|
||||||
|
if snapshots and getattr(snapshots[0], 'unit', None):
|
||||||
|
return snapshots[0].unit
|
||||||
lots = Invoice._get_report_preferred_lots(line)
|
lots = Invoice._get_report_preferred_lots(line)
|
||||||
if lots and getattr(lots[0], 'lot_unit_line', None):
|
if lots and getattr(lots[0], 'lot_unit_line', None):
|
||||||
return lots[0].lot_unit_line
|
return lots[0].lot_unit_line
|
||||||
@@ -1556,6 +1693,10 @@ class InvoicePaddingContext(ModelView):
|
|||||||
class InvoiceLine(metaclass=PoolMeta):
|
class InvoiceLine(metaclass=PoolMeta):
|
||||||
__name__ = 'account.invoice.line'
|
__name__ = 'account.invoice.line'
|
||||||
|
|
||||||
|
lot_weight_snapshots = fields.One2Many(
|
||||||
|
'account.invoice.line.lot.weight', 'invoice_line',
|
||||||
|
"Lot Weight Snapshots")
|
||||||
|
|
||||||
def _get_report_trade(self):
|
def _get_report_trade(self):
|
||||||
origin = getattr(self, 'origin', None)
|
origin = getattr(self, 'origin', None)
|
||||||
if not origin:
|
if not origin:
|
||||||
@@ -1648,6 +1789,15 @@ class InvoiceLine(metaclass=PoolMeta):
|
|||||||
def report_net(self):
|
def report_net(self):
|
||||||
if self.type == 'line':
|
if self.type == 'line':
|
||||||
invoice = getattr(self, 'invoice', None)
|
invoice = getattr(self, 'invoice', None)
|
||||||
|
snapshots = Invoice._get_report_invoice_line_weight_snapshots(self)
|
||||||
|
if snapshots:
|
||||||
|
sign = Invoice._get_report_line_sign(self)
|
||||||
|
net = sum(
|
||||||
|
Decimal(str(snapshot.net_quantity or 0))
|
||||||
|
for snapshot in snapshots)
|
||||||
|
unit = Invoice._get_report_invoice_line_unit(self)
|
||||||
|
net += Invoice._get_report_invoice_line_padding(self, unit)
|
||||||
|
return net * sign
|
||||||
if invoice and invoice._report_invoice_line_reuses_lot(self):
|
if invoice and invoice._report_invoice_line_reuses_lot(self):
|
||||||
return Invoice._get_report_invoice_line_quantity_from_line(self)
|
return Invoice._get_report_invoice_line_quantity_from_line(self)
|
||||||
lot = getattr(self, 'lot', None)
|
lot = getattr(self, 'lot', None)
|
||||||
|
|||||||
@@ -132,31 +132,37 @@ class Lot(metaclass=PoolMeta):
|
|||||||
"more than one virtual lot exists",
|
"more than one virtual lot exists",
|
||||||
[('virtual_lots', len(virtual_lots))]))
|
[('virtual_lots', len(virtual_lots))]))
|
||||||
|
|
||||||
vlot = virtual_lots[0]
|
# Temporarily suspended: repesages successifs are no longer tied
|
||||||
physical_quantity = sum(
|
# reliably to the original lot.qt forecast split. We keep the helper
|
||||||
cls._get_lot_current_quantity_for_consistency(lot, unit)
|
# calls in place, but do not enforce the two historical invariants:
|
||||||
for lot in physical_lots)
|
# 1) physical lots + virtual lot must equal quantity_theorical
|
||||||
virtual_quantity = cls._get_lot_current_quantity_for_consistency(
|
# 2) sum(non-zero lot.qt) must cover the positive virtual lot quantity
|
||||||
vlot, unit)
|
#
|
||||||
theorical_quantity = Decimal(str(theorical or 0))
|
# vlot = virtual_lots[0]
|
||||||
expected_diff = (
|
# physical_quantity = sum(
|
||||||
cls._round_consistency_quantity(physical_quantity)
|
# cls._get_lot_current_quantity_for_consistency(lot, unit)
|
||||||
+ cls._round_consistency_quantity(virtual_quantity)
|
# for lot in physical_lots)
|
||||||
- cls._round_consistency_quantity(theorical_quantity))
|
# virtual_quantity = cls._get_lot_current_quantity_for_consistency(
|
||||||
if expected_diff:
|
# vlot, unit)
|
||||||
raise UserError(
|
# theorical_quantity = Decimal(str(theorical or 0))
|
||||||
cls._format_consistency_error(
|
# expected_diff = (
|
||||||
line,
|
# cls._round_consistency_quantity(physical_quantity)
|
||||||
"physical lots + virtual lot must equal theoretical "
|
# + cls._round_consistency_quantity(virtual_quantity)
|
||||||
"quantity",
|
# - cls._round_consistency_quantity(theorical_quantity))
|
||||||
[
|
# if expected_diff:
|
||||||
('physical', physical_quantity),
|
# raise UserError(
|
||||||
('virtual', virtual_quantity),
|
# cls._format_consistency_error(
|
||||||
('theoretical', theorical_quantity),
|
# line,
|
||||||
('diff', expected_diff),
|
# "physical lots + virtual lot must equal theoretical "
|
||||||
]))
|
# "quantity",
|
||||||
|
# [
|
||||||
cls._assert_virtual_lot_open_quantity_consistency(vlot, line)
|
# ('physical', physical_quantity),
|
||||||
|
# ('virtual', virtual_quantity),
|
||||||
|
# ('theoretical', theorical_quantity),
|
||||||
|
# ('diff', expected_diff),
|
||||||
|
# ]))
|
||||||
|
#
|
||||||
|
# cls._assert_virtual_lot_open_quantity_consistency(vlot, line)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _assert_virtual_lot_open_quantity_consistency(cls, vlot, line=None):
|
def _assert_virtual_lot_open_quantity_consistency(cls, vlot, line=None):
|
||||||
|
|||||||
@@ -355,6 +355,29 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
self.assertEqual(fee.quantity, Decimal('40.00000'))
|
self.assertEqual(fee.quantity, Decimal('40.00000'))
|
||||||
save.assert_called_once_with([fee])
|
save.assert_called_once_with([fee])
|
||||||
|
|
||||||
|
def test_fee_ppack_auto_sync_keeps_auto_quantity(self):
|
||||||
|
'per packing auto fee keeps the on-change quantity on save'
|
||||||
|
Fee = Pool().get('fee.fee')
|
||||||
|
fee = Fee()
|
||||||
|
fee.id = 1
|
||||||
|
fee.mode = 'ppack'
|
||||||
|
fee.auto_calculation = True
|
||||||
|
fee.quantity = Decimal('3')
|
||||||
|
fee.unit = Mock()
|
||||||
|
lot = Mock(lot_type='physic', lot_qt=Decimal('990'))
|
||||||
|
fee_lots = Mock()
|
||||||
|
fee_lots.search.return_value = [Mock(lot=lot)]
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
'trytond.modules.purchase_trade.fee.Pool'
|
||||||
|
) as PoolMock, patch.object(Fee, 'save') as save:
|
||||||
|
PoolMock.return_value.get.return_value = fee_lots
|
||||||
|
|
||||||
|
fee.sync_quantity_from_lots()
|
||||||
|
|
||||||
|
self.assertEqual(fee.quantity, Decimal('3'))
|
||||||
|
save.assert_not_called()
|
||||||
|
|
||||||
def test_fee_pnl_regeneration_uses_shipment_lotqt_purchase_line(self):
|
def test_fee_pnl_regeneration_uses_shipment_lotqt_purchase_line(self):
|
||||||
'fee pnl regeneration follows shipment lot.qt back to purchase line'
|
'fee pnl regeneration follows shipment lot.qt back to purchase line'
|
||||||
Fee = Pool().get('fee.fee')
|
Fee = Pool().get('fee.fee')
|
||||||
@@ -4206,6 +4229,106 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
invoice.report_quantity_lines,
|
invoice.report_quantity_lines,
|
||||||
'950.00 LBS (950.00 LBS)')
|
'950.00 LBS (950.00 LBS)')
|
||||||
|
|
||||||
|
def test_invoice_report_weights_prefer_invoice_line_snapshot(self):
|
||||||
|
'invoice report weights use the invoicing snapshot when available'
|
||||||
|
Invoice = Pool().get('account.invoice')
|
||||||
|
|
||||||
|
unit = Mock(rec_name='LBS', symbol='LBS')
|
||||||
|
lot = Mock(lot_unit_line=unit)
|
||||||
|
lot.get_hist_quantity.return_value = (
|
||||||
|
Decimal('950'),
|
||||||
|
Decimal('980'),
|
||||||
|
)
|
||||||
|
snapshot = Mock(
|
||||||
|
net_quantity=Decimal('900'),
|
||||||
|
gross_quantity=Decimal('920'),
|
||||||
|
unit=unit,
|
||||||
|
)
|
||||||
|
line = Mock(
|
||||||
|
type='line',
|
||||||
|
quantity=Decimal('1000'),
|
||||||
|
lot=lot,
|
||||||
|
unit=Mock(rec_name='MT'),
|
||||||
|
lot_weight_snapshots=[snapshot],
|
||||||
|
)
|
||||||
|
invoice = Invoice()
|
||||||
|
invoice.lines = [line]
|
||||||
|
|
||||||
|
self.assertEqual(invoice.report_net, Decimal('900'))
|
||||||
|
self.assertEqual(invoice.report_gross, Decimal('920'))
|
||||||
|
self.assertEqual(invoice.report_weight_unit_upper, 'LBS')
|
||||||
|
self.assertEqual(
|
||||||
|
invoice.report_quantity_lines,
|
||||||
|
'900.00 LBS (900.00 LBS)')
|
||||||
|
|
||||||
|
def test_invoice_report_proforma_snapshot_adds_sale_padding(self):
|
||||||
|
'ICT provisional report displays snapshot weights plus sale padding'
|
||||||
|
Invoice = Pool().get('account.invoice')
|
||||||
|
|
||||||
|
unit = Mock(id=1, rec_name='LBS', symbol='LBS')
|
||||||
|
lot = Mock(lot_unit_line=unit, sale_invoice_padding=Decimal('10'))
|
||||||
|
snapshot = Mock(
|
||||||
|
net_quantity=Decimal('900'),
|
||||||
|
gross_quantity=Decimal('920'),
|
||||||
|
unit=unit,
|
||||||
|
)
|
||||||
|
line = Mock(
|
||||||
|
type='line',
|
||||||
|
description='Pro forma',
|
||||||
|
invoice_type='out',
|
||||||
|
quantity=Decimal('1010'),
|
||||||
|
lot=lot,
|
||||||
|
unit=unit,
|
||||||
|
lot_weight_snapshots=[snapshot],
|
||||||
|
)
|
||||||
|
invoice = Invoice()
|
||||||
|
invoice.lines = [line]
|
||||||
|
|
||||||
|
self.assertEqual(invoice.report_net, Decimal('910'))
|
||||||
|
self.assertEqual(invoice.report_gross, Decimal('930'))
|
||||||
|
self.assertEqual(
|
||||||
|
invoice.report_quantity_lines,
|
||||||
|
'910.00 LBS (910.00 LBS)')
|
||||||
|
|
||||||
|
def test_invoice_validation_creates_weight_snapshot_for_proforma_lines(self):
|
||||||
|
'invoice validation snapshots lot weights for pro forma invoice lines'
|
||||||
|
Invoice = Pool().get('account.invoice')
|
||||||
|
|
||||||
|
lot_ref = Mock(id=10)
|
||||||
|
lot = Mock(id=10)
|
||||||
|
proforma = Mock(
|
||||||
|
type='line',
|
||||||
|
description='Pro forma',
|
||||||
|
quantity=Decimal('1000'),
|
||||||
|
lot=lot_ref,
|
||||||
|
)
|
||||||
|
final = Mock(
|
||||||
|
type='line',
|
||||||
|
description='Final',
|
||||||
|
quantity=Decimal('1000'),
|
||||||
|
lot=lot_ref,
|
||||||
|
)
|
||||||
|
invoice = Invoice()
|
||||||
|
invoice.lines = [proforma, final]
|
||||||
|
|
||||||
|
snapshot_model = Mock()
|
||||||
|
lot_model = Mock(return_value=lot)
|
||||||
|
|
||||||
|
def get_model(name):
|
||||||
|
if name == 'account.invoice.line.lot.weight':
|
||||||
|
return snapshot_model
|
||||||
|
if name == 'lot.lot':
|
||||||
|
return lot_model
|
||||||
|
raise AssertionError(name)
|
||||||
|
|
||||||
|
with patch('trytond.modules.purchase_trade.invoice.Pool') as PoolMock:
|
||||||
|
PoolMock.return_value.get.side_effect = get_model
|
||||||
|
|
||||||
|
invoice._create_lot_weight_snapshots()
|
||||||
|
|
||||||
|
snapshot_model.create_for_invoice_line.assert_called_once_with(
|
||||||
|
proforma, lot)
|
||||||
|
|
||||||
def test_invoice_report_lbs_converts_kilogram_to_lbs(self):
|
def test_invoice_report_lbs_converts_kilogram_to_lbs(self):
|
||||||
'invoice lbs helper converts kilogram quantities with the proper uom ratio'
|
'invoice lbs helper converts kilogram quantities with the proper uom ratio'
|
||||||
Invoice = Pool().get('account.invoice')
|
Invoice = Pool().get('account.invoice')
|
||||||
|
|||||||
Reference in New Issue
Block a user