Lot invoicing + fee padding

This commit is contained in:
2026-06-23 13:12:37 +02:00
parent ef8d914820
commit fbf3842e6c
3 changed files with 200 additions and 10 deletions

View File

@@ -4916,11 +4916,9 @@ class LotInvoice(Wizard):
def default_message(self, fields):
fee_count = getattr(self, '_invoiced_fee_count', 0)
message = 'The invoice has been successfully created.'
message = 'Invoice created.'
if fee_count:
message += (
' %s selected fee invoice(s) have also been processed.'
% fee_count)
message += ' Fee invoices: %s.' % fee_count
return {
'message': message,
}
@@ -5031,10 +5029,83 @@ class LotInvoiceStart(ModelView):
amount += l.lot_amount
amount += padding_share * Decimal(str(l.lot_price or 0))
return amount
@classmethod
def default_action(cls):
return 'prov'
def _get_sale_padding_by_lot(self):
lots = [
line.lot for line in (self.lot_s or [])
if getattr(line, 'lot', None)]
return self._split_sale_padding(self.sale_padding, lots)
@staticmethod
def _record_key(record):
return getattr(record, 'id', None) or id(record)
def _fee_wizard_padding_quantity(self, fee, padding_by_lot):
if not getattr(fee, 'add_padding', False):
return Decimal(0)
quantity = Decimal(0)
for lot in fee._get_effective_fee_lots():
padding = padding_by_lot.get(self._record_key(lot), Decimal(0))
if not padding:
continue
source_line = (
getattr(fee, 'sale_line', None)
or getattr(lot, 'sale_line', None)
or getattr(fee, 'line', None)
or getattr(lot, 'line', None))
source_unit = getattr(source_line, 'unit', None)
if not source_unit:
source_unit = getattr(lot, 'lot_unit_line', None)
quantity += fee._convert_padding_quantity(padding, source_unit)
return quantity
def _fee_wizard_billing_quantity(self, fee, padding_by_lot):
quantity = fee._get_effective_fee_lots_quantity()
if quantity is None:
quantity = getattr(fee, 'quantity', None)
if quantity is None:
quantity = fee.get_quantity()
return (
Decimal(quantity or 0)
+ self._fee_wizard_padding_quantity(fee, padding_by_lot))
@staticmethod
def _fee_wizard_unit_price(fee):
line = getattr(fee, 'sale_line', None) or getattr(fee, 'line', None)
if line:
return Decimal(str(getattr(line, 'unit_price', 0) or 0))
for lot in fee._get_effective_fee_lots():
if getattr(lot, 'sale_line', None):
return Decimal(str(
getattr(lot.sale_line, 'unit_price', 0) or 0))
if getattr(lot, 'line', None):
return Decimal(str(getattr(lot.line, 'unit_price', 0) or 0))
return Decimal(0)
@fields.depends('type', 'sale_padding', 'lot_s', 'fee_sale')
def on_change_sale_padding(self):
if self.type != 'sale' or not self.fee_sale:
return
padding_by_lot = self._get_sale_padding_by_lot()
for fee_line in self.fee_sale:
fee = getattr(fee_line, 'fee', None)
if not fee or not getattr(fee, 'add_padding', False):
continue
if fee.mode not in {'perqt', 'pprice'}:
continue
quantity = self._fee_wizard_billing_quantity(fee, padding_by_lot)
fee_line.fee_quantity = quantity
if fee.mode == 'perqt':
fee_line.fee_amount = round(
quantity * Decimal(str(fee.price or 0)), 2)
elif fee.mode == 'pprice':
fee_line.fee_amount = round(
Decimal(str(fee.price or 0)) / Decimal(100)
* quantity * self._fee_wizard_unit_price(fee), 2)
@classmethod
def default_action(cls):
return 'prov'
@classmethod
def default_type(cls):