Price composition + Pnl open matched
This commit is contained in:
@@ -2554,6 +2554,90 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
self.assertEqual(values[0]['type'], 'sale fee')
|
||||
self.assertEqual(values[0]['lot'], sale_lot.id)
|
||||
|
||||
def test_purchase_open_fee_pnl_splits_by_matched_sale_lotqt(self):
|
||||
'purchase open fee pnl keeps one segment per matched sale lot.qt'
|
||||
Valuation = Pool().get('valuation.valuation')
|
||||
currency = Mock(id=1)
|
||||
unit = Mock(id=2)
|
||||
product = Mock(id=3, name='Broker commission')
|
||||
supplier = Mock(id=4)
|
||||
purchase = Mock(id=5, currency=currency, company=Mock(currency=currency))
|
||||
line = Mock(id=6, purchase=purchase, unit=unit, finished=False)
|
||||
purchase_lot = Mock(id=7, sale_line=None, lot_type='virtual')
|
||||
purchase_lot.get_current_quantity_converted.return_value = Decimal('60')
|
||||
line.lots = [purchase_lot]
|
||||
line.get_matched_lines.return_value = []
|
||||
sales = [Mock(id=20 + index) for index in range(3)]
|
||||
sale_lines = [
|
||||
Mock(id=30 + index, sale=sales[index], finished=False)
|
||||
for index in range(3)]
|
||||
sale_lots = [
|
||||
Mock(id=40 + index, sale_line=sale_lines[index])
|
||||
for index in range(3)]
|
||||
lot_qts = [
|
||||
Mock(
|
||||
id=50,
|
||||
lot_s=sale_lots[0],
|
||||
lot_quantity=Decimal('10'),
|
||||
lot_unit=unit,
|
||||
lot_shipment_in=None),
|
||||
Mock(
|
||||
id=51,
|
||||
lot_s=sale_lots[1],
|
||||
lot_quantity=Decimal('20'),
|
||||
lot_unit=unit,
|
||||
lot_shipment_in=None),
|
||||
Mock(
|
||||
id=52,
|
||||
lot_s=sale_lots[2],
|
||||
lot_quantity=Decimal('30'),
|
||||
lot_unit=unit,
|
||||
lot_shipment_in=None),
|
||||
]
|
||||
fee = Mock(
|
||||
id=60,
|
||||
line=line,
|
||||
sale_line=None,
|
||||
shipment_in=None,
|
||||
shipment_out=None,
|
||||
shipment_internal=None,
|
||||
product=product,
|
||||
supplier=supplier,
|
||||
type='budgeted',
|
||||
p_r='pay',
|
||||
mode='perqt',
|
||||
price=Decimal('2'),
|
||||
currency=currency,
|
||||
unit=unit,
|
||||
)
|
||||
fee.get_price_per_qt.return_value = Decimal('2')
|
||||
fee_lots = Mock()
|
||||
fee_lots.search.return_value = [Mock(fee=fee)]
|
||||
lot_qt_model = Mock()
|
||||
lot_qt_model.search.return_value = lot_qts
|
||||
|
||||
with patch('trytond.modules.purchase_trade.valuation.Pool') as PoolMock:
|
||||
PoolMock.return_value.get.side_effect = lambda name: {
|
||||
'ir.date': Mock(today=Mock(return_value=datetime.date(2026, 6, 30))),
|
||||
'currency.currency': Mock(),
|
||||
'fee.lots': fee_lots,
|
||||
'lot.qt': lot_qt_model,
|
||||
}[name]
|
||||
|
||||
values = Valuation.create_pnl_fee_from_line(line)
|
||||
|
||||
self.assertEqual(len(values), 3)
|
||||
self.assertEqual(
|
||||
[value['sale_line'] for value in values],
|
||||
[sale_line.id for sale_line in sale_lines])
|
||||
self.assertEqual(
|
||||
[value['quantity'] for value in values],
|
||||
[Decimal('10.00000'), Decimal('20.00000'), Decimal('30.00000')])
|
||||
self.assertEqual(
|
||||
[value['amount'] for value in values],
|
||||
[Decimal('-20.00'), Decimal('-40.00'), Decimal('-60.00')])
|
||||
self.assertEqual(len(Valuation._dedupe_values(values)), 3)
|
||||
|
||||
def test_sale_open_fee_pnl_splits_by_shipment_lotqt(self):
|
||||
'sale open fee pnl is split between shipped and unshipped lot.qt'
|
||||
Valuation = Pool().get('valuation.valuation')
|
||||
@@ -6345,8 +6429,10 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
line.linked_currency = None
|
||||
line.linked_unit = None
|
||||
line.unit = Mock(rec_name='MT')
|
||||
line.quantity = Decimal('25')
|
||||
line.unit_price = Decimal('2525')
|
||||
line.amount = Decimal('62493.75')
|
||||
line.amount = Decimal('63750')
|
||||
line.lots = []
|
||||
line.price_composition = [
|
||||
Mock(component='FOB', price=Decimal('2500')),
|
||||
Mock(component='FREIGHT', price=None),
|
||||
@@ -6367,13 +6453,55 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
[
|
||||
{
|
||||
'label': 'FOB value in EUR',
|
||||
'amount': Decimal('2500'),
|
||||
'amount_text': '2,500.00',
|
||||
'amount': Decimal('62500'),
|
||||
'amount_text': '62,500.00',
|
||||
},
|
||||
{
|
||||
'label': 'FREIGHT value in EUR',
|
||||
'amount': Decimal('59993.75'),
|
||||
'amount_text': '59,993.75',
|
||||
'amount': Decimal('1250'),
|
||||
'amount_text': '1,250.00',
|
||||
},
|
||||
])
|
||||
|
||||
def test_invoice_report_melya_price_composition_uses_invoice_quantity(self):
|
||||
'invoice_melya price composition applies the invoiced quantity'
|
||||
Invoice = Pool().get('account.invoice')
|
||||
unit = Mock(id=1, rec_name='MT')
|
||||
sale = Mock(currency=Mock(rec_name='EUR'), lines=[])
|
||||
sale_line = Mock(
|
||||
sale=sale,
|
||||
unit=unit,
|
||||
amount=Decimal('63750'),
|
||||
price_composition=[
|
||||
Mock(component='FOB', price=Decimal('2500')),
|
||||
Mock(component='FREIGHT', price=None),
|
||||
])
|
||||
invoice_line = Mock(
|
||||
type='line',
|
||||
origin=sale_line,
|
||||
unit=unit,
|
||||
quantity=Decimal('20'),
|
||||
amount=Decimal('51000'),
|
||||
currency=Mock(rec_name='EUR'),
|
||||
invoice=None,
|
||||
lot=None,
|
||||
lot_weight_snapshots=[])
|
||||
invoice = Invoice()
|
||||
invoice.lines = [invoice_line]
|
||||
invoice.sales = [sale]
|
||||
|
||||
self.assertEqual(
|
||||
invoice.report_melya_rate_rows,
|
||||
[
|
||||
{
|
||||
'label': 'FOB value in EUR',
|
||||
'amount': Decimal('50000'),
|
||||
'amount_text': '50,000.00',
|
||||
},
|
||||
{
|
||||
'label': 'FREIGHT value in EUR',
|
||||
'amount': Decimal('1000'),
|
||||
'amount_text': '1,000.00',
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user