From 28ef107949843d59c8bddf7f284ba9ed6b7bcd9e Mon Sep 17 00:00:00 2001 From: El Mau Date: Fri, 26 Nov 2021 13:14:43 -0600 Subject: [PATCH] =?UTF-8?q?Agregar=20cancelaci=C3=B3n=20con=20certificados?= =?UTF-8?q?=20con=20el=20pac=20CD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/main.py | 6 ++ source/app/controllers/pacs/cfdi_cert.py | 2 - .../pacs/comerciodigital/comercio.py | 16 +++- source/app/controllers/pacs/finkok/finkok.py | 8 +- source/app/controllers/utils.py | 8 +- source/app/models/db.py | 3 + source/app/models/main.py | 39 ++++++++-- source/app/settings.py | 29 -------- source/static/js/controller/products.js | 74 +++++++++++++++++++ source/static/js/ui/products.js | 8 ++ 10 files changed, 148 insertions(+), 45 deletions(-) diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index a0379d3..8146a19 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -725,6 +725,12 @@ class AppWareHouseProduct(object): req.context['result'] = self._db.warehouseproduct_get(values) resp.status = falcon.HTTP_200 + def on_post(self, req, resp): + values = req.params + user = req.env['beaker.session']['userobj'] + req.context['result'] = self._db.warehouseproduct_post(values, user) + resp.status = falcon.HTTP_200 + class AppTicketsDetails(object): diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index edb6455..4c3a0a2 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -173,8 +173,6 @@ class SATCertificate(object): tree, encoding='utf-8', xml_declaration=True).decode() # ~ xml_signed = xml_signed.replace("'", '"').replace('utf', 'UTF') - print(xml_signed) - return xml_signed @property diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index 1c17607..08c4ed9 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -17,6 +17,7 @@ # ~ along with this program. If not, see . +import base64 import logging import lxml.etree as ET @@ -146,6 +147,11 @@ class PACComercioDigital(object): return data def _get_data_cancel(self, cfdi, info, auth): + info['pass'] = '12345678a' + info['tipo'] = 'cfdi3.3' + info['key'] = base64.b64encode(info['key']).decode() + info['cer'] = base64.b64encode(info['cer']).decode() + NS_CFDI = { 'cfdi': 'http://www.sat.gob.mx/cfd/3', 'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital', @@ -200,7 +206,15 @@ class PACComercioDigital(object): self._error(result.headers['errmsg']) return '' - return result.text + tree = ET.fromstring(result.text) + date_cancel = tree.xpath('string(//Acuse/@Fecha)')[:19] + + data = { + 'acuse': result.text, + 'date': date_cancel, + } + + return data def _get_headers_cancel_xml(self, cfdi, info, auth): NS_CFDI = { diff --git a/source/app/controllers/pacs/finkok/finkok.py b/source/app/controllers/pacs/finkok/finkok.py index a333650..1bb095b 100644 --- a/source/app/controllers/pacs/finkok/finkok.py +++ b/source/app/controllers/pacs/finkok/finkok.py @@ -16,7 +16,7 @@ # ~ You should have received a copy of the GNU General Public License # ~ along with this program. If not, see . -import base64 +# ~ import base64 import datetime import logging import os @@ -129,7 +129,9 @@ class PACFinkok(object): return {} if self.CODE['200'] != ce: - log.error('CodEstatus', type(ce), ce) + self._error = ce + return {} + return result return result @@ -243,8 +245,6 @@ class PACFinkok(object): client = Client(self.URL[method], transport=self._transport, plugins=self._plugins) client.set_ns_prefix('can', 'http://facturacion.finkok.com/cancel') - # ~ xml = f'\n{xml}' - # ~ xml = f'\n{xml}' args = { 'xml': xml.encode(), 'username': auth['user'], diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index a698e6f..e5959dd 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -665,7 +665,7 @@ def get_pac_by_rfc(cfdi): return RFCS[rfc_pac] -def _cancel_finkok(invoice, auth, certificado): +def _cancel_with_cert(invoice, auth, certificado): cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) pac = PACS[auth['pac']]() info = {'cer': cert.cer_pem, 'key': cert.key_pem} @@ -682,8 +682,9 @@ def _cancel_finkok(invoice, auth, certificado): def cancel_xml_sign(invoice, auth, certificado): - if auth['pac'] == 'finkok': - return _cancel_finkok(invoice, auth, certificado) + # ~ if auth['pac'] == 'finkok': + # ~ return _cancel_finkok(invoice, auth, certificado) + return _cancel_with_cert(invoice, auth, certificado) cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) pac = PACS[auth['pac']]() @@ -695,6 +696,7 @@ def cancel_xml_sign(invoice, auth, certificado): template = TEMPLATE_CANCEL.format(**data) tree = ET.fromstring(template.encode()) sign_xml = cert.sign_xml(tree) + result = pac.cancel_xml(sign_xml, auth, invoice.xml) if pac.error: diff --git a/source/app/models/db.py b/source/app/models/db.py index e66ad23..371d006 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -496,6 +496,9 @@ class StorageEngine(object): def warehouseproduct_get(self, filters): return main.WareHouseProduct.get_data(filters) + def warehouseproduct_post(self, filters, user): + return main.WareHouseProduct.post(filters, user) + def users_get(self, filters, user): return main.Usuarios.get_data(filters, user) diff --git a/source/app/models/main.py b/source/app/models/main.py index 3e77ff9..3304533 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -4088,6 +4088,39 @@ class WareHouseProduct(BaseModel): obj.save() return + @classmethod + def _adjust_stock(cls, args, user): + cant = args['cant'] + fields = dict( + warehouse = args['storage'], + product = args['id_product'], + ) + obj = WareHouseProduct.get(**fields) + obj.exists += cant + obj.save() + + total = (WareHouseProduct + .select(fn.Sum(WareHouseProduct.exists)).alias('total') + .where(WareHouseProduct.product==fields['product']) + .limit(1) + .scalar() + ) + query = (Productos + .update(existencia=total) + .where(Productos.id==fields['product']) + ) + query.execute() + + result = {'ok': True, 'row': {'existencia': total}} + + return result + + @classmethod + def post(cls, values, user): + opt = values['opt'] + args = utils.loads(values['values']) + return getattr(cls, f'_{opt}')(args, user) + class RangosPrecios(BaseModel): producto = ForeignKeyField(Productos) @@ -4221,10 +4254,6 @@ class Facturas(BaseModel): msg = 'No es posible cancelar CFDI 3.2' return {'ok': False, 'msg': msg} - # ~ pac = Configuracion.get_('lst_pac').lower() - # ~ if pac: - # ~ data, result = utils.xml_cancel(obj.xml, auth, certificado, pac) - # ~ else: data, result = util.cancel_xml(auth, obj.uuid, certificado) if data['ok']: @@ -9915,8 +9944,6 @@ class InventoryEntries(BaseModel): result = {'ok': False, 'msg': msg} return result - print(0, args) - storage = args['target'] cant = Decimal(args['cant']) values = dict( diff --git a/source/app/settings.py b/source/app/settings.py index 4005397..7b4a3ff 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -250,35 +250,6 @@ DEFAULT_GLOBAL = { 'clave_sat': '01010101', } -# ~ TEMPLATE_CANCEL = """ - # ~ - # ~ {uuid} - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ - # ~ -# ~ -# ~ """ - TEMPLATE_CANCEL = """ {uuid} diff --git a/source/static/js/controller/products.js b/source/static/js/controller/products.js index c8b60a4..c7b31c5 100644 --- a/source/static/js/controller/products.js +++ b/source/static/js/controller/products.js @@ -910,3 +910,77 @@ function _add_entries_inventory_manual(row_id, data){ }) } + +function cmd_adjust_stock_click(id, e, node){ + var id_product = $$('txt_id_product').getValue() + var row = $$('grid_warehouse_exists').getSelectedItem() + if (row == undefined){ + msg_error('Selecciona un Almacen origen') + return + } + var warehouse_source = row.id + var cant_to_adjust = $$('txt_cant_to_adjust').getValue() + + if(cant_to_adjust == 0){ + msg_error('La cantidad a ajustar no puede ser cero') + return + } + + if(cant_to_adjust > row.exists){ + msg_error('La cantidad a ajustar no puede ser mayor a la existencia') + return + } + + var values = { + id_product: id_product, + cant: cant_to_adjust, + storage: warehouse_source, + } + + msg = '¿Estás seguro de hacer este ajuste?' + webix.confirm({ + title: 'Ajuste de Almacen', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + _adjust_stock(values) + } + } + }) +} + + +function _adjust_stock(args){ + var grid = $$('grid_products') + var row = grid.getSelectedItem() + + var values = { + opt: 'adjust_stock', + values: args, + } + + webix.ajax().sync().post('warehouseproduct', values, { + error:function(text, data, XmlHttpRequest){ + msg = 'Ocurrio un error, consulta a soporte técnico' + msg_error(msg) + }, + success:function(text, data, XmlHttpRequest){ + var values = data.json(); + if (values.ok) { + $$('txt_cant_to_adjust').setValue(0) + $$('grid_warehouse_exists').load('warehouseproduct?opt=by_product&id=' + args.id_product) + $$('grid_warehouse_exists').clearSelection() + + grid.updateItem(row['id'], values.row) + grid.refresh() + + msg_ok('Ajuste realizado correctamente') + }else{ + msg_error(values.msg) + } + } + }) +} diff --git a/source/static/js/ui/products.js b/source/static/js/ui/products.js index d908b06..eeb3472 100644 --- a/source/static/js/ui/products.js +++ b/source/static/js/ui/products.js @@ -502,6 +502,13 @@ var body_win_show_exists = {rows: [{maxHeight: 10, minHeight: 10}, labelPosition: 'top', required: false, options: []}, {maxWidth: 10}, {view: 'button', id: 'cmd_warehouse_move', label: 'Mover', maxWidth: 100}, {maxWidth: 10}]}, + {minHeight: 25, maxHeight: 25}, + {template: 'Ajuste de almacen', type: 'section'}, + {cols: [{maxWidth: 10}, + {view: 'counter', id: 'txt_cant_to_adjust', label: 'Cantidad a ajustar:', + labelPosition: 'top', step: 1, value: 0, min: -1000000}, + {view: 'button', id: 'cmd_adjust_stock', label: 'Ajustar', maxWidth: 100}, + {maxWidth: 10}]}, {maxHeight: 20, minHeight: 20}, {cols: [{}, {view: 'button', id: 'cmd_win_show_exists_close', label: 'Cerrar', type: 'danger'}, @@ -523,5 +530,6 @@ var win_show_exists = { }) $$('cmd_win_show_exists_close').attachEvent('onItemClick', cmd_win_show_exists_close_click) $$('cmd_warehouse_move').attachEvent('onItemClick', cmd_warehouse_move_click) + $$('cmd_adjust_stock').attachEvent('onItemClick', cmd_adjust_stock_click) } }