Fill payment means when parsing UBL invoice
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Fill payment means
|
||||
* Render payment means
|
||||
* Set BillingReference to Invoice and Credit Note
|
||||
* Render allowance and charge
|
||||
|
||||
@@ -17,6 +17,7 @@ import genshi.template
|
||||
# XXX fix: https://genshi.edgewall.org/ticket/582
|
||||
from genshi.template.astutil import ASTCodeGenerator, ASTTransformer
|
||||
from lxml import etree
|
||||
from stdnum import bic, iban
|
||||
|
||||
from trytond.i18n import gettext, ngettext
|
||||
from trytond.model import Model
|
||||
@@ -301,6 +302,7 @@ class Invoice(Model):
|
||||
root.findtext('./{*}IssueDate'))
|
||||
invoice.party = cls._parse_2_supplier(
|
||||
root.find('./{*}AccountingSupplierParty'), create=True)
|
||||
payees = [invoice.party]
|
||||
invoice.set_journal()
|
||||
invoice.on_change_party()
|
||||
invoice.invoice_address = cls._parse_2_address(
|
||||
@@ -333,6 +335,7 @@ class Invoice(Model):
|
||||
party = cls._create_2_party(payee_party)
|
||||
party.save()
|
||||
invoice.alternative_payees = [party]
|
||||
payees.append(party)
|
||||
|
||||
currency_code = root.findtext('./{*}DocumentCurrencyCode')
|
||||
if not currency_code:
|
||||
@@ -349,6 +352,10 @@ class Invoice(Model):
|
||||
'edocument_ubl.msg_currency_not_found',
|
||||
code=currency_code))
|
||||
|
||||
invoice.supplier_payment_reference = root.findtext(
|
||||
'./{*}PaymentMeans/{*}PaymentID')
|
||||
invoice.payment_means = cls._parse_2_payment_means(
|
||||
root.findall('./{*}PaymentMeans'), payees=payees)
|
||||
invoice.payment_term_date = cls._parse_2_payment_term_date(
|
||||
root.findall('./{*}PaymentTerms'))
|
||||
lines = [
|
||||
@@ -590,6 +597,7 @@ class Invoice(Model):
|
||||
root.findtext('./{*}IssueDate'))
|
||||
invoice.party = cls._parse_2_supplier(
|
||||
root.find('./{*}AccountingSupplierParty'), create=True)
|
||||
payees = [invoice.party]
|
||||
invoice.set_journal()
|
||||
invoice.on_change_party()
|
||||
if (seller := root.find('./{*}SellerSupplierParty')) is not None:
|
||||
@@ -607,6 +615,7 @@ class Invoice(Model):
|
||||
party = cls._create_2_party(payee_party)
|
||||
party.save()
|
||||
invoice.alternative_payees = [party]
|
||||
payees.append(party)
|
||||
if (currency_code := root.findtext('./{*}DocumentCurrencyCode')
|
||||
) is not None:
|
||||
try:
|
||||
@@ -617,6 +626,11 @@ class Invoice(Model):
|
||||
raise InvoiceError(gettext(
|
||||
'edocument_ubl.msg_currency_not_found',
|
||||
code=currency_code))
|
||||
|
||||
invoice.supplier_payment_reference = root.findtext(
|
||||
'./{*}PaymentMeans/{*}PaymentID')
|
||||
invoice.payment_means = cls._parse_2_payment_means(
|
||||
root.findall('./{*}PaymentMeans'), payees=payees)
|
||||
invoice.payment_term_date = cls._parse_2_payment_term_date(
|
||||
root.findall('./{*}PaymentTerms'))
|
||||
lines = [
|
||||
@@ -1059,6 +1073,20 @@ class Invoice(Model):
|
||||
company, = companies
|
||||
return company
|
||||
|
||||
@classmethod
|
||||
def _parse_2_payment_means(cls, payment_means, payees):
|
||||
pool = Pool()
|
||||
PaymentMean = pool.get('account.invoice.payment.mean')
|
||||
means = []
|
||||
for payment_mean in payment_means:
|
||||
if instrument := cls._parse_2_payment_mean(payment_mean, payees):
|
||||
means.append(PaymentMean(instrument=instrument))
|
||||
return means
|
||||
|
||||
@classmethod
|
||||
def _parse_2_payment_mean(cls, payment_mean, payees):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def _parse_2_payment_term_date(cls, payment_terms):
|
||||
dates = []
|
||||
@@ -1265,6 +1293,80 @@ class Invoice(Model):
|
||||
tax_total=lang.format_number(tax_total)))
|
||||
|
||||
|
||||
class Invoice_Bank(metaclass=PoolMeta):
|
||||
__name__ = 'edocument.ubl.invoice'
|
||||
|
||||
@classmethod
|
||||
def _parse_2_payment_mean(cls, payment_mean, payees):
|
||||
pool = Pool()
|
||||
Account = pool.get('bank.account')
|
||||
instrument = super()._parse_2_payment_mean(payment_mean, payees)
|
||||
if (financial_account := payment_mean.find(
|
||||
'./{*}PayeeFinancialAccount')) is not None:
|
||||
identifier = financial_account.findtext('./{*}ID')
|
||||
try:
|
||||
account, = Account.search([
|
||||
('numbers', 'where', ['OR',
|
||||
('number', '=', identifier),
|
||||
('number_compact', '=', identifier),
|
||||
]),
|
||||
('owners.id', 'in', payees),
|
||||
], limit=1)
|
||||
except ValueError:
|
||||
party = payees[-1]
|
||||
if party.id in Transaction().create_records['party.party']:
|
||||
account = cls._create_bank_account(
|
||||
financial_account, party)
|
||||
account.save()
|
||||
else:
|
||||
raise InvoiceError(gettext(
|
||||
'edocument_ubl.msg_account_not_found',
|
||||
parties=','.join([p.rec_name for p in payees]),
|
||||
account=etree.tostring(
|
||||
financial_account,
|
||||
pretty_print=True).decode()))
|
||||
instrument = account
|
||||
return instrument
|
||||
|
||||
@classmethod
|
||||
def _create_bank_account(cls, financial_account, party):
|
||||
pool = Pool()
|
||||
Bank = pool.get('bank')
|
||||
Account = pool.get('bank.account')
|
||||
Number = pool.get('bank.account.number')
|
||||
account = Account(owners=[party])
|
||||
if identifier := financial_account.findtext('./{*}ID'):
|
||||
number = Number(number=identifier)
|
||||
if iban.is_valid(identifier):
|
||||
number.type = 'iban'
|
||||
else:
|
||||
number.type = 'other'
|
||||
account.numbers = [number]
|
||||
if identifier := financial_account.findtext(
|
||||
'./{*}FinancialInstitutionBranch/{*}ID'):
|
||||
if bic.is_valid(identifier):
|
||||
account.bank = Bank.from_bic(identifier)
|
||||
return account
|
||||
|
||||
|
||||
class Invoice_Payment(metaclass=PoolMeta):
|
||||
__name__ = 'edocument.ubl.invoice'
|
||||
|
||||
@classmethod
|
||||
def _parse_invoice_2(cls, root):
|
||||
invoice, attachments = super()._parse_invoice_2(root)
|
||||
if root.find('./{*}PaymentMeans/{*}PaymentMandate') is not None:
|
||||
invoice.payment_direct_debit = True
|
||||
return invoice, attachments
|
||||
|
||||
@classmethod
|
||||
def _parse_credit_note_2(cls, root):
|
||||
invoice, attachments = super()._parse_invoice_2(root)
|
||||
if root.find('./{*}PaymentMeans/{*}PaymentMandate') is not None:
|
||||
invoice.payment_direct_debit = True
|
||||
return invoice, attachments
|
||||
|
||||
|
||||
class Invoice_Purchase(metaclass=PoolMeta):
|
||||
__name__ = 'edocument.ubl.invoice'
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ else:
|
||||
download_url = 'http://downloads.tryton.org/%s.%s/' % (
|
||||
major_version, minor_version)
|
||||
|
||||
requires = ['Genshi', 'lxml']
|
||||
requires = ['Genshi', 'lxml', 'python-stdnum']
|
||||
for dep in info.get('depends', []):
|
||||
if not re.match(r'(ir|res)(\W|$)', dep):
|
||||
requires.append(get_require_version('trytond_%s' % dep))
|
||||
@@ -54,6 +54,7 @@ tests_require = [
|
||||
get_require_version('proteus'),
|
||||
get_require_version('trytond_account_cash_rounding'),
|
||||
get_require_version('trytond_account_invoice'),
|
||||
get_require_version('trytond_bank'),
|
||||
get_require_version('trytond_document_incoming_invoice'),
|
||||
get_require_version('trytond_purchase'),
|
||||
get_require_version('trytond_sale'),
|
||||
|
||||
@@ -18,7 +18,7 @@ Imports::
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> modules = ['edocument_ubl', 'account_invoice', 'purchase']
|
||||
>>> modules = ['edocument_ubl', 'account_invoice', 'bank', 'purchase']
|
||||
>>> if cash_rounding:
|
||||
... modules.append('account_cash_rounding')
|
||||
>>> config = activate_modules(modules, create_company, create_chart)
|
||||
@@ -82,6 +82,12 @@ Parse the UBL invoice::
|
||||
>>> len(invoice.lines)
|
||||
7
|
||||
|
||||
>>> payment_mean, = invoice.payment_means
|
||||
>>> account_number, = payment_mean.instrument.numbers
|
||||
>>> account_number.number
|
||||
'DK1212341234123412'
|
||||
>>> assertEqual(payment_mean.instrument.owners, invoice.alternative_payees)
|
||||
|
||||
>>> attachments = Attachment.find([])
|
||||
>>> len(attachments)
|
||||
3
|
||||
|
||||
@@ -7,6 +7,8 @@ depends:
|
||||
extras_depend:
|
||||
account_cash_rounding
|
||||
account_invoice
|
||||
account_payment
|
||||
bank
|
||||
document_incoming_invoice
|
||||
purchase
|
||||
sale
|
||||
@@ -24,6 +26,14 @@ model:
|
||||
edocument.Invoice
|
||||
account.InvoiceEdocumentStart
|
||||
|
||||
[register account_invoice bank]
|
||||
model:
|
||||
edocument.Invoice_Bank
|
||||
|
||||
[register account_invoice account_payment]
|
||||
model:
|
||||
edocument.Invoice_Payment
|
||||
|
||||
[register account_invoice purchase]
|
||||
model:
|
||||
edocument.Invoice_Purchase
|
||||
|
||||
Reference in New Issue
Block a user