Fix mapper instantiation, vat_code format, identifier_type party selection

This commit is contained in:
Sergio Morillo 2017-06-08 08:36:48 +02:00
parent e584e3ddc1
commit bad19c9136
15 changed files with 113 additions and 90 deletions

68
aeat.py
View File

@ -247,7 +247,7 @@ class SIIReport(Workflow, ModelSQL, ModelView):
'readonly': Eval('state') != 'draft',
}, depends=['state'])
currency = fields.Function(fields.Many2One('currency.currency',
'Currency'), 'get_currency')
'Currency'), 'on_change_with_currency')
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
required=True, states={
'readonly': Eval('state') != 'draft',
@ -261,7 +261,7 @@ class SIIReport(Workflow, ModelSQL, ModelView):
domain=[('fiscalyear', '=', Eval('fiscalyear'))],
states={
'readonly': Eval('state') != 'draft',
}, depends=['state'])
}, depends=['state', 'fiscalyear'])
operation_type = fields.Selection(COMMUNICATION_TYPE, 'Operation Type',
required=True,
@ -335,14 +335,14 @@ class SIIReport(Workflow, ModelSQL, ModelView):
('cancelled', 'draft'),
))
@staticmethod
def default_company():
return Transaction().context.get('company')
def get_currency(self, name):
return self.company.currency.id
@fields.depends('company')
def on_change_with_currency(self, name):
if self.company:
return self.company.currency.id
@staticmethod
def default_fiscalyear():
@ -356,12 +356,21 @@ class SIIReport(Workflow, ModelSQL, ModelView):
@staticmethod
def default_version():
return '0.6'
return '0.7'
@fields.depends('company')
def on_change_with_company_vat(self):
if self.company:
return self.company.party.vat_code
return self.company.party.sii_vat_code
@classmethod
def copy(cls, records, default=None):
if default is None:
default = {}
else:
default = default.copy()
default['communication_state'] = None
return super(SIIReport, cls).copy(records, default=default)
@classmethod
@ModelView.button
@ -440,10 +449,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
_logger.info('Sending report %s to AEAT SII', self.id)
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
pool = Pool()
mapper = pool.get('aeat.sii.issued.invoice.mapper')(pool=pool)
mapper = IssuedTrytonInvoiceMapper(pool=pool)
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_issued_invoices_service(crt, key, test=True)
@ -467,10 +476,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
def delete_issued_invoices(self):
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
pool = Pool()
mapper = pool.get('aeat.sii.issued.invoice.mapper')(pool=pool)
mapper = IssuedTrytonInvoiceMapper(pool=pool)
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_issued_invoices_service(crt, key, test=True)
@ -497,7 +506,7 @@ class SIIReport(Workflow, ModelSQL, ModelView):
Invoice = pool.get('account.invoice')
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
with self.company.tmp_ssl_credentials() as (crt, key):
@ -544,10 +553,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
_logger.info('Sending report %s to AEAT SII', self.id)
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
pool = Pool()
mapper = pool.get('aeat.sii.recieved.invoice.mapper')(pool=pool)
mapper = RecievedTrytonInvoiceMapper(pool=pool)
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_recieved_invoices_service(crt, key, test=True)
@ -571,10 +580,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
def delete_recieved_invoices(self):
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
pool = Pool()
mapper = pool.get('aeat.sii.recieved.invoice.mapper')(pool=pool)
mapper = RecievedTrytonInvoiceMapper(pool=pool)
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_recieved_invoices_service(crt, key, test=True)
@ -601,7 +610,7 @@ class SIIReport(Workflow, ModelSQL, ModelView):
Invoice = pool.get('account.invoice')
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_code,
vat=self.company_vat,
comm_kind=self.operation_type)
with self.company.tmp_ssl_credentials() as (crt, key):
@ -646,23 +655,23 @@ class SIIReport(Workflow, ModelSQL, ModelView):
})
class BaseTrytonInvoiceMapper(Model):
class BaseTrytonInvoiceMapper(object):
def __init__(self, *args, **kwargs):
super(BaseTrytonInvoiceMapper, self).__init__(*args, **kwargs)
super(BaseTrytonInvoiceMapper, self).__init__()
self.pool = Pool()
year = attrgetter('move.period.fiscalyear.name')
period = attrgetter('move.period.start_date.month')
nif = attrgetter('company.party.vat_code')
nif = attrgetter('company.party.sii_vat_code')
issue_date = attrgetter('invoice_date')
invoice_kind = attrgetter('sii_operation_key')
rectified_invoice_kind = callback_utils.fixed_value('I')
not_exempt_kind = attrgetter('sii_subjected')
counterpart_name = attrgetter('party.name')
counterpart_nif = attrgetter('party.vat_code')
counterpart_nif = attrgetter('party.sii_vat_code')
counterpart_id_type = attrgetter('party.identifier_type')
counterpart_country = attrgetter('party.vat_country')
counterpart_country = attrgetter('party.sii_vat_country')
counterpart_id = counterpart_nif
taxes = attrgetter('taxes')
tax_rate = attrgetter('tax.rate')
@ -697,7 +706,6 @@ class IssuedTrytonInvoiceMapper(
"""
Tryton Issued Invoice to AEAT mapper
"""
__name__ = 'aeat.sii.issued.invoice.mapper'
serial_number = attrgetter('number')
specialkey_or_trascendence = attrgetter('sii_issued_key')
@ -708,7 +716,6 @@ class RecievedTrytonInvoiceMapper(
"""
Tryton Recieved Invoice to AEAT mapper
"""
__name__ = 'aeat.sii.recieved.invoice.mapper'
serial_number = attrgetter('reference')
specialkey_or_trascendence = attrgetter('sii_received_key')
move_date = attrgetter('move.date')
@ -735,3 +742,14 @@ class SIIReportLine(ModelSQL, ModelView):
@staticmethod
def default_company():
return Transaction().context.get('company')
@classmethod
def copy(cls, records, default=None):
if default is None:
default = {}
else:
default = default.copy()
default['state'] = None
default['communication_code'] = None
default['communication_msg'] = None
return super(SIIReportLine, cls).copy(records, default=default)

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>

View File

@ -1,6 +1,5 @@
#This file is part party_comment module for Tryton.
#The COPYRIGHT file at the top level of this repository contains
#the full copyright notices and license terms.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
from logging import getLogger
from contextlib import contextmanager
@ -27,6 +26,7 @@ class Company:
cls._error_messages.update({
'missing_fernet_key': "Missing Fernet key configuration",
'missing_pem_cert': "Missing PEM certificate"
})
pem_certificate = fields.Binary(
@ -90,6 +90,8 @@ class Company:
@contextmanager
def tmp_ssl_credentials(self):
if not self.pem_certificate:
self.raise_user_error('missing_pem_cert')
with NamedTemporaryFile(suffix='.crt') as crt:
with NamedTemporaryFile(suffix='.pem') as key:
crt.write(self.pem_certificate)

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>

View File

@ -61,7 +61,7 @@ class Invoice:
table = SIILines.__table__()
cursor = Transaction().connection.cursor()
cursor = Transaction().cursor
cursor.execute(*table.select(Max(table.id), table.invoice,
group_by=table.invoice))
@ -86,10 +86,10 @@ class Invoice:
SIILines = pool.get('aeat.sii.report.lines')
result = {}
for name in names:
result[name] = dict((i.id, '') for i in invoices)
result[name] = dict((i.id, None) for i in invoices)
table = SIILines.__table__()
cursor = Transaction().connection.cursor()
cursor = Transaction().cursor
cursor.execute(*table.select(Max(table.id), table.invoice,
where=table.invoice.in_([x.id for x in invoices]),
group_by=table.invoice))
@ -102,7 +102,6 @@ class Invoice:
for state, inv in cursor.fetchall():
result['sii_state'][inv] = state
return result
def _credit(self):

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="aeat_sii_invoice_form_view">

View File

@ -1,21 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>
<data>
<record model="ir.ui.view" id="load_pkcs12_start_view">
<field name="model">aeat.sii.load_pkcs12.start</field>
<field name="type">form</field>
<field name="name">load_pkcs12_start</field>
</record>
<record model="ir.action.wizard" id="act_aeat_sii_load_pkcs12">
<field name="name">Load PKCS12</field>
<field name="wiz_name">aeat.sii.load_pkcs12</field>
</record>
<record model="ir.action.keyword" id="act_aeat_sii_load_pkcs12_keyword1">
<field name="action" ref="act_aeat_sii_load_pkcs12"/>
<field name="keyword">form_action</field>
<field name="model">company.company,-1</field>
</record>
<record model="ir.ui.view" id="load_pkcs12_start_view">
<field name="model">aeat.sii.load_pkcs12.start</field>
<field name="type">form</field>
<field name="name">load_pkcs12_start</field>
</record>
<record model="ir.action.wizard" id="act_aeat_sii_load_pkcs12">
<field name="name">Load PKCS12</field>
<field name="wiz_name">aeat.sii.load_pkcs12</field>
</record>
<record model="ir.action.keyword" id="act_aeat_sii_load_pkcs12_keyword1">
<field name="action" ref="act_aeat_sii_load_pkcs12"/>
<field name="keyword">form_action</field>
<field name="model">company.company,-1</field>
</record>
</data>
</data>
</tryton>

View File

@ -8,7 +8,11 @@ msgstr "No se ha podido cargar PKCS12: %s"
msgctxt "error:company.company:"
msgid "Missing Fernet key configuration"
msgstr "Falta clave Fernet a la configuración"
msgstr "Falta clave Fernet en la configuración"
msgctxt "error:company.company:"
msgid "Missing PEM certificate"
msgstr "Falta certificado PEM"
msgctxt "field:account.invoice,sii_book_key:"
msgid "SII Book Key"
@ -122,7 +126,6 @@ msgctxt "field:aeat.sii.report,rec_name:"
msgid "Name"
msgstr "Nombre"
#, fuzzy
msgctxt "field:aeat.sii.report,state:"
msgid "State"
msgstr "Estado"
@ -131,7 +134,6 @@ msgctxt "field:aeat.sii.report,version:"
msgid "Version"
msgstr "Versión"
#, fuzzy
msgctxt "field:aeat.sii.report,write_date:"
msgid "Write Date"
msgstr "Fecha de modificación"
@ -184,7 +186,6 @@ msgctxt "field:aeat.sii.report.lines,write_date:"
msgid "Write Date"
msgstr "Fecha de modificación"
#, fuzzy
msgctxt "field:aeat.sii.report.lines,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
@ -251,7 +252,7 @@ msgstr "Informe SII"
msgctxt "model:ir.action,name:act_aeat_sii_report_line"
msgid "AEAT SII Report Lines"
msgstr "Línias informe SII"
msgstr "Líneas informe SII"
msgctxt "model:ir.action,name:act_aeat_sii_report_lines"
msgid "SII Report Lines"
@ -802,14 +803,13 @@ msgctxt "view:aeat.sii.report:"
msgid "Load Invoices"
msgstr "Cargar facturas"
#, fuzzy
msgctxt "view:aeat.sii.report:"
msgid "Send"
msgstr "Enviar"
msgctxt "view:company.company:"
msgid "Certificate"
msgstr ""
msgstr "Certificado"
msgctxt "wizard_button:aeat.sii.load_pkcs12,start,end:"
msgid "Cancel"

View File

@ -1,16 +1,27 @@
#This file is part party_comment module for Tryton.
#The COPYRIGHT file at the top level of this repository contains
#the full copyright notices and license terms.
# 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
from . import aeat
__all__ = ['Party']
class Party:
__name__ = 'party.party'
__metaclass__ = PoolMeta
# TODO: v4 change to party.identifier module
identifier_type = fields.Selection([('', '')] + aeat.PARTY_IDENTIFIER_TYPE,
'Identifier Type', )
identifier_type = fields.Selection(aeat.PARTY_IDENTIFIER_TYPE,
'Identifier Type')
sii_vat_code = fields.Function(fields.Char('VAT', size=9),
'get_sii_vat_data')
sii_vat_country = fields.Function(fields.Char('VAT', size=2),
'get_sii_vat_data')
def get_sii_vat_data(self, name=None):
if self.vat_code:
if name == 'sii_vat_code':
return self.vat_code[-9:]
elif name == 'sii_vat_country':
return self.vat_code[:2]

View File

@ -1,6 +1,5 @@
<?xml version="1.0"?>
<!-- This file is part party_comment module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<!-- The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="party_view_form">

View File

@ -3,29 +3,20 @@
import unittest
# import doctest
import trytond.tests.test_tryton
from trytond.tests.test_tryton import test_view, test_depends
from trytond.tests.test_tryton import ModuleTestCase
# TODO: Remove if no sceneario needed.
# from trytond.tests.test_tryton import doctest_setup, doctest_teardown
class TestCase(unittest.TestCase):
'Test module'
def setUp(self):
trytond.tests.test_tryton.install_module('aeat_sii')
def test0005views(self):
'Test views'
test_view('aeat_sii')
def test0006depends(self):
'Test depends'
test_depends()
class AeatSIITestCase(ModuleTestCase):
'Test AEAT SII module'
module = 'aeat_sii'
def suite():
suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCase))
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
AeatSIITestCase))
# TODO: remove if no scenario needed.
#suite.addTests(doctest.DocFileSuite('scenario_aeat_sii.rst',
# setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',

View File

@ -1,8 +1,6 @@
<?xml version="1.0"?>
<!-- This file is part of party_comment module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license types. -->
<data>
<xpath expr="/form/notebook/page[@id='reports']" position="after">
<page string="Certificate" col="2" id="certificate">

View File

@ -1,8 +1,6 @@
<?xml version="1.0"?>
<!-- This file is part of party_comment module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license types. -->
<form string="Load PKCS12" col="2">
<label name="pfx"/>
<field name="pfx"/>

View File

@ -1,12 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of party_comment module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license types. -->
<data>
<xpath expr="/form/notebook/page[@id='accounting']/field[@name='vat_number']"
position="after">
<xpath expr="/form/notebook/page[@name='identifiers']/field[@name='identifiers']"
position="before">
<label name="identifier_type"/>
<field name="identifier_type"/>
<newline/>
</xpath>
</data>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
<!-- The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form string="AEAT SII Data Reassigment Done" col="2">
<image name="tryton-dialog-information" xexpand="0" xfill="0"/>