02.04.26
This commit is contained in:
@@ -73,6 +73,52 @@ class Invoice(metaclass=PoolMeta):
|
||||
return lot
|
||||
return line.lots[0]
|
||||
|
||||
def _get_report_invoice_lots(self):
|
||||
invoice_lines = self._get_report_invoice_lines()
|
||||
if not invoice_lines:
|
||||
return []
|
||||
|
||||
def _same_invoice_line(left, right):
|
||||
if not left or not right:
|
||||
return False
|
||||
left_id = getattr(left, 'id', None)
|
||||
right_id = getattr(right, 'id', None)
|
||||
if left_id is not None and right_id is not None:
|
||||
return left_id == right_id
|
||||
return left is right
|
||||
|
||||
trade = self._get_report_trade()
|
||||
trade_lines = getattr(trade, 'lines', []) if trade else []
|
||||
lots = []
|
||||
for line in trade_lines or []:
|
||||
for lot in getattr(line, 'lots', []) or []:
|
||||
if getattr(lot, 'lot_type', None) != 'physic':
|
||||
continue
|
||||
refs = [
|
||||
getattr(lot, 'sale_invoice_line', None),
|
||||
getattr(lot, 'sale_invoice_line_prov', None),
|
||||
getattr(lot, 'invoice_line', None),
|
||||
getattr(lot, 'invoice_line_prov', None),
|
||||
]
|
||||
if any(
|
||||
_same_invoice_line(ref, invoice_line)
|
||||
for ref in refs for invoice_line in invoice_lines):
|
||||
lots.append(lot)
|
||||
return lots
|
||||
|
||||
@staticmethod
|
||||
def _format_report_package_label(unit):
|
||||
label = (
|
||||
getattr(unit, 'symbol', None)
|
||||
or getattr(unit, 'rec_name', None)
|
||||
or getattr(unit, 'name', None)
|
||||
or 'BALE'
|
||||
)
|
||||
label = label.upper()
|
||||
if not label.endswith('S'):
|
||||
label += 'S'
|
||||
return label
|
||||
|
||||
def _get_report_freight_fee(self):
|
||||
pool = Pool()
|
||||
Fee = pool.get('fee.fee')
|
||||
@@ -329,26 +375,37 @@ class Invoice(metaclass=PoolMeta):
|
||||
|
||||
@property
|
||||
def report_nb_bale(self):
|
||||
net = self.report_net
|
||||
line = self._get_report_trade_line() or self._get_report_invoice_line()
|
||||
unit = getattr(line, 'unit', None) if line else None
|
||||
if net != '' and unit:
|
||||
lots = self._get_report_invoice_lots()
|
||||
if lots:
|
||||
Uom = Pool().get('product.uom')
|
||||
bale_uom = Uom.get_by_name('bale')
|
||||
if not bale_uom:
|
||||
bale_uoms = Uom.search([
|
||||
('name', 'ilike', 'bale'),
|
||||
], limit=1)
|
||||
bale_uom = bale_uoms[0] if bale_uoms else None
|
||||
if bale_uom and getattr(unit, 'category', None) == getattr(
|
||||
bale_uom, 'category', None):
|
||||
bale_qty = Decimal(str(
|
||||
Uom.compute_qty(unit, float(net), bale_uom, round=False)
|
||||
or 0))
|
||||
bale_qty = bale_qty.quantize(
|
||||
line = self._get_report_invoice_line() or self._get_report_trade_line()
|
||||
invoice_unit = getattr(line, 'unit', None) if line else None
|
||||
net = Decimal(str(self.report_net or 0))
|
||||
total_packages = Decimal(0)
|
||||
total_weight = Decimal(0)
|
||||
package_unit = None
|
||||
for lot in lots:
|
||||
if getattr(lot, 'lot_qt', None):
|
||||
total_packages += Decimal(str(lot.lot_qt or 0))
|
||||
if not package_unit and getattr(lot, 'lot_unit', None):
|
||||
package_unit = lot.lot_unit
|
||||
lot_quantity = Decimal(str(getattr(lot, 'lot_quantity', 0) or 0))
|
||||
lot_unit_line = getattr(lot, 'lot_unit_line', None)
|
||||
if lot_quantity and lot_unit_line and invoice_unit:
|
||||
total_weight += Decimal(str(
|
||||
Uom.compute_qty(
|
||||
lot_unit_line, float(lot_quantity), invoice_unit,
|
||||
round=False) or 0))
|
||||
if total_packages:
|
||||
package_qty = total_packages
|
||||
if total_weight and net:
|
||||
package_qty = (
|
||||
net / (total_weight / total_packages))
|
||||
package_qty = package_qty.quantize(
|
||||
Decimal('1'), rounding=ROUND_HALF_UP)
|
||||
if bale_qty:
|
||||
return 'NB BALES: ' + str(int(bale_qty))
|
||||
if package_qty:
|
||||
label = self._format_report_package_label(package_unit)
|
||||
return f"NB {label}: {int(package_qty)}"
|
||||
sale = self._get_report_sale()
|
||||
if sale and sale.report_nb_bale:
|
||||
return sale.report_nb_bale
|
||||
|
||||
@@ -333,25 +333,37 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
|
||||
self.assertEqual(invoice.report_net, Decimal('800'))
|
||||
|
||||
def test_invoice_report_nb_bale_uses_uom_conversion_with_sign(self):
|
||||
'invoice final note converts signed net quantity to bale using UoM rules'
|
||||
def test_invoice_report_nb_bale_uses_linked_lot_packaging(self):
|
||||
'invoice reports packaging from linked physical lots with signed prorata'
|
||||
Invoice = Pool().get('account.invoice')
|
||||
|
||||
line = Mock(type='line', quantity=Decimal('-15'))
|
||||
line.unit = Mock(rec_name='MT')
|
||||
line.unit.category = Mock()
|
||||
bale_uom = Mock(category=line.unit.category)
|
||||
sale_line = Mock()
|
||||
lot = Mock(
|
||||
lot_type='physic',
|
||||
lot_qt=Decimal('700'),
|
||||
lot_unit=Mock(symbol='bale'),
|
||||
lot_quantity=Decimal('2000'),
|
||||
lot_unit_line=line.unit,
|
||||
sale_invoice_line=line,
|
||||
sale_invoice_line_prov=None,
|
||||
invoice_line=None,
|
||||
invoice_line_prov=None,
|
||||
)
|
||||
sale_line.lots = [lot]
|
||||
sale = Mock(lines=[sale_line])
|
||||
uom_model = Mock()
|
||||
uom_model.get_by_name.return_value = bale_uom
|
||||
uom_model.compute_qty.return_value = Decimal('-53.6')
|
||||
uom_model.compute_qty.return_value = Decimal('2000')
|
||||
invoice = Invoice()
|
||||
invoice.sales = [sale]
|
||||
invoice.lines = [line]
|
||||
|
||||
with patch(
|
||||
'trytond.modules.purchase_trade.invoice.Pool'
|
||||
) as PoolMock:
|
||||
PoolMock.return_value.get.return_value = uom_model
|
||||
self.assertEqual(invoice.report_nb_bale, 'NB BALES: -54')
|
||||
self.assertEqual(invoice.report_nb_bale, 'NB BALES: -5')
|
||||
|
||||
def test_invoice_report_positive_rate_lines_keep_positive_components(self):
|
||||
'invoice final note pricing section keeps only positive component lines'
|
||||
|
||||
Reference in New Issue
Block a user