diff --git a/l10n_es_pos_oca/README.rst b/l10n_es_pos_oca/README.rst new file mode 100644 index 00000000000..3059b9319df --- /dev/null +++ b/l10n_es_pos_oca/README.rst @@ -0,0 +1,159 @@ +================================================= +Punto de venta adaptado a la legislación española +================================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:58ee25e2b87c19728b5e42bf5406d8c09d1493ed61256017e38088e9e3bcda09 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--spain-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-spain/tree/17.0/l10n_es_pos_oca + :alt: OCA/l10n-spain +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-spain-17-0/l10n-spain-17-0-l10n_es_pos_oca + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/l10n-spain&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +- Adapta el terminal punto de venta a la legislación Española (no se + permite la emisión de tiquets, todo deben ser facturas o facturas + simplificadas con numeración) +- Adapta el ticket de venta a la factura simplificada, añadiendo una + secuencia correlativa y el NIF del emisor. +- Incluye los datos del cliente (nombre, NIF y dirección) si hay uno + asignado. +- Chequea que no se realice una factura simplificada con valor superior + a 3.000 euros (la cantidad es configurable por TPV). + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +Antes de instalar el módulo, podemos definir el relleno y el prefijo +automático en *Configuración > Parámetros del sistema*: + +- l10n_es_pos.simplified_invoice_sequence.padding (o 4 cifras por + defecto) +- l10n_es_pos.simplified_invoice_sequence.prefix (nombre del TPV más + este valor) + +Al instalarse el módulo, se define una secuencia para factura +simplificada por cada TPV existente. + +Configuration +============= + +Para activar la factura simplificada en un TPV, iremos a *Punto de Venta +> Configuración > Punto de Venta* y escogeremos uno de la lista. En la +sección *Facturación y recibos* activaremos la opción *Secuencia de +Factura Simplificada*. Podemos configurar el límite a partir del cual no +se considera factura simplificada, que por defecto es 3.000,00 €. + +Si entramos en la configuración del TPV en modo debug, podremos también +configurar la sequencia asociada al TPV. + +`Ver enlace de la +AEAT `__ + +Known issues / Roadmap +====================== + +- No se comprueba el límite en operaciones separadas para un mismo + cliente, algo que Hacienda proscribe. +- El soporte para usuarios concurrentes sobre una misma sesión es + limitado y solo es fiable si ambos puestos están online. En el caso + de que cualquiera de ellos estuviese offline, se correría el riesgo + de solapar la secuencia de factura simplificada. Se recomienda que en + estos casos se añada mejor una configuración de punto de venta + adicional. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Tecnativa +* Aselcis Consulting +* Acysos S.L. + +Contributors +------------ + +- `Antiun `__: + + - Endika Iglesias + +- `Aselcis `__: + + - David Gómez + - Miguel Paraíso + +- `Acysos `__: + + - Ignacio Ibeas + +- `Tecnativa `__: + + - David Vidal + - Pedro M. Baeza + - Antonio Espinosa + - Rafael Blasco + - Carlos Roca + - João Marques + +- `Sygel `__: + + - Manuel Regidor + +- `Factor Libre `__: + + - Daniel Duque + +- `APSL-Nagarro `__: + + - Antoni Marroig + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/l10n-spain `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/l10n_es_pos_oca/__init__.py b/l10n_es_pos_oca/__init__.py new file mode 100644 index 00000000000..7cac8ac3961 --- /dev/null +++ b/l10n_es_pos_oca/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models +from .hooks import post_init_hook, uninstall_hook +from . import wizard diff --git a/l10n_es_pos_oca/__manifest__.py b/l10n_es_pos_oca/__manifest__.py new file mode 100644 index 00000000000..5279b31877d --- /dev/null +++ b/l10n_es_pos_oca/__manifest__.py @@ -0,0 +1,23 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Punto de venta adaptado a la legislación española", + "category": "Sales/Point Of Sale", + "author": "Tecnativa, " + "Aselcis Consulting, " + "Acysos S.L., " + "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/l10n-spain", + "license": "AGPL-3", + "version": "17.0.1.0.0", + "depends": ["point_of_sale", "l10n_es"], + "data": ["views/pos_views.xml", "views/res_config_settings_views.xml"], + "assets": { + "point_of_sale._assets_pos": [ + "l10n_es_pos_oca/static/src/**/*", + ], + }, + "installable": True, + "post_init_hook": "post_init_hook", + "uninstall_hook": "uninstall_hook", +} diff --git a/l10n_es_pos_oca/hooks.py b/l10n_es_pos_oca/hooks.py new file mode 100644 index 00000000000..85f78cd339c --- /dev/null +++ b/l10n_es_pos_oca/hooks.py @@ -0,0 +1,48 @@ +# Copyright 2018 David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +def post_init_hook(env, vals=None): + """For brand new installations""" + IrSequence = env["ir.sequence"] + pos_config = env["pos.config"].search( + [("l10n_es_simplified_invoice_sequence_id", "=", False)] + ) + pos_name_dupes = {} + vals = {} if vals is None else vals + for pos in pos_config: + pos_name_dupes.setdefault(pos.name, -1) + pos_name_dupes[pos.name] += 1 + pos_vals = vals.get(pos, {}) + pos_name = ( + pos.name + if not pos_name_dupes[pos.name] + else "%s_%d" % (pos.name, pos_name_dupes[pos.name]) + ) + if not pos_vals.get("prefix"): + pos_vals["prefix"] = initial_prefix = "{}{}".format( + pos_name, pos._get_default_prefix() + ) + ith = 0 + while IrSequence.search_count([("prefix", "=", pos_vals["prefix"])]): + ith += 1 + pos_vals["prefix"] = f"{initial_prefix}_{ith}" + pos.l10n_es_simplified_invoice_sequence_id = IrSequence.create( + { + "name": ( + pos.with_context(lang=env.user.lang)._get_l10n_es_sequence_name() + % pos_name + ), + "prefix": pos_vals.get( + "prefix", f"{pos_name}{pos._get_default_prefix()}" + ), + "padding": pos_vals.get("padding", pos._get_default_padding()), + "implementation": pos_vals.get("implementation", "standard"), + "code": "pos.config.simplified_invoice", + "company_id": pos_vals.get("company_id", pos.company_id.id), + } + ) + + +def uninstall_hook(env): + env["ir.sequence"].search([("code", "=", "pos.config.simplified_invoice")]).unlink() diff --git a/l10n_es_pos_oca/i18n/ca.po b/l10n_es_pos_oca/i18n/ca.po new file mode 100644 index 00000000000..875c7f9de41 --- /dev/null +++ b/l10n_es_pos_oca/i18n/ca.po @@ -0,0 +1,227 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_pos +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-06-23 13:11+0000\n" +"Last-Translator: eccit-quim \n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Above this limit the simplified invoice won't be made" +msgstr "Per sobre d'aquest límit no es crearà factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Autogenerate for each POS created" +msgstr "Autogenerada per cada TPV creat" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_res_config_settings +msgid "Config Settings" +msgstr "Paràmetres de configuració" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "Customer:" +msgstr "Client:" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Invoices" +msgstr "Factures" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__is_simplified_config +msgid "Is Simplified Config" +msgstr "És configuració simpl." + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Over this amount is not legally posible to create a simplified invoice" +msgstr "" +"Per sobre d'aquesta quantitat no és legal crear una factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configuració Punt de Venda" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_order +msgid "Point of Sale Orders" +msgstr "Comandes del Punt de Venda" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_session +msgid "Point of Sale Session" +msgstr "Sessió Punt de Venda" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_ir_sequence +msgid "Sequence" +msgstr "Seqüència" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Set simplified invoice sequence for this POS" +msgstr "Establir seqüència de factura simplificada per aquest TPV" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Sim.Inv limit amount" +msgstr "Límit de factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_number +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_number +msgid "Sim.Inv number" +msgstr "Nombre de factura simplificada" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/js/Screens/TicketScreen/TicketScreen.js:0 +#: code:addons/l10n_es_pos/static/src/xml/Screens/OrderManagementScreen/TicketScreen.xml:0 +#, python-format +msgid "Simplified Invoice" +msgstr "Factura simplificada" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/pos_config.py:0 +#, python-format +msgid "Simplified Invoice %s" +msgstr "Factura simplificada %s" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Simplified Invoice IDs Sequence" +msgstr "Seqüència de Factura Simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Limit" +msgstr "Límit de Factura Simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Sequence" +msgstr "Seqüència de Factura Simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_padding +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_padding +msgid "Simplified Invoice padding" +msgstr "Farcit de Factura Simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_prefix +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_prefix +msgid "Simplified Invoice prefix" +msgstr "Prefix de Factura Simplificada" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__is_l10n_es_simplified_invoice +#, python-format +msgid "Simplified invoice" +msgstr "Factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__l10n_es_unique_id +msgid "Simplified invoice number" +msgstr "Número de factura simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Simplified invoices" +msgstr "Factures simplificades" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/ir_sequence.py:0 +#, python-format +msgid "" +"There is already a simplified invoice sequence with that prefix and it " +"should be unique." +msgstr "" +"Ja hi ha una seqüència de Factura Simplificada amb aquest prefix i aquest " +"hauria de ser únic." + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__iface_l10n_es_simplified_invoice +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_iface_l10n_es_simplified_invoice +msgid "Use simplified invoices for this POS" +msgstr "Utilitza Factures simplificades en aquest punt de venda" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "on" +msgstr "sobre" + +#~ msgid "Invoice Journal" +#~ msgstr "Diari de Factures" + +#, python-format +#~ msgid "" +#~ "!env.pos.config.iface_l10n_es_simplified_invoice or receipt.is_to_invoice" +#~ msgstr "" +#~ "! env.pos.config.iface_l10n_es_simplified_invoice o ticket.is_to_invoice" + +#~ msgid "Display Name" +#~ msgstr "Nom visible" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Darrera modificació el" + +#~ msgid "Unique Order ID" +#~ msgstr "ID únic de comanda" + +#~ msgid "VAT:" +#~ msgstr "NIF:" + +#~ msgid "Address:" +#~ msgstr "Adreça:" + +#~ msgid "Customer data" +#~ msgstr "Dades de client" + +#~ msgid "Name:" +#~ msgstr "Nom:" + +#~ msgid "Product" +#~ msgstr "Producte" + +#~ msgid "Qty" +#~ msgstr "Quantitat" + +#~ msgid "Simplified invoice:" +#~ msgstr "Factura simplificada:" + +#~ msgid "Subt" +#~ msgstr "Subt" + +#~ msgid "Unit" +#~ msgstr "Unitat" diff --git a/l10n_es_pos_oca/i18n/ca_ES.po b/l10n_es_pos_oca/i18n/ca_ES.po new file mode 100644 index 00000000000..22e3cc7967c --- /dev/null +++ b/l10n_es_pos_oca/i18n/ca_ES.po @@ -0,0 +1,174 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_pos +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ca_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Above this limit the simplified invoice won't be made" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Autogenerate for each POS created" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "Customer:" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Invoices" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__is_simplified_config +msgid "Is Simplified Config" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Over this amount is not legally posible to create a simplified invoice" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_session +msgid "Point of Sale Session" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_ir_sequence +msgid "Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Set simplified invoice sequence for this POS" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Sim.Inv limit amount" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_number +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_number +msgid "Sim.Inv number" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/js/Screens/TicketScreen/TicketScreen.js:0 +#: code:addons/l10n_es_pos/static/src/xml/Screens/OrderManagementScreen/TicketScreen.xml:0 +#, python-format +msgid "Simplified Invoice" +msgstr "" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/pos_config.py:0 +#, python-format +msgid "Simplified Invoice %s" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Simplified Invoice IDs Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Limit" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_padding +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_padding +msgid "Simplified Invoice padding" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_prefix +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_prefix +msgid "Simplified Invoice prefix" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__is_l10n_es_simplified_invoice +#, python-format +msgid "Simplified invoice" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__l10n_es_unique_id +msgid "Simplified invoice number" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Simplified invoices" +msgstr "" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/ir_sequence.py:0 +#, python-format +msgid "" +"There is already a simplified invoice sequence with that prefix and it " +"should be unique." +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__iface_l10n_es_simplified_invoice +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_iface_l10n_es_simplified_invoice +msgid "Use simplified invoices for this POS" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "on" +msgstr "" diff --git a/l10n_es_pos_oca/i18n/es.po b/l10n_es_pos_oca/i18n/es.po new file mode 100644 index 00000000000..b85f1e2a848 --- /dev/null +++ b/l10n_es_pos_oca/i18n/es.po @@ -0,0 +1,179 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_pos +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-11-21 10:09+0000\n" +"PO-Revision-Date: 2024-02-11 19:35+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Above this limit the simplified invoice won't be made" +msgstr "Por encima de este límite no se creará factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Autogenerate for each POS created" +msgstr "Autogenerada por cada TPV creado" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_res_config_settings +msgid "Config Settings" +msgstr "Opciones de configuración" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "Customer:" +msgstr "Cliente:" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Invoices" +msgstr "Diario de facturas" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__is_simplified_config +msgid "Is Simplified Config" +msgstr "Es la configuración simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Over this amount is not legally posible to create a simplified invoice" +msgstr "Por encima de esta cantidad no es legal crear una factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configuración Punto de Venta" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_order +msgid "Point of Sale Orders" +msgstr "Pedidos del Punto de Venta" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_session +msgid "Point of Sale Session" +msgstr "Sesión del Punto de Venta" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_ir_sequence +msgid "Sequence" +msgstr "Secuencia" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Set simplified invoice sequence for this POS" +msgstr "Establecer secuencia de factura simplificada para este TPV" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Sim.Inv limit amount" +msgstr "Límite de factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_number +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_number +msgid "Sim.Inv number" +msgstr "Número de factura simplificada" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/js/Screens/TicketScreen/TicketScreen.js:0 +#: code:addons/l10n_es_pos/static/src/xml/Screens/OrderManagementScreen/TicketScreen.xml:0 +#, python-format +msgid "Simplified Invoice" +msgstr "Factura simplificada" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/pos_config.py:0 +#, python-format +msgid "Simplified Invoice %s" +msgstr "Factura simplificada %s" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Simplified Invoice IDs Sequence" +msgstr "Secuencia de Factura Simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Limit" +msgstr "Límite de Factura Simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Sequence" +msgstr "Secuencia de Factura Simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_padding +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_padding +msgid "Simplified Invoice padding" +msgstr "Relleno de Factura Simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_prefix +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_prefix +msgid "Simplified Invoice prefix" +msgstr "Prefijo de Factura Simplificada" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__is_l10n_es_simplified_invoice +#, python-format +msgid "Simplified invoice" +msgstr "Factura simplificada" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__l10n_es_unique_id +msgid "Simplified invoice number" +msgstr "Número de factura simplificada" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Simplified invoices" +msgstr "Facturas simplificadas" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/ir_sequence.py:0 +#, python-format +msgid "" +"There is already a simplified invoice sequence with that prefix and it " +"should be unique." +msgstr "" +"Ya existe una secuencia de Factura Simplificada con ese prefijo y este " +"debería ser único." + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__iface_l10n_es_simplified_invoice +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_iface_l10n_es_simplified_invoice +msgid "Use simplified invoices for this POS" +msgstr "Usar Facturas Simplificadas en este Punto de Venta" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "on" +msgstr "sobre" diff --git a/l10n_es_pos_oca/i18n/l10n_es_pos.pot b/l10n_es_pos_oca/i18n/l10n_es_pos.pot new file mode 100644 index 00000000000..c1b55d3bcff --- /dev/null +++ b/l10n_es_pos_oca/i18n/l10n_es_pos.pot @@ -0,0 +1,176 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_es_pos +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \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_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Above this limit the simplified invoice won't be made" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Autogenerate for each POS created" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "Customer:" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Invoices" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__is_simplified_config +msgid "Is Simplified Config" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,help:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,help:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Over this amount is not legally posible to create a simplified invoice" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_pos_session +msgid "Point of Sale Session" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model,name:l10n_es_pos.model_ir_sequence +msgid "Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Set simplified invoice sequence for this POS" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_limit +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_limit +msgid "Sim.Inv limit amount" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_number +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_number +msgid "Sim.Inv number" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/js/Screens/TicketScreen/TicketScreen.js:0 +#: code:addons/l10n_es_pos/static/src/xml/Screens/OrderManagementScreen/TicketScreen.xml:0 +#: code:addons/l10n_es_pos/static/src/xml/Screens/OrderManagementScreen/TicketScreen.xml:0 +#, python-format +msgid "Simplified Invoice" +msgstr "" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/pos_config.py:0 +#: code:addons/l10n_es_pos/models/pos_config.py:0 +#, python-format +msgid "Simplified Invoice %s" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_sequence_id +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_sequence_id +msgid "Simplified Invoice IDs Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Limit" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.res_config_settings_view_form +msgid "Simplified Invoice Sequence" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_padding +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_padding +msgid "Simplified Invoice padding" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__l10n_es_simplified_invoice_prefix +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_l10n_es_simplified_invoice_prefix +msgid "Simplified Invoice prefix" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__is_l10n_es_simplified_invoice +#, python-format +msgid "Simplified invoice" +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_order__l10n_es_unique_id +msgid "Simplified invoice number" +msgstr "" + +#. module: l10n_es_pos +#: model_terms:ir.ui.view,arch_db:l10n_es_pos.view_pos_order_filter_simplified_invoice +msgid "Simplified invoices" +msgstr "" + +#. module: l10n_es_pos +#. odoo-python +#: code:addons/l10n_es_pos/models/ir_sequence.py:0 +#, python-format +msgid "" +"There is already a simplified invoice sequence with that prefix and it " +"should be unique." +msgstr "" + +#. module: l10n_es_pos +#: model:ir.model.fields,field_description:l10n_es_pos.field_pos_config__iface_l10n_es_simplified_invoice +#: model:ir.model.fields,field_description:l10n_es_pos.field_res_config_settings__pos_iface_l10n_es_simplified_invoice +msgid "Use simplified invoices for this POS" +msgstr "" + +#. module: l10n_es_pos +#. odoo-javascript +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#: code:addons/l10n_es_pos/static/src/xml/pos.xml:0 +#, python-format +msgid "on" +msgstr "" diff --git a/l10n_es_pos_oca/models/__init__.py b/l10n_es_pos_oca/models/__init__.py new file mode 100644 index 00000000000..7466682f7ce --- /dev/null +++ b/l10n_es_pos_oca/models/__init__.py @@ -0,0 +1,4 @@ +from . import ir_sequence +from . import pos_config +from . import pos_order +from . import pos_session diff --git a/l10n_es_pos_oca/models/ir_sequence.py b/l10n_es_pos_oca/models/ir_sequence.py new file mode 100644 index 00000000000..c39dbf7560c --- /dev/null +++ b/l10n_es_pos_oca/models/ir_sequence.py @@ -0,0 +1,33 @@ +# Copyright 2018 David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, models +from odoo.exceptions import UserError + + +class IrSequence(models.Model): + _inherit = "ir.sequence" + + @api.constrains("prefix", "code") + def check_simplified_invoice_unique_prefix(self): + if self._context.get("copy_pos_config"): + return + for sequence in self.filtered( + lambda x: x.code == "pos.config.simplified_invoice" + ): + if ( + self.search_count( + [ + ("code", "=", "pos.config.simplified_invoice"), + ("prefix", "=", sequence.prefix), + ] + ) + > 1 + ): + raise UserError( + _( + "There is already a simplified invoice " + "sequence with that prefix and it should be " + "unique." + ) + ) diff --git a/l10n_es_pos_oca/models/pos_config.py b/l10n_es_pos_oca/models/pos_config.py new file mode 100644 index 00000000000..3db0054ce3f --- /dev/null +++ b/l10n_es_pos_oca/models/pos_config.py @@ -0,0 +1,142 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models + + +class PosConfig(models.Model): + _inherit = "pos.config" + + @api.depends( + "l10n_es_simplified_invoice_sequence_id.number_next_actual", + "l10n_es_simplified_invoice_sequence_id.prefix", + "l10n_es_simplified_invoice_sequence_id.padding", + ) + def _compute_simplified_invoice_sequence(self): + for pos in self: + seq = pos.l10n_es_simplified_invoice_sequence_id + pos.l10n_es_simplified_invoice_number = ( + seq._get_current_sequence().number_next_actual + ) + pos.l10n_es_simplified_invoice_prefix = seq._get_prefix_suffix()[0] + pos.l10n_es_simplified_invoice_padding = seq.padding + + iface_l10n_es_simplified_invoice = fields.Boolean( + string="Use simplified invoices for this POS", + ) + is_simplified_config = fields.Boolean( + store=False, compute="_compute_simplified_config" + ) + l10n_es_simplified_invoice_sequence_id = fields.Many2one( + "ir.sequence", + string="Simplified Invoice IDs Sequence", + help="Autogenerate for each POS created", + copy=False, + ) + l10n_es_simplified_invoice_limit = fields.Float( + string="Sim.Inv limit amount", + digits="Account", + help="Over this amount is not legally posible to create " + "a simplified invoice", + default=3000, # Spanish legal limit + ) + l10n_es_simplified_invoice_prefix = fields.Char( + "Simplified Invoice prefix", + compute="_compute_simplified_invoice_sequence", + ) + l10n_es_simplified_invoice_padding = fields.Integer( + "Simplified Invoice padding", + compute="_compute_simplified_invoice_sequence", + ) + l10n_es_simplified_invoice_number = fields.Integer( + "Sim.Inv number", + compute="_compute_simplified_invoice_sequence", + ) + simplified_partner_id = fields.Many2one( + comodel_name="res.partner", + string="Simplified invoice partner", + compute="_compute_simplified_partner_id", + ) + + @api.depends("iface_l10n_es_simplified_invoice") + def _compute_simplified_config(self): + for pos in self: + pos.is_simplified_config = pos.iface_l10n_es_simplified_invoice + + def _compute_simplified_partner_id(self): + for config in self: + config.simplified_partner_id = self.env.ref("l10n_es.partner_simplified").id + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + # Auto create simp. inv. sequence + prefix = initial_prefix = "{}{}".format( + vals["name"], self._get_default_prefix() + ) + ith = 0 + while self.env["ir.sequence"].search_count([("prefix", "=", prefix)]): + ith += 1 + prefix = f"{initial_prefix}_{ith}" + simp_inv_seq_id = self.env["ir.sequence"].create( + { + "name": _("Simplified Invoice %s") % vals["name"], + "implementation": "standard", + "padding": self._get_default_padding(), + "prefix": prefix, + "code": "pos.config.simplified_invoice", + "company_id": vals.get("company_id", False), + } + ) + vals["l10n_es_simplified_invoice_sequence_id"] = simp_inv_seq_id.id + return super().create(vals_list) + + @api.onchange("iface_l10n_es_simplified_invoice") + def _onchange_l10n_iface_l10n_es_simplified_invoice(self): + if self.iface_l10n_es_simplified_invoice and not self.invoice_journal_id: + self.invoice_journal_id = self._default_invoice_journal() + + def copy(self, default=None): + return super( + PosConfig, + self.with_context(copy_pos_config=True), + ).copy(default) + + def write(self, vals): + if not self._context.get("copy_pos_config") and "name" not in vals: + for pos in self: + sequence = pos.l10n_es_simplified_invoice_sequence_id + sequence.check_simplified_invoice_unique_prefix() + if "name" in vals: + prefix = self.l10n_es_simplified_invoice_prefix.replace( + self.name, vals["name"] + ) + if prefix != self.l10n_es_simplified_invoice_prefix: + self.l10n_es_simplified_invoice_sequence_id.update( + { + "prefix": prefix, + "name": ( + self.l10n_es_simplified_invoice_sequence_id.name.replace( + self.name, vals["name"] + ) + ), + } + ) + return super().write(vals) + + def unlink(self): + self.mapped("l10n_es_simplified_invoice_sequence_id").unlink() + return super().unlink() + + def _get_default_padding(self): + return self.env["ir.config_parameter"].get_param( + "l10n_es_pos.simplified_invoice_sequence.padding", 4 + ) + + def _get_default_prefix(self): + return self.env["ir.config_parameter"].get_param( + "l10n_es_pos.simplified_invoice_sequence.prefix", "" + ) + + def _get_l10n_es_sequence_name(self): + """HACK: This is done for getting the proper translation.""" + return _("Simplified Invoice %s") diff --git a/l10n_es_pos_oca/models/pos_order.py b/l10n_es_pos_oca/models/pos_order.py new file mode 100644 index 00000000000..aec25d2ce87 --- /dev/null +++ b/l10n_es_pos_oca/models/pos_order.py @@ -0,0 +1,74 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from odoo.tools import float_compare + + +class PosOrder(models.Model): + _inherit = "pos.order" + + is_l10n_es_simplified_invoice = fields.Boolean( + "Simplified invoice", + copy=False, + default=False, + ) + l10n_es_unique_id = fields.Char( + "Simplified invoice number", + copy=False, + ) + + @api.model + def _simplified_limit_check(self, amount_total, limit=3000): + precision_digits = self.env["decimal.precision"].precision_get("Account") + # -1 or 0: amount_total <= limit, simplified + # 1: amount_total > limit, can not be simplified + return float_compare(amount_total, limit, precision_digits=precision_digits) < 0 + + @api.model + def _order_fields(self, ui_order): + res = super()._order_fields(ui_order) + if ui_order.get("l10n_es_unique_id", False): + res.update( + { + "l10n_es_unique_id": ui_order["l10n_es_unique_id"], + "is_l10n_es_simplified_invoice": True, + } + ) + return res + + @api.model + def _update_sequence_number(self, pos): + pos.l10n_es_simplified_invoice_sequence_id.next_by_id() + + @api.model + def _process_order(self, pos_order, draft, existing_order): + order_data = pos_order.get("data", {}) + simplified_invoice_number = order_data.get("l10n_es_unique_id", False) + if not simplified_invoice_number: + return super()._process_order(pos_order, draft, existing_order) + pos_order_obj = self.env["pos.order"] + pos = self.env["pos.session"].browse(order_data.get("pos_session_id")).config_id + if pos_order_obj._simplified_limit_check( + order_data.get("amount_total", 0), pos.l10n_es_simplified_invoice_limit + ): + pos_order["data"].update( + { + "l10n_es_unique_id": simplified_invoice_number, + "is_l10n_es_simplified_invoice": True, + } + ) + self._update_sequence_number(pos) + return super()._process_order(pos_order, draft, existing_order) + + def _get_fields_for_draft_order(self): + fields = super()._get_fields_for_draft_order() + + fields += ["l10n_es_unique_id"] + return fields + + def _export_for_ui(self, order): + res = super()._export_for_ui(order) + + res.update({"l10n_es_unique_id": order.l10n_es_unique_id}) + + return res diff --git a/l10n_es_pos_oca/models/pos_session.py b/l10n_es_pos_oca/models/pos_session.py new file mode 100644 index 00000000000..9b7f704c6ae --- /dev/null +++ b/l10n_es_pos_oca/models/pos_session.py @@ -0,0 +1,12 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class PosSession(models.Model): + _inherit = "pos.session" + + def _loader_params_res_company(self): + res = super()._loader_params_res_company() + res["search_params"]["fields"] += ["street", "city", "zip"] + return res diff --git a/l10n_es_pos_oca/pyproject.toml b/l10n_es_pos_oca/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/l10n_es_pos_oca/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/l10n_es_pos_oca/readme/CONFIGURE.md b/l10n_es_pos_oca/readme/CONFIGURE.md new file mode 100644 index 00000000000..b307f0eda59 --- /dev/null +++ b/l10n_es_pos_oca/readme/CONFIGURE.md @@ -0,0 +1,11 @@ +Para activar la factura simplificada en un TPV, iremos a *Punto de Venta +\> Configuración \> Punto de Venta* y escogeremos uno de la lista. En la +sección *Facturación y recibos* activaremos la opción *Secuencia de +Factura Simplificada*. Podemos configurar el límite a partir del cual no +se considera factura simplificada, que por defecto es 3.000,00 €. + +Si entramos en la configuración del TPV en modo debug, podremos también +configurar la sequencia asociada al TPV. + +[Ver enlace de la +AEAT](https://www.agenciatributaria.es/AEAT.internet/Inicio/_Segmentos_/Empresas_y_profesionales/Empresas/IVA/Obligaciones_de_facturacion/Tipos_de_factura.shtml) diff --git a/l10n_es_pos_oca/readme/CONTRIBUTORS.md b/l10n_es_pos_oca/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..fad81e9afe8 --- /dev/null +++ b/l10n_es_pos_oca/readme/CONTRIBUTORS.md @@ -0,0 +1,20 @@ +- [Antiun](https://www.antiun.com): + - Endika Iglesias \<\> +- [Aselcis](https://www.aselcis.com): + - David Gómez \<\> + - Miguel Paraíso \<\> +- [Acysos](https://www.acysos.com): + - Ignacio Ibeas \<\> +- [Tecnativa](https://www.tecnativa.com): + - David Vidal + - Pedro M. Baeza + - Antonio Espinosa + - Rafael Blasco + - Carlos Roca + - João Marques +- [Sygel](https://www.sygel.es): + - Manuel Regidor +- [Factor Libre](https://factorlibre.com/): + - Daniel Duque \<\> +- [APSL-Nagarro](https://www.apsl.tech): + - Antoni Marroig \<\> diff --git a/l10n_es_pos_oca/readme/DESCRIPTION.md b/l10n_es_pos_oca/readme/DESCRIPTION.md new file mode 100644 index 00000000000..d2ad100395d --- /dev/null +++ b/l10n_es_pos_oca/readme/DESCRIPTION.md @@ -0,0 +1,9 @@ +- Adapta el terminal punto de venta a la legislación Española (no se + permite la emisión de tiquets, todo deben ser facturas o facturas + simplificadas con numeración) +- Adapta el ticket de venta a la factura simplificada, añadiendo una + secuencia correlativa y el NIF del emisor. +- Incluye los datos del cliente (nombre, NIF y dirección) si hay uno + asignado. +- Chequea que no se realice una factura simplificada con valor superior + a 3.000 euros (la cantidad es configurable por TPV). diff --git a/l10n_es_pos_oca/readme/INSTALL.md b/l10n_es_pos_oca/readme/INSTALL.md new file mode 100644 index 00000000000..5bc295748df --- /dev/null +++ b/l10n_es_pos_oca/readme/INSTALL.md @@ -0,0 +1,10 @@ +Antes de instalar el módulo, podemos definir el relleno y el prefijo +automático en *Configuración \> Parámetros del sistema*: + +- l10n_es_pos.simplified_invoice_sequence.padding (o 4 cifras por + defecto) +- l10n_es_pos.simplified_invoice_sequence.prefix (nombre del TPV más + este valor) + +Al instalarse el módulo, se define una secuencia para factura +simplificada por cada TPV existente. diff --git a/l10n_es_pos_oca/readme/ROADMAP.md b/l10n_es_pos_oca/readme/ROADMAP.md new file mode 100644 index 00000000000..06f448178a1 --- /dev/null +++ b/l10n_es_pos_oca/readme/ROADMAP.md @@ -0,0 +1,8 @@ +- No se comprueba el límite en operaciones separadas para un mismo + cliente, algo que Hacienda proscribe. +- El soporte para usuarios concurrentes sobre una misma sesión es + limitado y solo es fiable si ambos puestos están online. En el caso de + que cualquiera de ellos estuviese offline, se correría el riesgo de + solapar la secuencia de factura simplificada. Se recomienda que en + estos casos se añada mejor una configuración de punto de venta + adicional. diff --git a/l10n_es_pos_oca/static/description/icon.png b/l10n_es_pos_oca/static/description/icon.png new file mode 100644 index 00000000000..4fea0817b01 Binary files /dev/null and b/l10n_es_pos_oca/static/description/icon.png differ diff --git a/l10n_es_pos_oca/static/description/index.html b/l10n_es_pos_oca/static/description/index.html new file mode 100644 index 00000000000..7c286a4a90a --- /dev/null +++ b/l10n_es_pos_oca/static/description/index.html @@ -0,0 +1,509 @@ + + + + + +Punto de venta adaptado a la legislación española + + + +
+

Punto de venta adaptado a la legislación española

+ + +

Beta License: AGPL-3 OCA/l10n-spain Translate me on Weblate Try me on Runboat

+
    +
  • Adapta el terminal punto de venta a la legislación Española (no se +permite la emisión de tiquets, todo deben ser facturas o facturas +simplificadas con numeración)
  • +
  • Adapta el ticket de venta a la factura simplificada, añadiendo una +secuencia correlativa y el NIF del emisor.
  • +
  • Incluye los datos del cliente (nombre, NIF y dirección) si hay uno +asignado.
  • +
  • Chequea que no se realice una factura simplificada con valor superior +a 3.000 euros (la cantidad es configurable por TPV).
  • +
+

Table of contents

+ +
+

Installation

+

Antes de instalar el módulo, podemos definir el relleno y el prefijo +automático en Configuración > Parámetros del sistema:

+
    +
  • l10n_es_pos.simplified_invoice_sequence.padding (o 4 cifras por +defecto)
  • +
  • l10n_es_pos.simplified_invoice_sequence.prefix (nombre del TPV más +este valor)
  • +
+

Al instalarse el módulo, se define una secuencia para factura +simplificada por cada TPV existente.

+
+
+

Configuration

+

Para activar la factura simplificada en un TPV, iremos a Punto de Venta +> Configuración > Punto de Venta y escogeremos uno de la lista. En la +sección Facturación y recibos activaremos la opción Secuencia de +Factura Simplificada. Podemos configurar el límite a partir del cual no +se considera factura simplificada, que por defecto es 3.000,00 €.

+

Si entramos en la configuración del TPV en modo debug, podremos también +configurar la sequencia asociada al TPV.

+

Ver enlace de la +AEAT

+
+
+

Known issues / Roadmap

+
    +
  • No se comprueba el límite en operaciones separadas para un mismo +cliente, algo que Hacienda proscribe.
  • +
  • El soporte para usuarios concurrentes sobre una misma sesión es +limitado y solo es fiable si ambos puestos están online. En el caso +de que cualquiera de ellos estuviese offline, se correría el riesgo +de solapar la secuencia de factura simplificada. Se recomienda que en +estos casos se añada mejor una configuración de punto de venta +adicional.
  • +
+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
  • Aselcis Consulting
  • +
  • Acysos S.L.
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

This module is part of the OCA/l10n-spain project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/l10n_es_pos_oca/static/src/app/screens/payment_screen/payment_screen.esm.js b/l10n_es_pos_oca/static/src/app/screens/payment_screen/payment_screen.esm.js new file mode 100644 index 00000000000..c5db352f52b --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/screens/payment_screen/payment_screen.esm.js @@ -0,0 +1,32 @@ +/** @odoo-module */ + +/* Copyright 2016 David Gómez Quilón + Copyright 2018 Tecnativa - David Vidal + Copyright 2020 Tecnativa - João Marques + Copyright 2024 (APSL-Nagarro) - Antoni Marroig + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {PaymentScreen} from "@point_of_sale/app/screens/payment_screen/payment_screen"; +import {patch} from "@web/core/utils/patch"; + +patch(PaymentScreen.prototype, { + async validateOrder(isForceValidate) { + const below_limit = + this.currentOrder.get_total_with_tax() <= + this.pos.config.l10n_es_simplified_invoice_limit; + if (this.pos.config.is_simplified_config) { + const order = this.currentOrder; + if (below_limit && !order.to_invoice) { + await order.set_simple_inv_number(); + } else { + // Force invoice above limit. Online is needed. + order.to_invoice = true; + } + order.partner = + order.partner || + this.pos.db.partner_by_id[this.pos.config.simplified_partner_id[0]]; + } + await super.validateOrder(isForceValidate); + }, +}); diff --git a/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/order_receipt.xml b/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/order_receipt.xml new file mode 100644 index 00000000000..b2d9d280ee4 --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/order_receipt.xml @@ -0,0 +1,19 @@ + + + + + props.data.pos_qr_code and (!props.data.is_simplified_config or props.data.is_to_invoice) + + + props.data.ticket_code and (!props.data.is_simplified_config or props.data.is_to_invoice) + + + diff --git a/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml b/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml new file mode 100644 index 00000000000..4c8a50ffa4f --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml @@ -0,0 +1,34 @@ + + + + + +
Simplified invoice
+
+ +
+
+
+
()
+ + + + +
Customer:
+
:
+
+ + + + diff --git a/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.esm.js b/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.esm.js new file mode 100644 index 00000000000..d5c1d0b4531 --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.esm.js @@ -0,0 +1,23 @@ +/** @odoo-module */ + +/* Copyright 2016 David Gómez Quilón + Copyright 2018-19 Tecnativa - David Vidal + Copyright 2024 (APSL-Nagarro) - Antoni Marroig + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {TicketScreen} from "@point_of_sale/app/screens/ticket_screen/ticket_screen"; +import {_t} from "@web/core/l10n/translation"; +import {patch} from "@web/core/utils/patch"; + +patch(TicketScreen.prototype, { + _getSearchFields() { + const fields = super._getSearchFields(); + fields.SIMPLIFIED_INVOICE = { + repr: (order) => order.name, + displayName: _t("Simplified Invoice"), + modelField: "l10n_es_unique_id", + }; + return fields; + }, +}); diff --git a/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.xml b/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.xml new file mode 100644 index 00000000000..7350c4e8a55 --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/screens/ticket_screen/ticket_screen.xml @@ -0,0 +1,23 @@ + + + + + +
Simplified Invoice
+
+ +
+
Simplified Invoice
+
+
+
+
+ +
diff --git a/l10n_es_pos_oca/static/src/app/store/models.esm.js b/l10n_es_pos_oca/static/src/app/store/models.esm.js new file mode 100644 index 00000000000..493a0733dd0 --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/store/models.esm.js @@ -0,0 +1,84 @@ +/** @odoo-module */ + +/* Copyright 2016 David Gómez Quilón + Copyright 2018-19 Tecnativa - David Vidal + Copyright 2024 (APSL-Nagarro) - Antoni Marroig + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {ConnectionLostError} from "@web/core/network/rpc_service"; +import {Order} from "@point_of_sale/app/store/models"; +import {patch} from "@web/core/utils/patch"; + +patch(Order.prototype, { + get_total_with_tax() { + const total = super.get_total_with_tax(...arguments); + const below_limit = total <= this.pos.config.l10n_es_simplified_invoice_limit; + this.is_simplified_invoice = + below_limit && this.pos.config.is_simplified_config; + return total; + }, + set_simple_inv_number() { + return this.pos + .get_simple_inv_next_number() + .then(([config]) => { + // We'll get the number from DB only when we're online. Otherwise + // the sequence will run on the client side until the orders are + // synced. + this.pos._set_simplified_invoice_number(config); + }) + .catch((error) => { + // We'll only consider network errors + if (!error instanceof ConnectionLostError) { + throw error; + } + }) + .finally(() => { + const simplified_invoice_number = + this.pos._get_simplified_invoice_number(); + this.l10n_es_unique_id = simplified_invoice_number; + this.is_simplified_invoice = true; + }); + }, + get_base_by_tax() { + const base_by_tax = {}; + this.get_orderlines().forEach(function (line) { + const tax_detail = line.get_tax_details(); + const base_price = line.get_price_without_tax(); + if (tax_detail) { + Object.keys(tax_detail).forEach(function (tax) { + if (Object.keys(base_by_tax).includes(tax)) { + base_by_tax[tax] += base_price; + } else { + base_by_tax[tax] = base_price; + } + }); + } + }); + return base_by_tax; + }, + init_from_JSON(json) { + super.init_from_JSON(...arguments); + this.to_invoice = json.to_invoice; + this.l10n_es_unique_id = json.l10n_es_unique_id; + }, + export_as_JSON() { + const res = super.export_as_JSON(...arguments); + res.to_invoice = this.is_to_invoice(); + if (!res.to_invoice) { + res.l10n_es_unique_id = this.l10n_es_unique_id; + } + return res; + }, + export_for_printing() { + const result = super.export_for_printing(...arguments); + result.l10n_es_unique_id = this.l10n_es_unique_id; + result.is_simplified_config = this.pos.config.is_simplified_config; + result.to_invoice = this.to_invoice; + const base_by_tax = this.get_base_by_tax(); + for (const tax of result.tax_details) { + tax.base = base_by_tax[tax.tax.id]; + } + return result; + }, +}); diff --git a/l10n_es_pos_oca/static/src/app/store/pos_store.esm.js b/l10n_es_pos_oca/static/src/app/store/pos_store.esm.js new file mode 100644 index 00000000000..99ce26cc1ef --- /dev/null +++ b/l10n_es_pos_oca/static/src/app/store/pos_store.esm.js @@ -0,0 +1,97 @@ +/** @odoo-module */ + +/* Copyright 2016 David Gómez Quilón + Copyright 2018-19 Tecnativa - David Vidal + Copyright 2024 (APSL-Nagarro) - Antoni Marroig + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {ConnectionLostError} from "@web/core/network/rpc_service"; +import {PosStore} from "@point_of_sale/app/store/pos_store"; +import {patch} from "@web/core/utils/patch"; + +patch(PosStore.prototype, { + async setup() { + await super.setup(...arguments); + this.pushed_simple_invoices = []; + // Unique UUID + this.own_simplified_invoice_prefix = ""; + }, + get_simple_inv_next_number() { + // If we had pending orders to sync we want to avoid getting the next number + // from the DB as we'd be ovelaping the sequence. + if (this.db.get_orders().length) { + return Promise.reject(new ConnectionLostError()); + } + return this.orm.searchRead( + "pos.config", + ["id", "=", this.config.id], + ["l10n_es_simplified_invoice_number"] + ); + }, + get_padding_simple_inv(number, padding) { + var diff = padding - number.toString().length; + let result = ""; + if (diff <= 0) { + result = number; + } else { + for (let i = 0; i < diff; i++) { + result += "0"; + } + result += number; + } + return result; + }, + _update_sequence_number() { + ++this.config.l10n_es_simplified_invoice_number; + }, + push_simple_invoice(order) { + if (this.pushed_simple_invoices.indexOf(order.data.l10n_es_unique_id) === -1) { + this.pushed_simple_invoices.push(order.data.l10n_es_unique_id); + this._update_sequence_number(); + } + }, + async _flush_orders(orders) { + var self = this; + // Save pushed orders numbers + orders.forEach((order) => { + if (!order.data.to_invoice) { + self.push_simple_invoice(order); + } + }); + return await super._flush_orders(...arguments); + }, + _set_simplified_invoice_number(config) { + this.config.l10n_es_simplified_invoice_number = + config.l10n_es_simplified_invoice_number; + }, + _get_simplified_invoice_number() { + return ( + this.config.l10n_es_simplified_invoice_prefix + + this.get_padding_simple_inv( + this.config.l10n_es_simplified_invoice_number, + this.config.l10n_es_simplified_invoice_padding + ) + ); + }, + getReceiptHeaderData(order) { + const result = super.getReceiptHeaderData(...arguments); + if (order) { + result.is_simplified_config = this.config.is_simplified_config; + result.partner = order.get_partner(); + result.l10n_es_unique_id = order.l10n_es_unique_id; + result.to_invoice = order.to_invoice; + } + return result; + }, + _getCreateOrderContext(orders) { + let context = super._getCreateOrderContext(...arguments); + const noOrderPrinting = orders.every( + (order) => !order.to_invoice && order.data.is_simplified_config + ); + if (noOrderPrinting) { + context = {...context, generate_pdf: false}; + } + return context; + }, +}); diff --git a/l10n_es_pos_oca/views/pos_views.xml b/l10n_es_pos_oca/views/pos_views.xml new file mode 100644 index 00000000000..56fde6eef30 --- /dev/null +++ b/l10n_es_pos_oca/views/pos_views.xml @@ -0,0 +1,48 @@ + + + + + pos.order.form + pos.order + + + + + + + + + + + pos.order + + + + + + + + + + + POS Order (add filters for simplified field) + pos.order + + 20 + + + + + + + + + diff --git a/l10n_es_pos_oca/views/res_config_settings_views.xml b/l10n_es_pos_oca/views/res_config_settings_views.xml new file mode 100644 index 00000000000..ca4f204f232 --- /dev/null +++ b/l10n_es_pos_oca/views/res_config_settings_views.xml @@ -0,0 +1,54 @@ + + + + res.config.settings.view.form + res.config.settings + + + + + + + + + + + + pos_company_has_template or pos_l10n_es_simplified_invoice_sequence_id + + + + + diff --git a/l10n_es_pos_oca/wizard/__init__.py b/l10n_es_pos_oca/wizard/__init__.py new file mode 100644 index 00000000000..0deb68c4680 --- /dev/null +++ b/l10n_es_pos_oca/wizard/__init__.py @@ -0,0 +1 @@ +from . import res_config_settings diff --git a/l10n_es_pos_oca/wizard/res_config_settings.py b/l10n_es_pos_oca/wizard/res_config_settings.py new file mode 100644 index 00000000000..486f41bdd8f --- /dev/null +++ b/l10n_es_pos_oca/wizard/res_config_settings.py @@ -0,0 +1,27 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + pos_iface_l10n_es_simplified_invoice = fields.Boolean( + related="pos_config_id.iface_l10n_es_simplified_invoice", + readonly=False, + ) + pos_l10n_es_simplified_invoice_sequence_id = fields.Many2one( + related="pos_config_id.l10n_es_simplified_invoice_sequence_id", + ) + pos_l10n_es_simplified_invoice_limit = fields.Float( + related="pos_config_id.l10n_es_simplified_invoice_limit", + readonly=False, + ) + pos_l10n_es_simplified_invoice_prefix = fields.Char( + related="pos_config_id.l10n_es_simplified_invoice_prefix", + ) + pos_l10n_es_simplified_invoice_padding = fields.Integer( + related="pos_config_id.l10n_es_simplified_invoice_padding", + ) + pos_l10n_es_simplified_invoice_number = fields.Integer( + related="pos_config_id.l10n_es_simplified_invoice_number", + )