Allow third modules generate facturae XML
task-030940 Graffted from changeset-b7f312439714
This commit is contained in:
parent
9cb7c1ec56
commit
3b6d38630f
|
@ -16,11 +16,11 @@ def register():
|
|||
invoice.Invoice,
|
||||
invoice.InvoiceLine,
|
||||
invoice.CreditInvoiceStart,
|
||||
invoice.GenerateSignedFacturaeAskPassword,
|
||||
invoice.GenerateFacturaeStart,
|
||||
party.Party,
|
||||
payment_type.PaymentType,
|
||||
module='account_invoice_facturae', type_='model')
|
||||
Pool.register(
|
||||
invoice.CreditInvoice,
|
||||
invoice.GenerateSignedFacturae,
|
||||
invoice.GenerateFacturae,
|
||||
module='account_invoice_facturae', type_='wizard')
|
||||
|
|
85
invoice.py
85
invoice.py
|
@ -20,7 +20,7 @@ from trytond.transaction import Transaction
|
|||
from trytond.wizard import Wizard, StateView, StateTransition, Button
|
||||
|
||||
__all__ = ['Invoice', 'InvoiceLine', 'CreditInvoiceStart', 'CreditInvoice',
|
||||
'GenerateSignedFacturaeAskPassword', 'GenerateSignedFacturae']
|
||||
'GenerateFacturaeStart', 'GenerateFacturae']
|
||||
|
||||
# Get from XSD scheme of Facturae 3.2.1
|
||||
# http://www.facturae.gob.es/formato/Versiones/Facturaev3_2_1.xml
|
||||
|
@ -102,7 +102,7 @@ UOM_CODE2TYPE = {
|
|||
# "31", Envelopes-EN
|
||||
# "32", Tubs-TB
|
||||
# "35", Watt-WTT
|
||||
|
||||
FACe_REQUIRED_FIELDS = ['facturae_person_type', 'facturae_residence_type']
|
||||
|
||||
_slugify_strip_re = re.compile(r'[^\w\s-]')
|
||||
_slugify_hyphenate_re = re.compile(r'[-\s]+')
|
||||
|
@ -137,8 +137,7 @@ class Invoice:
|
|||
invoice_facturae = fields.Binary('Factura-e',
|
||||
filename='invoice_facturae_filename', readonly=True)
|
||||
invoice_facturae_filename = fields.Function(fields.Char(
|
||||
'Factura-e filename'),
|
||||
'get_invoice_facturae_filename')
|
||||
'Factura-e filename'), 'get_invoice_facturae_filename')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
|
@ -154,8 +153,6 @@ class Invoice:
|
|||
cls._error_messages.update({
|
||||
'missing_certificate': (
|
||||
'Missing Factura-e Certificate in company "%s".'),
|
||||
'company_facturae_fields': (
|
||||
'Missing some Factura-e fields in company\'s Party "%s".'),
|
||||
'company_vat_identifier': (
|
||||
'Missing VAT Identifier in company\'s Party "%s", or its '
|
||||
'length is not between 3 and 30.'),
|
||||
|
@ -164,7 +161,7 @@ class Invoice:
|
|||
'default address of company\'s Party "%s".'),
|
||||
'party_facturae_fields': (
|
||||
'Missing some Factura-e fields in party "%(party)s" of '
|
||||
'invoice "%(invoice)s".'),
|
||||
'invoice "%(invoice)s": "%(field)s"'),
|
||||
'party_vat_identifier': (
|
||||
'Missing VAT Identifier in party "%(party)s" of invoice '
|
||||
'"%(invoice)s", or its length is not between 3 and 30.'),
|
||||
|
@ -197,7 +194,7 @@ class Invoice:
|
|||
'it\'s required to generate the Factura-e document.'),
|
||||
'invalid_factura_xml_file': (
|
||||
'The Factura-e file (XML) generated for invoice "%s" is '
|
||||
'not valid against the oficial XML Schema Definition.'),
|
||||
'not valid against the oficial XML Schema Definition:\n%s'),
|
||||
'error_signing': ('Error signing invoice "%(invoice)s".\n'
|
||||
'Message returned by signing process: %(process_output)s'),
|
||||
})
|
||||
|
@ -260,7 +257,7 @@ class Invoice:
|
|||
pass
|
||||
|
||||
@classmethod
|
||||
def generate_facturae(cls, invoices, certificate_password):
|
||||
def generate_facturae_default(cls, invoices, certificate_password):
|
||||
to_save = []
|
||||
for invoice in invoices:
|
||||
if invoice.invoice_facturae:
|
||||
|
@ -296,14 +293,14 @@ class Invoice:
|
|||
assert len(self.taxes_outputs) > 0, (
|
||||
"Missing some tax in invoice %s" % self.id)
|
||||
|
||||
if not self.company.facturae_certificate:
|
||||
self.raise_user_error('missing_certificate',
|
||||
(self.company.rec_name,))
|
||||
|
||||
if (not self.company.party.facturae_person_type
|
||||
or not self.company.party.facturae_residence_type):
|
||||
self.raise_user_error('company_facturae_fields',
|
||||
(self.company.party.rec_name,))
|
||||
for field in FACe_REQUIRED_FIELDS:
|
||||
for party in [self.party, self.company.party]:
|
||||
if not getattr(party, field):
|
||||
self.raise_user_error('party_facturae_fields', {
|
||||
'party': party.rec_name,
|
||||
'invoice': self.rec_name,
|
||||
'field': field,
|
||||
})
|
||||
if (not self.company.party.vat_code
|
||||
or len(self.company.party.vat_code) < 3
|
||||
or len(self.company.party.vat_code) > 30):
|
||||
|
@ -318,12 +315,6 @@ class Invoice:
|
|||
self.raise_user_error('company_address_fields',
|
||||
(self.company.party.rec_name,))
|
||||
|
||||
if (not self.party.facturae_person_type
|
||||
or not self.party.facturae_residence_type):
|
||||
self.raise_user_error('party_facturae_fields', {
|
||||
'party': self.party.rec_name,
|
||||
'invoice': self.rec_name,
|
||||
})
|
||||
if (not self.party.vat_code
|
||||
or len(self.party.vat_code) < 3
|
||||
or len(self.party.vat_code) > 30):
|
||||
|
@ -440,19 +431,20 @@ class Invoice:
|
|||
facturae_schema.assertValid(etree.fromstring(xml_string))
|
||||
logger.debug("Factura-e XML of invoice %s validated",
|
||||
self.rec_name)
|
||||
except Exception:
|
||||
except Exception, e:
|
||||
logger.warning("Error validating generated Factura-e file",
|
||||
exc_info=True)
|
||||
logger.warning(xml_string)
|
||||
self.raise_user_error('invalid_factura_xml_file', (self.rec_name,))
|
||||
logger.debug(xml_string)
|
||||
self.raise_user_error('invalid_factura_xml_file', (self.rec_name, e))
|
||||
return True
|
||||
|
||||
def _sign_facturae(self, xml_string, certificate_password):
|
||||
"""
|
||||
Inspired by https://github.com/pedrobaeza/l10n-spain/blob/d01d049934db55130471e284012be7c860d987eb/l10n_es_facturae/wizard/create_facturae.py
|
||||
"""
|
||||
assert self.company.facturae_certificate, (
|
||||
'Missing Factura-e certificate in company "%s"' % self.company.id)
|
||||
if not self.company.facturae_certificate:
|
||||
self.raise_user_error('missing_certificate',
|
||||
(self.company.rec_name,))
|
||||
|
||||
logger = logging.getLogger('account_invoice_facturae')
|
||||
|
||||
|
@ -567,26 +559,37 @@ class CreditInvoice:
|
|||
return super(CreditInvoice, self).do_credit(action)
|
||||
|
||||
|
||||
class GenerateSignedFacturaeAskPassword(ModelView):
|
||||
'Generate Signed Factura-e file - Ask Password'
|
||||
__name__ = 'account.invoice.generate_facturae.ask_password'
|
||||
certificate_password = fields.Char('Certificate Password', required=True)
|
||||
class GenerateFacturaeStart(ModelView):
|
||||
'Generate Factura-e file - Start'
|
||||
__name__ = 'account.invoice.generate_facturae.start'
|
||||
service = fields.Selection([
|
||||
('default', 'Default'),
|
||||
], 'Service', required=True)
|
||||
certificate_password = fields.Char('Certificate Password',
|
||||
states={
|
||||
'required': Eval('service') == 'default',
|
||||
'invisible': Eval('service') != 'default',
|
||||
}, depends=['service'])
|
||||
|
||||
@staticmethod
|
||||
def default_service():
|
||||
return 'default'
|
||||
|
||||
|
||||
class GenerateSignedFacturae(Wizard):
|
||||
'Generate Signed Factura-e file'
|
||||
class GenerateFacturae(Wizard):
|
||||
'Generate Factura-e file'
|
||||
__name__ = 'account.invoice.generate_facturae'
|
||||
start = StateView('account.invoice.generate_facturae.ask_password',
|
||||
'account_invoice_facturae.ask_password_view_form', [
|
||||
start = StateView('account.invoice.generate_facturae.start',
|
||||
'account_invoice_facturae.generate_facturae_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Generate', 'generate', 'tryton-executable', default=True),
|
||||
])
|
||||
generate = StateTransition()
|
||||
|
||||
def transition_generate(self):
|
||||
pool = Pool()
|
||||
Invoice = pool.get('account.invoice')
|
||||
Invoice.generate_facturae(Invoice.browse(
|
||||
Transaction().context['active_ids']),
|
||||
self.start.certificate_password)
|
||||
Invoice = Pool().get('account.invoice')
|
||||
|
||||
invoices = Invoice.browse(Transaction().context['active_ids'])
|
||||
service = 'generate_facturae_%s' % self.start.service
|
||||
getattr(Invoice, service)(invoices, self.start.certificate_password)
|
||||
return 'end'
|
||||
|
|
|
@ -38,10 +38,10 @@
|
|||
</record>
|
||||
|
||||
<!-- account.invoice.generate_facturae -->
|
||||
<record model="ir.ui.view" id="ask_password_view_form">
|
||||
<field name="model">account.invoice.generate_facturae.ask_password</field>
|
||||
<record model="ir.ui.view" id="generate_facturae_start_view_form">
|
||||
<field name="model">account.invoice.generate_facturae.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">ask_password_form</field>
|
||||
<field name="name">generate_facturae_start_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_generate_signed_facturae">
|
||||
|
|
12
locale/ca.po
12
locale/ca.po
|
@ -46,17 +46,13 @@ msgstr ""
|
|||
"Falta l'identificador VAT del tercer \"%(party)s\" de la factura "
|
||||
"\"%(invoice)s\", o la seva longitud no és superior a 3 i inferior a 30."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid "Missing some Factura-e fields in company's Party \"%s\"."
|
||||
msgstr "Falta algun camp Factura-e al tercer de l'empresa \"%s\"."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
"Missing some Factura-e fields in party \"%(party)s\" of invoice "
|
||||
"\"%(invoice)s\"."
|
||||
"\"%(invoice)s\": \"%(field)s\"."
|
||||
msgstr ""
|
||||
"Falta algun camp Factura-e al tercer \"%(party)s\" de la factura "
|
||||
"\"%(invoice)s\"."
|
||||
"\"%(invoice)s\": \"%(field)s\"."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid "No rate found for currency \"%(currency)s\" on \"%(date)s\""
|
||||
|
@ -89,10 +85,10 @@ msgstr ""
|
|||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
"The Factura-e file (XML) generated for invoice \"%s\" is not valid against "
|
||||
"the oficial XML Schema Definition."
|
||||
"the oficial XML Schema Definition.\n%s"
|
||||
msgstr ""
|
||||
"El fitxer Factura-e (XML) generat per la factura \"%s\" no és vàlid segons "
|
||||
"el XML Schema Definition oficial."
|
||||
"el XML Schema Definition oficial.\n%s"
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
|
|
14
locale/es.po
14
locale/es.po
|
@ -46,17 +46,13 @@ msgstr ""
|
|||
"Falta el identificador VAT del tercero \"%(party)s\" de la factura "
|
||||
"\"%(invoice)s\", o su longitud no es superior a 3 e inferior a 30."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid "Missing some Factura-e fields in company's Party \"%s\"."
|
||||
msgstr "Falta algún campo Factura-e en el tercero de la empresa \"%s\"."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
"Missing some Factura-e fields in party \"%(party)s\" of invoice "
|
||||
"\"%(invoice)s\"."
|
||||
"\"%(invoice)s\": \"%(field)s\"."
|
||||
msgstr ""
|
||||
"Falta algún campo Factura-e en el tercero \"%(party)s\" de la factura "
|
||||
"\"%(invoice)s\"."
|
||||
"\"%(invoice)s\": \"%(field)s\"."
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid "No rate found for currency \"%(currency)s\" on \"%(date)s\""
|
||||
|
@ -88,10 +84,10 @@ msgstr ""
|
|||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
"The Factura-e file (XML) generated for invoice \"%s\" is not valid against "
|
||||
"the oficial XML Schema Definition."
|
||||
"the oficial XML Schema Definition.\n%s"
|
||||
msgstr ""
|
||||
"El fichero Factura-e (XML) generado para la factura \"%s\" no es válido "
|
||||
"según el XML Schema Definition oficial."
|
||||
"según el XML Schema Definition oficial.\n%s"
|
||||
|
||||
msgctxt "error:account.invoice:"
|
||||
msgid ""
|
||||
|
@ -505,7 +501,7 @@ msgstr "Factura-e"
|
|||
|
||||
msgctxt "wizard_button:account.invoice.generate_facturae,start,end:"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·lar"
|
||||
msgstr "Cancelar"
|
||||
|
||||
msgctxt "wizard_button:account.invoice.generate_facturae,start,generate:"
|
||||
msgid "Generate"
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
<label string="It will generate a Factura-e file for selected invoices, will sign them with the certificate stored in the company and will save the resulting files in each invoice."
|
||||
id="explanation" colspan="2"
|
||||
yalign="0.0" xalign="0.0" xexpand="1"/>
|
||||
<label name="service"/>
|
||||
<field name="service"/>
|
||||
<label name="certificate_password"/>
|
||||
<field name="certificate_password" widget="password"/>
|
||||
</group>
|
Loading…
Reference in New Issue