padding acc
This commit is contained in:
@@ -15,6 +15,180 @@ from trytond.modules.purchase.purchase import (
|
||||
class Invoice(metaclass=PoolMeta):
|
||||
__name__ = 'account.invoice'
|
||||
|
||||
def do_lot_invoicing(self):
|
||||
super().do_lot_invoicing()
|
||||
self._create_sale_padding_moves()
|
||||
|
||||
@classmethod
|
||||
def _post(cls, invoices):
|
||||
pool = Pool()
|
||||
Move = pool.get('account.move')
|
||||
|
||||
super()._post(invoices)
|
||||
|
||||
padding_moves = []
|
||||
for invoice in invoices:
|
||||
padding_moves.extend(invoice._create_sale_padding_moves())
|
||||
padding_moves.extend([
|
||||
move for move in (invoice.additional_moves or [])
|
||||
if move.description in {
|
||||
invoice._get_sale_padding_move_description(False),
|
||||
invoice._get_sale_padding_move_description(True),
|
||||
}
|
||||
and move.state != 'posted'
|
||||
])
|
||||
if padding_moves:
|
||||
cls.save(invoices)
|
||||
Move.post([m for m in padding_moves if m.state != 'posted'])
|
||||
|
||||
def _get_sale_padding_accounts(self):
|
||||
Configuration = Pool().get('account.configuration')
|
||||
config = Configuration(1)
|
||||
sale_account = config.get_multivalue(
|
||||
'default_sale_padding_account', company=self.company.id)
|
||||
accrual_account = config.get_multivalue(
|
||||
'default_accrual_padding_account', company=self.company.id)
|
||||
if not sale_account or not accrual_account:
|
||||
raise UserError(
|
||||
'Default Sale Padding and Default Accrual Padding '
|
||||
'accounts must be configured.')
|
||||
return sale_account, accrual_account
|
||||
|
||||
def _has_sale_padding_move(self, reversal=False):
|
||||
description = self._get_sale_padding_move_description(reversal)
|
||||
return any(
|
||||
move.description == description
|
||||
for move in (self.additional_moves or []))
|
||||
|
||||
@staticmethod
|
||||
def _get_sale_padding_move_description(reversal=False):
|
||||
if reversal:
|
||||
return 'Sale padding reversal'
|
||||
return 'Sale padding accrual'
|
||||
|
||||
def _get_padding_company_amount(self, invoice_line, padding):
|
||||
Currency = Pool().get('currency.currency')
|
||||
invoice = invoice_line.invoice
|
||||
amount = Decimal(str(padding or 0)) * Decimal(
|
||||
str(invoice_line.unit_price or 0))
|
||||
amount = invoice.currency.round(amount)
|
||||
if invoice.currency == invoice.company.currency:
|
||||
return amount, amount
|
||||
if invoice.rate:
|
||||
company_amount = invoice.company.currency.round(
|
||||
amount / invoice.rate)
|
||||
else:
|
||||
with Transaction().set_context(date=invoice.currency_date):
|
||||
company_amount = Currency.compute(
|
||||
invoice.currency, amount, invoice.company.currency)
|
||||
return amount, company_amount
|
||||
|
||||
def _get_sale_padding_entries(self):
|
||||
if self.type != 'out':
|
||||
return []
|
||||
|
||||
entries = []
|
||||
for line in self.lines or []:
|
||||
if getattr(line, 'type', None) != 'line':
|
||||
continue
|
||||
lot = getattr(line, 'lot', None)
|
||||
if not lot:
|
||||
continue
|
||||
padding = Decimal(str(
|
||||
getattr(lot, 'sale_invoice_padding', 0) or 0))
|
||||
if padding <= 0:
|
||||
continue
|
||||
|
||||
if self.reference == 'Provisional' and line.description == 'Pro forma':
|
||||
entries.append((lot, line, padding, False))
|
||||
elif self.reference == 'Final' and line.description == 'Final':
|
||||
provisional_line = getattr(lot, 'sale_invoice_line_prov', None)
|
||||
if provisional_line:
|
||||
entries.append((lot, provisional_line, padding, True))
|
||||
return entries
|
||||
|
||||
def _get_sale_padding_move_lines(self, entries):
|
||||
MoveLine = Pool().get('account.move.line')
|
||||
sale_account, accrual_account = self._get_sale_padding_accounts()
|
||||
|
||||
move_lines = []
|
||||
for lot, invoice_line, padding, reversal in entries:
|
||||
padding_amount, company_amount = self._get_padding_company_amount(
|
||||
invoice_line, padding)
|
||||
if not company_amount:
|
||||
continue
|
||||
|
||||
sale_line = MoveLine()
|
||||
accrual_line = MoveLine()
|
||||
for move_line in (sale_line, accrual_line):
|
||||
move_line.lot = lot
|
||||
move_line.origin = invoice_line
|
||||
if move_line.account and move_line.account.party_required:
|
||||
move_line.party = self.party
|
||||
|
||||
if not reversal:
|
||||
sale_line.account = sale_account
|
||||
sale_line.debit = company_amount
|
||||
sale_line.credit = Decimal(0)
|
||||
accrual_line.account = accrual_account
|
||||
accrual_line.debit = Decimal(0)
|
||||
accrual_line.credit = company_amount
|
||||
else:
|
||||
accrual_line.account = accrual_account
|
||||
accrual_line.debit = company_amount
|
||||
accrual_line.credit = Decimal(0)
|
||||
sale_line.account = sale_account
|
||||
sale_line.debit = Decimal(0)
|
||||
sale_line.credit = company_amount
|
||||
|
||||
if self.currency != self.company.currency:
|
||||
sale_line.second_currency = self.currency
|
||||
accrual_line.second_currency = self.currency
|
||||
sale_line.amount_second_currency = padding_amount.copy_sign(
|
||||
sale_line.debit - sale_line.credit)
|
||||
accrual_line.amount_second_currency = padding_amount.copy_sign(
|
||||
accrual_line.debit - accrual_line.credit)
|
||||
|
||||
if sale_line.account.party_required:
|
||||
sale_line.party = self.party
|
||||
if accrual_line.account.party_required:
|
||||
accrual_line.party = self.party
|
||||
move_lines.extend([sale_line, accrual_line])
|
||||
return move_lines
|
||||
|
||||
def _create_sale_padding_moves(self):
|
||||
pool = Pool()
|
||||
Move = pool.get('account.move')
|
||||
Period = pool.get('account.period')
|
||||
Date = pool.get('ir.date')
|
||||
|
||||
entries = self._get_sale_padding_entries()
|
||||
if not entries:
|
||||
return []
|
||||
reversal = entries[0][3]
|
||||
if self._has_sale_padding_move(reversal):
|
||||
return []
|
||||
|
||||
move_lines = self._get_sale_padding_move_lines(entries)
|
||||
if not move_lines:
|
||||
return []
|
||||
|
||||
with Transaction().set_context(company=self.company.id):
|
||||
today = Date.today()
|
||||
accounting_date = self.accounting_date or self.invoice_date or today
|
||||
period = Period.find(self.company, date=accounting_date)
|
||||
move = Move()
|
||||
move.journal = self.journal
|
||||
move.period = period
|
||||
move.date = accounting_date
|
||||
move.origin = self
|
||||
move.company = self.company
|
||||
move.description = self._get_sale_padding_move_description(reversal)
|
||||
move.lines = move_lines
|
||||
Move.save([move])
|
||||
self.additional_moves = tuple(self.additional_moves or ()) + (move,)
|
||||
return [move]
|
||||
|
||||
@staticmethod
|
||||
def _format_report_number(value, digits='0.0000', keep_trailing_decimal=False,
|
||||
strip_trailing_zeros=True):
|
||||
|
||||
Reference in New Issue
Block a user