From 4224ad3783b272490d19e31bbbbbebc6675b744e Mon Sep 17 00:00:00 2001 From: "Ignacio Ibeas - Acysos S.L" Date: Mon, 13 Mar 2017 11:06:40 +0100 Subject: [PATCH 001/298] =?UTF-8?q?l10n=5Fes=5Faeat=5Fsii:=20presentaci?= =?UTF-8?q?=C3=B3n=20inmediata=20de=20impuesto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- l10n_es_aeat_sii_oca/README.rst | 108 +++++ l10n_es_aeat_sii_oca/__init__.py | 9 + l10n_es_aeat_sii_oca/__openerp__.py | 26 ++ .../data/ir_config_parameter.xml | 17 + l10n_es_aeat_sii_oca/models/__init__.py | 6 + .../models/account_invoice.py | 439 ++++++++++++++++++ l10n_es_aeat_sii_oca/models/res_company.py | 67 +++ .../views/account_invoice_view.xml | 46 ++ .../views/res_company_view.xml | 29 ++ 9 files changed, 747 insertions(+) create mode 100644 l10n_es_aeat_sii_oca/README.rst create mode 100644 l10n_es_aeat_sii_oca/__init__.py create mode 100644 l10n_es_aeat_sii_oca/__openerp__.py create mode 100644 l10n_es_aeat_sii_oca/data/ir_config_parameter.xml create mode 100644 l10n_es_aeat_sii_oca/models/__init__.py create mode 100644 l10n_es_aeat_sii_oca/models/account_invoice.py create mode 100644 l10n_es_aeat_sii_oca/models/res_company.py create mode 100644 l10n_es_aeat_sii_oca/views/account_invoice_view.xml create mode 100644 l10n_es_aeat_sii_oca/views/res_company_view.xml diff --git a/l10n_es_aeat_sii_oca/README.rst b/l10n_es_aeat_sii_oca/README.rst new file mode 100644 index 00000000000..6529f4c132a --- /dev/null +++ b/l10n_es_aeat_sii_oca/README.rst @@ -0,0 +1,108 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============== +Suministro Inmediato de Información en el IVA +============== + +Módulo para la presentación inmediata del IVA +http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_05/SII_Descripcion_ServicioWeb_v0.5_es_es.pdf + +Installation +============ + +Para instalar esté módulo necesita: + +#. Libreria Python Zeep, se puede instalar con el comando 'pip install zeep' +#. Libreria Python Requests, se puede instalar con el comando 'pip install requests' + +Configuration +============= + +Para configurar este módulo necesitas: + +#. En la compañia se almacenan las URLs del servicio SOAP de hacienda. +Estas URLs pueden cambiar según comunidades +#. Los certificados deben alojarse en una carpeta accesible por la instalación +de Odoo. Las rutas de los certificados se pueden indicar en Configuración-> +Parámetros->Parametros del sistemas con las claves l10n_es_aeat_sii.publicCrt y +l10n_es_aeat_sii.privateKey +#. Preparar el certificado. El certificado enviado por la FMNT es en formato +p12, este certificado no se puede usar directamente con Zeep. Se tiene que +extraer la clave pública y la clave privada. +El linux se pueden usar los siguientes comandos: +- Clave pública: "openssl pkcs12 -in Certificado.p12 -nokeys -out publicCert.crt -nodes" +- Clave privada: "openssl pkcs12 -in Certifcado.p12 -nocerts -out privateKey.pem -nodes" + + +Usage +===== + +Cuando se válida una factura actumáticamente envia la comunicación al servidor +de AEAT. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Known issues / Roadmap +====================== + +* Facturas de bienes de inversión +* Comunicación de cobros y pagos +* Determinadas facturas intracomunitarias +* Factura simplificada +* Facturas No sujetas según el art 7.14 y no sujetas en el TAI +* Asistente para consultar los documentos comunicados +* Carga directa del certificado desde Odoo (PR Enviado) +* Control de longitud y tipo de datos +* Usar modulo connector + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Ignacio Ibeas + +Funders +------- + +The development of this module has been financially supported by: + +* Company 1 name +* Company 2 name + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/l10n_es_aeat_sii_oca/__init__.py b/l10n_es_aeat_sii_oca/__init__.py new file mode 100644 index 00000000000..0562ab10129 --- /dev/null +++ b/l10n_es_aeat_sii_oca/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models +# from . import wizards +# from . import controllers +# from . import report +# from .hooks import pre_init_hook, post_load, post_init_hook, uninstall_hook diff --git a/l10n_es_aeat_sii_oca/__openerp__.py b/l10n_es_aeat_sii_oca/__openerp__.py new file mode 100644 index 00000000000..8e7a01a9d1e --- /dev/null +++ b/l10n_es_aeat_sii_oca/__openerp__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Suministro Inmediato de Información en el IVA", + "version": "8.0.1.0.1", + "category": "Accounting & Finance", + "website": "https://odoo-community.org/", + "author": "Acysos S.L., Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "external_dependencies": { + "python": ["zeep", + "requests"], + }, + "depends": [ + "base", + "account" + ], + "data": [ + "data/ir_config_parameter.xml", + "views/res_company_view.xml", + "views/account_invoice_view.xml" + ], +} diff --git a/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml new file mode 100644 index 00000000000..56880baf719 --- /dev/null +++ b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml @@ -0,0 +1,17 @@ + + + + + + l10n_es_aeat_sii.publicCrt + /opt/certificates/publicCert.crt + + + + l10n_es_aeat_sii.privateKey + /opt/certificates/privateKey.pem + + + + diff --git a/l10n_es_aeat_sii_oca/models/__init__.py b/l10n_es_aeat_sii_oca/models/__init__.py new file mode 100644 index 00000000000..e63f5145d47 --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import res_company +from . import account_invoice diff --git a/l10n_es_aeat_sii_oca/models/account_invoice.py b/l10n_es_aeat_sii_oca/models/account_invoice.py new file mode 100644 index 00000000000..53902200541 --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/account_invoice.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import models, fields, api +from requests import Session +from zeep import Client +from zeep.transports import Transport +from zeep.plugins import HistoryPlugin +from datetime import datetime + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + sii_sent = fields.Boolean('SII Sent') + sii_return = fields.Text('SII Return') + refund_type = fields.Selection( + selection=[('S', 'By substitution'), ('I', 'By differences')], + string="Refund Type") + + @api.multi + def _change_date_format(self, date): + datetimeobject = datetime.strptime(date,'%Y-%m-%d') + new_date = datetimeobject.strftime('%d-%m-%Y') + return new_date + + @api.multi + def _get_header(self, company, TipoComunicacion): + header = { + "IDVersionSii": company.sii_version, + "Titular": { + "NombreRazon": company.name, + "NIF": company.vat[2:]}, + "TipoComunicacion": TipoComunicacion + } + return header + + @api.multi + def _get_tax_line_req(self, tax_type, line, line_taxes): + taxes = False + if len(line_taxes) > 1: + req_ids = line_taxes.search([('description', 'in', [ + 'P_REQ5.2', 'S_REQ52', 'P_REQ14', 'S_REQ14', 'P_REQ05', + 'S_REQ05'])]) + for tax in line_taxes: + if tax in req_ids: + price = line.price_unit * (1 - ( + line.discount or 0.0) / 100.0) + taxes = tax.compute_all( + price, line.quantity, line.product_id, + line.invoice_id.partner_id) + taxes['percentage'] = tax.amount + return taxes + return taxes + + @api.multi + def _get_sii_tax_line(self, tax_line, line, line_taxes, invoice): + tax_type = tax_line.amount * 100 + tax_line_req = self._get_tax_line_req(tax_type, line, line_taxes) + taxes = tax_line.compute_all( + (line.price_unit * (1 - (line.discount or 0.0) / 100.0)), + line.quantity, line.product_id, line.invoice_id.partner_id) + if tax_line_req: + TipoRecargo = tax_line_req['percentage'] * 100 + CuotaRecargo = tax_line_req['taxes'][0]['amount'] + else: + TipoRecargo = 0 + CuotaRecargo = 0 + tax_sii = { + "TipoImpositivo":tax_type, + "BaseImponible":taxes['total'], + "TipoRecargoEquivalencia":TipoRecargo, + "CuotaRecargoEquivalencia":CuotaRecargo + } + if invoice.type in ['out_invoice', 'out_refund']: + tax_sii['CuotaRepercutida'] = taxes['taxes'][0]['amount'] + if invoice.type in ['in_invoice', 'in_refund']: + tax_sii['CuotaSoportada'] = taxes['taxes'][0]['amount'] + return tax_sii + + @api.multi + def _update_sii_tax_line(self, taxes, tax_line, line, line_taxes, invoice): + tax_type = tax_type = tax_line.amount * 100 + tax_line_req = self._get_tax_line_req(tax_type, line, line_taxes) + taxes = tax_line.compute_all( + (line.price_unit * (1 - (line.discount or 0.0) / 100.0)), + line.quantity, line.product_id, line.invoice_id.partner_id) + if tax_line_req: + TipoRecargo = tax_line_req['percentage'] * 100 + CuotaRecargo = tax_line_req['taxes'][0]['amount'] + else: + TipoRecargoEquivalencia = 0 + CuotaRecargoEquivalencia = 0 + taxes[str(tax_type)]['BaseImponible'] += taxes['total'] + taxes[str(tax_type)]['TipoRecargoEquivalencia'] += TipoRecargo + taxes[str(tax_type)]['CuotaRecargoEquivalencia'] += CuotaRecargo + if invoice.type in ['out_invoice', 'out_refund']: + tax_sii['CuotaRepercutida'] += taxes['taxes'][0]['amount'] + if invoice.type in ['in_invoice', 'in_refund']: + tax_sii['CuotaSoportada'] += taxes['taxes'][0]['amount'] + return taxes + + @api.multi + def _get_sii_out_taxes(self, invoice): + taxes_sii = {} + taxes_f = {} + taxes_to = {} + for line in invoice.invoice_line: + for tax_line in line.invoice_line_tax_id: + if tax_line.description in [ + 'S_IVA21B', 'S_IVA10B', 'S_IVA4B', 'S_IVA0_ISP', + 'S_IVA_NS']: + if 'DesgloseFactura' not in taxes_sii: + taxes_sii['DesgloseFactura'] = {} + if tax_line.description in [ + 'S_IVA21B', 'S_IVA10B', 'S_IVA4B']: + if 'Sujeta' not in taxes_sii['DesgloseFactura']: + taxes_sii['DesgloseFactura']['Sujeta'] = {} +# TODO l10n_es no tiene impuesto exento de bienes corrientes +# if tax_line.description in ['S_IVA0']: +# if 'Exenta' not in taxes_sii['DesgloseFactura'][ +# 'Sujeta']: +# taxes_sii['DesgloseFactura']['Sujeta'][ +# 'Exenta'] = {'BaseImponible': line.price_subtotal} +# else: +# taxes_sii['DesgloseFactura']['Sujeta'][ +# 'Exenta']['BaseImponible'] += line.price_subtotal +# TODO Facturas No sujetas + if tax_line.description in [ + 'S_IVA21B', 'S_IVA10B', 'S_IVA4B', 'S_IVA0_ISP']: + if 'NoExenta' not in taxes_sii['DesgloseFactura'][ + 'Sujeta']: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'NoExenta'] = {} + if tax_line.description in ['S_IVA0_ISP']: + TipoNoExenta = 'S2' + else: + TipoNoExenta = 'S1' + taxes_sii['DesgloseFactura']['Sujeta']['NoExenta'][ + 'TipoNoExenta'] = TipoNoExenta + if 'DesgloseIVA' not in taxes_sii[ + 'DesgloseFactura']['Sujeta']['NoExenta']: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'NoExenta']['DesgloseIVA'] = {} + taxes_sii['DesgloseFactura']['Sujeta'][ + 'NoExenta']['DesgloseIVA'][ + 'DetalleIVA'] = [] + tax_type = tax_line.amount * 100 + if tax_type not in taxes_f: + taxes_f[str(tax_type)] = self._get_sii_tax_line( + tax_line, line, line.invoice_line_tax_id, + invoice) + else: + taxes_f = self._update_sii_tax_line( + taxes_f, tax_line, line, + line.invoice_line_tax_id, + invoice) + if tax_line.description in [ + 'S_IVA21S', 'S_IVA10S', 'S_IVA4S', 'S_IVA0']: + if 'DesgloseTipoOperacion' not in taxes_sii: + taxes_sii['DesgloseTipoOperacion'] = {} + if 'PrestacionServicios' not in taxes_sii[ + 'DesgloseTipoOperacion']: + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios'] = {} + if 'Sujeta' not in taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']: + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta'] = {} + if tax_line.description in ['']: + if 'Exenta' not in taxes_sii['DesgloseFactura'][ + 'Sujeta']: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'Exenta'] = { + 'BaseImponible': line.price_subtotal} + else: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'Exenta']['BaeImponible'] += line.price_subtotal +# TODO Facturas no sujetas + if tax_line.description in [ + 'S_IVA21S', 'S_IVA10S', 'S_IVA4S']: + if 'NoExenta' not in taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta']: + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta']['NoExenta'] = {} +# TODO l10n_es_ no tiene impuesto ISP de servicios +# if tax_line.description in ['S_IVA0S_ISP']: +# TipoNoExenta = 'S2' +# else: + TipoNoExenta = 'S1' + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta']['NoExenta'][ + 'TipoNoExenta'] = TipoNoExenta + if 'DesgloseIVA' not in taxes_sii[ + 'DesgloseTipoOperacion']['PrestacionServicios'][ + 'Sujeta']['NoExenta']: + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta']['NoExenta'][ + 'DesgloseIVA'] = {} + taxes_sii['DesgloseTipoOperacion'][ + 'PrestacionServicios']['Sujeta']['NoExenta'][ + 'DesgloseIVA']['DetalleIVA'] = [] + tax_type = tax_line.amount * 100 + if tax_type not in taxes_to: + taxes_to[str(tax_type)] = self._get_sii_tax_line( + tax_line, line, line.invoice_line_tax_id, + invoice) + else: + taxes_to = self._update_sii_tax_line( + taxes_to, tax_line, line, + line.invoice_line_tax_id, + invoice) + + if len(taxes_f) > 0: + for key, line in taxes_f.iteritems(): + taxes_sii['DesgloseFactura']['Sujeta']['NoExenta'][ + 'DesgloseIVA']['DetalleIVA'].append(line) + if len(taxes_to) > 0: + for key, line in taxes_to.iteritems(): + taxes_sii['DesgloseTipoOperacion']['PrestacionServicios'][ + 'Sujeta']['NoExenta']['DesgloseIVA'][ + 'DetalleIVA'].append(line) + + return taxes_sii + + @api.multi + def _get_sii_in_taxes(self, invoice): + taxes_sii = {} + taxes_f = {} + taxes_isp = {} + for line in invoice.invoice_line: + for tax_line in line.invoice_line_tax_id: + if tax_line.description in [ + 'P_IVA21_BC', 'P_IVA21_SC', 'P_IVA21_ISP', 'P_IVA10_BC', + 'P_IVA10_SC', 'P_IVA10_ISP', 'P_IVA4_BC', 'P_IVA4_SC', + 'P_IVA4_ISP', 'P_IVA0_BC', 'P_IVA0_NS']: + if tax_line.description in [ + 'P_IVA21_ISP', 'P_IVA10_ISP', 'P_IVA4_ISP']: + if 'InversionSujetoPasivo' not in taxes_sii: + taxes_sii['InversionSujetoPasivo'] = {} + taxes_sii['InversionSujetoPasivo'][ + 'DetalleIVA'] = [] + tax_type = tax_line.amount * 100 + if tax_type not in taxes_isp: + taxes_isp[str(tax_type)] = self._get_sii_tax_line( + tax_line, line, line.invoice_line_tax_id, + invoice) + else: + taxes_isp = self._update_sii_tax_line( + taxes_isp, tax_line, line, + line.invoice_line_tax_id, + invoice) + else: + if 'DesgloseIVA' not in taxes_sii: + taxes_sii['DesgloseIVA'] = {} + taxes_sii['DesgloseIVA'][ + 'DetalleIVA'] = [] + tax_type = tax_line.amount * 100 + if tax_type not in taxes_f: + taxes_f[str(tax_type)] = self._get_sii_tax_line( + tax_line, line, line.invoice_line_tax_id, + invoice) + else: + taxes_f = self._update_sii_tax_line( + taxes_f, tax_line, line, + line.invoice_line_tax_id, + invoice) + + for key, line in taxes_f.iteritems(): + taxes_sii['DesgloseIVA']['DetalleIVA'].append(line) + for key, line in taxes_isp.iteritems(): + taxes_sii['InversionSujetoPasivo']['DetalleIVA'].append(line) + return taxes_sii + + + @api.multi + def _get_invoices(self, company, invoice): + invoice_date = self._change_date_format(invoice.date_invoice) + Ejercicio = fields.Date.from_string( + invoice.period_id.fiscalyear_id.date_start).year + Periodo = '%02d' % fields.Date.from_string( + invoice.period_id.date_start).month + + if invoice.type in ['out_invoice', 'out_refund']: + TipoFactura = 'F1' +# TODO Los 5 tipos de facturas rectificativas + if invoice.type == 'out_refund': + TipoFactura = 'R4' + TipoDesglose = self._get_sii_out_taxes(invoice) + invoices = { + "IDFactura":{ + "IDEmisorFactura": { + "NIF": company.vat[2:] + }, + "NumSerieFacturaEmisor": invoice.number, + "FechaExpedicionFacturaEmisor": invoice_date}, + "PeriodoImpositivo": { + "Ejercicio": Ejercicio, + "Periodo": Periodo + }, + "FacturaExpedida": { + "TipoFactura": TipoFactura, + "ClaveRegimenEspecialOTrascendencia": "01", + "DescripcionOperacion": invoice.name, + "Contraparte": { + "NombreRazon": invoice.partner_id.name, + "NIF": invoice.partner_id.vat[2:] + }, + "TipoDesglose": TipoDesglose + } + } + if invoice.type == 'out_refund': + invoices['FacturaExpedida'][ + 'TipoRectificativa'] = invoice.refund_type + + if invoice.type in ['in_invoice', 'in_refund']: +# TODO Los 5 tipos de facturas rectificativas + TipoFactura = 'F1' + if invoice.type == 'in_refund': + TipoFactura = 'R4' + DesgloseFactura = self._get_sii_in_taxes(invoice) + invoices = { + "IDFactura":{ + "IDEmisorFactura": { + "NIF": invoice.partner_id.vat[2:] + }, + "NumSerieFacturaEmisor": invoice.supplier_invoice_number, + "FechaExpedicionFacturaEmisor": invoice_date}, + "PeriodoImpositivo": { + "Ejercicio": Ejercicio, + "Periodo": Periodo + }, + "FacturaRecibida": { + "TipoFactura": TipoFactura, + "ClaveRegimenEspecialOTrascendencia": "01", + "DescripcionOperacion": invoice.name, + "DesgloseFactura": DesgloseFactura, + "Contraparte": { + "NombreRazon": invoice.partner_id.name, + "NIF": invoice.partner_id.vat[2:] + }, + "FechaRegContable": invoice_date, + "CuotaDeducible": invoice.amount_tax + } + } + if invoice.type == 'in_refund': + invoices['FacturaRecibida'][ + 'TipoRectificativa'] = invoice.refund_type + + return invoices + + @api.multi + def _connect_sii(self, wsdl): + publicCrt = self.env['ir.config_parameter'].get_param( + 'l10n_es_aeat_sii.publicCrt', False) + privateKey = self.env['ir.config_parameter'].get_param( + 'l10n_es_aeat_sii.privateKey', False) + + session = Session() + session.cert = (publicCrt, privateKey) + transport = Transport(session=session) + + history = HistoryPlugin() + client = Client(wsdl=wsdl,transport=transport,plugins=[history]) + return client + + @api.multi + def _send_invoice_to_sii(self): + for invoice in self: + company = invoice.company_id + port_name = '' + if invoice.type == 'out_invoice': + wsdl = company.wsdl_out + client = self._connect_sii(wsdl) + port_name = 'SuministroFactEmitidas' + if company.sii_test: + port_name += 'Pruebas' + elif invoice.type == 'in_invoice': + wsdl = company.wsdl_in + client = self._connect_sii(wsdl) + port_name = 'SuministroFactRecibidas' + if company.sii_test: + port_name += 'Pruebas' +# TODO Property Investiment +# elif invoice == 'Property Investiment': +# wsdl = company.wsdl_pi +# client = self._connect_sii(wsdl) +# port_name = 'SuministroBienesInversion' +# if company.sii_test: +# port_name += 'Pruebas' + elif invoice.fiscal_position.id == self.env.ref( + 'account.fp_intra').id: + wsdl = company.wsdl_ic + client = self._connect_sii(wsdl) + port_name = 'SuministroOpIntracomunitarias' + if company.sii_test: + port_name += 'Pruebas' + serv = client.bind('siiService', port_name) + if not invoice.sii_sent: + TipoComunicacion = 'A0' + else: + TipoComunicacion = 'A1' + + header = self._get_header(company, TipoComunicacion) + invoices = self._get_invoices(company, invoice) + try: + if invoice.type == 'out_invoice': + res = serv.SuministroLRFacturasEmitidas( + header, invoices) + elif invoice.type == 'in_invoice': + res = serv.SuministroLRFacturasRecibidas( + header, invoices) +# TODO Factura Bienes de inversión +# elif invoice == 'Property Investiment': +# res = serv.SuministroLRBienesInversion( +# header, invoices) +# TODO Facturas intracomunitarias +# elif invoice.fiscal_position.id == self.env.ref( +# 'account.fp_intra').id: +# res = serv.SuministroLRDetOperacionIntracomunitaria( +# header, invoices) + if res['EstadoEnvio'] == 'Correcto': + self.sii_sent = True + self.sii_return = res + except Exception as fault: + self.sii_return = fault + + @api.multi + def invoice_validate(self): + res = super(AccountInvoice, self).invoice_validate() + + if not self.company_id.use_connector: + self._send_invoice_to_sii() +# TODO +# else: +# Use connector + + return res diff --git a/l10n_es_aeat_sii_oca/models/res_company.py b/l10n_es_aeat_sii_oca/models/res_company.py new file mode 100644 index 00000000000..2d39ae5e631 --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/res_company.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import models, fields, api + + +class ResCompany(models.Model): + _inherit = 'res.company' + + @api.onchange('use_connector') + def _check_connector_installed(self): + module = self.env['ir.module'].search( + [('name', '=', 'connector'), ('state', '=', 'installed')]) + if not module: + raise exceptions.Warning( + _('The module "Connector" is not installed. You have ' + 'to install it to activate this option')) + + sii_test = fields.Boolean(string='Test Enviroment') + sii_version = fields.Char(string='SII Version', default='0.6') + use_connector = fields.Boolean( + string='Use connector', + help='Check it to use connector instead to send the invoice ' + 'when it is validated') + wsdl_out = fields.Char( + string='WSDL Invoice Out', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroFactEmitidas.wsdl') + wsdl_in = fields.Char( + string='WSDL Invoice In', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroFactRecibidas.wsdl') + wsdl_pi = fields.Char( + string='WSDL Property Investment', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroBienesInversion.wsdl') + wsdl_ic = fields.Char( + string='WSDL Intra-Community', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroOpIntracomunitarias.wsdl') + wsdl_pr = fields.Char( + string='WSDL Payment Received', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroCobrosEmitidas.wsdl') + wsdl_prm = fields.Char( + string='WSDL Money Payment Received', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroCobrosMetalico.wsdl') + wsdl_ps = fields.Char( + string='WSDL Payment Sent', + default='http://www.agenciatributaria.es/static_files/AEAT/' + 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' + 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' + 'SuministroPagosRecibidas.wsdl') diff --git a/l10n_es_aeat_sii_oca/views/account_invoice_view.xml b/l10n_es_aeat_sii_oca/views/account_invoice_view.xml new file mode 100644 index 00000000000..b0fc509dfeb --- /dev/null +++ b/l10n_es_aeat_sii_oca/views/account_invoice_view.xml @@ -0,0 +1,46 @@ + + + + + + account.invoice.supplier.sii.form + account.invoice + + + + + + + + + + + + + + + + + + account.invoice.sii.form + account.invoice + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/views/res_company_view.xml b/l10n_es_aeat_sii_oca/views/res_company_view.xml new file mode 100644 index 00000000000..063adad6c2d --- /dev/null +++ b/l10n_es_aeat_sii_oca/views/res_company_view.xml @@ -0,0 +1,29 @@ + + + + + + res.company.sii.form + res.company + + + + + + + + + + + + + + + + + + + + + From f661b3998097ce16840efdff1778a74bd9554d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n?= Date: Tue, 21 Mar 2017 17:52:18 +0100 Subject: [PATCH 002/298] l10n_es_aeat_sii: Carga directa del certificado --- l10n_es_aeat_sii_oca/README.rst | 1 + l10n_es_aeat_sii_oca/__init__.py | 2 +- l10n_es_aeat_sii_oca/__openerp__.py | 7 +- l10n_es_aeat_sii_oca/models/__init__.py | 1 + l10n_es_aeat_sii_oca/models/aeat_sii.py | 48 ++++++++++++ l10n_es_aeat_sii_oca/views/aeat_sii_view.xml | 61 +++++++++++++++ l10n_es_aeat_sii_oca/wizard/__init__.py | 5 ++ .../wizard/aeat_sii_password.py | 77 +++++++++++++++++++ .../wizard/aeat_sii_password_view.xml | 23 ++++++ 9 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 l10n_es_aeat_sii_oca/models/aeat_sii.py create mode 100644 l10n_es_aeat_sii_oca/views/aeat_sii_view.xml create mode 100644 l10n_es_aeat_sii_oca/wizard/__init__.py create mode 100644 l10n_es_aeat_sii_oca/wizard/aeat_sii_password.py create mode 100644 l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml diff --git a/l10n_es_aeat_sii_oca/README.rst b/l10n_es_aeat_sii_oca/README.rst index 6529f4c132a..5e5b32f7e16 100644 --- a/l10n_es_aeat_sii_oca/README.rst +++ b/l10n_es_aeat_sii_oca/README.rst @@ -16,6 +16,7 @@ Para instalar esté módulo necesita: #. Libreria Python Zeep, se puede instalar con el comando 'pip install zeep' #. Libreria Python Requests, se puede instalar con el comando 'pip install requests' +#. Libreria pyOpenSSL, versión 0.15 o posterior Configuration ============= diff --git a/l10n_es_aeat_sii_oca/__init__.py b/l10n_es_aeat_sii_oca/__init__.py index 0562ab10129..7db7b96ca63 100644 --- a/l10n_es_aeat_sii_oca/__init__.py +++ b/l10n_es_aeat_sii_oca/__init__.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models -# from . import wizards +from . import wizard # from . import controllers # from . import report # from .hooks import pre_init_hook, post_load, post_init_hook, uninstall_hook diff --git a/l10n_es_aeat_sii_oca/__openerp__.py b/l10n_es_aeat_sii_oca/__openerp__.py index 8e7a01a9d1e..527edab9ad2 100644 --- a/l10n_es_aeat_sii_oca/__openerp__.py +++ b/l10n_es_aeat_sii_oca/__openerp__.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # Copyright 2017 Ignacio Ibeas +# (c) 2017 Diagram Software S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Suministro Inmediato de Información en el IVA", "version": "8.0.1.0.1", "category": "Accounting & Finance", "website": "https://odoo-community.org/", - "author": "Acysos S.L., Odoo Community Association (OCA)", + "author": "Acysos S.L., Odoo Community Association (OCA), Diagram Software S.L.", "license": "AGPL-3", "application": False, "installable": True, @@ -21,6 +22,8 @@ "data": [ "data/ir_config_parameter.xml", "views/res_company_view.xml", - "views/account_invoice_view.xml" + "views/account_invoice_view.xml", + "views/aeat_sii_view.xml", + "wizard/aeat_sii_password_view.xml", ], } diff --git a/l10n_es_aeat_sii_oca/models/__init__.py b/l10n_es_aeat_sii_oca/models/__init__.py index e63f5145d47..dfb29431ebb 100644 --- a/l10n_es_aeat_sii_oca/models/__init__.py +++ b/l10n_es_aeat_sii_oca/models/__init__.py @@ -4,3 +4,4 @@ from . import res_company from . import account_invoice +from . import aeat_sii diff --git a/l10n_es_aeat_sii_oca/models/aeat_sii.py b/l10n_es_aeat_sii_oca/models/aeat_sii.py new file mode 100644 index 00000000000..b5ccda724ed --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/aeat_sii.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# (c) 2017 Diagram Software S.L. +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp import api, models, fields, _ + + +class l10nEsAeatSii(models.Model): + _name = 'l10n.es.aeat.sii' + + name = fields.Char(string="Name") + state = fields.Selection([ + ('draft', 'Draft'), + ('active', 'Active') + ], string="State", default="draft") + file = fields.Binary(string="File", required=True) + folder = fields.Char(string="Folder Name", required=True) + date_start = fields.Date(string="Start Date") + date_end = fields.Date(string="End Date") + public_key = fields.Char(string="Public Key", readonly=True) + private_key = fields.Char(string="Private Key", readonly=True) + + @api.multi + def load_password_wizard(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': _('Insert Password'), + 'res_model': 'l10n.es.aeat.sii.password', + 'view_mode': 'form', + 'view_type': 'form', + 'views': [(False, 'form')], + 'target': 'new', + } + + @api.multi + def action_active(self): + self.ensure_one() + if self.public_key: + sii_crt = self.env.ref('l10n_es_aeat_sii.config_parameter_sii_crt') + sii_crt.value = self.public_key + if self.private_key: + sii_key = self.env.ref('l10n_es_aeat_sii.config_parameter_sii_key') + sii_key.value = self.private_key + other_configs = self.search([('id', '!=', self.id)]) + for config_id in other_configs: + config_id.state = 'draft' + self.state = 'active' diff --git a/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml b/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml new file mode 100644 index 00000000000..c89a822b944 --- /dev/null +++ b/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml @@ -0,0 +1,61 @@ + + + + + l10n.es.aeat.sii.form + l10n.es.aeat.sii + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + l10n.es.aeat.sii.tree + l10n.es.aeat.sii + + + + + + + + + + + + SII + ir.actions.act_window + l10n.es.aeat.sii + form + tree,form + + + + + + +
+
diff --git a/l10n_es_aeat_sii_oca/wizard/__init__.py b/l10n_es_aeat_sii_oca/wizard/__init__.py new file mode 100644 index 00000000000..c03da3b358b --- /dev/null +++ b/l10n_es_aeat_sii_oca/wizard/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2017 Diagram Software S.L. +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import aeat_sii_password diff --git a/l10n_es_aeat_sii_oca/wizard/aeat_sii_password.py b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password.py new file mode 100644 index 00000000000..8c0f79ac754 --- /dev/null +++ b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# (c) 2017 Diagram Software S.L. +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + + +from openerp import _, api, exceptions, fields, models +from openerp.exceptions import ValidationError +from openerp.tools import config +from openerp import release +import contextlib +import OpenSSL.crypto +import os +import tempfile +import base64 +import logging + +_logger = logging.getLogger(__name__) + +if tuple(map(int, OpenSSL.__version__.split('.'))) < (0, 15): + _logger.warning( + 'OpenSSL version is not supported. Upgrade to 0.15 or greater.') + + +@contextlib.contextmanager +def pfx_to_pem(file, pfx_password, directory=None): + with tempfile.NamedTemporaryFile( + prefix='private_', suffix='.pem', delete=False, + dir=directory) as t_pem: + f_pem = open(t_pem.name, 'wb') + p12 = OpenSSL.crypto.load_pkcs12(file, pfx_password) + f_pem.write(OpenSSL.crypto.dump_privatekey( + OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())) + f_pem.close() + yield t_pem.name + + +@contextlib.contextmanager +def pfx_to_crt(file, pfx_password, directory=None): + with tempfile.NamedTemporaryFile( + prefix='public_', suffix='.crt', delete=False, + dir=directory) as t_crt: + f_crt = open(t_crt.name, 'wb') + p12 = OpenSSL.crypto.load_pkcs12(file, pfx_password) + f_crt.write(OpenSSL.crypto.dump_certificate( + OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())) + f_crt.close() + yield t_crt.name + + +class l10nEsAeatSiiPassword(models.TransientModel): + _name = 'l10n.es.aeat.sii.password' + + password = fields.Char(string="Password", required=True) + + @api.multi + def get_keys(self): + record = self.env['l10n.es.aeat.sii'].browse( + self.env.context.get('active_id')) + directory = os.path.join( + os.path.abspath(config['data_dir']), 'certificates', + release.series, self.env.cr.dbname, record.folder) + file = base64.decodestring(record.file) + if tuple(map(int, OpenSSL.__version__.split('.'))) < (0, 15): + raise exceptions.Warning( + _('OpenSSL version is not supported. Upgrade to 0.15 ' + 'or greater.')) + try: + if directory and not os.path.exists(directory): + os.makedirs(directory) + with pfx_to_pem(file, self.password, directory) as private_key: + record.private_key = private_key + with pfx_to_crt(file, self.password, directory) as public_key: + record.public_key = public_key + except Exception as e: + if e.args: + args = list(e.args) + raise ValidationError(args[-1]) diff --git a/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml new file mode 100644 index 00000000000..992d20ab2c2 --- /dev/null +++ b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml @@ -0,0 +1,23 @@ + + + + + + l10n.es.aeat.sii.password.wizard + l10n.es.aeat.sii.password + +
+ + + +
+
+
+
+
+ +
+
From ab436d1efd31ffdd34d1434a327fce8e562b0df6 Mon Sep 17 00:00:00 2001 From: "Ignacio Ibeas - Acysos S.L" Date: Mon, 8 May 2017 09:05:30 +0200 Subject: [PATCH 003/298] =?UTF-8?q?l10n=5Fes=5Faeat=5Fsii:=20se=20a=C3=B1a?= =?UTF-8?q?de=20mapeo=20de=20impuestos,=20traducciones=20y=20permisos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit l10n_es_aeat_sii: añadidas facturas de bienes de inversión e intracomunitarias. Se traspasa la configuración del WSDL a parametros --- l10n_es_aeat_sii_oca/README.rst | 13 +- l10n_es_aeat_sii_oca/__openerp__.py | 13 +- .../data/aeat_sii_map_data.xml | 131 ++++++ ...eat_sii_mapping_registration_keys_data.xml | 151 +++++++ .../data/ir_config_parameter.xml | 42 +- l10n_es_aeat_sii_oca/i18n/es.po | 388 +++++++++++++++++ .../i18n/l10n_es_aeat_sii.pot | 396 ++++++++++++++++++ l10n_es_aeat_sii_oca/models/__init__.py | 2 + .../models/account_invoice.py | 249 +++++++---- l10n_es_aeat_sii_oca/models/aeat_sii_map.py | 61 +++ .../aeat_sii_mapping_registration_keys.py | 44 ++ l10n_es_aeat_sii_oca/models/res_company.py | 47 +-- .../security/ir.model.access.csv | 7 + .../views/account_invoice_view.xml | 7 +- .../views/aeat_sii_map_view.xml | 59 +++ ...eat_sii_mapping_registration_keys_view.xml | 54 +++ .../views/res_company_view.xml | 12 +- 17 files changed, 1521 insertions(+), 155 deletions(-) create mode 100644 l10n_es_aeat_sii_oca/data/aeat_sii_map_data.xml create mode 100644 l10n_es_aeat_sii_oca/data/aeat_sii_mapping_registration_keys_data.xml create mode 100644 l10n_es_aeat_sii_oca/i18n/es.po create mode 100644 l10n_es_aeat_sii_oca/i18n/l10n_es_aeat_sii.pot create mode 100644 l10n_es_aeat_sii_oca/models/aeat_sii_map.py create mode 100644 l10n_es_aeat_sii_oca/models/aeat_sii_mapping_registration_keys.py create mode 100644 l10n_es_aeat_sii_oca/security/ir.model.access.csv create mode 100644 l10n_es_aeat_sii_oca/views/aeat_sii_map_view.xml create mode 100644 l10n_es_aeat_sii_oca/views/aeat_sii_mapping_registration_keys_view.xml diff --git a/l10n_es_aeat_sii_oca/README.rst b/l10n_es_aeat_sii_oca/README.rst index 5e5b32f7e16..3c8b4761d8e 100644 --- a/l10n_es_aeat_sii_oca/README.rst +++ b/l10n_es_aeat_sii_oca/README.rst @@ -54,14 +54,13 @@ de AEAT. Known issues / Roadmap ====================== -* Facturas de bienes de inversión * Comunicación de cobros y pagos -* Determinadas facturas intracomunitarias +* Determinadas facturas intracomunitarias (Articulo 66 RIVA) * Factura simplificada * Facturas No sujetas según el art 7.14 y no sujetas en el TAI -* Asistente para consultar los documentos comunicados -* Carga directa del certificado desde Odoo (PR Enviado) -* Control de longitud y tipo de datos +* Asistente para consultar los documentos comunicados +* Libro de bienes de inversión (Libro anual se crea un módulo aparte) +* Regimenes especial de seguros y agencias de viaje * Usar modulo connector Bug Tracker @@ -83,7 +82,9 @@ Images Contributors ------------ -* Ignacio Ibeas +* Ignacio Ibeas - Acysos S.L. +* Diagram Software S.L. +* Ramon Guiu - Minorisa S.L. Funders ------- diff --git a/l10n_es_aeat_sii_oca/__openerp__.py b/l10n_es_aeat_sii_oca/__openerp__.py index 527edab9ad2..4e1a94ea33c 100644 --- a/l10n_es_aeat_sii_oca/__openerp__.py +++ b/l10n_es_aeat_sii_oca/__openerp__.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- # Copyright 2017 Ignacio Ibeas # (c) 2017 Diagram Software S.L. +# Copyright (c) 2017-TODAY MINORISA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Suministro Inmediato de Información en el IVA", - "version": "8.0.1.0.1", + "version": "8.0.1.0.2", "category": "Accounting & Finance", "website": "https://odoo-community.org/", - "author": "Acysos S.L., Odoo Community Association (OCA), Diagram Software S.L.", + "author": "Acysos S.L., Odoo Community Association (OCA)", "license": "AGPL-3", "application": False, "installable": True, @@ -16,8 +17,7 @@ "requests"], }, "depends": [ - "base", - "account" + "l10n_es_aeat" ], "data": [ "data/ir_config_parameter.xml", @@ -25,5 +25,10 @@ "views/account_invoice_view.xml", "views/aeat_sii_view.xml", "wizard/aeat_sii_password_view.xml", + "views/aeat_sii_mapping_registration_keys_view.xml", + "data/aeat_sii_mapping_registration_keys_data.xml", + "views/aeat_sii_map_view.xml", + "data/aeat_sii_map_data.xml", + "security/ir.model.access.csv" ], } diff --git a/l10n_es_aeat_sii_oca/data/aeat_sii_map_data.xml b/l10n_es_aeat_sii_oca/data/aeat_sii_map_data.xml new file mode 100644 index 00000000000..f7b3a9aaaf2 --- /dev/null +++ b/l10n_es_aeat_sii_oca/data/aeat_sii_map_data.xml @@ -0,0 +1,131 @@ + + + + + SII + + + + SFESB + + + SuministroFactEmitidas Sujetas Bienes + + + + SFESISP + + + SuministroFactEmitidas Sujetas ISP + + + + SFENS + + + SuministroFactEmitidas No Sujeta + + + + SFESS + + + SuministroFactEmitidas Sujetas Servicios + + + + SFESBE + + + SuministroFactEmitidas Bienes Exento + + + + SFESSE + + + SuministroFactEmitidas Servicios Exento + + + + SFRS + + + SuministroFactRecibidas Sujetas + + + + SFRISP + + + SuministroFactRecibidas ISP + + + + SFRBI + + + SuministroFactRecibidas Bienes de Inversión + + + + RE + + + SuministroFact Recargo Equivalencia + + + \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/data/aeat_sii_mapping_registration_keys_data.xml b/l10n_es_aeat_sii_oca/data/aeat_sii_mapping_registration_keys_data.xml new file mode 100644 index 00000000000..61c58acb354 --- /dev/null +++ b/l10n_es_aeat_sii_oca/data/aeat_sii_mapping_registration_keys_data.xml @@ -0,0 +1,151 @@ + + + + + + 01 + Operación de régimen general + sale + + + + 02 + Exportación + sale + + + + 03 + Operaciones a las que se aplique el régimen especial de bienes usados, objetos de arte, antigüedades y objetos de colección (135-139 LIVA) + sale + + + 04 + Régimen especial oro de inversión + sale + + + 05 + Régimen especial agencias de viajes + sale + + + 06 + Régimen especial grupo de entidades en IVA (Nivel Avanzado) + sale + + + 07 + Régimen especial criterio de caja + sale + + + 08 + Operaciones sujetas al IPSI / IGIC + sale + + + 09 + Facturación de las prestaciones de servicios de agencias de viaje que actúan como mediadoras en nombre y por cuenta ajena (D.A.4ª RD1619/2012) + sale + + + + 10 + Cobros por cuenta de terceros de honorarios profesionales o de derechos derivados de la propiedad industrial, de autor u otros por cuenta de sus socios, asociados o colegiados efectuados por sociedades, asociaciones, colegios profesionales u otras entidades que realicen estas funciones de cobro + sale + + + 11 + Operaciones de arrendamiento de local de negocio sujetas a retención + sale + + + 12 + Operaciones de arrendamiento de local de negocio no sujetos a retención + sale + + + 13 + Operaciones de arrendamiento de local de negocio sujetas y no sujetas a retención + sale + + + 14 + Factura con IVA pendiente de devengo (certificaciones de obra cuyo destinatario sea una Administración Pública) + sale + + + 15 + Factura con IVA pendiente de devengo - operaciones de tracto sucesivo + sale + + + 01 + Operación de régimen general + purchase + + + + + 02 + Operaciones por las que los empresarios satisfacen compensaciones REAGYP + purchase + + + 03 + Operaciones a las que se aplique el régimen especial de bienes usados, objetos de arte, antigüedades y objetos de colección (135-139 LIVA) + purchase + + + 04 + Régimen especial oro de inversión + purchase + + + 05 + Régimen especial agencias de viajes + purchase + + + 06 + Régimen especial grupo de entidades en IVA (Nivel Avanzado) + purchase + + + 07 + Régimen especial criterio de caja + purchase + + + 08 + Operaciones sujetas al IPSI / IGIC + purchase + + + 09 + Adquisiciones intracomunitarias de bienes y prestaciones de servicios + purchase + + + 10 + Compra de agencias viajes: operaciones de mediación en nombre y por cuenta ajena en los servicios de transporte prestados al destinatario de los servicios de acuerdo con el apartado 3 de la D.A.4ª RD1619/2012 + purchase + + + 11 + Facturación de las prestaciones de servicios de agencias de viaje que actúan como mediadoras en nombre y por cuenta ajena (D.A.4ª RD1619/2012) + purchase + + + 12 + Operaciones de arrendamiento de local de negocio + purchase + + + 13 + Factura correspondiente a una importación (informada sin asociar a un DUA) + purchase + + + \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml index 56880baf719..270bbfc30ef 100644 --- a/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml +++ b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml @@ -2,7 +2,7 @@ - + l10n_es_aeat_sii.publicCrt /opt/certificates/publicCert.crt @@ -13,5 +13,45 @@ /opt/certificates/privateKey.pem + + l10n_es_aeat_sii.version + 0.7 + + + + l10n_es_aeat_sii.wsdl_out + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactEmitidas.wsdl + + + + l10n_es_aeat_sii.wsdl_in + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactRecibidas.wsdl + + + + l10n_es_aeat_sii.wsdl_pi + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroBienesInversion.wsdl + + + + l10n_es_aeat_sii.wsdl_ic + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroOpIntracomunitarias.wsdl + + + + l10n_es_aeat_sii.wsdl_pr + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroCobrosEmitidas.wsdl + + + + l10n_es_aeat_sii.wsdl_prm + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroCobrosMetalico.wsdl + + + + l10n_es_aeat_sii.wsdl_ps + http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroPagosRecibidas.wsdl + + diff --git a/l10n_es_aeat_sii_oca/i18n/es.po b/l10n_es_aeat_sii_oca/i18n/es.po new file mode 100644 index 00000000000..701cce49f3c --- /dev/null +++ b/l10n_es_aeat_sii_oca/i18n/es.po @@ -0,0 +1,388 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_aeat_sii +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-29 07:08+0000\n" +"PO-Revision-Date: 2017-05-29 09:11+0200\n" +"Last-Translator: Ignacio Ibeas - Acysos S.L. \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"Language: es\n" +"X-Generator: Poedit 1.8.7.1\n" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "AEAT" +msgstr "AEAT" + +#. module: l10n_es_aeat_sii +#: view:res.company:l10n_es_aeat_sii.view_company_sii_form +msgid "AEAT SII Configuration" +msgstr "Configuración AEAT SII" + +#. module: l10n_es_aeat_sii +#: selection:l10n.es.aeat.sii,state:0 +msgid "Active" +msgstr "Activo" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_mapping_registration_keys +#: model:ir.model,name:l10n_es_aeat_sii.model_l10n_es_aeat_sii_mapping_registration_keys +msgid "Aeat SII Invoice Registration Keys" +msgstr "AEAT SII Claves de Identificación Operaciones" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_form +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_tree +#: view:aeat.sii.map.lines:l10n_es_aeat_sii.l10n_es_aeat_sii_map_lines_view_tree +#: field:aeat.sii.map.lines,sii_map_id:0 +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.action_aeat_sii_mapping +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_map +#: model:ir.ui.menu,name:l10n_es_aeat_sii.menu_aeat_sii_map +msgid "Aeat SII Map" +msgstr "SII - Mapeo de impuestos" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_map_lines +msgid "Aeat SII Map Lines" +msgstr "SII - Lineas de mapeo" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_tree +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.action_aeat_sii_mapping_registration_keys +#: model:ir.ui.menu,name:l10n_es_aeat_sii.menu_aeat_sii_mapping_registration_keys +msgid "Aeat SII Registration Keys" +msgstr "Aeat SII Tabla de claves: régimen especial/identificación operaciones con transedencia tributaria" + +#. module: l10n_es_aeat_sii +#: selection:account.invoice,refund_type:0 +msgid "By differences" +msgstr "Por diferencias" + +#. module: l10n_es_aeat_sii +#: selection:account.invoice,refund_type:0 +msgid "By substitution" +msgstr "Por sustitución" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "Cancel" +msgstr "Cancelar" + +#. module: l10n_es_aeat_sii +#: field:res.company,chart_template_id:0 +msgid "Chart Template" +msgstr "Plantilla de cuentas" + +#. module: l10n_es_aeat_sii +#: help:res.company,use_connector:0 +msgid "Check it to use connector instead to send the invoice when it is validated" +msgstr "Activar si se va usar el módulo connector en vez de enviar la factura cuando el validada" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,code:0 +#: field:aeat.sii.mapping.registration.keys,code:0 +msgid "Code" +msgstr "Código" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_res_company +msgid "Companies" +msgstr "Compañías" + +#. module: l10n_es_aeat_sii +#: view:res.company:l10n_es_aeat_sii.view_company_sii_form +msgid "Configuration" +msgstr "Configuración" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,create_uid:0 field:aeat.sii.map.lines,create_uid:0 +#: field:aeat.sii.mapping.registration.keys,create_uid:0 +#: field:l10n.es.aeat.sii,create_uid:0 +#: field:l10n.es.aeat.sii.password,create_uid:0 +msgid "Created by" +msgstr "Creado por" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,create_date:0 field:aeat.sii.map.lines,create_date:0 +#: field:aeat.sii.mapping.registration.keys,create_date:0 +#: field:l10n.es.aeat.sii,create_date:0 +#: field:l10n.es.aeat.sii.password,create_date:0 +msgid "Created on" +msgstr "Creado en" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,date_from:0 +msgid "Date from" +msgstr "Fecha desde" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,date_to:0 +msgid "Date to" +msgstr "Fecha hasta" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,display_name:0 field:aeat.sii.map.lines,display_name:0 +#: field:aeat.sii.mapping.registration.keys,display_name:0 +#: field:l10n.es.aeat.sii,display_name:0 +#: field:l10n.es.aeat.sii.password,display_name:0 +msgid "Display Name" +msgstr "Nombre" + +#. module: l10n_es_aeat_sii +#: selection:l10n.es.aeat.sii,state:0 +msgid "Draft" +msgstr "Borrador" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_enabled:0 field:res.company,sii_enabled:0 +msgid "Enable SII" +msgstr "Activar SII" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,date_end:0 +msgid "End Date" +msgstr "Fecha hasta" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/aeat_sii_map.py:38 +#, python-format +msgid "Error! The dates of the record overlap with an existing record." +msgstr "Error! Las fecha del registro se superponen con otro registro" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,file:0 +msgid "File" +msgstr "Fichero" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,folder:0 +msgid "Folder Name" +msgstr "Nombre Carpeta" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +msgid "Group By..." +msgstr "Agrupar por..." + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,id:0 field:aeat.sii.map.lines,id:0 +#: field:aeat.sii.mapping.registration.keys,id:0 field:l10n.es.aeat.sii,id:0 +#: field:l10n.es.aeat.sii.password,id:0 +msgid "ID" +msgstr "ID" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/aeat_sii.py:28 +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +#, python-format +msgid "Insert Password" +msgstr "Introduzca contraseña" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_account_invoice +msgid "Invoice" +msgstr "Factura" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,__last_update:0 field:aeat.sii.map.lines,__last_update:0 +#: field:aeat.sii.mapping.registration.keys,__last_update:0 +#: field:l10n.es.aeat.sii,__last_update:0 +#: field:l10n.es.aeat.sii.password,__last_update:0 +msgid "Last Modified on" +msgstr "Últ. modificación en" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,write_uid:0 field:aeat.sii.map.lines,write_uid:0 +#: field:aeat.sii.mapping.registration.keys,write_uid:0 +#: field:l10n.es.aeat.sii,write_uid:0 +#: field:l10n.es.aeat.sii.password,write_uid:0 +msgid "Last Updated by" +msgstr "Últ. actualización por" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,write_date:0 field:aeat.sii.map.lines,write_date:0 +#: field:aeat.sii.mapping.registration.keys,write_date:0 +#: field:l10n.es.aeat.sii,write_date:0 +#: field:l10n.es.aeat.sii.password,write_date:0 +msgid "Last Updated on" +msgstr "Últ. actualización en" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,map_lines:0 +msgid "Lines" +msgstr "Líneas" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +msgid "Load Certificate" +msgstr "Cargar Certificado" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_form +msgid "Mapping Lines" +msgstr "Líneas del mapeo" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,name:0 +msgid "Model" +msgstr "Modelo" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,name:0 +#: field:aeat.sii.mapping.registration.keys,name:0 +#: field:l10n.es.aeat.sii,name:0 +msgid "Name" +msgstr "Nombre" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "Obtain Keys" +msgstr "Obtener Claves" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/wizard/aeat_sii_password.py:65 +#, python-format +msgid "OpenSSL version is not supported. Upgrade to 0.15 or greater." +msgstr "Versión de OpenSSL no soportada. Actualice a la 0.15 o superior." + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii.password,password:0 +msgid "Password" +msgstr "Contraseña" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,private_key:0 +msgid "Private Key" +msgstr "Clave privada" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,public_key:0 +msgid "Public Key" +msgstr "Clave pública" + +#. module: l10n_es_aeat_sii +#: selection:aeat.sii.mapping.registration.keys,type:0 +msgid "Purchase" +msgstr "Compras" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,refund_type:0 +msgid "Refund Type" +msgstr "Tipo rectificativa" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,registration_key:0 +msgid "Registration key" +msgstr "Clave del registro" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.l10n_es_sii_action +#: model:ir.ui.menu,name:l10n_es_aeat_sii.l10n_es_aeat_sii_parent_menu +msgid "SII" +msgstr "SII" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_csv:0 +msgid "SII CSV" +msgstr "SII CSV" + +#. module: l10n_es_aeat_sii +#: model:ir.ui.menu,name:l10n_es_aeat_sii.l10n_es_aeat_sii_menu +msgid "SII Certificate" +msgstr "Certificado SII" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_description:0 +msgid "SII Description" +msgstr "Descripción SII" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "SII Information" +msgstr "Información SII" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "SII Result" +msgstr "Resultado SII" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_return:0 +msgid "SII Return" +msgstr "Respuesta SII" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_sent:0 +msgid "SII Sent" +msgstr "Enviado" + +#. module: l10n_es_aeat_sii +#: selection:aeat.sii.mapping.registration.keys,type:0 +msgid "Sale" +msgstr "Ventas" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,date_start:0 +msgid "Start Date" +msgstr "Fecha de inicio" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,state:0 +msgid "State" +msgstr "Estado" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,taxes:0 +msgid "Taxes" +msgstr "Impuestos" + +#. module: l10n_es_aeat_sii +#: field:res.company,sii_test:0 +msgid "Test Enviroment" +msgstr "Entorno de pruebas" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/res_company.py:17 +#, python-format +msgid "The module \"Connector\" is not installed. You have to install it to activate this option" +msgstr "El módulo \"Connector\" no esta instalado. Tiene que instalarlo para activar esta opción." + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +msgid "To Active" +msgstr "Activar" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +#: field:aeat.sii.mapping.registration.keys,type:0 +msgid "Type" +msgstr "Tipo" + +#. module: l10n_es_aeat_sii +#: field:res.company,use_connector:0 +msgid "Use connector" +msgstr "Usar conector" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/account_invoice.py:359 +#, python-format +msgid "You have to select what account chart template use this company." +msgstr "Debe seleccionar que plan contable utiliza esta compañía" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "or" +msgstr "o" diff --git a/l10n_es_aeat_sii_oca/i18n/l10n_es_aeat_sii.pot b/l10n_es_aeat_sii_oca/i18n/l10n_es_aeat_sii.pot new file mode 100644 index 00000000000..17663e66745 --- /dev/null +++ b/l10n_es_aeat_sii_oca/i18n/l10n_es_aeat_sii.pot @@ -0,0 +1,396 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_aeat_sii +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-29 07:07+0000\n" +"PO-Revision-Date: 2017-05-29 07:07+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "AEAT" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:res.company:l10n_es_aeat_sii.view_company_sii_form +msgid "AEAT SII Configuration" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:l10n.es.aeat.sii,state:0 +msgid "Active" +msgstr "" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_mapping_registration_keys +#: model:ir.model,name:l10n_es_aeat_sii.model_l10n_es_aeat_sii_mapping_registration_keys +msgid "Aeat SII Invoice Registration Keys" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_form +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_tree +#: view:aeat.sii.map.lines:l10n_es_aeat_sii.l10n_es_aeat_sii_map_lines_view_tree +#: field:aeat.sii.map.lines,sii_map_id:0 +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.action_aeat_sii_mapping +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_map +#: model:ir.ui.menu,name:l10n_es_aeat_sii.menu_aeat_sii_map +msgid "Aeat SII Map" +msgstr "" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_aeat_sii_map_lines +msgid "Aeat SII Map Lines" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_tree +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.action_aeat_sii_mapping_registration_keys +#: model:ir.ui.menu,name:l10n_es_aeat_sii.menu_aeat_sii_mapping_registration_keys +msgid "Aeat SII Registration Keys" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:account.invoice,refund_type:0 +msgid "By differences" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:account.invoice,refund_type:0 +msgid "By substitution" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "Cancel" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:res.company,chart_template_id:0 +msgid "Chart Template" +msgstr "" + +#. module: l10n_es_aeat_sii +#: help:res.company,use_connector:0 +msgid "Check it to use connector instead to send the invoice when it is validated" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,code:0 +#: field:aeat.sii.mapping.registration.keys,code:0 +msgid "Code" +msgstr "" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_res_company +msgid "Companies" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:res.company:l10n_es_aeat_sii.view_company_sii_form +msgid "Configuration" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,create_uid:0 +#: field:aeat.sii.map.lines,create_uid:0 +#: field:aeat.sii.mapping.registration.keys,create_uid:0 +#: field:l10n.es.aeat.sii,create_uid:0 +#: field:l10n.es.aeat.sii.password,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,create_date:0 +#: field:aeat.sii.map.lines,create_date:0 +#: field:aeat.sii.mapping.registration.keys,create_date:0 +#: field:l10n.es.aeat.sii,create_date:0 +#: field:l10n.es.aeat.sii.password,create_date:0 +msgid "Created on" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,date_from:0 +msgid "Date from" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,date_to:0 +msgid "Date to" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,display_name:0 +#: field:aeat.sii.map.lines,display_name:0 +#: field:aeat.sii.mapping.registration.keys,display_name:0 +#: field:l10n.es.aeat.sii,display_name:0 +#: field:l10n.es.aeat.sii.password,display_name:0 +msgid "Display Name" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:l10n.es.aeat.sii,state:0 +msgid "Draft" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_enabled:0 +#: field:res.company,sii_enabled:0 +msgid "Enable SII" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,date_end:0 +msgid "End Date" +msgstr "" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/aeat_sii_map.py:38 +#, python-format +msgid "Error! The dates of the record overlap with an existing record." +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,file:0 +msgid "File" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,folder:0 +msgid "Folder Name" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +msgid "Group By..." +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,id:0 +#: field:aeat.sii.map.lines,id:0 +#: field:aeat.sii.mapping.registration.keys,id:0 +#: field:l10n.es.aeat.sii,id:0 +#: field:l10n.es.aeat.sii.password,id:0 +msgid "ID" +msgstr "" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/aeat_sii.py:28 +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +#, python-format +msgid "Insert Password" +msgstr "" + +#. module: l10n_es_aeat_sii +#: model:ir.model,name:l10n_es_aeat_sii.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,__last_update:0 +#: field:aeat.sii.map.lines,__last_update:0 +#: field:aeat.sii.mapping.registration.keys,__last_update:0 +#: field:l10n.es.aeat.sii,__last_update:0 +#: field:l10n.es.aeat.sii.password,__last_update:0 +msgid "Last Modified on" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,write_uid:0 +#: field:aeat.sii.map.lines,write_uid:0 +#: field:aeat.sii.mapping.registration.keys,write_uid:0 +#: field:l10n.es.aeat.sii,write_uid:0 +#: field:l10n.es.aeat.sii.password,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,write_date:0 +#: field:aeat.sii.map.lines,write_date:0 +#: field:aeat.sii.mapping.registration.keys,write_date:0 +#: field:l10n.es.aeat.sii,write_date:0 +#: field:l10n.es.aeat.sii.password,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,map_lines:0 +msgid "Lines" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +msgid "Load Certificate" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.map:l10n_es_aeat_sii.aeat_sii_map_view_form +msgid "Mapping Lines" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map,name:0 +msgid "Model" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,name:0 +#: field:aeat.sii.mapping.registration.keys,name:0 +#: field:l10n.es.aeat.sii,name:0 +msgid "Name" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "Obtain Keys" +msgstr "" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/wizard/aeat_sii_password.py:65 +#, python-format +msgid "OpenSSL version is not supported. Upgrade to 0.15 or greater." +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii.password,password:0 +msgid "Password" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,private_key:0 +msgid "Private Key" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,public_key:0 +msgid "Public Key" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:aeat.sii.mapping.registration.keys,type:0 +msgid "Purchase" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,refund_type:0 +msgid "Refund Type" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,registration_key:0 +msgid "Registration key" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: model:ir.actions.act_window,name:l10n_es_aeat_sii.l10n_es_sii_action +#: model:ir.ui.menu,name:l10n_es_aeat_sii.l10n_es_aeat_sii_parent_menu +msgid "SII" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_csv:0 +msgid "SII CSV" +msgstr "" + +#. module: l10n_es_aeat_sii +#: model:ir.ui.menu,name:l10n_es_aeat_sii.l10n_es_aeat_sii_menu +msgid "SII Certificate" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_description:0 +msgid "SII Description" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "SII Information" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:account.invoice:l10n_es_aeat_sii.invoice_sii_form +#: view:account.invoice:l10n_es_aeat_sii.invoice_supplier_sii_form +msgid "SII Result" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_return:0 +msgid "SII Return" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:account.invoice,sii_sent:0 +msgid "SII Sent" +msgstr "" + +#. module: l10n_es_aeat_sii +#: selection:aeat.sii.mapping.registration.keys,type:0 +msgid "Sale" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,date_start:0 +msgid "Start Date" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:l10n.es.aeat.sii,state:0 +msgid "State" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:aeat.sii.map.lines,taxes:0 +msgid "Taxes" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:res.company,sii_test:0 +msgid "Test Enviroment" +msgstr "" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/res_company.py:17 +#, python-format +msgid "The module \"Connector\" is not installed. You have to install it to activate this option" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii:l10n_es_aeat_sii.l10n_es_sii_form_view +msgid "To Active" +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:aeat.sii.mapping.registration.keys:l10n_es_aeat_sii.aeat_sii_mapping_registration_keys_view_search +#: field:aeat.sii.mapping.registration.keys,type:0 +msgid "Type" +msgstr "" + +#. module: l10n_es_aeat_sii +#: field:res.company,use_connector:0 +msgid "Use connector" +msgstr "" + +#. module: l10n_es_aeat_sii +#: code:addons/l10n_es_aeat_sii/models/account_invoice.py:359 +#, python-format +msgid "You have to select what account chart template use this company." +msgstr "" + +#. module: l10n_es_aeat_sii +#: view:l10n.es.aeat.sii.password:l10n_es_aeat_sii.l10n_es_sii_password_wizard_view +msgid "or" +msgstr "" + diff --git a/l10n_es_aeat_sii_oca/models/__init__.py b/l10n_es_aeat_sii_oca/models/__init__.py index dfb29431ebb..254fcbbfe8a 100644 --- a/l10n_es_aeat_sii_oca/models/__init__.py +++ b/l10n_es_aeat_sii_oca/models/__init__.py @@ -5,3 +5,5 @@ from . import res_company from . import account_invoice from . import aeat_sii +from . import aeat_sii_mapping_registration_keys +from . import aeat_sii_map \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/models/account_invoice.py b/l10n_es_aeat_sii_oca/models/account_invoice.py index 53902200541..358fb1d9ab5 100644 --- a/l10n_es_aeat_sii_oca/models/account_invoice.py +++ b/l10n_es_aeat_sii_oca/models/account_invoice.py @@ -2,23 +2,90 @@ # Copyright 2017 Ignacio Ibeas # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api +from openerp import models, fields, api, _ from requests import Session from zeep import Client from zeep.transports import Transport from zeep.plugins import HistoryPlugin from datetime import datetime +from openerp.exceptions import Warning class AccountInvoice(models.Model): _inherit = 'account.invoice' - - sii_sent = fields.Boolean('SII Sent') - sii_return = fields.Text('SII Return') + + def _get_default_key(self): + sii_key_obj = self.env['aeat.sii.mapping.registration.keys'] + type = self._context.get('type') + if type in ['in_invoice', 'in_refund']: + key = sii_key_obj.search( + [('code', '=', '01'), ('type', '=', 'purchase')], limit=1) + else: + key = sii_key_obj.search( + [('code', '=', '01'), ('type', '=', 'sale')], limit=1) + return key + + sii_description = fields.Text(string='SII Description') + sii_sent = fields.Boolean(string='SII Sent') + sii_csv = fields.Char(string='SII CSV') + sii_return = fields.Text(string='SII Return') refund_type = fields.Selection( selection=[('S', 'By substitution'), ('I', 'By differences')], string="Refund Type") - + registration_key = fields.Many2one( + comodel_name='aeat.sii.mapping.registration.keys', + string="Registration key", required=True, default=_get_default_key) + sii_enabled = fields.Boolean(string='Enable SII', + related='company_id.sii_enabled') + + @api.multi + def map_tax_template(self, tax_template, mapping_taxes): + # Adapted from account_chart_update module + """Adds a tax template -> tax id to the mapping.""" + if not tax_template: + return self.env['account.tax'] + if mapping_taxes.get(tax_template): + return mapping_taxes[tax_template] + # search inactive taxes too, to avoid re-creating + # taxes that have been deactivated before + tax_obj = self.env['account.tax'].with_context(active_test=False) + criteria = ['|', + ('name', '=', tax_template.name), + ('description', '=', tax_template.name)] + if tax_template.description: + criteria = ['|', '|'] + criteria + criteria += [('description', '=', tax_template.description), + ('name', '=', tax_template.description)] + criteria += [('company_id', '=', self.company_id.id)] + taxes = tax_obj.search(criteria) + mapping_taxes[tax_template] = ( + taxes and taxes[0] or self.env['account.tax']) + return mapping_taxes[tax_template] + + @api.multi + def _get_taxes_map(self, codes, date): + # Return the codes that correspond to that sii map line codes + taxes = [] + sii_map_obj = self.env['aeat.sii.map'] + sii_map_line_obj = self.env['aeat.sii.map.lines'] + sii_map = sii_map_obj.search( + ['|', + ('date_from', '<=', date), + ('date_from', '=', False), + '|', + ('date_to', '>=', date), + ('date_to', '=', False)], limit=1) + mapping_taxes = {} + for code in codes: + tax_templates = sii_map_line_obj.search( + [('code', '=', code), ('sii_map_id', '=', sii_map.id)], + limit=1).taxes + for tax_template in tax_templates: + tax = self.map_tax_template(tax_template, mapping_taxes) + if tax: + taxes.append(tax) + return taxes + @api.multi def _change_date_format(self, date): datetimeobject = datetime.strptime(date,'%Y-%m-%d') @@ -27,10 +94,12 @@ def _change_date_format(self, date): @api.multi def _get_header(self, company, TipoComunicacion): + IDVersionSii = self.env['ir.config_parameter'].get_param( + 'l10n_es_aeat_sii.version', False) header = { - "IDVersionSii": company.sii_version, + "IDVersionSii": IDVersionSii, "Titular": { - "NombreRazon": company.name, + "NombreRazon": company.name[0:120], "NIF": company.vat[2:]}, "TipoComunicacion": TipoComunicacion } @@ -39,12 +108,11 @@ def _get_header(self, company, TipoComunicacion): @api.multi def _get_tax_line_req(self, tax_type, line, line_taxes): taxes = False + taxes_RE = self._get_taxes_map( + ['RE'], line.invoice_id.date_invoice) if len(line_taxes) > 1: - req_ids = line_taxes.search([('description', 'in', [ - 'P_REQ5.2', 'S_REQ52', 'P_REQ14', 'S_REQ14', 'P_REQ05', - 'S_REQ05'])]) for tax in line_taxes: - if tax in req_ids: + if tax in taxes_RE: price = line.price_unit * (1 - ( line.discount or 0.0) / 100.0) taxes = tax.compute_all( @@ -61,18 +129,16 @@ def _get_sii_tax_line(self, tax_line, line, line_taxes, invoice): taxes = tax_line.compute_all( (line.price_unit * (1 - (line.discount or 0.0) / 100.0)), line.quantity, line.product_id, line.invoice_id.partner_id) - if tax_line_req: - TipoRecargo = tax_line_req['percentage'] * 100 - CuotaRecargo = tax_line_req['taxes'][0]['amount'] - else: - TipoRecargo = 0 - CuotaRecargo = 0 tax_sii = { "TipoImpositivo":tax_type, - "BaseImponible":taxes['total'], - "TipoRecargoEquivalencia":TipoRecargo, - "CuotaRecargoEquivalencia":CuotaRecargo + "BaseImponible":taxes['total'] } + if tax_line_req: + TipoRecargo = tax_line_req['percentage'] * 100 + CuotaRecargo = tax_line_req['taxes'][0]['amount'] + tax_sii['TipoRecargoEquivalencia'] = TipoRecargo + tax_sii['CuotaRecargoEquivalencia'] = CuotaRecargo + if invoice.type in ['out_invoice', 'out_refund']: tax_sii['CuotaRepercutida'] = taxes['taxes'][0]['amount'] if invoice.type in ['in_invoice', 'in_refund']: @@ -89,12 +155,10 @@ def _update_sii_tax_line(self, taxes, tax_line, line, line_taxes, invoice): if tax_line_req: TipoRecargo = tax_line_req['percentage'] * 100 CuotaRecargo = tax_line_req['taxes'][0]['amount'] - else: - TipoRecargoEquivalencia = 0 - CuotaRecargoEquivalencia = 0 + taxes[str(tax_type)]['TipoRecargoEquivalencia'] += TipoRecargo + taxes[str(tax_type)]['CuotaRecargoEquivalencia'] += CuotaRecargo + taxes[str(tax_type)]['BaseImponible'] += taxes['total'] - taxes[str(tax_type)]['TipoRecargoEquivalencia'] += TipoRecargo - taxes[str(tax_type)]['CuotaRecargoEquivalencia'] += CuotaRecargo if invoice.type in ['out_invoice', 'out_refund']: tax_sii['CuotaRepercutida'] += taxes['taxes'][0]['amount'] if invoice.type in ['in_invoice', 'in_refund']: @@ -106,34 +170,46 @@ def _get_sii_out_taxes(self, invoice): taxes_sii = {} taxes_f = {} taxes_to = {} + taxes_SFESB = self._get_taxes_map( + ['SFESB'], invoice.date_invoice) + taxes_SFESBE = self._get_taxes_map( + ['SFESBE'], invoice.date_invoice) + taxes_SFESISP = self._get_taxes_map( + ['SFESISP'], invoice.date_invoice) +# taxes_SFESISPS = self._get_taxes_map( +# ['SFESISPS'], invoice.date_invoice) + taxes_SFENS = self._get_taxes_map( + ['SFENS'], invoice.date_invoice) + taxes_SFESS = self._get_taxes_map( + ['SFESS'], invoice.date_invoice) + taxes_SFESSE = self._get_taxes_map( + ['SFESSE'], invoice.date_invoice) for line in invoice.invoice_line: for tax_line in line.invoice_line_tax_id: - if tax_line.description in [ - 'S_IVA21B', 'S_IVA10B', 'S_IVA4B', 'S_IVA0_ISP', - 'S_IVA_NS']: + if (tax_line in taxes_SFESB or tax_line in taxes_SFESISP or + tax_line in taxes_SFENS): if 'DesgloseFactura' not in taxes_sii: taxes_sii['DesgloseFactura'] = {} - if tax_line.description in [ - 'S_IVA21B', 'S_IVA10B', 'S_IVA4B']: + if tax_line in taxes_SFESB: if 'Sujeta' not in taxes_sii['DesgloseFactura']: taxes_sii['DesgloseFactura']['Sujeta'] = {} -# TODO l10n_es no tiene impuesto exento de bienes corrientes -# if tax_line.description in ['S_IVA0']: -# if 'Exenta' not in taxes_sii['DesgloseFactura'][ -# 'Sujeta']: -# taxes_sii['DesgloseFactura']['Sujeta'][ -# 'Exenta'] = {'BaseImponible': line.price_subtotal} -# else: -# taxes_sii['DesgloseFactura']['Sujeta'][ -# 'Exenta']['BaseImponible'] += line.price_subtotal -# TODO Facturas No sujetas - if tax_line.description in [ - 'S_IVA21B', 'S_IVA10B', 'S_IVA4B', 'S_IVA0_ISP']: +# TODO l10n_es no tiene impuesto exento de bienes corrientes +# nacionales + if tax_line in taxes_SFESBE: + if 'Exenta' not in taxes_sii['DesgloseFactura'][ + 'Sujeta']: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'Exenta'] = {'BaseImponible': line.price_subtotal} + else: + taxes_sii['DesgloseFactura']['Sujeta'][ + 'Exenta']['BaseImponible'] += line.price_subtotal +# TODO Facturas No sujetas + if tax_line in taxes_SFESB or tax_line in taxes_SFESISP: if 'NoExenta' not in taxes_sii['DesgloseFactura'][ 'Sujeta']: taxes_sii['DesgloseFactura']['Sujeta'][ 'NoExenta'] = {} - if tax_line.description in ['S_IVA0_ISP']: + if tax_line in taxes_SFESISP: TipoNoExenta = 'S2' else: TipoNoExenta = 'S1' @@ -156,8 +232,7 @@ def _get_sii_out_taxes(self, invoice): taxes_f, tax_line, line, line.invoice_line_tax_id, invoice) - if tax_line.description in [ - 'S_IVA21S', 'S_IVA10S', 'S_IVA4S', 'S_IVA0']: + if tax_line in taxes_SFESS or tax_line in taxes_SFESSE: if 'DesgloseTipoOperacion' not in taxes_sii: taxes_sii['DesgloseTipoOperacion'] = {} if 'PrestacionServicios' not in taxes_sii[ @@ -168,7 +243,7 @@ def _get_sii_out_taxes(self, invoice): 'PrestacionServicios']: taxes_sii['DesgloseTipoOperacion'][ 'PrestacionServicios']['Sujeta'] = {} - if tax_line.description in ['']: + if tax_line in taxes_SFESSE: if 'Exenta' not in taxes_sii['DesgloseFactura'][ 'Sujeta']: taxes_sii['DesgloseFactura']['Sujeta'][ @@ -178,14 +253,13 @@ def _get_sii_out_taxes(self, invoice): taxes_sii['DesgloseFactura']['Sujeta'][ 'Exenta']['BaeImponible'] += line.price_subtotal # TODO Facturas no sujetas - if tax_line.description in [ - 'S_IVA21S', 'S_IVA10S', 'S_IVA4S']: + if tax_line in taxes_SFESS: if 'NoExenta' not in taxes_sii['DesgloseTipoOperacion'][ 'PrestacionServicios']['Sujeta']: taxes_sii['DesgloseTipoOperacion'][ 'PrestacionServicios']['Sujeta']['NoExenta'] = {} # TODO l10n_es_ no tiene impuesto ISP de servicios -# if tax_line.description in ['S_IVA0S_ISP']: +# if tax_line in taxes_SFESISPS: # TipoNoExenta = 'S2' # else: TipoNoExenta = 'S1' @@ -229,14 +303,14 @@ def _get_sii_in_taxes(self, invoice): taxes_sii = {} taxes_f = {} taxes_isp = {} + taxes_SFRS = self._get_taxes_map( + ['SFRS'], invoice.date_invoice) + taxes_SFRISP = self._get_taxes_map( + ['SFRISP'], invoice.date_invoice) for line in invoice.invoice_line: for tax_line in line.invoice_line_tax_id: - if tax_line.description in [ - 'P_IVA21_BC', 'P_IVA21_SC', 'P_IVA21_ISP', 'P_IVA10_BC', - 'P_IVA10_SC', 'P_IVA10_ISP', 'P_IVA4_BC', 'P_IVA4_SC', - 'P_IVA4_ISP', 'P_IVA0_BC', 'P_IVA0_NS']: - if tax_line.description in [ - 'P_IVA21_ISP', 'P_IVA10_ISP', 'P_IVA4_ISP']: + if tax_line in taxes_SFRS or tax_line in taxes_SFRISP: + if tax_line in taxes_SFRISP: if 'InversionSujetoPasivo' not in taxes_sii: taxes_sii['InversionSujetoPasivo'] = {} taxes_sii['InversionSujetoPasivo'][ @@ -281,19 +355,23 @@ def _get_invoices(self, company, invoice): invoice.period_id.fiscalyear_id.date_start).year Periodo = '%02d' % fields.Date.from_string( invoice.period_id.date_start).month - + if not company.chart_template_id: + raise Warning(_( + 'You have to select what account chart template use this' + ' company.')) if invoice.type in ['out_invoice', 'out_refund']: TipoFactura = 'F1' # TODO Los 5 tipos de facturas rectificativas if invoice.type == 'out_refund': TipoFactura = 'R4' TipoDesglose = self._get_sii_out_taxes(invoice) + key = invoice.registration_key.code invoices = { "IDFactura":{ "IDEmisorFactura": { "NIF": company.vat[2:] }, - "NumSerieFacturaEmisor": invoice.number, + "NumSerieFacturaEmisor": invoice.number[0:60], "FechaExpedicionFacturaEmisor": invoice_date}, "PeriodoImpositivo": { "Ejercicio": Ejercicio, @@ -301,10 +379,10 @@ def _get_invoices(self, company, invoice): }, "FacturaExpedida": { "TipoFactura": TipoFactura, - "ClaveRegimenEspecialOTrascendencia": "01", + "ClaveRegimenEspecialOTrascendencia": key, "DescripcionOperacion": invoice.name, "Contraparte": { - "NombreRazon": invoice.partner_id.name, + "NombreRazon": invoice.partner_id.name[0:120], "NIF": invoice.partner_id.vat[2:] }, "TipoDesglose": TipoDesglose @@ -325,7 +403,8 @@ def _get_invoices(self, company, invoice): "IDEmisorFactura": { "NIF": invoice.partner_id.vat[2:] }, - "NumSerieFacturaEmisor": invoice.supplier_invoice_number, + "NumSerieFacturaEmisor": invoice.supplier_invoice_number[ + 0:60], "FechaExpedicionFacturaEmisor": invoice_date}, "PeriodoImpositivo": { "Ejercicio": Ejercicio, @@ -334,10 +413,10 @@ def _get_invoices(self, company, invoice): "FacturaRecibida": { "TipoFactura": TipoFactura, "ClaveRegimenEspecialOTrascendencia": "01", - "DescripcionOperacion": invoice.name, + "DescripcionOperacion": invoice.sii_description[0:500], "DesgloseFactura": DesgloseFactura, "Contraparte": { - "NombreRazon": invoice.partner_id.name, + "NombreRazon": invoice.partner_id.name[0:120], "NIF": invoice.partner_id.vat[2:] }, "FechaRegContable": invoice_date, @@ -371,31 +450,19 @@ def _send_invoice_to_sii(self): company = invoice.company_id port_name = '' if invoice.type == 'out_invoice': - wsdl = company.wsdl_out + wsdl = self.env['ir.config_parameter'].get_param( + 'l10n_es_aeat_sii.wsdl_out', False) client = self._connect_sii(wsdl) port_name = 'SuministroFactEmitidas' if company.sii_test: port_name += 'Pruebas' elif invoice.type == 'in_invoice': - wsdl = company.wsdl_in + wsdl = self.env['ir.config_parameter'].get_param( + 'l10n_es_aeat_sii.wsdl_in', False) client = self._connect_sii(wsdl) port_name = 'SuministroFactRecibidas' if company.sii_test: - port_name += 'Pruebas' -# TODO Property Investiment -# elif invoice == 'Property Investiment': -# wsdl = company.wsdl_pi -# client = self._connect_sii(wsdl) -# port_name = 'SuministroBienesInversion' -# if company.sii_test: -# port_name += 'Pruebas' - elif invoice.fiscal_position.id == self.env.ref( - 'account.fp_intra').id: - wsdl = company.wsdl_ic - client = self._connect_sii(wsdl) - port_name = 'SuministroOpIntracomunitarias' - if company.sii_test: - port_name += 'Pruebas' + port_name += 'Pruebas' serv = client.bind('siiService', port_name) if not invoice.sii_sent: TipoComunicacion = 'A0' @@ -405,23 +472,22 @@ def _send_invoice_to_sii(self): header = self._get_header(company, TipoComunicacion) invoices = self._get_invoices(company, invoice) try: - if invoice.type == 'out_invoice': + if invoice.type in ['out_invoice', 'out_refund']: res = serv.SuministroLRFacturasEmitidas( header, invoices) - elif invoice.type == 'in_invoice': + elif invoice.type in ['in_invoice', 'in_refund']: res = serv.SuministroLRFacturasRecibidas( header, invoices) -# TODO Factura Bienes de inversión -# elif invoice == 'Property Investiment': -# res = serv.SuministroLRBienesInversion( -# header, invoices) -# TODO Facturas intracomunitarias +# TODO Facturas intracomunitarias 66 RIVA # elif invoice.fiscal_position.id == self.env.ref( # 'account.fp_intra').id: # res = serv.SuministroLRDetOperacionIntracomunitaria( # header, invoices) if res['EstadoEnvio'] == 'Correcto': self.sii_sent = True + self.sii_csv = res['CSV'] + else: + self.sii_sent = False self.sii_return = res except Exception as fault: self.sii_return = fault @@ -430,10 +496,11 @@ def _send_invoice_to_sii(self): def invoice_validate(self): res = super(AccountInvoice, self).invoice_validate() - if not self.company_id.use_connector: - self._send_invoice_to_sii() -# TODO -# else: -# Use connector + if self.company_id.sii_enabled: + if not self.company_id.use_connector: + self._send_invoice_to_sii() +# TODO +# else: +# Use connector return res diff --git a/l10n_es_aeat_sii_oca/models/aeat_sii_map.py b/l10n_es_aeat_sii_oca/models/aeat_sii_map.py new file mode 100644 index 00000000000..01ea8be35a0 --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/aeat_sii_map.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Ignacio Ibeas +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import api, models, fields, _ +from openerp.exceptions import ValidationError + +class AeatSiiMap(models.Model): + _name = 'aeat.sii.map' + _description = 'Aeat SII Map' + + @api.one + @api.constrains('date_from', 'date_to') + def _unique_date_range(self): + # Based in l10n_es_aeat module + domain = [('id', '!=', self.id)] + if self.date_from and self.date_to: + domain += ['|', '&', + ('date_from', '<=', self.date_to), + ('date_from', '>=', self.date_from), + '|', '&', + ('date_to', '<=', self.date_to), + ('date_to', '>=', self.date_from), + '|', '&', + ('date_from', '=', False), + ('date_to', '>=', self.date_from), + '|', '&', + ('date_to', '=', False), + ('date_from', '<=', self.date_to), + ] + elif self.date_from: + domain += [('date_to', '>=', self.date_from)] + elif self.date_to: + domain += [('date_from', '<=', self.date_to)] + date_lst = self.search(domain) + if date_lst: + raise exceptions.Warning( + _("Error! The dates of the record overlap with an existing " + "record.")) + + name = fields.Char(string='Model', required=True) + date_from = fields.Date(string='Date from') + date_to = fields.Date(string='Date to') + map_lines = fields.One2many( + comodel_name='aeat.sii.map.lines', + inverse_name='sii_map_id', + string='Lines') + + +class AeatSiiMapLines(models.Model): + _name = 'aeat.sii.map.lines' + _description = 'Aeat SII Map Lines' + + code = fields.Char(string='Code', required=True) + name = fields.Char(string='Name') + taxes = fields.Many2many( + comodel_name='account.tax.template', string="Taxes") + sii_map_id = fields.Many2one( + comodel_name='aeat.sii.map', + string='Aeat SII Map', + ondelete='cascade') diff --git a/l10n_es_aeat_sii_oca/models/aeat_sii_mapping_registration_keys.py b/l10n_es_aeat_sii_oca/models/aeat_sii_mapping_registration_keys.py new file mode 100644 index 00000000000..9ca99e59c24 --- /dev/null +++ b/l10n_es_aeat_sii_oca/models/aeat_sii_mapping_registration_keys.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2015-TODAY MINORISA (http://www.minorisa.net) All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import api, models, fields, _ +from openerp.exceptions import ValidationError + + +class AeatSiiMappingRegistrationKeys(models.Model): + _name='aeat.sii.mapping.registration.keys' + _description = 'Aeat SII Invoice Registration Keys' + + + #registration_id = fields.Many2one('aeat.sii.invoice.registration','Aeat SII Invoice Registration') + code = fields.Char('Code',required=True,size=2) + name = fields.Char('Name',required=True) + #type = fields.Selection([('sale','Sale'),('purchase','Purchase'),('all','All')],'Type',required=True) + type = fields.Selection([('sale','Sale'),('purchase','Purchase')],'Type',required=True) + + @api.multi + def name_get(self): + vals = [] + for record in self: + name=u'' + name += "[%s]" % record.code + name+= "-%s"%record.name + vals.append(tuple([record.id, name])) + return vals \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/models/res_company.py b/l10n_es_aeat_sii_oca/models/res_company.py index 2d39ae5e631..7962adea653 100644 --- a/l10n_es_aeat_sii_oca/models/res_company.py +++ b/l10n_es_aeat_sii_oca/models/res_company.py @@ -17,51 +17,12 @@ def _check_connector_installed(self): _('The module "Connector" is not installed. You have ' 'to install it to activate this option')) + sii_enabled = fields.Boolean(string='Enable SII') sii_test = fields.Boolean(string='Test Enviroment') - sii_version = fields.Char(string='SII Version', default='0.6') + chart_template_id = fields.Many2one( + comodel_name='account.chart.template', string='Chart Template', + required=True) use_connector = fields.Boolean( string='Use connector', help='Check it to use connector instead to send the invoice ' 'when it is validated') - wsdl_out = fields.Char( - string='WSDL Invoice Out', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroFactEmitidas.wsdl') - wsdl_in = fields.Char( - string='WSDL Invoice In', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroFactRecibidas.wsdl') - wsdl_pi = fields.Char( - string='WSDL Property Investment', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroBienesInversion.wsdl') - wsdl_ic = fields.Char( - string='WSDL Intra-Community', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroOpIntracomunitarias.wsdl') - wsdl_pr = fields.Char( - string='WSDL Payment Received', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroCobrosEmitidas.wsdl') - wsdl_prm = fields.Char( - string='WSDL Money Payment Received', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroCobrosMetalico.wsdl') - wsdl_ps = fields.Char( - string='WSDL Payment Sent', - default='http://www.agenciatributaria.es/static_files/AEAT/' - 'Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/' - 'Suministro_inmediato_informacion/FicherosSuministros/V_06/' - 'SuministroPagosRecibidas.wsdl') diff --git a/l10n_es_aeat_sii_oca/security/ir.model.access.csv b/l10n_es_aeat_sii_oca/security/ir.model.access.csv new file mode 100644 index 00000000000..fd16c3acbd7 --- /dev/null +++ b/l10n_es_aeat_sii_oca/security/ir.model.access.csv @@ -0,0 +1,7 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_model_aeat_sii_map_admin,aeat.sii.map admin,model_aeat_sii_map,base.group_system,1,1,1,1 +access_model_aeat_sii_map_aeat,aeat.sii.map aeat,model_aeat_sii_map,l10n_es_aeat.group_account_aeat,1,0,0,0 +access_model_aeat_sii_map_lines_admin,aeat.sii.map.lines admin,model_aeat_sii_map_lines,base.group_system,1,1,1,1 +access_model_aeat_sii_map_lines_aeat,aeat.sii.map.lines aeat,model_aeat_sii_map_lines,l10n_es_aeat.group_account_aeat,1,0,0,0 +access_model_aeat_sii_mapping_registration_keys_admin,aeat.sii.mapping.registration.keys admin,model_aeat_sii_mapping_registration_keys,base.group_system,1,1,1,1 +access_model_aeat_sii_mapping_registration_keys_aeat,aeat.sii.mapping.registration.keys aeat,model_aeat_sii_mapping_registration_keys,l10n_es_aeat.group_account_aeat,1,0,0,0 diff --git a/l10n_es_aeat_sii_oca/views/account_invoice_view.xml b/l10n_es_aeat_sii_oca/views/account_invoice_view.xml index b0fc509dfeb..7886daea3b9 100644 --- a/l10n_es_aeat_sii_oca/views/account_invoice_view.xml +++ b/l10n_es_aeat_sii_oca/views/account_invoice_view.xml @@ -12,6 +12,7 @@ + @@ -28,13 +29,17 @@ - + + + + + diff --git a/l10n_es_aeat_sii_oca/views/aeat_sii_map_view.xml b/l10n_es_aeat_sii_oca/views/aeat_sii_map_view.xml new file mode 100644 index 00000000000..21fc3027250 --- /dev/null +++ b/l10n_es_aeat_sii_oca/views/aeat_sii_map_view.xml @@ -0,0 +1,59 @@ + + + + + + aeat.sii.map.view.tree + aeat.sii.map + + + + + + + + + + + aeat.sii.map.view.form + aeat.sii.map + +
+ + + + + + + + +
+
+
+ + + Aeat SII Map + aeat.sii.map + form + tree,form + + + + + + aeat.sii.map.lines.view.tree + aeat.sii.map.lines + + + + + + + + + +
+
\ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/views/aeat_sii_mapping_registration_keys_view.xml b/l10n_es_aeat_sii_oca/views/aeat_sii_mapping_registration_keys_view.xml new file mode 100644 index 00000000000..bad3bf5ec55 --- /dev/null +++ b/l10n_es_aeat_sii_oca/views/aeat_sii_mapping_registration_keys_view.xml @@ -0,0 +1,54 @@ + + + + + + + aeat.sii.mapping.registration.keys.view.tree + aeat.sii.mapping.registration.keys + + + + + + + + + + + + aeat.sii.mapping.registration.keys.view.search + aeat.sii.mapping.registration.keys + + + + + + + + + + + + + + + + + Aeat SII Registration Keys + aeat.sii.mapping.registration.keys + form + tree,form + + + + + + + + + + \ No newline at end of file diff --git a/l10n_es_aeat_sii_oca/views/res_company_view.xml b/l10n_es_aeat_sii_oca/views/res_company_view.xml index 063adad6c2d..554283267b3 100644 --- a/l10n_es_aeat_sii_oca/views/res_company_view.xml +++ b/l10n_es_aeat_sii_oca/views/res_company_view.xml @@ -10,15 +10,9 @@ - - - - - - - - - + + + From ca03f8525a645d22510a41f16c70f77490399450 Mon Sep 17 00:00:00 2001 From: Pablo Fuentes Date: Mon, 29 May 2017 12:25:29 +0200 Subject: [PATCH 004/298] l10n_es_aeat_sii: Mejoras del certificado + otros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ocultar la contraseña del certificado * Plantilla de cuentas solo obligatorio si "activar SII" activado * Habilitar un certificado por compañía * Permisos de acceso * Tener en cuenta las fechas de los certificados MP] l10n_es_aeat_sii: No utilizar los parámetros del sistema y buscar solo certificados activos --- l10n_es_aeat_sii_oca/README.rst | 4 +-- l10n_es_aeat_sii_oca/__openerp__.py | 8 +++--- .../data/ir_config_parameter.xml | 10 ------- l10n_es_aeat_sii_oca/models/__init__.py | 4 +-- .../models/account_invoice.py | 26 ++++++++++++++----- l10n_es_aeat_sii_oca/models/aeat_sii.py | 16 +++++++----- l10n_es_aeat_sii_oca/models/res_company.py | 10 +++---- l10n_es_aeat_sii_oca/security/aeat_sii.xml | 13 ++++++++++ .../security/ir.model.access.csv | 3 +++ l10n_es_aeat_sii_oca/views/aeat_sii_view.xml | 1 + .../views/res_company_view.xml | 3 ++- .../wizard/aeat_sii_password_view.xml | 2 +- 12 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 l10n_es_aeat_sii_oca/security/aeat_sii.xml diff --git a/l10n_es_aeat_sii_oca/README.rst b/l10n_es_aeat_sii_oca/README.rst index 3c8b4761d8e..bb3654ebd89 100644 --- a/l10n_es_aeat_sii_oca/README.rst +++ b/l10n_es_aeat_sii_oca/README.rst @@ -26,9 +26,7 @@ Para configurar este módulo necesitas: #. En la compañia se almacenan las URLs del servicio SOAP de hacienda. Estas URLs pueden cambiar según comunidades #. Los certificados deben alojarse en una carpeta accesible por la instalación -de Odoo. Las rutas de los certificados se pueden indicar en Configuración-> -Parámetros->Parametros del sistemas con las claves l10n_es_aeat_sii.publicCrt y -l10n_es_aeat_sii.privateKey +de Odoo. #. Preparar el certificado. El certificado enviado por la FMNT es en formato p12, este certificado no se puede usar directamente con Zeep. Se tiene que extraer la clave pública y la clave privada. diff --git a/l10n_es_aeat_sii_oca/__openerp__.py b/l10n_es_aeat_sii_oca/__openerp__.py index 4e1a94ea33c..455c7f94961 100644 --- a/l10n_es_aeat_sii_oca/__openerp__.py +++ b/l10n_es_aeat_sii_oca/__openerp__.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # Copyright 2017 Ignacio Ibeas # (c) 2017 Diagram Software S.L. -# Copyright (c) 2017-TODAY MINORISA +# Copyright (c) 2017-TODAY MINORISA +# (c) 2017 Consultoría Informática Studio 73 S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Suministro Inmediato de Información en el IVA", - "version": "8.0.1.0.2", + "version": "8.0.1.1.0", "category": "Accounting & Finance", "website": "https://odoo-community.org/", "author": "Acysos S.L., Odoo Community Association (OCA)", @@ -29,6 +30,7 @@ "data/aeat_sii_mapping_registration_keys_data.xml", "views/aeat_sii_map_view.xml", "data/aeat_sii_map_data.xml", - "security/ir.model.access.csv" + "security/ir.model.access.csv", + "security/aeat_sii.xml" ], } diff --git a/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml index 270bbfc30ef..46f8fdaa951 100644 --- a/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml +++ b/l10n_es_aeat_sii_oca/data/ir_config_parameter.xml @@ -3,16 +3,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> - - l10n_es_aeat_sii.publicCrt - /opt/certificates/publicCert.crt - - - - l10n_es_aeat_sii.privateKey - /opt/certificates/privateKey.pem - - l10n_es_aeat_sii.version 0.7 diff --git a/l10n_es_aeat_sii_oca/models/__init__.py b/l10n_es_aeat_sii_oca/models/__init__.py index 254fcbbfe8a..bde867978a0 100644 --- a/l10n_es_aeat_sii_oca/models/__init__.py +++ b/l10n_es_aeat_sii_oca/models/__init__.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import res_company -from . import account_invoice from . import aeat_sii from . import aeat_sii_mapping_registration_keys -from . import aeat_sii_map \ No newline at end of file +from . import aeat_sii_map +from . import account_invoice diff --git a/l10n_es_aeat_sii_oca/models/account_invoice.py b/l10n_es_aeat_sii_oca/models/account_invoice.py index 358fb1d9ab5..25039067008 100644 --- a/l10n_es_aeat_sii_oca/models/account_invoice.py +++ b/l10n_es_aeat_sii_oca/models/account_invoice.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2017 Ignacio Ibeas +# (c) 2017 Consultoría Informática Studio 73 S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from openerp import models, fields, api, _ @@ -431,17 +432,28 @@ def _get_invoices(self, company, invoice): @api.multi def _connect_sii(self, wsdl): - publicCrt = self.env['ir.config_parameter'].get_param( - 'l10n_es_aeat_sii.publicCrt', False) - privateKey = self.env['ir.config_parameter'].get_param( - 'l10n_es_aeat_sii.privateKey', False) - + today = fields.Date.today() + sii_config = self.env['l10n.es.aeat.sii'].search( + [('company_id', '=', self.company_id.id), + ('public_key', '!=', False), + ('private_key', '!=', False), + '|', ('date_start', '=', False), + ('date_start', '<=', today), + '|', ('date_end', '=', False), + ('date_end', '>=', today), + ('active', '=', True)], + limit=1 + ) + if not sii_config: + raise Warning(u'No hay un SII correctamente configurado para la ' + u'compañia %s' % self.company_id.name_get()[0][1]) + session = Session() - session.cert = (publicCrt, privateKey) + session.cert = (sii_config.public_key, sii_config.private_key) transport = Transport(session=session) history = HistoryPlugin() - client = Client(wsdl=wsdl,transport=transport,plugins=[history]) + client = Client(wsdl=wsdl, transport=transport, plugins=[history]) return client @api.multi diff --git a/l10n_es_aeat_sii_oca/models/aeat_sii.py b/l10n_es_aeat_sii_oca/models/aeat_sii.py index b5ccda724ed..53dce0e5b10 100644 --- a/l10n_es_aeat_sii_oca/models/aeat_sii.py +++ b/l10n_es_aeat_sii_oca/models/aeat_sii.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # (c) 2017 Diagram Software S.L. +# (c) 2017 Consultoría Informática Studio 73 S.L. # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from openerp import api, models, fields, _ @@ -19,6 +20,12 @@ class l10nEsAeatSii(models.Model): date_end = fields.Date(string="End Date") public_key = fields.Char(string="Public Key", readonly=True) private_key = fields.Char(string="Private Key", readonly=True) + company_id = fields.Many2one( + comodel_name="res.company", + string="Compañía", + required=True, + default=lambda self: self.env.user.company_id.id + ) @api.multi def load_password_wizard(self): @@ -36,13 +43,8 @@ def load_password_wizard(self): @api.multi def action_active(self): self.ensure_one() - if self.public_key: - sii_crt = self.env.ref('l10n_es_aeat_sii.config_parameter_sii_crt') - sii_crt.value = self.public_key - if self.private_key: - sii_key = self.env.ref('l10n_es_aeat_sii.config_parameter_sii_key') - sii_key.value = self.private_key - other_configs = self.search([('id', '!=', self.id)]) + other_configs = self.search([('id', '!=', self.id), + ('company_id', '=', self.company_id.id)]) for config_id in other_configs: config_id.state = 'draft' self.state = 'active' diff --git a/l10n_es_aeat_sii_oca/models/res_company.py b/l10n_es_aeat_sii_oca/models/res_company.py index 7962adea653..149f448404a 100644 --- a/l10n_es_aeat_sii_oca/models/res_company.py +++ b/l10n_es_aeat_sii_oca/models/res_company.py @@ -2,7 +2,8 @@ # Copyright 2017 Ignacio Ibeas # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api +from openerp import models, fields, api, _ +from openerp.exceptions import Warning class ResCompany(models.Model): @@ -10,18 +11,17 @@ class ResCompany(models.Model): @api.onchange('use_connector') def _check_connector_installed(self): - module = self.env['ir.module'].search( + module = self.env['ir.module.module'].search( [('name', '=', 'connector'), ('state', '=', 'installed')]) if not module: - raise exceptions.Warning( + raise Warning( _('The module "Connector" is not installed. You have ' 'to install it to activate this option')) sii_enabled = fields.Boolean(string='Enable SII') sii_test = fields.Boolean(string='Test Enviroment') chart_template_id = fields.Many2one( - comodel_name='account.chart.template', string='Chart Template', - required=True) + comodel_name='account.chart.template', string='Chart Template') use_connector = fields.Boolean( string='Use connector', help='Check it to use connector instead to send the invoice ' diff --git a/l10n_es_aeat_sii_oca/security/aeat_sii.xml b/l10n_es_aeat_sii_oca/security/aeat_sii.xml new file mode 100644 index 00000000000..232c1594ca0 --- /dev/null +++ b/l10n_es_aeat_sii_oca/security/aeat_sii.xml @@ -0,0 +1,13 @@ + + + + + + AEAT SII config + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + diff --git a/l10n_es_aeat_sii_oca/security/ir.model.access.csv b/l10n_es_aeat_sii_oca/security/ir.model.access.csv index fd16c3acbd7..609a42697c0 100644 --- a/l10n_es_aeat_sii_oca/security/ir.model.access.csv +++ b/l10n_es_aeat_sii_oca/security/ir.model.access.csv @@ -5,3 +5,6 @@ access_model_aeat_sii_map_lines_admin,aeat.sii.map.lines admin,model_aeat_sii_ma access_model_aeat_sii_map_lines_aeat,aeat.sii.map.lines aeat,model_aeat_sii_map_lines,l10n_es_aeat.group_account_aeat,1,0,0,0 access_model_aeat_sii_mapping_registration_keys_admin,aeat.sii.mapping.registration.keys admin,model_aeat_sii_mapping_registration_keys,base.group_system,1,1,1,1 access_model_aeat_sii_mapping_registration_keys_aeat,aeat.sii.mapping.registration.keys aeat,model_aeat_sii_mapping_registration_keys,l10n_es_aeat.group_account_aeat,1,0,0,0 +access_l10n_es_aeat_sii_admin,l10n.es.aeat.sii admin,model_l10n_es_aeat_sii,base.group_system,1,1,1,1 +access_l10n_es_aeat_sii_aeat,l10n.es.aeat.sii aeat,model_l10n_es_aeat_sii,l10n_es_aeat.group_account_aeat,1,0,0,0 + diff --git a/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml b/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml index c89a822b944..4d4f160e7f4 100644 --- a/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml +++ b/l10n_es_aeat_sii_oca/views/aeat_sii_view.xml @@ -18,6 +18,7 @@ + diff --git a/l10n_es_aeat_sii_oca/views/res_company_view.xml b/l10n_es_aeat_sii_oca/views/res_company_view.xml index 554283267b3..a4749406024 100644 --- a/l10n_es_aeat_sii_oca/views/res_company_view.xml +++ b/l10n_es_aeat_sii_oca/views/res_company_view.xml @@ -12,7 +12,8 @@ - + diff --git a/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml index 992d20ab2c2..03c56b562e7 100644 --- a/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml +++ b/l10n_es_aeat_sii_oca/wizard/aeat_sii_password_view.xml @@ -8,7 +8,7 @@
- +