Clean methods to import from old FacturaLibre

This commit is contained in:
Mauricio Baeza 2020-12-31 12:17:26 -06:00
parent cb04910a84
commit 0389c0734f
3 changed files with 395 additions and 366 deletions

View File

@ -50,10 +50,11 @@ from dateutil import parser
from .cfdi_xml import CFDI
from settings import DEBUG, DB_COMPANIES, PATHS
from settings import DEBUG, DB_COMPANIES, PATHS, TEMPLATE_CANCEL
from .cfdi_cert import SATCertificate
from .pacs import PACComercioDigital
# ~ from .pacs import PACFinkok
from .pac import Finkok as PACFinkok
# ~ from .finkok import PACFinkok

View File

@ -9780,388 +9780,387 @@ def _importar_valores(archivo='', rfc=''):
return
def _importar_socios(rows):
log.info('\tImportando Clientes...')
totals = len(rows)
for i, row in enumerate(rows):
msg = '\tGuardando cliente {} de {}'.format(i+1, totals)
log.info(msg)
try:
with database_proxy.atomic() as txn:
Socios.create(**row)
except IntegrityError:
msg = '\tSocio existente: {}'.format(row['nombre'])
log.info(msg)
log.info('\tClientes importados...')
return
# ~ def _importar_socios(rows):
# ~ log.info('\tImportando Clientes...')
# ~ totals = len(rows)
# ~ for i, row in enumerate(rows):
# ~ msg = '\tGuardando cliente {} de {}'.format(i+1, totals)
# ~ log.info(msg)
# ~ try:
# ~ with database_proxy.atomic() as txn:
# ~ Socios.create(**row)
# ~ except IntegrityError:
# ~ msg = '\tSocio existente: {}'.format(row['nombre'])
# ~ log.info(msg)
# ~ log.info('\tClientes importados...')
# ~ return
def _existe_factura(row):
filtro = (Facturas.uuid==row['uuid'])
if row['uuid'] is None:
filtro = (
(Facturas.serie==row['serie']) &
(Facturas.folio==row['folio'])
)
return Facturas.select().where(filtro).exists()
# ~ def _existe_factura(row):
# ~ filtro = (Facturas.uuid==row['uuid'])
# ~ if row['uuid'] is None:
# ~ filtro = (
# ~ (Facturas.serie==row['serie']) &
# ~ (Facturas.folio==row['folio'])
# ~ )
# ~ return Facturas.select().where(filtro).exists()
def _importar_facturas(rows):
log.info('\tImportando Facturas...')
totals = len(rows)
for i, row in enumerate(rows):
msg = '\tGuardando factura {} de {}'.format(i+1, totals)
log.info(msg)
# ~ def _importar_facturas(rows):
# ~ log.info('\tImportando Facturas...')
# ~ totals = len(rows)
# ~ for i, row in enumerate(rows):
# ~ msg = '\tGuardando factura {} de {}'.format(i+1, totals)
# ~ log.info(msg)
try:
detalles = row.pop('detalles')
impuestos = row.pop('impuestos')
cliente = row.pop('cliente')
row['cliente'] = Socios.get(**cliente)
with database_proxy.atomic() as txn:
if _existe_factura(row):
msg = '\tFactura existente: {}{}'.format(
row['serie'], row['folio'])
log.info(msg)
continue
obj = Facturas.create(**row)
for detalle in detalles:
detalle['factura'] = obj
FacturasDetalle.create(**detalle)
for impuesto in impuestos:
imp = SATImpuestos.get(**impuesto['filtro'])
new = {
'factura': obj,
'impuesto': imp,
'importe': impuesto['importe'],
}
try:
with database_proxy.atomic() as txn:
FacturasImpuestos.create(**new)
except IntegrityError as e:
pass
# ~ try:
# ~ detalles = row.pop('detalles')
# ~ impuestos = row.pop('impuestos')
# ~ cliente = row.pop('cliente')
# ~ row['cliente'] = Socios.get(**cliente)
# ~ with database_proxy.atomic() as txn:
# ~ if _existe_factura(row):
# ~ msg = '\tFactura existente: {}{}'.format(
# ~ row['serie'], row['folio'])
# ~ log.info(msg)
# ~ continue
# ~ obj = Facturas.create(**row)
# ~ for detalle in detalles:
# ~ detalle['factura'] = obj
# ~ FacturasDetalle.create(**detalle)
# ~ for impuesto in impuestos:
# ~ imp = SATImpuestos.get(**impuesto['filtro'])
# ~ new = {
# ~ 'factura': obj,
# ~ 'impuesto': imp,
# ~ 'importe': impuesto['importe'],
# ~ }
# ~ try:
# ~ with database_proxy.atomic() as txn:
# ~ FacturasImpuestos.create(**new)
# ~ except IntegrityError as e:
# ~ pass
except IntegrityError as e:
print (e)
msg = '\tFactura: id: {}'.format(row['serie'] + str(row['folio']))
log.error(msg)
break
log.info('\tFacturas importadas...')
return
def _importar_categorias(rows):
log.info('\tImportando Categorías...')
for row in rows:
with database_proxy.atomic() as txn:
try:
Categorias.create(**row)
except IntegrityError:
msg = '\tCategoria: ({}) {}'.format(row['padre'], row['categoria'])
log.error(msg)
log.info('\tCategorías importadas...')
return
def _get_id_unidad(unidad):
try:
if 'pieza' in unidad.lower():
unidad = 'pieza'
if 'metros' in unidad.lower():
unidad = 'metro'
if 'tramo' in unidad.lower():
unidad = 'paquete'
if 'juego' in unidad.lower():
unidad = 'par'
if 'bolsa' in unidad.lower():
unidad = 'globo'
if unidad.lower() == 'no aplica':
unidad = 'servicio'
obj = SATUnidades.get(SATUnidades.name.contains(unidad))
except SATUnidades.DoesNotExist:
msg = '\tNo se encontró la unidad: {}'.format(unidad)
# ~ log.error(msg)
return unidad
return str(obj.id)
def _get_impuestos(impuestos):
lines = '|'
for impuesto in impuestos:
if impuesto['tasa'] == '-2/3':
tasa = str(round(2/3, 6))
else:
if impuesto['tasa'] == 'EXENTO':
tasa = '0.00'
else:
tasa = str(round(float(impuesto['tasa']) / 100.0, 6))
info = (
IMPUESTOS.get(impuesto['nombre']),
impuesto['nombre'],
impuesto['tipo'][0],
tasa,
)
lines += '|'.join(info) + '|'
return lines
def _generar_archivo_productos(archivo):
rfc = input('Introduce el RFC: ').strip().upper()
if not rfc:
msg = 'El RFC es requerido'
log.error(msg)
return
args = util.get_con(rfc)
if not args:
return
conectar(args)
log.info('Importando datos...')
app = util.ImportFacturaLibre(archivo, rfc)
if not app.is_connect:
log.error('\t{}'.format(app._error))
return
rows = app.import_productos()
p, _, _, _ = util.get_path_info(archivo)
path_txt = util._join(p, 'productos_{}.txt'.format(rfc))
log.info('\tGenerando archivo: {}'.format(path_txt))
fields = (
'clave',
'clave_sat',
'unidad',
'categoria',
'descripcion',
'valor_unitario',
'existencia',
'inventario',
'codigo_barras',
'cuenta_predial',
'ultimo_precio',
'minimo',
)
data = ['|'.join(fields)]
not_units = []
for row in rows:
impuestos = row.pop('impuestos', ())
line = [str(row[r]) for r in fields]
if line[10] == 'None':
line[10] = '0.0'
line[2] = _get_id_unidad(line[2])
try:
int(line[2])
except ValueError:
if not line[2] in not_units:
not_units.append(line[2])
msg = 'No se encontró la unidad: {}'.format(line[2])
log.error(msg)
continue
line = '|'.join(line) + _get_impuestos(impuestos)
data.append(line)
with open(path_txt, 'w') as fh:
fh.write('\n'.join(data))
log.info('\tArchivo generado: {}'.format(path_txt))
return
def importar_bdfl():
try:
emisor = Emisor.select()[0]
except IndexError:
msg = 'Configura primero al emisor'
return {'ok': False, 'msg': msg}
name = '{}.sqlite'.format(emisor.rfc.lower())
path = util._join('/tmp', name)
log.info('Importando datos...')
app = util.ImportFacturaLibre(path, emisor.rfc)
if not app.is_connect:
msg = app._error
log.error('\t{}'.format(msg))
return {'ok': False, 'msg': msg}
data = app.import_data()
_importar_socios(data['Socios'])
_importar_facturas(data['Facturas'])
_importar_categorias(data['Categorias'])
msg = 'Importación terminada...'
log.info(msg)
return {'ok': True, 'msg': msg}
def _importar_factura_libre(archivo):
rfc = input('Introduce el RFC: ').strip().upper()
if not rfc:
msg = 'El RFC es requerido'
log.error(msg)
return
args = util.get_con(rfc)
if not args:
return
conectar(args)
log.info('Importando datos...')
app = util.ImportFacturaLibre(archivo, rfc)
if not app.is_connect:
log.error('\t{}'.format(app._error))
return
data = app.import_data()
_importar_socios(data['Socios'])
_importar_facturas(data['Facturas'])
_importar_categorias(data['Categorias'])
log.info('Importación terminada...')
return
def _exist_ticket(row):
filters = (
(Tickets.serie==row['serie']) &
(Tickets.folio==row['folio'])
)
return Tickets.select().where(filters).exists()
def _import_tickets(rows):
log.info('\tImportando Tickets...')
for row in rows:
try:
details = row.pop('details')
taxes = row.pop('taxes')
with database_proxy.atomic() as txn:
if _exist_ticket(row):
msg = '\tTicket existente: {}{}'.format(
row['serie'], row['folio'])
log.info(msg)
continue
if not row['factura'] is None and row['factura']:
row['factura'] = Facturas.get(
Facturas.serie==row['factura']['serie'],
Facturas.folio==row['factura']['folio'])
else:
row['factura'] = None
obj = Tickets.create(**row)
for detail in details:
detail['ticket'] = obj
TicketsDetalle.create(**detail)
for tax in taxes:
imp = SATImpuestos.get(**tax['filter'])
new = {
'ticket': obj,
'impuesto': imp,
'importe': tax['import'],
}
TicketsImpuestos.create(**new)
except IntegrityError as e:
# ~ except IntegrityError as e:
# ~ print (e)
msg = '\tTicket: id: {}'.format(row['serie'] + str(row['folio']))
log.error(msg)
# ~ msg = '\tFactura: id: {}'.format(row['serie'] + str(row['folio']))
# ~ log.error(msg)
# ~ break
log.info('\tTickets importadas...')
return
# ~ log.info('\tFacturas importadas...')
# ~ return
def _importar_productos(archivo):
rfc = input('Introduce el RFC: ').strip().upper()
if not rfc:
msg = 'El RFC es requerido'
log.error(msg)
return
# ~ def _importar_categorias(rows):
# ~ log.info('\tImportando Categorías...')
# ~ for row in rows:
# ~ with database_proxy.atomic() as txn:
# ~ try:
# ~ Categorias.create(**row)
# ~ except IntegrityError:
# ~ msg = '\tCategoria: ({}) {}'.format(row['padre'], row['categoria'])
# ~ log.error(msg)
args = util.get_con(rfc)
if not args:
return
# ~ log.info('\tCategorías importadas...')
# ~ return
conectar(args)
log.info('Importando productos...')
fields = (
'clave',
'clave_sat',
'unidad',
'categoria',
'descripcion',
'valor_unitario',
'existencia',
'inventario',
'codigo_barras',
'cuenta_predial',
'ultimo_precio',
'minimo',
)
# ~ def _get_id_unidad(unidad):
# ~ try:
# ~ if 'pieza' in unidad.lower():
# ~ unidad = 'pieza'
# ~ if 'metros' in unidad.lower():
# ~ unidad = 'metro'
# ~ if 'tramo' in unidad.lower():
# ~ unidad = 'paquete'
# ~ if 'juego' in unidad.lower():
# ~ unidad = 'par'
# ~ if 'bolsa' in unidad.lower():
# ~ unidad = 'globo'
# ~ if unidad.lower() == 'no aplica':
# ~ unidad = 'servicio'
rows = util.read_file(archivo, 'r').split('\n')
for i, row in enumerate(rows):
if i == 0:
continue
data = row.split('|')
# ~ obj = SATUnidades.get(SATUnidades.name.contains(unidad))
# ~ except SATUnidades.DoesNotExist:
# ~ msg = '\tNo se encontró la unidad: {}'.format(unidad)
# ~ return unidad
# ~ return str(obj.id)
# ~ def _get_impuestos(impuestos):
# ~ lines = '|'
# ~ for impuesto in impuestos:
# ~ if impuesto['tasa'] == '-2/3':
# ~ tasa = str(round(2/3, 6))
# ~ else:
# ~ if impuesto['tasa'] == 'EXENTO':
# ~ tasa = '0.00'
# ~ else:
# ~ tasa = str(round(float(impuesto['tasa']) / 100.0, 6))
# ~ info = (
# ~ IMPUESTOS.get(impuesto['nombre']),
# ~ impuesto['nombre'],
# ~ impuesto['tipo'][0],
# ~ tasa,
# ~ )
# ~ lines += '|'.join(info) + '|'
# ~ return lines
# ~ def _generar_archivo_productos(archivo):
# ~ rfc = input('Introduce el RFC: ').strip().upper()
# ~ if not rfc:
# ~ msg = 'El RFC es requerido'
# ~ log.error(msg)
# ~ return
# ~ args = util.get_con(rfc)
# ~ if not args:
# ~ return
# ~ conectar(args)
# ~ log.info('Importando datos...')
# ~ app = util.ImportFacturaLibre(archivo, rfc)
# ~ if not app.is_connect:
# ~ log.error('\t{}'.format(app._error))
# ~ return
# ~ rows = app.import_productos()
# ~ p, _, _, _ = util.get_path_info(archivo)
# ~ path_txt = util._join(p, 'productos_{}.txt'.format(rfc))
# ~ log.info('\tGenerando archivo: {}'.format(path_txt))
# ~ fields = (
# ~ 'clave',
# ~ 'clave_sat',
# ~ 'unidad',
# ~ 'categoria',
# ~ 'descripcion',
# ~ 'valor_unitario',
# ~ 'existencia',
# ~ 'inventario',
# ~ 'codigo_barras',
# ~ 'cuenta_predial',
# ~ 'ultimo_precio',
# ~ 'minimo',
# ~ )
# ~ data = ['|'.join(fields)]
# ~ not_units = []
# ~ for row in rows:
# ~ impuestos = row.pop('impuestos', ())
# ~ line = [str(row[r]) for r in fields]
# ~ if line[10] == 'None':
# ~ line[10] = '0.0'
# ~ line[2] = _get_id_unidad(line[2])
# ~ try:
# ~ int(line[2])
# ~ except ValueError:
# ~ if not line[2] in not_units:
# ~ not_units.append(line[2])
# ~ msg = 'No se encontró la unidad: {}'.format(line[2])
# ~ log.error(msg)
# ~ continue
# ~ line = '|'.join(line) + _get_impuestos(impuestos)
# ~ data.append(line)
# ~ with open(path_txt, 'w') as fh:
# ~ fh.write('\n'.join(data))
# ~ log.info('\tArchivo generado: {}'.format(path_txt))
# ~ return
# ~ def importar_bdfl():
# ~ try:
# ~ emisor = Emisor.select()[0]
# ~ except IndexError:
# ~ msg = 'Configura primero al emisor'
# ~ return {'ok': False, 'msg': msg}
# ~ name = '{}.sqlite'.format(emisor.rfc.lower())
# ~ path = util._join('/tmp', name)
# ~ log.info('Importando datos...')
# ~ app = util.ImportFacturaLibre(path, emisor.rfc)
# ~ if not app.is_connect:
# ~ msg = app._error
# ~ log.error('\t{}'.format(msg))
# ~ return {'ok': False, 'msg': msg}
# ~ data = app.import_data()
# ~ _importar_socios(data['Socios'])
# ~ _importar_facturas(data['Facturas'])
# ~ _importar_categorias(data['Categorias'])
# ~ msg = 'Importación terminada...'
# ~ log.info(msg)
# ~ return {'ok': True, 'msg': msg}
# ~ def _importar_factura_libre(archivo):
# ~ rfc = input('Introduce el RFC: ').strip().upper()
# ~ if not rfc:
# ~ msg = 'El RFC es requerido'
# ~ log.error(msg)
# ~ return
# ~ args = util.get_con(rfc)
# ~ if not args:
# ~ return
# ~ conectar(args)
# ~ log.info('Importando datos...')
# ~ app = util.ImportFacturaLibre(archivo, rfc)
# ~ if not app.is_connect:
# ~ log.error('\t{}'.format(app._error))
# ~ return
# ~ data = app.import_data()
# ~ _importar_socios(data['Socios'])
# ~ _importar_facturas(data['Facturas'])
# ~ _importar_categorias(data['Categorias'])
# ~ log.info('Importación terminada...')
# ~ return
# ~ def _exist_ticket(row):
# ~ filters = (
# ~ (Tickets.serie==row['serie']) &
# ~ (Tickets.folio==row['folio'])
# ~ )
# ~ return Tickets.select().where(filters).exists()
# ~ def _import_tickets(rows):
# ~ log.info('\tImportando Tickets...')
# ~ for row in rows:
# ~ try:
# ~ details = row.pop('details')
# ~ taxes = row.pop('taxes')
# ~ with database_proxy.atomic() as txn:
# ~ if _exist_ticket(row):
# ~ msg = '\tTicket existente: {}{}'.format(
# ~ row['serie'], row['folio'])
# ~ log.info(msg)
# ~ continue
# ~ if not row['factura'] is None and row['factura']:
# ~ row['factura'] = Facturas.get(
# ~ Facturas.serie==row['factura']['serie'],
# ~ Facturas.folio==row['factura']['folio'])
# ~ else:
# ~ row['factura'] = None
# ~ obj = Tickets.create(**row)
# ~ for detail in details:
# ~ detail['ticket'] = obj
# ~ TicketsDetalle.create(**detail)
# ~ for tax in taxes:
# ~ imp = SATImpuestos.get(**tax['filter'])
# ~ new = {
# ~ 'ticket': obj,
# ~ 'impuesto': imp,
# ~ 'importe': tax['import'],
# ~ }
# ~ TicketsImpuestos.create(**new)
# ~ except IntegrityError as e:
# ~ print (e)
# ~ msg = '\tTicket: id: {}'.format(row['serie'] + str(row['folio']))
# ~ log.error(msg)
# ~ log.info('\tTickets importadas...')
# ~ return
# ~ def _importar_productos(archivo):
# ~ rfc = input('Introduce el RFC: ').strip().upper()
# ~ if not rfc:
# ~ msg = 'El RFC es requerido'
# ~ log.error(msg)
# ~ return
# ~ args = util.get_con(rfc)
# ~ if not args:
# ~ return
# ~ conectar(args)
# ~ log.info('Importando productos...')
# ~ fields = (
# ~ 'clave',
# ~ 'clave_sat',
# ~ 'unidad',
# ~ 'categoria',
# ~ 'descripcion',
# ~ 'valor_unitario',
# ~ 'existencia',
# ~ 'inventario',
# ~ 'codigo_barras',
# ~ 'cuenta_predial',
# ~ 'ultimo_precio',
# ~ 'minimo',
# ~ )
# ~ rows = util.read_file(archivo, 'r').split('\n')
# ~ for i, row in enumerate(rows):
# ~ if i == 0:
# ~ continue
# ~ data = row.split('|')
# ~ print (data)
new = {}
for i, f in enumerate(fields):
if not len(data[0]):
continue
# ~ new = {}
# ~ for i, f in enumerate(fields):
# ~ if not len(data[0]):
# ~ continue
if i in (2, 3):
try:
new[f] = int(data[i])
except ValueError:
continue
elif i in (5, 6, 10, 11):
new[f] = float(data[i])
elif i == 7:
new[f] = bool(data[i])
else:
new[f] = data[i]
# ~ if i in (2, 3):
# ~ try:
# ~ new[f] = int(data[i])
# ~ except ValueError:
# ~ continue
# ~ elif i in (5, 6, 10, 11):
# ~ new[f] = float(data[i])
# ~ elif i == 7:
# ~ new[f] = bool(data[i])
# ~ else:
# ~ new[f] = data[i]
impuestos = data[i + 1:-1]
if not impuestos:
taxes = [SATImpuestos.select().where(SATImpuestos.id==6)]
else:
taxes = []
try:
for i in range(0, len(impuestos), 4):
w = {
'key': impuestos[i],
'name': impuestos[i+1],
'tipo': impuestos[i+2],
'tasa': float(impuestos[i+3]),
}
taxes.append(SATImpuestos.get_o_crea(w))
except IndexError:
print ('IE', data)
continue
# ~ impuestos = data[i + 1:-1]
# ~ if not impuestos:
# ~ taxes = [SATImpuestos.select().where(SATImpuestos.id==6)]
# ~ else:
# ~ taxes = []
# ~ try:
# ~ for i in range(0, len(impuestos), 4):
# ~ w = {
# ~ 'key': impuestos[i],
# ~ 'name': impuestos[i+1],
# ~ 'tipo': impuestos[i+2],
# ~ 'tasa': float(impuestos[i+3]),
# ~ }
# ~ taxes.append(SATImpuestos.get_o_crea(w))
# ~ except IndexError:
# ~ print ('IE', data)
# ~ continue
with database_proxy.transaction():
try:
obj = Productos.create(**new)
obj.impuestos = taxes
except IntegrityError as e:
pass
# ~ with database_proxy.transaction():
# ~ try:
# ~ obj = Productos.create(**new)
# ~ obj.impuestos = taxes
# ~ except IntegrityError as e:
# ~ pass
log.info('Importación terminada...')
return
# ~ log.info('Importación terminada...')
# ~ return
def _import_from_folder(path):

View File

@ -73,8 +73,8 @@ PATH_SESSIONS = {
IV = 'valores_iniciales.json'
INIT_VALUES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', IV))
CT = 'cancel_template.xml'
TEMPLATE_CANCEL = os.path.abspath(os.path.join(PATH_TEMPLATES, CT))
# ~ CT = 'cancel_template.xml'
# ~ TEMPLATE_CANCEL = os.path.abspath(os.path.join(PATH_TEMPLATES, CT))
PATH_XSLT = os.path.abspath(os.path.join(BASE_DIR, '..', 'xslt'))
PATH_BIN = os.path.abspath(os.path.join(BASE_DIR, '..', 'bin'))
@ -245,3 +245,32 @@ DEFAULT_GLOBAL = {
'descripcion': 'Venta',
'clave_sat': '01010101',
}
TEMPLATE_CANCEL = """<Cancelacion RfcEmisor="{rfc}" Fecha="{fecha}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://cancelacfd.sat.gob.mx">
<Folios>
<UUID>{uuid}</UUID>
</Folios>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue />
</Reference>
</SignedInfo>
<SignatureValue />
<KeyInfo>
<X509Data>
<X509SubjectName />
<X509IssuerSerial />
<X509Certificate />
</X509Data>
<KeyValue />
</KeyInfo>
</Signature>
</Cancelacion>
"""