Add e-documents as reports on invoices
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Add e-documents as reports
|
||||
* Add payment references to invoices
|
||||
|
||||
Version 7.6.0 - 2025-04-28
|
||||
|
||||
@@ -3499,6 +3499,64 @@ class InvoiceReport(Report):
|
||||
return context
|
||||
|
||||
|
||||
class InvoiceEdocument(Wizard):
|
||||
__name__ = 'account.invoice.edocument'
|
||||
|
||||
start = StateView(
|
||||
'account.invoice.edocument.start',
|
||||
'account_invoice.edocument_start_view_form', [
|
||||
Button("Cancel", 'end', 'tryton-cancel'),
|
||||
Button("Render", 'render', 'tryton-ok', default=True),
|
||||
])
|
||||
render = StateTransition()
|
||||
result = StateView(
|
||||
'account.invoice.edocument.result',
|
||||
'account_invoice.edocument_result_view_form', [
|
||||
Button("Close", 'end', 'tryton-close', default=True),
|
||||
])
|
||||
|
||||
def transition_render(self):
|
||||
pool = Pool()
|
||||
Start = pool.get('account.invoice.edocument.start')
|
||||
if self.start.format not in dict(Start.format.selection):
|
||||
raise ValueError("Unsupported format")
|
||||
Edocument = pool.get(self.start.format)
|
||||
edocument = Edocument(self.record)
|
||||
file = edocument.render(self.start.template)
|
||||
if isinstance(file, str):
|
||||
file = file.decode('utf-8')
|
||||
self.result.file = file
|
||||
self.result.filename = edocument.filename
|
||||
return 'result'
|
||||
|
||||
def default_result(self, fields):
|
||||
file = self.result.file
|
||||
self.result.file = None # No need to store it in the session
|
||||
return {
|
||||
'file': file,
|
||||
'filename': self.result.filename,
|
||||
}
|
||||
|
||||
|
||||
class InvoiceEdocumentStart(ModelView):
|
||||
__name__ = 'account.invoice.edocument.start'
|
||||
|
||||
format = fields.Selection([
|
||||
], "Format", required=True)
|
||||
template = fields.Selection('get_templates', "Template", required=True)
|
||||
|
||||
@fields.depends()
|
||||
def get_templates(self):
|
||||
return []
|
||||
|
||||
|
||||
class InvoiceEdocumentResult(ModelView):
|
||||
__name__ = 'account.invoice.edocument.result'
|
||||
|
||||
file = fields.Binary("File", readonly=True, filename='filename')
|
||||
filename = fields.Char("File Name", readonly=True)
|
||||
|
||||
|
||||
class PayInvoiceStart(ModelView):
|
||||
__name__ = 'account.invoice.pay.start'
|
||||
|
||||
|
||||
@@ -305,6 +305,30 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="action" ref="report_invoice"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="edocument">
|
||||
<field name="name">E-document</field>
|
||||
<field name="wiz_name">account.invoice.edocument</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="edocument_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">account.invoice,-1</field>
|
||||
<field name="action" ref="edocument"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="edocument_start_view_form">
|
||||
<field name="model">account.invoice.edocument.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">edocument_start_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="edocument_result_view_form">
|
||||
<field name="model">account.invoice.edocument.result</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">edocument_result_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="sequence_type_account_invoice">
|
||||
<field name="name">Invoice</field>
|
||||
</record>
|
||||
|
||||
@@ -31,6 +31,8 @@ model:
|
||||
invoice.InvoiceLine
|
||||
invoice.InvoiceLineTax
|
||||
invoice.InvoiceTax
|
||||
invoice.InvoiceEdocumentStart
|
||||
invoice.InvoiceEdocumentResult
|
||||
invoice.PayInvoiceStart
|
||||
invoice.PayInvoiceAsk
|
||||
invoice.CreditInvoiceStart
|
||||
@@ -54,6 +56,7 @@ model:
|
||||
company.Company
|
||||
wizard:
|
||||
payment_term.TestPaymentTerm
|
||||
invoice.InvoiceEdocument
|
||||
invoice.PayInvoice
|
||||
invoice.CreditInvoice
|
||||
invoice.RescheduleLinesToPay
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<form col="2">
|
||||
<label name="file"/>
|
||||
<field name="file"/>
|
||||
</form>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="format"/>
|
||||
<field name="format"/>
|
||||
<label name="template"/>
|
||||
<field name="template"/>
|
||||
</form>
|
||||
@@ -0,0 +1,22 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.model import fields
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
class InvoiceEdocumentStart(metaclass=PoolMeta):
|
||||
__name__ = 'account.invoice.edocument.start'
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.format.selection.append(
|
||||
('edocument.ubl.invoice', "UBL"))
|
||||
|
||||
@fields.depends('format')
|
||||
def get_templates(self):
|
||||
templates = super().get_templates()
|
||||
if self.format == 'edocument.ubl.invoice':
|
||||
templates.append(('2', '2'))
|
||||
return templates
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data depends="account_invoice">
|
||||
<record model="ir.action.wizard" id="account_invoice.edocument">
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -14,7 +14,7 @@ from genshi.template.astutil import ASTCodeGenerator, ASTTransformer
|
||||
from trytond.model import Model
|
||||
from trytond.pool import Pool
|
||||
from trytond.rpc import RPC
|
||||
from trytond.tools import cached_property
|
||||
from trytond.tools import cached_property, slugify
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
if not hasattr(ASTCodeGenerator, 'visit_NameConstant'):
|
||||
@@ -83,6 +83,10 @@ class Invoice(Model):
|
||||
else:
|
||||
return loader.load(os.path.join(version, 'Invoice.xml'))
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return f'{slugify(self.invoice.rec_name)}.xml'
|
||||
|
||||
@cached_property
|
||||
def type_code(self):
|
||||
if self.invoice.type == 'out':
|
||||
|
||||
@@ -6,9 +6,15 @@ depends:
|
||||
party
|
||||
extras_depend:
|
||||
account_invoice
|
||||
xml:
|
||||
account.xml
|
||||
|
||||
[register]
|
||||
model:
|
||||
party.Party
|
||||
party.Identifier
|
||||
|
||||
[register account_invoice]
|
||||
model:
|
||||
edocument.Invoice
|
||||
account.InvoiceEdocumentStart
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.model import fields
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
class InvoiceEdocumentStart(metaclass=PoolMeta):
|
||||
__name__ = 'account.invoice.edocument.start'
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.format.selection.append(
|
||||
('edocument.uncefact.invoice', "UN/CEFACT"))
|
||||
|
||||
@fields.depends('format')
|
||||
def get_templates(self):
|
||||
templates = super().get_templates()
|
||||
if self.format == 'edocument.uncefact.invoice':
|
||||
templates.append(('16B-CII', '16B-CII'))
|
||||
return templates
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data depends="account_invoice">
|
||||
<record model="ir.action.wizard" id="account_invoice.edocument">
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -11,7 +11,7 @@ from genshi.template.astutil import ASTCodeGenerator, ASTTransformer
|
||||
from trytond.model import Model
|
||||
from trytond.pool import Pool
|
||||
from trytond.rpc import RPC
|
||||
from trytond.tools import cached_property
|
||||
from trytond.tools import cached_property, slugify
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
if not hasattr(ASTCodeGenerator, 'visit_NameConstant'):
|
||||
@@ -86,6 +86,10 @@ class Invoice(Model):
|
||||
def _get_template(self, version):
|
||||
return loader.load(os.path.join(version, 'CrossIndustryInvoice.xml'))
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return f'{slugify(self.invoice.rec_name)}.xml'
|
||||
|
||||
@cached_property
|
||||
def type_code(self):
|
||||
if self.invoice.type == 'out':
|
||||
|
||||
@@ -5,7 +5,10 @@ depends:
|
||||
edocument_unece
|
||||
extras_depend:
|
||||
account_invoice
|
||||
xml:
|
||||
account.xml
|
||||
|
||||
[register]
|
||||
[register account_invoice]
|
||||
model:
|
||||
edocument.Invoice
|
||||
account.InvoiceEdocumentStart
|
||||
|
||||
Reference in New Issue
Block a user