Delete issued invoices from SII

This commit is contained in:
Daniel Möller 2017-05-23 17:04:16 +02:00
parent c1ac4ed2f1
commit 16d275f83b
3 changed files with 76 additions and 55 deletions

75
aeat.py
View File

@ -10,6 +10,7 @@ __all__ = [
import unicodedata
from logging import getLogger
from decimal import Decimal
from operator import attrgetter
from trytond.model import ModelSQL, ModelView, fields, Workflow
from trytond.pyson import Eval
@ -124,6 +125,7 @@ AEAT_INVOICE_STATE = [
('Correcto', 'Accepted'),
('AceptadoConErrores', 'Accepted with Errors'),
('AceptadaConErrores', 'Accepted with Errors'), # Shame on AEAT
('Anulada', 'Deleted'),
('Incorrecto', 'Rejected')
]
@ -356,6 +358,8 @@ class SIIReport(Workflow, ModelSQL, ModelView):
report.submit_issued_invoices()
elif report.operation_type == 'C0': # query invoices
report.query_issued_invoices()
elif report.operation_type == 'D0': # delete invoices
report.delete_issued_invoices()
else:
raise NotImplementedError
else:
@ -398,15 +402,13 @@ class SIIReport(Workflow, ModelSQL, ModelView):
def submit_issued_invoices(self):
_logger.info('Sending report %s to AEAT SII', self.id)
pool = Pool()
Company = pool.get('company.company')
Invoice = pool.get('account.invoice')
company = Company(Transaction().context.get('company'))
headers = mapping.get_headers(
name=company.party.name, vat=company.party.vat_number,
name=self.company.party.name,
vat=self.company.party.vat_number,
comm_kind=self.operation_type)
invoices = Invoice.map_to_aeat_sii(
line.invoice for line in self.lines)
invoices = map(
IssuedTrytonInvoiceMapper.build_submit_request,
(line.invoice for line in self.lines))
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_SuministroFactEmitidas(crt, key, test=True)
@ -415,12 +417,34 @@ class SIIReport(Workflow, ModelSQL, ModelView):
for (report_line, response_line) in zip(
self.lines, res.RespuestaLinea):
report_line.write([report_line], {
'state':
response_line.EstadoRegistro,
'communication_code':
response_line.CodigoErrorRegistro,
'communication_msg':
response_line.DescripcionErrorRegistro,
'state': response_line.EstadoRegistro,
'communication_code': response_line.CodigoErrorRegistro,
'communication_msg': response_line.DescripcionErrorRegistro,
})
self.write([self], {
'communication_state': res.EstadoEnvio,
'csv': res.CSV,
})
def delete_issued_invoices(self):
headers = mapping.get_headers(
name=self.company.party.name,
vat=self.company.party.vat_number,
comm_kind=self.operation_type)
invoices = map(
IssuedTrytonInvoiceMapper.build_delete_request,
(line.invoice for line in self.lines))
res = None
with self.company.tmp_ssl_credentials() as (crt, key):
srv = service.bind_SuministroFactEmitidas(crt, key, test=True)
res = srv.AnulacionLRFacturasEmitidas(headers, invoices)
# TODO: assert response order matches report order
for (report_line, response_line) in zip(
self.lines, res.RespuestaLinea):
report_line.write([report_line], {
'state': response_line.EstadoRegistro,
'communication_code': response_line.CodigoErrorRegistro,
'communication_msg': response_line.DescripcionErrorRegistro,
})
self.write([self], {
'communication_state': res.EstadoEnvio,
@ -430,11 +454,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
def query_issued_invoices(self):
res = None
pool = Pool()
Company = pool.get('company.company')
Invoice = pool.get('account.invoice')
company = Company(Transaction().context.get('company'))
headers = mapping.get_headers(
name=company.party.name, vat=company.party.vat_number,
name=self.company.party.name,
vat=self.company.party.vat_number,
comm_kind=self.operation_type)
filter_ = {
'PeriodoImpositivo': {
@ -484,6 +507,26 @@ class SIIReport(Workflow, ModelSQL, ModelView):
})
class IssuedTrytonInvoiceMapper(mapping.OutInvoiceMapper):
year = attrgetter('move.period.fiscalyear.name')
period = attrgetter('move.period.start_date.month')
nif = attrgetter('company.party.vat_number')
serial_number = attrgetter('number')
issue_date = attrgetter('invoice_date')
invoice_kind = attrgetter('sii_operation_key')
specialkey_or_trascendence = attrgetter('sii_issued_key')
description = attrgetter('description')
not_exempt_kind = attrgetter('sii_subjected')
counterpart_name = attrgetter('party.name')
counterpart_nif = attrgetter('party.vat_number')
counterpart_id_type = attrgetter('party.identifier_type')
counterpart_country = attrgetter('party.vat_country')
taxes = attrgetter('taxes')
tax_rate = attrgetter('tax.rate')
tax_base = attrgetter('base')
tax_amount = attrgetter('amount')
class SIIReportLine(ModelSQL, ModelView):
'''
AEAT SII Issued

View File

@ -1,24 +1,22 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from operator import attrgetter
from trytond import backend
from trytond.model import ModelSQL, ModelView, fields
from trytond.model import ModelView, fields
from trytond.wizard import Wizard, StateView, StateTransition, Button
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, And, Bool
from trytond.pyson import Eval
from trytond.transaction import Transaction
from sql.operators import In
from sql.aggregate import Max
from .aeat import (OPERATION_KEY, BOOK_KEY, SEND_SPECIAL_REGIME_KEY,
RECEIVE_SPECIAL_REGIME_KEY, AEAT_INVOICE_STATE, IVA_SUBJECTED,
EXCEMPTION_CAUSE, INTRACOMUNITARY_TYPE)
from .aeat import (
OPERATION_KEY, BOOK_KEY, SEND_SPECIAL_REGIME_KEY,
RECEIVE_SPECIAL_REGIME_KEY, AEAT_INVOICE_STATE, IVA_SUBJECTED,
EXCEMPTION_CAUSE, INTRACOMUNITARY_TYPE)
from .pyAEATsii import mapping
__all__ = ['Invoice', 'ReasignSIIRecord', 'ReasignSIIRecordStart',
'ReasignSIIRecordEnd']
__all__ = [
'Invoice', 'ReasignSIIRecord', 'ReasignSIIRecordStart',
'ReasignSIIRecordEnd'
]
class Invoice:
@ -112,31 +110,6 @@ class Invoice:
return result
@classmethod
def map_to_aeat_sii(cls, invoices):
mapper = IssuedTrytonInvoiceMapper()
return map(mapper.build_request, invoices)
class IssuedTrytonInvoiceMapper(mapping.OutInvoiceMapper):
year = attrgetter('move.period.fiscalyear.name')
period = attrgetter('move.period.start_date.month')
nif = attrgetter('company.party.vat_number')
serial_number = attrgetter('number')
issue_date = attrgetter('invoice_date')
invoice_kind = attrgetter('sii_operation_key')
specialkey_or_trascendence = attrgetter('sii_issued_key')
description = attrgetter('description')
not_exempt_kind = attrgetter('sii_subjected')
counterpart_name = attrgetter('party.name')
counterpart_nif = attrgetter('party.vat_number')
counterpart_id_type = attrgetter('party.identifier_type')
counterpart_country = attrgetter('party.vat_country')
taxes = attrgetter('taxes')
tax_rate = attrgetter('tax.rate')
tax_base = attrgetter('base')
tax_amount = attrgetter('amount')
class ReasignSIIRecordStart(ModelView):
"""

View File

@ -19,13 +19,18 @@ def get_headers(name=None, vat=None, comm_kind=None, version='0.7'):
class OutInvoiceMapper(object):
@classmethod
def build_request(cls, invoice):
def build_delete_request(cls, invoice):
return {
'PeriodoImpositivo': cls.build_period(invoice),
'IDFactura': cls.build_invoice_id(invoice),
'FacturaExpedida': cls.build_issued_invoice(invoice),
}
@classmethod
def build_submit_request(cls, invoice):
request = cls.build_delete_request(invoice)
request['FacturaExpedida'] = cls.build_issued_invoice(invoice)
return request
@classmethod
def build_period(cls, invoice):
return {