diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py index ec369ee..7054bbe 100644 --- a/source/app/controllers/cfdi_xml.py +++ b/source/app/controllers/cfdi_xml.py @@ -84,6 +84,12 @@ SAT = { 'xmlns': 'http://www.sat.gob.mx/Pagos', 'schema': ' http://www.sat.gob.mx/Pagos http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd', }, + 'divisas': { + 'version': '1.0', + 'prefix': 'divisas', + 'xmlns': 'http://www.sat.gob.mx/divisas', + 'schema': ' http://www.sat.gob.mx/divisas http://www.sat.gob.mx/sitio_internet/cfd/divisas/divisas.xsd', + }, } @@ -101,6 +107,7 @@ class CFDI(object): self._edu = False self._pagos = False self._is_nomina = False + self._divisas = '' self.error = '' def _now(self): @@ -152,6 +159,8 @@ class CFDI(object): self._ine = True self._pagos = bool(datos['complementos'].get('pagos', False)) + self._divisas = datos['comprobante'].pop('divisas', '') + if 'nomina' in datos: self._is_nomina = True return self._validate_nomina(datos) @@ -190,6 +199,12 @@ class CFDI(object): attributes[name] = SAT['edu']['xmlns'] schema_edu = SAT['edu']['schema'] + schema_divisas = '' + if self._divisas: + name = 'xmlns:{}'.format(SAT['divisas']['prefix']) + attributes[name] = SAT['divisas']['xmlns'] + schema_divisas = SAT['divisas']['schema'] + schema_nomina = '' if self._is_nomina: name = 'xmlns:{}'.format(SAT['nomina']['prefix']) @@ -204,7 +219,7 @@ class CFDI(object): attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \ schema_locales + schema_donativo + schema_ine + schema_edu + \ - schema_nomina + schema_pagos + schema_divisas + schema_nomina + schema_pagos attributes.update(datos) if not 'Version' in attributes: @@ -426,6 +441,13 @@ class CFDI(object): self._complemento = ET.SubElement( self._cfdi, '{}:Complemento'.format(self._pre)) + if self._divisas: + atributos = { + 'version': SAT['divisas']['version'], + 'tipoOperacion': self._divisas, + } + ET.SubElement(self._complemento, 'divisas:Divisas', atributos) + if 'ine' in datos: atributos = {'Version': SAT['ine']['version']} atributos.update(datos['ine']) diff --git a/source/app/models/main.py b/source/app/models/main.py index f0e47e9..082b780 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -290,6 +290,7 @@ def config_timbrar(): 'cfdi_anticipo': Configuracion.get_('chk_config_anticipo'), 'cfdi_ine': Configuracion.get_bool('chk_config_ine'), 'cfdi_edu': Configuracion.get_bool('chk_config_edu'), + 'cfdi_divisas': Configuracion.get_bool('chk_config_divisas'), 'cfdi_metodo_pago': Configuracion.get_bool('chk_config_ocultar_metodo_pago'), 'cfdi_condicion_pago': Configuracion.get_bool('chk_config_ocultar_condiciones_pago'), 'cfdi_open_pdf': Configuracion.get_bool('chk_config_open_pdf'), @@ -421,6 +422,7 @@ class Configuracion(BaseModel): 'chk_config_ine', 'chk_config_edu', 'chk_config_pagos', + 'chk_config_divisas', 'chk_cfg_pays_data_bank', ) data = (Configuracion @@ -3630,6 +3632,7 @@ class Facturas(BaseModel): estatus = TextField(default='Guardada') estatus_sat = TextField(default='Vigente') regimen_fiscal = TextField(default='') + divisas = TextField(default='') notas = TextField(default='') saldo = DecimalField(default=0.0, max_digits=20, decimal_places=6, auto_round=True) @@ -4506,6 +4509,12 @@ class Facturas(BaseModel): ine = values.pop('ine', {}) tipo_comprobante = values['tipo_comprobante'] folio_custom = values.pop('folio_custom', '') + divisas = values.pop('divisas', '') + if Configuracion.get_bool('chk_config_divisas'): + divisas = divisas.lower() + if divisas == 'ninguna': + divisas = '' + values['divisas'] = divisas emisor = Emisor.select()[0] values['serie'] = cls._get_serie(cls, user, values['serie']) @@ -4576,6 +4585,9 @@ class Facturas(BaseModel): relacionados = {} donativo = {} complementos = FacturasComplementos.get_(invoice) + comprobante['divisas'] = invoice.divisas + if invoice.divisas: + complementos['divisas'] = True if invoice.donativo: donativo['noAutorizacion'] = emisor.autorizacion @@ -4808,6 +4820,7 @@ class Facturas(BaseModel): 'edu': is_edu, 'complementos': complementos, } + return util.make_xml(data, certificado, auth) @classmethod @@ -8973,6 +8986,12 @@ def _migrate_tables(rfc=''): migrations.append(migrator.add_column( table, 'empaques', empaques)) + table = 'facturas' + columns = [c.name for c in database_proxy.get_columns(table)] + if not 'divisas' in columns: + divisas = TextField(default='') + migrations.append(migrator.add_column(table, 'divisas', divisas)) + if migrations: with database_proxy.atomic() as txn: migrate(*migrations) diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index d533bdc..e577f4d 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -107,6 +107,7 @@ var controllers = { $$('chk_config_ine').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_edu').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_pagos').attachEvent('onItemClick', chk_config_item_click) + $$('chk_config_divisas').attachEvent('onItemClick', chk_config_item_click) $$('chk_cfg_pays_data_bank').attachEvent('onItemClick', chk_config_item_click) $$('chk_usar_punto_de_venta').attachEvent('onItemClick', chk_config_item_click) $$('chk_ticket_pdf_show').attachEvent('onItemClick', chk_config_item_click) diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 0d607d1..bb7c799 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -217,6 +217,7 @@ function default_config(){ $$('grid_details').showColumn('student') } show('fs_students', values.cfdi_edu) + show('fs_divisas', values.cfdi_divisas) show('txt_folio_custom', values.cfdi_folio_custom) }) } @@ -638,6 +639,7 @@ function guardar_y_timbrar(values){ data['donativo'] = donativo data['notas'] = values.notas data['folio_custom'] = $$('txt_folio_custom').getValue() + data['divisas'] = $$('opt_divisas').getValue() var usar_ine = $$('chk_cfdi_usar_ine').getValue() if(usar_ine){ diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 405e968..d419f15 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -756,6 +756,12 @@ var options_admin_complements = [ {view: 'text', id: 'txt_config_cfdipay_folio', name: 'txt_config_cfdipay_serie', label: 'Folio', labelWidth: 50, labelAlign: 'right'}, {maxWidth: 15}]}, + {maxHeight: 20}, + {template: 'Complemento de Divisas', type: 'section'}, + {cols: [{maxWidth: 15}, + {view: 'checkbox', id: 'chk_config_divisas', labelWidth: 0, + labelRight: 'Usar complemento de divisas'}, + {maxWidth: 15}]}, ] diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 0370bb1..9357a55 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -535,6 +535,12 @@ var body_moneda = {cols: [ ]} +var body_divisas = {cols: [ + {view: 'radio', id: 'opt_divisas', name: 'opt_divisas', + options: ['Ninguna', 'Compra', 'Venta']}, +]} + + var body_regimen_fiscal = { view: 'richselect', id: 'lst_regimen_fiscal', @@ -593,6 +599,7 @@ var controls_generate = [ {view: 'fieldset', label: 'Comprobante', body: body_comprobante}, {view: 'fieldset', label: 'Opciones de Pago', body: body_opciones}, {view: 'fieldset', id: 'fs_moneda', label: 'Moneda', body: body_moneda}, + {view: 'fieldset', id: 'fs_divisas', label: 'Divisas - Tipo de OperaciĆ³n', body: body_divisas}, {view: 'fieldset', id: 'fs_regimen_fiscal', label: 'Regimen Fiscal', body: body_regimen_fiscal}, ]} diff --git a/source/xslt/cadena.xslt b/source/xslt/cadena.xslt index 81d45ac..4c6e2d5 100644 --- a/source/xslt/cadena.xslt +++ b/source/xslt/cadena.xslt @@ -13,9 +13,10 @@ + + + + + + + + + + + +