Padding logic in fee

This commit is contained in:
2026-06-23 09:21:10 +02:00
parent d08510f084
commit 423d9476fc
8 changed files with 3517 additions and 16588 deletions

View File

@@ -3047,6 +3047,64 @@ class PurchaseTradeTestCase(ModuleTestCase):
fee, '_get_effective_fee_lots', return_value=[lot]):
self.assertEqual(fee.get_amount(), Decimal('20.00'))
def test_per_quantity_fee_with_padding_uses_lots_plus_padding(self):
'per quantity fee can bill linked lots plus sale invoice padding'
Fee = Pool().get('fee.fee')
fee = Fee()
unit = SimpleNamespace(id=1)
sale_line = SimpleNamespace(unit=unit)
lot = SimpleNamespace(
id=1,
lot_type='physic',
sale_line=sale_line,
sale_invoice_padding=Decimal('2'),
lot_hist=[],
get_current_quantity_converted=(
lambda state=0, unit=None: Decimal('5')))
fee.mode = 'perqt'
fee.price = Decimal('10')
fee.add_padding = True
fee.unit = unit
fee.quantity = Decimal('5')
fee.line = None
fee.sale_line = sale_line
fee.shipment_in = None
with patch.object(
fee, '_get_effective_fee_lots', return_value=[lot]):
self.assertEqual(fee.get_billing_quantity(), Decimal('7'))
self.assertEqual(fee.get_amount(), Decimal('70.00'))
def test_percent_price_fee_with_padding_uses_lots_padding_unit_price(self):
'% price fee with padding uses fee lots plus padding as amount base'
Fee = Pool().get('fee.fee')
fee = Fee()
unit = SimpleNamespace(id=1)
sale_line = SimpleNamespace(
unit=unit,
unit_price=Decimal('100'),
amount=Decimal('9999'))
lot = SimpleNamespace(
id=1,
lot_type='physic',
sale_line=sale_line,
sale_invoice_padding=Decimal('2'),
lot_hist=[],
get_current_quantity_converted=(
lambda state=0, unit=None: Decimal('5')))
fee.mode = 'pprice'
fee.price = Decimal('2')
fee.add_padding = True
fee.unit = unit
fee.quantity = Decimal('5')
fee.line = None
fee.sale_line = sale_line
fee.shipment_in = None
with patch.object(
fee, '_get_effective_fee_lots', return_value=[lot]):
self.assertEqual(fee.get_amount(), Decimal('14.00'))
def test_percent_price_fee_warns_when_line_lots_are_partial(self):
'% price fee warns when it does not cover all line lots'
Fee = Pool().get('fee.fee')
@@ -3111,6 +3169,75 @@ class PurchaseTradeTestCase(ModuleTestCase):
purchase_line_model.save.assert_called_once_with([purchase_line])
purchase_model.save.assert_called_once_with([fee.purchase])
def test_per_quantity_fee_padding_adjusts_generated_purchase_quantity(self):
'per quantity fee with padding updates the generated purchase quantity'
Fee = Pool().get('fee.fee')
fee = Fee()
fee.type = 'ordered'
fee.mode = 'perqt'
fee.add_padding = True
fee.price = Decimal('10')
fee.product = Mock()
fee.supplier = Mock()
fee.currency = Mock()
purchase_line = Mock(
unit_price=Decimal('10'),
quantity=Decimal('5'),
product=fee.product)
fee.purchase = Mock(
lines=[purchase_line],
party=fee.supplier,
currency=fee.currency)
purchase_model = Mock()
purchase_line_model = Mock()
with patch(
'trytond.modules.purchase_trade.fee.Pool'
) as PoolMock, patch.object(
fee, 'get_billing_quantity',
return_value=Decimal('7')):
PoolMock.return_value.get.side_effect = lambda name: {
'purchase.purchase': purchase_model,
'purchase.line': purchase_line_model,
}[name]
fee.adjust_purchase_values()
self.assertEqual(purchase_line.unit_price, Decimal('10'))
self.assertEqual(purchase_line.quantity, Decimal('7'))
purchase_line_model.save.assert_called_once_with([purchase_line])
purchase_model.save.assert_called_once_with([fee.purchase])
def test_purchase_trade_service_fee_invoice_uses_padding_quantity(self):
'service fee invoice line uses billing quantity when padding is enabled'
Line = purchase_module.Line
line = Line()
line.purchase = Mock(id=20)
lot = Mock(id=30)
invoice_line = Mock(quantity=Decimal('5'), unit_price=Decimal('10'))
fee = Mock(
state='not invoiced',
mode='perqt',
add_padding=True,
warn_percent_price_partial_lots=Mock(),
get_billing_quantity=Mock(return_value=Decimal('7')))
fee_model = Mock()
fee_model.search.return_value = [fee]
with patch(
'trytond.modules.purchase_trade.purchase.Pool'
) as PoolMock:
PoolMock.return_value.get.side_effect = lambda name: {
'fee.fee': fee_model,
}[name]
result = line._get_service_fee_invoice_lines(invoice_line, lot)
self.assertEqual(result, [invoice_line])
self.assertEqual(invoice_line.fee, fee)
self.assertEqual(invoice_line.quantity, Decimal('7'))
fee.get_billing_quantity.assert_called_once_with()
def test_fee_get_non_cog_returns_zero_without_move_lines(self):
'fee non-cog amount is zero before any accounting move line exists'
fee = fee_module.Fee()