forked from elmau/empresa-libre
Cancel by rfc of pac
This commit is contained in:
parent
348a7f6ecb
commit
a7945dba58
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,7 +1,30 @@
|
|||
v 1.40.0 [20-12-2020]
|
||||
v 1.40.0 [04-ene-2021]
|
||||
----------------------
|
||||
- Error: Al parsear XML en Python 3.9+
|
||||
- Mejora: Agregar versión de Empresa Libre a plantilla.
|
||||
- Mejora: Sellado en memoria
|
||||
- Mejora: Se agrega un segundo PAC y se refactoriza el timbrado.
|
||||
|
||||
* **IMPORTANTE**
|
||||
|
||||
Es necesario seguir una serie de pasos **obligatorios** para migrar a esta
|
||||
versión, **no continues hasta seguir paso a paso** estas instrucciones.
|
||||
**Antes** de comenzar ten a la mano tus certificados de sello para timbrar, es
|
||||
necesario subirlos de nuevo. **NO actualices si no tienes tus certificados**
|
||||
con su respectiva contraseña, te quedarás sin poder timbrar.
|
||||
|
||||
1. Entra a la parte administrativa y toma de tus credenciales de timbrado en el
|
||||
menú "Emisor" ficha "Otros Datos", usuario y token de timbrado.
|
||||
1. Agregar nuevo requerimiento `pip install xmlsec`
|
||||
1. Actualizar `git pull origin master`
|
||||
1. Entrar a `app/controllers/pacs` y copiar `conf.py.example` a `conf.py`
|
||||
1. Reiniciar el servicio: `sudo systemctl restart empresalibre`
|
||||
1. Sube de nuevo tus certificados en el menú "Emisor" ficha "Certificado".
|
||||
1. Ve al menú "Opciones", ficha "Otros".
|
||||
1. Selecciona tu PAC, si tu usuario es un correo electrónico, invariablemente
|
||||
debes seleccionar Finkok.
|
||||
1. Establece las credenciales del punto 1.
|
||||
1. Guarda los datos.
|
||||
|
||||
|
||||
v 1.39.1 [17-sep-2020]
|
||||
|
|
|
@ -231,7 +231,7 @@ class PACComercioDigital(object):
|
|||
|
||||
return headers
|
||||
|
||||
def cancel_xml(self, cfdi, xml, auth={}, info={'tipo': 'cfdi3.3'}):
|
||||
def cancel_xml(self, xml, auth={}, cfdi='', info={'tipo': 'cfdi3.3'}):
|
||||
if DEBUG or not auth:
|
||||
auth = AUTH
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ logging.getLogger('zeep').setLevel(logging.ERROR)
|
|||
|
||||
|
||||
TIMEOUT = 10
|
||||
DEBUG_SOAP = True
|
||||
DEBUG_SOAP = False
|
||||
|
||||
|
||||
class DebugPlugin(Plugin):
|
||||
|
@ -113,6 +113,10 @@ class PACFinkok(object):
|
|||
self._error = 'UUID ' + self.CODE['NE']
|
||||
return {}
|
||||
|
||||
if ce == 'UUID Not Found':
|
||||
self._error = 'UUID ' + self.CODE['NE']
|
||||
return {}
|
||||
|
||||
if self.CODE['200'] != ce:
|
||||
log.error('CodEstatus', type(ce), ce)
|
||||
return result
|
||||
|
@ -228,8 +232,8 @@ class PACFinkok(object):
|
|||
}
|
||||
return data
|
||||
|
||||
def cancel_xml(self, xml, auth={}):
|
||||
if not auth:
|
||||
def cancel_xml(self, xml, auth={}, cfdi=''):
|
||||
if DEBUG or not auth:
|
||||
auth = AUTH
|
||||
|
||||
method = 'cancel'
|
||||
|
|
|
@ -50,7 +50,7 @@ from dateutil import parser
|
|||
|
||||
from .cfdi_xml import CFDI
|
||||
|
||||
from settings import DEBUG, DB_COMPANIES, PATHS, TEMPLATE_CANCEL
|
||||
from settings import DEBUG, DB_COMPANIES, PATHS, TEMPLATE_CANCEL, RFCS
|
||||
|
||||
from .pacs.cfdi_cert import SATCertificate
|
||||
from .pacs import PACComercioDigital
|
||||
|
@ -79,6 +79,11 @@ PACS = {
|
|||
'finkok': PACFinkok,
|
||||
'comercio': PACComercioDigital,
|
||||
}
|
||||
NS_CFDI = {
|
||||
'cfdi': 'http://www.sat.gob.mx/cfd/3',
|
||||
'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
}
|
||||
|
||||
|
||||
#~ https://github.com/kennethreitz/requests/blob/v1.2.3/requests/structures.py#L37
|
||||
class CaseInsensitiveDict(collections.MutableMapping):
|
||||
|
@ -645,6 +650,13 @@ def make_xml(data, certificado):
|
|||
return cfdi.add_sello(stamp, cert.cer_txt)
|
||||
|
||||
|
||||
def get_pac_by_rfc(cfdi):
|
||||
tree = ET.fromstring(cfdi.encode())
|
||||
path = 'string(//cfdi:Complemento/tdf:TimbreFiscalDigital/@RfcProvCertif)'
|
||||
rfc_pac = tree.xpath(path, namespaces=NS_CFDI)
|
||||
return RFCS[rfc_pac]
|
||||
|
||||
|
||||
def cancel_xml_sign(invoice, auth, certificado):
|
||||
cert = SATCertificate(certificado.cer, certificado.key_enc.encode())
|
||||
pac = PACS[auth['pac']]()
|
||||
|
@ -658,7 +670,7 @@ def cancel_xml_sign(invoice, auth, certificado):
|
|||
tree = cert.sign_xml(tree)
|
||||
sign_xml = ET.tostring(tree).decode()
|
||||
|
||||
result = pac.cancel_xml(invoice.xml, sign_xml, auth)
|
||||
result = pac.cancel_xml(sign_xml, auth, invoice.xml)
|
||||
if pac.error:
|
||||
result = {'ok': False, 'msg': pac.error, 'row': {}}
|
||||
return result
|
||||
|
|
|
@ -404,7 +404,7 @@ class Configuracion(BaseModel):
|
|||
return values
|
||||
|
||||
|
||||
def _get_admin_products(self):
|
||||
def _get_admin_products(self, args={}):
|
||||
fields = (
|
||||
'chk_config_cuenta_predial',
|
||||
'chk_config_codigo_barras',
|
||||
|
@ -419,7 +419,7 @@ class Configuracion(BaseModel):
|
|||
values = {r.clave: util.get_bool(r.valor) for r in data}
|
||||
return values
|
||||
|
||||
def _get_main_products(self):
|
||||
def _get_main_products(self, args={}):
|
||||
fields = (
|
||||
'chk_config_cuenta_predial',
|
||||
'chk_config_codigo_barras',
|
||||
|
@ -436,7 +436,7 @@ class Configuracion(BaseModel):
|
|||
values['default_unidad'] = SATUnidades.get_default()
|
||||
return values
|
||||
|
||||
def _get_complements(self):
|
||||
def _get_complements(self, args={}):
|
||||
fields = (
|
||||
'chk_config_ine',
|
||||
'chk_config_edu',
|
||||
|
@ -464,7 +464,7 @@ class Configuracion(BaseModel):
|
|||
|
||||
return values
|
||||
|
||||
def _get_folios(self):
|
||||
def _get_folios(self, args={}):
|
||||
fields = (
|
||||
'chk_folio_custom',
|
||||
)
|
||||
|
@ -475,7 +475,7 @@ class Configuracion(BaseModel):
|
|||
values = {r.clave: util.get_bool(r.valor) for r in data}
|
||||
return values
|
||||
|
||||
def _get_correo(self):
|
||||
def _get_correo(self, args={}):
|
||||
fields = ('correo_servidor', 'correo_puerto', 'correo_ssl',
|
||||
'correo_usuario', 'correo_copia', 'correo_asunto',
|
||||
'correo_mensaje', 'correo_directo', 'correo_confirmacion')
|
||||
|
@ -486,7 +486,7 @@ class Configuracion(BaseModel):
|
|||
values = {r.clave: r.valor for r in data}
|
||||
return values
|
||||
|
||||
def _get_admin_config_users(self):
|
||||
def _get_admin_config_users(self, args={}):
|
||||
fields = (
|
||||
'chk_users_notify_access',
|
||||
)
|
||||
|
@ -523,7 +523,7 @@ class Configuracion(BaseModel):
|
|||
}
|
||||
return values
|
||||
|
||||
def _get_pac_auth(cls):
|
||||
def _get_pac_auth(cls, args={}):
|
||||
pac = cls.get_('lst_pac').lower()
|
||||
user = cls.get_(f'user_timbrado_{pac}')
|
||||
token = cls.get_(f'token_timbrado_{pac}')
|
||||
|
@ -534,6 +534,17 @@ class Configuracion(BaseModel):
|
|||
data['pass'] = token
|
||||
return data
|
||||
|
||||
def _get_auth_by_pac(cls, args):
|
||||
pac = args['pac']
|
||||
user = cls.get_(f'user_timbrado_{pac}')
|
||||
token = cls.get_(f'token_timbrado_{pac}')
|
||||
data = {}
|
||||
if pac and user and token:
|
||||
data['pac'] = pac
|
||||
data['user'] = user
|
||||
data['pass'] = token
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def get_(cls, keys):
|
||||
if isinstance(keys, str):
|
||||
|
@ -553,10 +564,11 @@ class Configuracion(BaseModel):
|
|||
'correo',
|
||||
'admin_config_users',
|
||||
'pac_auth',
|
||||
'auth_by_pac',
|
||||
)
|
||||
opt = keys['fields']
|
||||
if opt in options:
|
||||
return getattr(cls, '_get_{}'.format(opt))(cls)
|
||||
return getattr(cls, f'_get_{opt}')(cls, keys)
|
||||
|
||||
if opt == 'pac':
|
||||
return cls._get_pac(cls, keys['pac'])
|
||||
|
@ -3857,7 +3869,9 @@ class Facturas(BaseModel):
|
|||
msg = 'Solo es posible cancelar CFDI 3.3'
|
||||
return {'ok': False, 'msg': msg}
|
||||
|
||||
auth = Configuracion.get_({'fields': 'pac_auth'})
|
||||
pac = utils.get_pac_by_rfc(invoice.xml)
|
||||
auth = Configuracion.get_({'fields': 'auth_by_pac', 'pac': pac})
|
||||
|
||||
certificado = Certificado.get(Certificado.es_fiel==False)
|
||||
result = utils.cancel_xml_sign(invoice, auth, certificado)
|
||||
|
||||
|
|
|
@ -233,6 +233,8 @@ VALUES_PDF = {
|
|||
RFCS = {
|
||||
'PUBLIC': 'XAXX010101000',
|
||||
'FOREIGN': 'XEXX010101000',
|
||||
'CVD110412TF6': 'finkok',
|
||||
'SCD110105654': 'comercio',
|
||||
}
|
||||
|
||||
URL = {
|
||||
|
|
Loading…
Reference in New Issue