diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py
index 8a77554..1692db4 100644
--- a/source/app/controllers/cfdi_xml.py
+++ b/source/app/controllers/cfdi_xml.py
@@ -265,7 +265,7 @@ class CFDI(object):
return
def _impuestos(self, datos):
- if self._is_nomina:
+ if self._is_nomina or not datos:
return
if not datos:
diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py
index c23ac9b..6100ece 100644
--- a/source/app/controllers/util.py
+++ b/source/app/controllers/util.py
@@ -1420,7 +1420,8 @@ def _comprobante(doc, options):
data['tipodecomprobante'] = tipos.get(data['tipodecomprobante'])
data['lugarexpedicion'] = \
'C.P. de Expedición: {}'.format(data['lugarexpedicion'])
- data['metododepago'] = options['metododepago']
+ if 'metododepago' in options:
+ data['metododepago'] = options['metododepago']
data['formadepago'] = options['formadepago']
if 'condicionesdepago' in data:
@@ -2199,7 +2200,7 @@ def local_copy(files):
args = 'df -P {} | tail -1 | cut -d" " -f 1'.format(path_bk)
try:
result = _call(args)
- log.info(result)
+ # ~ log.info(result)
except:
pass
# ~ if result != 'empresalibre\n':
diff --git a/source/app/models/main.py b/source/app/models/main.py
index 744bda5..f74a8c6 100644
--- a/source/app/models/main.py
+++ b/source/app/models/main.py
@@ -3235,8 +3235,9 @@ class Facturas(BaseModel):
'PUE': 'Pago en una sola exhibición',
'PPD': 'Pago en parcialidades o diferido',
}
- values['metododepago'] = 'Método de Pago: ({}) {}'.format(
- invoice.metodo_pago, mp[invoice.metodo_pago])
+ if invoice.metodo_pago:
+ values['metododepago'] = 'Método de Pago: ({}) {}'.format(
+ invoice.metodo_pago, mp[invoice.metodo_pago])
obj = SATFormaPago.get(SATFormaPago.key==invoice.forma_pago)
values['formadepago'] = str(obj)
@@ -3591,7 +3592,7 @@ class Facturas(BaseModel):
return inicio
- def _calculate_totals(self, invoice, products):
+ def _calculate_totals(self, invoice, products, tipo_comprobante):
tax_locales = Configuracion.get_bool('chk_config_tax_locales')
tax_decimals = Configuracion.get_bool('chk_config_tax_decimals')
subtotal = 0
@@ -3618,6 +3619,9 @@ class Facturas(BaseModel):
cantidad = float(product['cantidad'])
valor_unitario = float(product['valor_unitario'])
descuento = float(product['descuento'])
+ if tipo_comprobante == 'T':
+ valor_unitario = 0.0
+ descuento = 0.0
precio_final = valor_unitario - descuento
importe = round(cantidad * precio_final, DECIMALES)
@@ -3639,6 +3643,9 @@ class Facturas(BaseModel):
FacturasDetalle.create(**product)
+ if tipo_comprobante == 'T':
+ continue
+
base = product['importe'] - product['descuento']
for tax in p.impuestos:
if tax_locales and tax.tipo == 'R' and tax.key == '000':
@@ -3666,17 +3673,18 @@ class Facturas(BaseModel):
tax.suma_impuestos = impuesto_producto
totals_tax[tax.id] = tax
- for tax in totals_tax.values():
- if tax.tipo == 'E':
- continue
+ if tipo_comprobante != 'T':
+ for tax in totals_tax.values():
+ if tax.tipo == 'E':
+ continue
- invoice_tax = {
- 'factura': invoice.id,
- 'impuesto': tax.id,
- 'base': tax.base,
- 'importe': tax.suma_impuestos,
- }
- FacturasImpuestos.create(**invoice_tax)
+ invoice_tax = {
+ 'factura': invoice.id,
+ 'impuesto': tax.id,
+ 'base': tax.base,
+ 'importe': tax.suma_impuestos,
+ }
+ FacturasImpuestos.create(**invoice_tax)
total = subtotal - descuento_cfdi + \
(total_trasladados or 0) - (total_retenciones or 0) \
@@ -3725,6 +3733,7 @@ class Facturas(BaseModel):
productos = util.loads(values.pop('productos'))
relacionados = util.loads(values.pop('relacionados'))
ine = values.pop('ine', {})
+ tipo_comprobante = values['tipo_comprobante']
emisor = Emisor.select()[0]
values['serie'] = cls._get_serie(cls, user, values['serie'])
@@ -3733,10 +3742,12 @@ class Facturas(BaseModel):
values['lugar_expedicion'] = emisor.cp_expedicion or emisor.codigo_postal
values['anticipo'] = util.get_bool(values['anticipo'])
values['donativo'] = util.get_bool(values['donativo'])
+ if tipo_comprobante == 'T':
+ values['metodo_pago'] = ''
with database_proxy.atomic() as txn:
obj = Facturas.create(**values)
- totals = cls._calculate_totals(cls, obj, productos)
+ totals = cls._calculate_totals(cls, obj, productos, tipo_comprobante)
cls._guardar_relacionados(cls, obj, relacionados)
cls._guardar_ine(cls, obj, ine)
obj.subtotal = totals['subtotal']
@@ -3798,7 +3809,8 @@ class Facturas(BaseModel):
comprobante['TipoCambio'] = FORMAT.format(invoice.tipo_cambio)
comprobante['Total'] = FORMAT.format(invoice.total)
comprobante['TipoDeComprobante'] = invoice.tipo_comprobante
- comprobante['MetodoPago'] = invoice.metodo_pago
+ if invoice.metodo_pago:
+ comprobante['MetodoPago'] = invoice.metodo_pago
comprobante['LugarExpedicion'] = invoice.lugar_expedicion
if invoice.descuento:
comprobante['Descuento'] = FORMAT.format(invoice.descuento)
@@ -3857,38 +3869,45 @@ class Facturas(BaseModel):
traslados = []
retenciones = []
- for impuesto in row.producto.impuestos:
- if impuesto.tipo == 'E':
- continue
+ if invoice.tipo_comprobante != 'T':
+ for impuesto in row.producto.impuestos:
+ base = float(row.importe - row.descuento)
+ if impuesto.tipo == 'E':
+ tax = {
+ 'Base': FORMAT.format(base),
+ 'Impuesto': '002',
+ 'TipoFactor': 'Exento',
+ }
+ traslados.append(tax)
+ continue
- if impuesto.key == '000':
- continue
+ if impuesto.key == '000':
+ continue
- base = float(row.importe - row.descuento)
- tasa = float(impuesto.tasa)
+ tasa = float(impuesto.tasa)
- if tax_decimals:
- import_tax = round(tasa * base, DECIMALES_TAX)
- tmp += import_tax
- xml_importe = FORMAT_TAX.format(import_tax)
- else:
- import_tax = round(tasa * base, DECIMALES)
- xml_importe = FORMAT.format(import_tax)
+ if tax_decimals:
+ import_tax = round(tasa * base, DECIMALES_TAX)
+ tmp += import_tax
+ xml_importe = FORMAT_TAX.format(import_tax)
+ else:
+ import_tax = round(tasa * base, DECIMALES)
+ xml_importe = FORMAT.format(import_tax)
- tipo_factor = 'Tasa'
- if impuesto.factor != 'T':
- tipo_factor = 'Cuota'
- tax = {
- "Base": FORMAT.format(base),
- "Impuesto": impuesto.key,
- "TipoFactor": tipo_factor,
- "TasaOCuota": str(impuesto.tasa),
- "Importe": xml_importe,
- }
- if impuesto.tipo == 'T':
- traslados.append(tax)
- else:
- retenciones.append(tax)
+ tipo_factor = 'Tasa'
+ if impuesto.factor != 'T':
+ tipo_factor = 'Cuota'
+ tax = {
+ "Base": FORMAT.format(base),
+ "Impuesto": impuesto.key,
+ "TipoFactor": tipo_factor,
+ "TasaOCuota": str(impuesto.tasa),
+ "Importe": xml_importe,
+ }
+ if impuesto.tipo == 'T':
+ traslados.append(tax)
+ else:
+ retenciones.append(tax)
if traslados:
taxes['traslados'] = traslados
@@ -3974,6 +3993,9 @@ class Facturas(BaseModel):
impuestos['locales_trasladados'] = locales_trasladados
impuestos['locales_retenciones'] = locales_retenciones
+ if invoice.tipo_comprobante == 'T':
+ impuestos = {}
+
data = {
'comprobante': comprobante,
'relacionados': relacionados,
@@ -7856,6 +7878,45 @@ def _import_from_folder(path):
return
+def _exportar_documentos():
+ 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('Exportar documentos...')
+
+ n = util.now()
+ year = input('Introduce el año [{}]: '.format(n.year)).strip()
+ if not year:
+ year = str(n.year)
+ month = input('Introduce el mes [{}]: '.format(n.month)).strip()
+ if not month:
+ month = str(n.month)
+
+ filters = {
+ 'year': year,
+ 'month': month,
+ }
+ result = Facturas.get_(filters)
+ if result['ok']:
+ t = len(result['rows'])
+ for i, row in enumerate(result['rows']):
+ msg = 'Extrayendo factura {} de {}: {}-{}'.format(
+ i+1, t, row['serie'], row['folio'])
+ log.info(msg)
+ Facturas.get_xml(row['id'])
+ Facturas.get_pdf(row['id'], rfc, True)
+ log.info('Documentos exportados...')
+ return
+
+
def _test():
rfc = input('Introduce el RFC: ').strip().upper()
if not rfc:
@@ -7907,11 +7968,12 @@ help_lr = 'Listar RFCs'
@click.option('-r', '--rfc')
@click.option('-d', '--detalle', is_flag=True, default=False)
@click.option('-id', '--importar-directorio')
+@click.option('-ed', '--exportar_documentos', is_flag=True, default=False)
def main(iniciar_bd, migrar_bd, nuevo_superusuario, cambiar_contraseña,
agregar_rfc, borrar_rfc, listar_rfc, importar_valores, archivo, conexion,
factura_libre, factura_libre_gambas, test, generar_archivo_productos,
importar_productos, backup_dbs, no_bd, alta, rfc, detalle,
- importar_directorio):
+ importar_directorio, exportar_documentos):
opt = locals()
@@ -8019,9 +8081,14 @@ def main(iniciar_bd, migrar_bd, nuevo_superusuario, cambiar_contraseña,
if opt['importar_directorio']:
_import_from_folder(opt['importar_directorio'])
+ sys.exit(0)
if opt['backup_dbs']:
util.backup_dbs()
+ sys.exit(0)
+
+ if opt['exportar_documentos']:
+ _exportar_documentos()
return
diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js
index 7ec6581..775fb9f 100644
--- a/source/static/js/controller/invoices.js
+++ b/source/static/js/controller/invoices.js
@@ -406,6 +406,11 @@ function validate_invoice(values){
}
+ var tipo_comprobante = $$('lst_tipo_comprobante').getValue()
+ if(tipo_comprobante == 'T'){
+ msg_ok('El CFDI es de tipo Traslado')
+ }
+
return true
}
@@ -565,7 +570,6 @@ function guardar_y_timbrar(values){
delete rows[i]['delete']
delete rows[i]['clave']
delete rows[i]['clave_sat']
- //~ delete rows[i]['unidad']
delete rows[i]['importe']
delete rows[i]['student']
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
@@ -630,7 +634,9 @@ function cmd_timbrar_click(id, e, node){
if(!validate_invoice(values)){
return
}
- //~ showvar(values)
+
+ var tipo_comprobante = $$('lst_tipo_comprobante').getValue()
+
query = table_relaciones.chain().data()
msg = '¿Todos los datos son correctos?
'
if(query.length > 0){
@@ -650,7 +656,12 @@ function cmd_timbrar_click(id, e, node){
if(usar_ine){
msg += 'Estas usando el complemento INE
'
}
- msg += '¿Estás seguro de timbrar esta factura?'
+
+ if(tipo_comprobante == 'T'){
+ msg += 'El Tipo de Comprobante es Traslado, todos los importes serán puesto a 0 (Cero), asegurate de que sea el tipo de comprobante correcto
'
+ }
+
+ msg += '¿Estás seguro de timbrar esta factura?
'
webix.confirm({
title: 'Timbrar Factura',
diff --git a/source/static/js/controller/partners.js b/source/static/js/controller/partners.js
index 2aa28ca..155ab7f 100644
--- a/source/static/js/controller/partners.js
+++ b/source/static/js/controller/partners.js
@@ -337,6 +337,7 @@ function partner_reset_saldo(id){
if(values.ok){
msg = 'Saldo actualizado correctamente'
$$('grid_partners').updateItem(id, {saldo_cliente: 0.0})
+ $$('cmd_partner_zero').disable()
msg_ok(msg)
}
}