From dc61d3b01063e76d8506c4b6fb307daf0d923857 Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Thu, 10 Jun 2021 21:39:15 -0500 Subject: [PATCH] Parse details from CFDI --- requirements.txt | 1 - source/app/controllers/pycfdi.py | 20 ++++++++++++++++++++ source/app/controllers/utils.py | 14 ++++++++++++++ source/static/js/controller/products.js | 5 +++++ source/static/js/ui/products.js | 6 +++--- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6e32811..d65df38 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,4 +19,3 @@ xmlsec # pyusb # pyserial # qrcode - diff --git a/source/app/controllers/pycfdi.py b/source/app/controllers/pycfdi.py index 956d57f..f098330 100644 --- a/source/app/controllers/pycfdi.py +++ b/source/app/controllers/pycfdi.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +from decimal import Decimal, getcontext +getcontext().prec = 6 + import lxml.etree as ET from requests.structures import CaseInsensitiveDict as CIDict @@ -54,6 +57,10 @@ class CfdiRead(object): self._data['receptor'] = self._get_attr(node_name) self._rfc_receptor = self._data['receptor']['Rfc'] + node_name = f'{PRE}/cfdi:Complemento/tfd:TimbreFiscalDigital' + self._data['timbre'] = self._get_attr(node_name) + + self._parse_details() return def _get_attr(self, node_name): @@ -61,6 +68,19 @@ class CfdiRead(object): attr = dict(node.attrib) return attr + def _parse_details(self): + node_name = f'{PRE}/cfdi:Conceptos/cfdi:Concepto' + details = self._tree.xpath(node_name, namespaces=NS_CFDI) + rows = [] + for detail in details: + row = dict(detail.attrib) + for k, v in row.items(): + if k in ('Cantidad', 'ValorUnitario', 'Descuento', 'Importe'): + row[k] = Decimal(v) + # ~ row['taxes'] = self._get_taxes(detail) + rows.append(row) + self._data['conceptos'] = rows + return class CfdiWrite(object): diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index a181e01..05e04ae 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -792,6 +792,20 @@ def _products_from_xml(rfc, data): return result result['data'] = cfdi.data + products = result['data']['conceptos'] + rows = [] + for p in products: + row = { + 'key': p['NoIdentificacion'], + 'key_sat': p['ClaveProdServ'], + 'description': p['Descripcion'], + 'unit': p['Unidad'], + 'unit_value': p['ValorUnitario'], + 'import': p['Importe'], + 'cant': p['Cantidad'], + } + rows.append(row) + result['data']['conceptos'] = rows return result diff --git a/source/static/js/controller/products.js b/source/static/js/controller/products.js index e6d50a3..05ebef1 100644 --- a/source/static/js/controller/products.js +++ b/source/static/js/controller/products.js @@ -512,10 +512,15 @@ function up_products_from_xml_upload_complete(response){ return } + var grid = $$('grid_partner_products') var data = response.data var html = '' html += data.emisor.Nombre + ' (' + data.emisor.Rfc + ')' $$('lbl_partner').setValue(html) + grid.clearAll(); + grid.parse(data.conceptos, 'json'); + grid.refresh() + } diff --git a/source/static/js/ui/products.js b/source/static/js/ui/products.js index 5021d39..4f3a650 100644 --- a/source/static/js/ui/products.js +++ b/source/static/js/ui/products.js @@ -233,10 +233,10 @@ var grid_partner_products_cols = [ {id: 'key_sat', header:{text: 'Clave SAT', css: 'center'}, width: 100, adjust: 'data'}, {id: 'description', header:{text: 'DescripciĆ³n', css: 'center'}, - fillspace: true, editor: 'popup'}, + fillspace: true}, {id: "pedimento", header: 'Pedimento', editor: 'text', hidden: true}, {id: 'unit', header:{text: 'Unidad', css: 'center'}, width: 100, - editor: 'select', options: 'values/unidades'}, + adjust: 'data'}, {id: 'unit_value', header:{text: 'Valor Unitario', css: 'center'}, width: 100, format: format_currency, css: 'right', editor: 'text'}, //~ {id: 'descuento', header:{text: 'Descuento', css: 'center'}, @@ -245,7 +245,7 @@ var grid_partner_products_cols = [ //~ format: webix.i18n.priceFormat, css: 'right'}, {id: 'import', header:{text: 'Importe', css: 'center'}, width: 100, format: webix.i18n.priceFormat, css: 'right'}, - {id: 'cantidad', header: {text: 'Cantidad', css: 'center'}, width: 50, + {id: 'cant', header: {text: 'Cantidad', css: 'center'}, width: 50, format: webix.i18n.numberFormat, css: 'right', editor: 'text'}, {id: 'separate', header: '', width: 25}, {id: 'id_product', header: '', hidden: true},