net gross

This commit is contained in:
2026-04-09 21:46:28 +02:00
parent 4bbd7a5e76
commit 8a90216357
2 changed files with 84 additions and 1 deletions

View File

@@ -146,6 +146,22 @@ class Invoice(metaclass=PoolMeta):
return True
return False
def _get_report_reused_lot_lines(self):
groups = {}
for line in self._get_report_invoice_lines():
lots = self._get_report_preferred_lots(line)
if not lots:
continue
for lot in lots:
lot_id = getattr(lot, 'id', None)
key = lot_id if lot_id is not None else id(lot)
groups.setdefault(key, {'lot': lot, 'lines': []})
groups[key]['lines'].append(line)
return {
key: value for key, value in groups.items()
if len(value['lines']) > 1
}
@staticmethod
def _convert_report_quantity(quantity, from_unit, to_unit):
value = Decimal(str(quantity or 0))
@@ -170,6 +186,50 @@ class Invoice(metaclass=PoolMeta):
cls._get_report_invoice_line_unit(line),
)
@classmethod
def _find_report_hist_entry_for_quantity(cls, lot, quantity, exclude_state_id=None):
target = Decimal(str(quantity or 0)).copy_abs()
for entry in list(getattr(lot, 'lot_hist', []) or []):
quantity_type = getattr(entry, 'quantity_type', None)
if getattr(quantity_type, 'id', None) == exclude_state_id:
continue
entry_quantity = Decimal(str(getattr(entry, 'quantity', 0) or 0))
if entry_quantity == target:
return entry
return None
def _get_report_reused_lot_gross_total(self):
reused_lots = self._get_report_reused_lot_lines()
if not reused_lots:
return None
total = Decimal(0)
for data in reused_lots.values():
lot = data['lot']
_, current_gross = self._get_report_lot_hist_weights(lot)
if current_gross is None:
continue
current_state = getattr(getattr(lot, 'lot_state', None), 'id', None)
negative_lines = [
line for line in data['lines']
if Decimal(str(getattr(line, 'quantity', 0) or 0)) < 0
]
previous_gross = Decimal(0)
matched = False
for line in negative_lines:
previous_entry = self._find_report_hist_entry_for_quantity(
lot,
self._get_report_invoice_line_quantity_from_line(line),
exclude_state_id=current_state,
)
if not previous_entry:
continue
previous_gross += Decimal(str(
getattr(previous_entry, 'gross_quantity', 0) or 0))
matched = True
if matched:
total += current_gross - previous_gross
return total
@staticmethod
def _get_report_invoice_line_unit(line):
lots = Invoice._get_report_preferred_lots(line)
@@ -799,6 +859,13 @@ class Invoice(metaclass=PoolMeta):
@property
def report_gross(self):
if self.lines:
reused_gross = self._get_report_reused_lot_gross_total()
if reused_gross is not None:
non_reused_total = sum(
self._get_report_invoice_line_weights(line)[1]
for line in self._get_report_invoice_lines()
if not self._report_invoice_line_reuses_lot(line))
return non_reused_total + reused_gross
return sum(
self._get_report_invoice_line_weights(line)[1]
for line in self._get_report_invoice_lines())

View File

@@ -1189,11 +1189,26 @@ class PurchaseTradeTestCase(ModuleTestCase):
mt = Mock(id=1, rec_name='MT')
kg = Mock(id=2, rec_name='KILOGRAM')
current_type = Mock(id=100)
previous_type = Mock(id=200)
shared_lot = Mock(id=10, lot_type='physic', lot_unit_line=kg)
shared_lot.lot_state = current_type
shared_lot.get_hist_quantity.return_value = (
Decimal('999995'),
Decimal('999995'),
Decimal('999992'),
)
shared_lot.lot_hist = [
Mock(
quantity_type=previous_type,
quantity=Decimal('999995'),
gross_quantity=Decimal('999998'),
),
Mock(
quantity_type=current_type,
quantity=Decimal('999990'),
gross_quantity=Decimal('999992'),
),
]
negative = Mock(
type='line',
@@ -1233,6 +1248,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
PoolMock.return_value.get.return_value = uom_model
self.assertEqual(invoice.report_net, Decimal('-5.000'))
self.assertEqual(invoice.report_gross, Decimal('-6'))
self.assertEqual(
invoice.report_quantity_lines.splitlines(),
[