From a54ad8d760533c7284e291bbb783226b38f26fb5 Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Thu, 31 Dec 2020 15:08:49 -0600 Subject: [PATCH] Cancel sign xml --- .../pacs/comerciodigital/comercio.py | 5 +-- source/app/controllers/utils.py | 27 ++++++++++++++ source/app/models/main.py | 36 ++++++++++++++++--- source/static/js/controller/invoices.js | 1 + 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index bcca148..cc38b90 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -231,9 +231,10 @@ class PACComercioDigital(object): return headers - def cancel_xml(self, cfdi, xml, info, auth={}): - if not auth: + def cancel_xml(self, cfdi, xml, auth={}, info={'tipo': 'cfdi3.3'}): + if DEBUG or not auth: auth = AUTH + url = self.URL['cancelxml'] headers = self._get_headers_cancel_xml(cfdi, info, auth) result = self._post(url, xml, headers) diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 475543f..b73feb9 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -645,3 +645,30 @@ def make_xml(data, certificado): xslt.close() return cfdi.add_sello(stamp, cert.cer_txt) + + +def cancel_xml_sign(invoice, auth, certificado): + cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) + pac = PACS[auth['pac']]() + data = { + 'rfc': certificado.rfc, + 'fecha': now().isoformat()[:19], + 'uuid': invoice.uuid, + } + template = TEMPLATE_CANCEL.format(**data) + tree = ET.fromstring(template.encode()) + tree = cert.sign_xml(tree) + sign_xml = ET.tostring(tree).decode() + + result = pac.cancel_xml(invoice.xml, sign_xml, auth) + if pac.error: + result = {'ok': False, 'msg': pac.error, 'row': {}} + return result + + tree = ET.fromstring(result) + date_cancel = tree.xpath('string(//Acuse/@Fecha)')[:19] + + msg = 'Factura cancelada correctamente' + result = {'ok': True, 'msg': '', 'row': {'estatus': 'Cancelada'}, + 'Fecha': date_cancel, 'Acuse': result} + return result diff --git a/source/app/models/main.py b/source/app/models/main.py index ace7519..adeb242 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -3845,11 +3845,39 @@ class Facturas(BaseModel): obj.fecha_cancelacion = util.now() obj.save() msg = 'Factura cancelada correctamente' - return {'ok': True, 'msg': msg, 'row': {'estatus': 'Cancelada'}} + return {'ok': True, 'msg': msg, 'row': {'estatus': obj.estatus}} + + # ~ if CANCEL_SIGNATURE: + # ~ return cls._cancel_signature(cls, id) + # ~ return cls._cancel_xml(cls, id) + return cls._cancel_xml_sign(obj) + + @classmethod + def _cancel_xml_sign(cls, invoice): + if invoice.version != '3.3': + msg = 'Solo es posible cancelar CFDI 3.3' + return {'ok': False, 'msg': msg} + + auth = Configuracion.get_({'fields': 'pac_auth'}) + certificado = Certificado.get(Certificado.es_fiel==False) + result = utils.cancel_xml_sign(invoice, auth, certificado) + + if result['ok']: + invoice.estatus = 'Cancelada' + invoice.error = '' + invoice.cancelada = True + invoice.fecha_cancelacion = result['Fecha'] + invoice.acuse = result['Acuse'] or '' + cls._actualizar_saldo_cliente(cls, invoice, True) + cls._update_inventory(cls, invoice, True) + cls._uncancel_tickets(cls, invoice) + else: + invoice.error = result['msg'] + invoice.save() + + data = {'ok': result['ok'], 'msg': result['msg'], 'row': result['row']} + return data - if CANCEL_SIGNATURE: - return cls._cancel_signature(cls, id) - return cls._cancel_xml(cls, id) def _cancel_xml(self, id): msg = 'Factura cancelada correctamente' diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 1cbd0a3..c95f30f 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -1366,6 +1366,7 @@ function send_cancel(id){ msg_ok(values.msg) gi.updateItem(id, values.row) }else{ + msg_error('No fue posible cancelar') webix.alert({ title: 'Error al Cancelar', text: values.msg,