From 533f8c5f4172db61ca2a2872f466746d76aa7f99 Mon Sep 17 00:00:00 2001 From: "Bruno Zanotti (ADHOC)" Date: Fri, 4 Jun 2021 12:17:56 -0300 Subject: [PATCH] [ADD] l10n_ar_pos: New module l10n_ar_pos Inherit all the functionalities of Odoo POS and adapt to the Argentinean localization. --- l10n_ar_pos/__init__.py | 3 + l10n_ar_pos/__manifest__.py | 26 ++ l10n_ar_pos/models/__init__.py | 2 + l10n_ar_pos/models/pos_config.py | 21 ++ l10n_ar_pos/models/res_partner.py | 15 ++ l10n_ar_pos/static/description/icon.png | Bin 0 -> 1564 bytes l10n_ar_pos/static/src/css/pos_receipts.css | 5 + l10n_ar_pos/static/src/js/models.js | 130 ++++++++++ l10n_ar_pos/static/src/js/screens.js | 209 ++++++++++++++++ l10n_ar_pos/static/src/xml/pos.xml | 262 ++++++++++++++++++++ l10n_ar_pos/static/src/xml/xml_receipt.xml | 258 +++++++++++++++++++ l10n_ar_pos/views/assets_backend.xml | 11 + l10n_ar_pos/views/pos_config.xml | 33 +++ 13 files changed, 975 insertions(+) create mode 100644 l10n_ar_pos/__init__.py create mode 100644 l10n_ar_pos/__manifest__.py create mode 100644 l10n_ar_pos/models/__init__.py create mode 100755 l10n_ar_pos/models/pos_config.py create mode 100755 l10n_ar_pos/models/res_partner.py create mode 100644 l10n_ar_pos/static/description/icon.png create mode 100644 l10n_ar_pos/static/src/css/pos_receipts.css create mode 100644 l10n_ar_pos/static/src/js/models.js create mode 100644 l10n_ar_pos/static/src/js/screens.js create mode 100644 l10n_ar_pos/static/src/xml/pos.xml create mode 100644 l10n_ar_pos/static/src/xml/xml_receipt.xml create mode 100644 l10n_ar_pos/views/assets_backend.xml create mode 100755 l10n_ar_pos/views/pos_config.xml diff --git a/l10n_ar_pos/__init__.py b/l10n_ar_pos/__init__.py new file mode 100644 index 00000000..d6210b12 --- /dev/null +++ b/l10n_ar_pos/__init__.py @@ -0,0 +1,3 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/l10n_ar_pos/__manifest__.py b/l10n_ar_pos/__manifest__.py new file mode 100644 index 00000000..ffb7cada --- /dev/null +++ b/l10n_ar_pos/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': 'Argentinian Point of Sale', + 'version': "1.0", + 'description': "Adapt the Point of Sale to Argentinean localization.", + 'author': 'ADHOC SA, Ing. Gabriela Rivero', + 'category': 'Localization', + 'depends': [ + 'l10n_ar_edi', + 'point_of_sale', + ], + 'data': [ + 'views/assets_backend.xml', + 'views/pos_config.xml', + ], + 'demo': [ + ], + 'qweb': [ + 'static/src/xml/pos.xml', + 'static/src/xml/xml_receipt.xml', + ], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/l10n_ar_pos/models/__init__.py b/l10n_ar_pos/models/__init__.py new file mode 100644 index 00000000..011438e7 --- /dev/null +++ b/l10n_ar_pos/models/__init__.py @@ -0,0 +1,2 @@ +from . import res_partner +from . import pos_config diff --git a/l10n_ar_pos/models/pos_config.py b/l10n_ar_pos/models/pos_config.py new file mode 100755 index 00000000..e2206c3c --- /dev/null +++ b/l10n_ar_pos/models/pos_config.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models, _ + + +class pos_config(models.Model): + + _inherit = "pos.config" + + pos_auto_invoice = fields.Boolean( + 'POS auto invoice', + help='POS auto to checked to invoice button', + default=True, + ) + receipt_invoice_number = fields.Boolean( + 'Receipt show invoice number', + default=True, + ) + receipt_customer_vat = fields.Boolean( + 'Receipt show customer VAT', + default=True, + ) diff --git a/l10n_ar_pos/models/res_partner.py b/l10n_ar_pos/models/res_partner.py new file mode 100755 index 00000000..b9c048df --- /dev/null +++ b/l10n_ar_pos/models/res_partner.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from odoo import api, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + # TODO: sin esto sale un error al guardar un nuevo cliente. Revisar. + @api.constrains('vat', 'l10n_latam_identification_type_id') + def check_vat(self): + type_id = int(self.l10n_latam_identification_type_id.id) + l10n_ar_partners = self.filtered(lambda self: self.env['l10n_latam.identification.type'].browse(type_id).l10n_ar_afip_code) + l10n_ar_partners.l10n_ar_identification_validation() + return super(ResPartner, self - l10n_ar_partners).check_vat() + diff --git a/l10n_ar_pos/static/description/icon.png b/l10n_ar_pos/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bc3bad4fb1aae12563cdfae3aad069a8892c588a GIT binary patch literal 1564 zcmV+%2IKjOP)Px&08mU+MF0Q*S-06(roC6V*j2B+SGLnxv(8zx(pRm$ zShv|%uDw{c+*q^IR;$QPo3K~E|NsC0Sib&N!2MUh{Z+sJ|Ns6~!ueRf`)bDdRlojM zz4-Y4{8_;HrQZDh|NmFL>;M1#$?o}Az3Tq{{#L*L$nN=Az4ceW{8_l)|Nj2q;NZya z_*lL9|Ns2{{{8s={H5Ogqu%>kzWx6G{Qmv@TD|_I-TYX-{a3#K|Ni?}zxV$C`~Cm@ z{{Q{`{rmj;`0Le2RlxpOzW-Lg{#n2J{r~$`zx`Lh`&qyJSiSf7{rvy__5T0=S-Ic; z{Qdp@`uF|%{{8j;|NHFcvH$+~?(4+n-je6iSn1e%SHAOEzx-Cd{aL>B#_#!P$M{&h z`BcIDQ^NiC{rUd?`BuOCTDRcf;NDld-u(LTYQ*>X`SADm*u)0?fCoo?&aE$ z`}*qm_UiWV+VASi=H#aI^3V44-2MLY=ijjT_u=f=bLQEH<=vX(*MsHPW8~PA=+|-L z*ns8DKknF6`uY0l+j{BMdgR=m>(fr#$Z6ciJLS+z@YF%%%sk`CGvLb*x1Jf0dkR&) z@K(L+Sia*{zwf5p{cFYfSF_Pqz3E!I@@U2TRl)I7!~0pb-B-Ba`}gVD;NO+X;`s6E z`1Rla{{Qpu-TL+M?&ZPp?a}My()axN_3zZ@+@1XU>EhUg*@+oajonCRe==i`Xw z;;-1wbn)`xS-RW(`uFG5faTYH?(5Fw+KW}e_GY}@-r?b~*5Bvab==O8-^xz)^WNss zRN~NF;>%qB`}zC-{NvYp+0&%y(QM<)I_cr5>*l-M&UowQrQgLr?CZMY$VB4MKI`DE z?(5U>@XO`m%G$Ci{w%S`LjV${D8wWSo{%}CS0Jj$^t<DDl7o_W%F@4|GyaQvlI_(F%Wme+tnG(b3TgrajB}0007?Nkl1$%`;w#T0m_+gN{mqn+Vl_ z+X99dAu)F$s(}<=1~ozVC_$rv|EqRNQZAOBDKI%(o#hxUe5b`%@9bCEzDab7k^dpe2MS%ty z>nbQHXaa!(7NDz}?CPJfHhAOaZNVig0=+GDb+IYagaOMm27iB7S5X2WWPNr{cA>qU zrKK(*rD+UF0bT*p1c29?HEWUr0=&Gu2&t4_#9(MJ-ONlDKQJ={0s{~rq|$IPLyW1Z zk&6s|;9>*><{lm%QG`@lr7}c1OGZ0O5&$Yd0952iNS$QLXzOd#z)=H74a91oFGHlG zqnj|*fO|T_)M=BaD9K|3O1ObME--5*0~;$VJM{n?)9Ap}C>RC90{{Se@!WOwiV=+f O0000 0) { + if (orders[0]['account_move']) { + // el array 1 de Split es el que tiene el nro! + var invoice_number = orders[0]['account_move'][1].split(" ")[1]; + var invoice_letter = orders[0]['account_move'][1].split(" ")[0].substring(3, 4); + var account_move = orders[0]['account_move'][0] + self.receipt_data['order']['invoice_number'] = invoice_number; + self.receipt_data['order']['invoice_letter'] = invoice_letter; + //---- + var company_id = self['pos']['company']['id']; + var partner_id = self['pos']['company']['partner_id'][0]; + rpc.query({ + model: 'res.company', + method: 'search_read', + args: [[['id', '=', company_id]], ['l10n_ar_afip_start_date']], + }).then(function (company_dict) { + self.pos.get_order()['l10n_ar_afip_start_date'] = company_dict[0]['l10n_ar_afip_start_date']; + + rpc.query({ + model: 'res.partner', + method: 'search_read', + args: [[['id', '=', partner_id]], ['vat', + 'l10n_ar_gross_income_number', + 'l10n_ar_afip_responsibility_type_id', + 'street', 'city', 'state_id', 'country_id', 'company_registry']], + } + + ).then(function (company_partner) { + self.receipt_data['order']['vat'] = company_partner[0]['vat']; + self.receipt_data['order']['l10n_ar_gross_income_number'] = company_partner[0]['l10n_ar_gross_income_number']; + self.receipt_data['order']['l10n_ar_afip_start_date'] = company_partner[0]['l10n_ar_afip_start_date']; + self.receipt_data['order']['l10n_ar_afip_responsibility_type_id'] = company_partner[0]['l10n_ar_afip_responsibility_type_id'][1]; + self.receipt_data['order']['street'] = company_partner[0]['street'] + ', ' + + company_partner[0]['city'] + ', ' + + company_partner[0]['state_id'][1] + ', ' + + company_partner[0]['country_id'][1]; + self.receipt_data['order']['company_registry'] = company_partner[0]['company_registry']; + //--------- + rpc.query({ + model: 'account.move', + method: 'search_read', + args: [[['id', '=', account_move]], ['l10n_ar_afip_auth_code', + 'l10n_ar_afip_auth_code_due', + 'l10n_ar_afip_qr_code', + 'l10n_latam_document_type_id', + ]], + } + + ).then(function (invoices) { + self.receipt_data['order']['l10n_ar_afip_qr_code'] = invoices[0]['l10n_ar_afip_qr_code']; + self.receipt_data['order']['l10n_ar_afip_auth_code'] = invoices[0]['l10n_ar_afip_auth_code']; + self.receipt_data['order']['l10n_ar_afip_auth_code_due'] = invoices[0]['l10n_ar_afip_auth_code_due']; + self.receipt_data['order']['l10n_latam_document_type_id'] = invoices[0]['l10n_latam_document_type_id'][1].split(" ")[0]; + var receipt = qweb.render('XmlReceipt', self.receipt_data); + self.pos.proxy.print_receipt(receipt); + }); + }); + }); + } + } + }); + } else { + this._super(); + } + }, + // CON LA FUNCION RENDER_RECEIPT deben traerse los modelos para poder usar en el recibo + render_receipt: function () { + this._super(); + var self = this; + var order = this.pos.get_order(); // Ok!! + + if (!this.pos.config.iface_print_via_proxy && this.pos.config.receipt_invoice_number && order.is_to_invoice()) { + var invoiced = new $.Deferred(); + rpc.query({ + // IMPORTANTISIMO **************************** + // DESDE ESTE MODELO SE ESTA IMPORTANDO account_move para relacionar + // + model: 'pos.order', + method: 'search_read', + domain: [['pos_reference', '=', order['name']]], + // account_move es un campo nativo de pos.order + fields: ['account_move'] + }).then(function (orders) { + if (orders.length > 0 && orders[0]['account_move'] && orders[0]['account_move'][1]) { + var invoice_number = orders[0]['account_move'][1].split(" ")[1]; + var invoice_letter = orders[0]['account_move'][1].split(" ")[0].substring(3, 4); + var account_move = orders[0]['account_move'][0] + self.pos.get_order()['invoice_number'] = invoice_number; + self.pos.get_order()['invoice_letter'] = invoice_letter; + //---- + var company_id = self['pos']['company']['id']; + var partner_id = self['pos']['company']['partner_id'][0]; + + rpc.query({ + model: 'res.company', + method: 'search_read', + args: [[['id', '=', company_id]], ['l10n_ar_afip_start_date', 'company_registry']], + }).then(function (company_dict) { + self.pos.get_order()['l10n_ar_afip_start_date'] = company_dict[0]['l10n_ar_afip_start_date']; + self.pos.get_order()['company_registry'] = company_dict[0]['company_registry']; + rpc.query({ + model: 'res.partner', + method: 'search_read', + args: [[['id', '=', partner_id]], ['vat', + 'l10n_ar_gross_income_number', + 'l10n_ar_afip_responsibility_type_id', + 'street', 'city', 'state_id', 'country_id']], + } + + ).then(function (company_partner) { + self.pos.get_order()['vat'] = company_partner[0]['vat']; + self.pos.get_order()['l10n_ar_gross_income_number'] = company_partner[0]['l10n_ar_gross_income_number']; + self.pos.get_order()['l10n_ar_afip_responsibility_type_id'] = company_partner[0]['l10n_ar_afip_responsibility_type_id'][1]; + self.pos.get_order()['street'] = company_partner[0]['street'] + ', ' + + company_partner[0]['city'] + ', ' + + company_partner[0]['state_id'][1] + ', ' + + company_partner[0]['country_id'][1]; + //--------- + rpc.query({ + model: 'account.move', + method: 'search_read', + args: [[['id', '=', account_move]], ['l10n_ar_afip_auth_code', + 'l10n_ar_afip_auth_code_due', + 'l10n_ar_afip_qr_code', + 'l10n_latam_document_type_id', + 'invoice_date', + ]], + } + + ).then(function (invoices) { + console.log('invoices', invoices); + self.pos.get_order()['l10n_ar_afip_qr_code'] = invoices[0]['l10n_ar_afip_qr_code']; + self.pos.get_order()['l10n_ar_afip_auth_code'] = invoices[0]['l10n_ar_afip_auth_code']; + self.pos.get_order()['l10n_ar_afip_auth_code_due'] = invoices[0]['l10n_ar_afip_auth_code_due']; + self.pos.get_order()['l10n_latam_document_type_id'] = invoices[0]['l10n_latam_document_type_id'][1].split(" ")[0]; + self.pos.get_order()['invoice_date'] = invoices[0]['invoice_date']; + self.$('.pos-receipt-container').html(qweb.render('OrderReceipt', self.get_receipt_render_env())); + + }); + }); + }); + } + invoiced.resolve(); + }).catch(function (type, error) { + invoiced.reject(error); + }); + return invoiced; + } else { + this._super(); + } + } + }) + + screens.ClientListScreenWidget.include({ + save_client_details: function (partner) { + var self = this; + var fields = {}; + this.$('.client-details-contents .detail').each(function(idx,el){ + if (self.integer_client_details.includes(el.name)){ + var parsed_value = parseInt(el.value, 10); + if (isNaN(parsed_value)){ + fields[el.name] = false; + } + else{ + fields[el.name] = parsed_value + } + } + else{ + fields[el.name] = el.value || false; + } + }); + // If the responsibility type is "responsable inscripto", then the document number is required. + if (!fields.vat && fields.l10n_ar_afip_responsibility_type_id == '1' ) { + this.gui.show_popup('error',_t('For the selected AFIP Responsibility el campo "Document number" es requerido.')); + return; + } + // If the responsibility type is "responsable inscripto", then the document type should be CUIT. + if (fields.l10n_latam_identification_type_id != '4' && fields.l10n_ar_afip_responsibility_type_id == '1' ) { + this.gui.show_popup('error',_t('For the selected AFIP Responsibility you will need to set CUIT Identification Type')); + return; + } + this._super(partner); + }, + }); + +}); diff --git a/l10n_ar_pos/static/src/xml/pos.xml b/l10n_ar_pos/static/src/xml/pos.xml new file mode 100644 index 00000000..b07d3cba --- /dev/null +++ b/l10n_ar_pos/static/src/xml/pos.xml @@ -0,0 +1,262 @@ + + + + + + +
+ AFIP Resp. + +
+
+ Document type + +
+
+
+ + + +
+ AFIP Resp. + + + + + N/A + +
+
+ Document type + + + + + N/A + +
+
+
+ + + + AFIP Responsibility + Document Type + Document Number + + + + + + + + + + + + + +
+ + + +
+
+ + +

+ +

+
+
+ +
+ +
CUIT:
+
Ing. Brutos:
+
Inicio de actividades:
+
+
Dirección:
+
+
+
+ + +
+
+ + FACTURA - ORIGINAL + + - COD + +
+ N° DE FACTURA:
+ FECHA:
+
+
+
+
+ + +
+ + CLIENTE:
+ + : + + +
+
+ +
+
+ + CALLE: + + , + + + , + + + , + +
+
+ + Email:
+
+ + Tel:
+
+ + Website:
+
+ +
+
+ +
+
+
Servido por
+
+
+
+ +
DESCRIPCIÓN
+
CANT. x PRECIO UNIT. +         +         +         + IMPORTE
+
+
+
+ + +
+ +
+ +
+ CAE: +
+ Vto. CAE: +
+
+
+
+ +
+ + + +
+ +
->
+
+ +
+ + + + + + +
+
+ +
+ Discount: % +
+
+
+ + + x + + + + + + + + + + + + + + + + + + +
+
+ + + +
--------
+
+
Subtotal
+ +
+ + +
+
+
+ +
--------
+
+
Subtotal
+ +
+ + +
+
+
+
+
+ + +
+ + diff --git a/l10n_ar_pos/static/src/xml/xml_receipt.xml b/l10n_ar_pos/static/src/xml/xml_receipt.xml new file mode 100644 index 00000000..b5f19fe9 --- /dev/null +++ b/l10n_ar_pos/static/src/xml/xml_receipt.xml @@ -0,0 +1,258 @@ + + + + + + + + + + + +
+
+ + + + +


+
+
+
+ CUIT: + +
+
+ IIBB: +
+
+ Inicio de actividades: +
+
+ Dirección: +
+
+ +
+ Teléfono: +
+
+
+
+ + +
+
+ FACTURA - ORIGINAL + + - COD + +
+ N° DE FACTURA:
+ FECHA: +
+
+
+ + + + CLIENTE: + + : + + +
+
+ +
+
+ + DIRECCION: + + , + + + , + + + , + +
+
+ + Email:
+
+ + Tel:
+
+ + Website:
+
+
+
+
+ + + + +
+ + + + + + + + + + + + + + Discount: % + + + + + + + + + + + + + + + + + + + + + + x + + + + + + + + + + + +
+ + + + + + + + -------- + Subtotal + + + + + + + + + + + -------- + +
        TOTAL
+ +
+

+ + + + + + + + + +
+ + + +
        CHANGE
+ +
+
+
+ + + + + + Discounts + + + + + + + + + + + + + + + Total Taxes + + + + + +