forked from elmau/empresa-libre
commit
4bd7e335d8
|
@ -20,5 +20,6 @@ credenciales.conf
|
||||||
*.sqlite
|
*.sqlite
|
||||||
*.sql
|
*.sql
|
||||||
*.service
|
*.service
|
||||||
|
*.orig
|
||||||
rfc.db
|
rfc.db
|
||||||
|
|
||||||
|
|
|
@ -936,6 +936,10 @@ class LIBO(object):
|
||||||
self._set_cell('{ine.%s}' % k, v)
|
self._set_cell('{ine.%s}' % k, v)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _nomina(self, data):
|
||||||
|
print(data)
|
||||||
|
return
|
||||||
|
|
||||||
def _render(self, data):
|
def _render(self, data):
|
||||||
self._set_search()
|
self._set_search()
|
||||||
self._es_pre = data.pop('es_pre', False)
|
self._es_pre = data.pop('es_pre', False)
|
||||||
|
@ -944,7 +948,10 @@ class LIBO(object):
|
||||||
self._emisor(data['emisor'])
|
self._emisor(data['emisor'])
|
||||||
self._receptor(data['receptor'])
|
self._receptor(data['receptor'])
|
||||||
self._conceptos(data['conceptos'])
|
self._conceptos(data['conceptos'])
|
||||||
self._totales(data['totales'])
|
if 'nomina' in data and data['nomina']:
|
||||||
|
self._nomina(data['nomina'])
|
||||||
|
else:
|
||||||
|
self._totales(data['totales'])
|
||||||
self._timbre(data['timbre'])
|
self._timbre(data['timbre'])
|
||||||
self._donataria(data['donataria'])
|
self._donataria(data['donataria'])
|
||||||
self._ine(data['ine'])
|
self._ine(data['ine'])
|
||||||
|
@ -1200,6 +1207,8 @@ def to_pdf(data, emisor_rfc, ods=False):
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
rfc = emisor_rfc
|
rfc = emisor_rfc
|
||||||
version = data['comprobante']['version']
|
version = data['comprobante']['version']
|
||||||
|
if 'nomina' in data and data['nomina']:
|
||||||
|
version = '{}_{}'.format(data['nomina']['version'], version)
|
||||||
|
|
||||||
if APP_LIBO:
|
if APP_LIBO:
|
||||||
app = LIBO()
|
app = LIBO()
|
||||||
|
@ -1288,6 +1297,11 @@ def _comprobante(doc, options):
|
||||||
serie = '{} -'.format(data['serie'])
|
serie = '{} -'.format(data['serie'])
|
||||||
data['seriefolio'] = '{}{}'.format(serie, data['folio'])
|
data['seriefolio'] = '{}{}'.format(serie, data['folio'])
|
||||||
data['totalenletras'] = to_letters(float(data['total']), data['moneda'])
|
data['totalenletras'] = to_letters(float(data['total']), data['moneda'])
|
||||||
|
|
||||||
|
is_nomina = options.get('is_nomina', False)
|
||||||
|
if is_nomina:
|
||||||
|
return data
|
||||||
|
|
||||||
if data['version'] == '3.3':
|
if data['version'] == '3.3':
|
||||||
tipos = {
|
tipos = {
|
||||||
'I': 'ingreso',
|
'I': 'ingreso',
|
||||||
|
@ -1372,11 +1386,19 @@ def _receptor(doc, version, values):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def _conceptos(doc, version):
|
def _conceptos(doc, version, options):
|
||||||
|
is_nomina = options.get('is_nomina', False)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
conceptos = doc.find('{}Conceptos'.format(PRE[version]))
|
conceptos = doc.find('{}Conceptos'.format(PRE[version]))
|
||||||
for c in conceptos.getchildren():
|
for c in conceptos.getchildren():
|
||||||
values = CaseInsensitiveDict(c.attrib.copy())
|
values = CaseInsensitiveDict(c.attrib.copy())
|
||||||
|
if is_nomina:
|
||||||
|
values['noidentificacion'] = values['ClaveProdServ']
|
||||||
|
values['unidad'] = values['ClaveUnidad']
|
||||||
|
data.append(values)
|
||||||
|
continue
|
||||||
|
|
||||||
if version == '3.3':
|
if version == '3.3':
|
||||||
values['noidentificacion'] = '{}\n(SAT {})'.format(
|
values['noidentificacion'] = '{}\n(SAT {})'.format(
|
||||||
values['noidentificacion'], values['ClaveProdServ'])
|
values['noidentificacion'], values['ClaveProdServ'])
|
||||||
|
@ -1519,14 +1541,24 @@ def _ine(doc, version):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def _nomina(invoice, values):
|
||||||
|
is_nomina = values.get('is_nomina', False)
|
||||||
|
if not is_nomina:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return {'version': '1.2'}
|
||||||
|
|
||||||
|
|
||||||
def get_data_from_xml(invoice, values):
|
def get_data_from_xml(invoice, values):
|
||||||
data = {'cancelada': invoice.cancelada, 'donativo': invoice.donativo}
|
data = {'cancelada': invoice.cancelada, 'donativo': False}
|
||||||
|
if hasattr('invoice', 'donativo'):
|
||||||
|
data['donativo'] = invoice.donativo
|
||||||
doc = parse_xml(invoice.xml)
|
doc = parse_xml(invoice.xml)
|
||||||
data['comprobante'] = _comprobante(doc, values)
|
data['comprobante'] = _comprobante(doc, values)
|
||||||
version = data['comprobante']['version']
|
version = data['comprobante']['version']
|
||||||
data['emisor'] = _emisor(doc, version, values)
|
data['emisor'] = _emisor(doc, version, values)
|
||||||
data['receptor'] = _receptor(doc, version, values)
|
data['receptor'] = _receptor(doc, version, values)
|
||||||
data['conceptos'] = _conceptos(doc, version)
|
data['conceptos'] = _conceptos(doc, version, values)
|
||||||
data['totales'] = _totales(doc, data['comprobante'], version)
|
data['totales'] = _totales(doc, data['comprobante'], version)
|
||||||
data['donataria'] = _donataria(doc, version, values['fechadof'])
|
data['donataria'] = _donataria(doc, version, values['fechadof'])
|
||||||
data['ine'] = _ine(doc, version)
|
data['ine'] = _ine(doc, version)
|
||||||
|
@ -1540,6 +1572,8 @@ def get_data_from_xml(invoice, values):
|
||||||
del data['timbre']['version']
|
del data['timbre']['version']
|
||||||
data['comprobante'].update(data['timbre'])
|
data['comprobante'].update(data['timbre'])
|
||||||
|
|
||||||
|
data['nomina'] = _nomina(invoice, values)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@ -1655,6 +1689,15 @@ def upload_file(rfc, opt, file_obj):
|
||||||
|
|
||||||
name = '{}_3.3_donativo.ods'.format(rfc.lower())
|
name = '{}_3.3_donativo.ods'.format(rfc.lower())
|
||||||
path = _join(PATH_MEDIA, 'templates', name)
|
path = _join(PATH_MEDIA, 'templates', name)
|
||||||
|
elif opt == 'txt_plantilla_nomina1233':
|
||||||
|
tmp = file_obj.filename.split('.')
|
||||||
|
ext = tmp[-1].lower()
|
||||||
|
if ext != 'ods':
|
||||||
|
msg = 'Extensión de archivo incorrecta, selecciona un archivo ODS'
|
||||||
|
return {'status': 'server', 'name': msg, 'ok': False}
|
||||||
|
|
||||||
|
name = '{}_1.2_3.3.ods'.format(rfc.lower())
|
||||||
|
path = _join(PATH_MEDIA, 'templates', name)
|
||||||
elif opt == 'bdfl':
|
elif opt == 'bdfl':
|
||||||
tmp = file_obj.filename.split('.')
|
tmp = file_obj.filename.split('.')
|
||||||
ext = tmp[-1].lower()
|
ext = tmp[-1].lower()
|
||||||
|
|
|
@ -186,10 +186,12 @@ def get_doc(type_doc, id, rfc):
|
||||||
data, file_name = PreFacturas.get_pdf(id)
|
data, file_name = PreFacturas.get_pdf(id)
|
||||||
elif type_doc == 'tpdf':
|
elif type_doc == 'tpdf':
|
||||||
data, file_name = Tickets.get_pdf(id)
|
data, file_name = Tickets.get_pdf(id)
|
||||||
elif type_doc == 'xmlnom':
|
elif type_doc == 'nomxml':
|
||||||
data, file_name = CfdiNomina.get_xml(id)
|
data, file_name = CfdiNomina.get_xml(id)
|
||||||
elif type_doc == 'nomlog':
|
elif type_doc == 'nomlog':
|
||||||
data, file_name = util.get_log('nomina')
|
data, file_name = util.get_log('nomina')
|
||||||
|
elif type_doc == 'nompdf':
|
||||||
|
data, file_name = CfdiNomina.get_pdf(id, rfc)
|
||||||
|
|
||||||
return data, file_name, content_type
|
return data, file_name, content_type
|
||||||
|
|
||||||
|
@ -3595,10 +3597,12 @@ class Facturas(BaseModel):
|
||||||
for tax in p.impuestos:
|
for tax in p.impuestos:
|
||||||
if tax_locales and tax.tipo == 'R' and tax.key == '000':
|
if tax_locales and tax.tipo == 'R' and tax.key == '000':
|
||||||
base = product['importe']
|
base = product['importe']
|
||||||
|
|
||||||
if tax_decimals:
|
if tax_decimals:
|
||||||
impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX)
|
impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX)
|
||||||
else:
|
else:
|
||||||
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
|
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
|
||||||
|
|
||||||
if tax.tipo == 'T' and tax.key != '000':
|
if tax.tipo == 'T' and tax.key != '000':
|
||||||
total_trasladados = (total_trasladados or 0) + impuesto_producto
|
total_trasladados = (total_trasladados or 0) + impuesto_producto
|
||||||
elif tax.tipo == 'R' and tax.key != '000':
|
elif tax.tipo == 'R' and tax.key != '000':
|
||||||
|
@ -3814,14 +3818,17 @@ class Facturas(BaseModel):
|
||||||
if impuesto.key == '000':
|
if impuesto.key == '000':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
base = row.importe - row.descuento
|
base = float(row.importe - row.descuento)
|
||||||
|
tasa = float(impuesto.tasa)
|
||||||
|
|
||||||
if tax_decimals:
|
if tax_decimals:
|
||||||
import_tax = round(impuesto.tasa * base, DECIMALES_TAX)
|
import_tax = round(tasa * base, DECIMALES_TAX)
|
||||||
tmp += import_tax
|
tmp += import_tax
|
||||||
xml_importe = FORMAT_TAX.format(import_tax)
|
xml_importe = FORMAT_TAX.format(import_tax)
|
||||||
else:
|
else:
|
||||||
import_tax = round(impuesto.tasa * base, DECIMALES)
|
import_tax = round(tasa * base, DECIMALES)
|
||||||
xml_importe = FORMAT.format(import_tax)
|
xml_importe = FORMAT.format(import_tax)
|
||||||
|
|
||||||
tipo_factor = 'Tasa'
|
tipo_factor = 'Tasa'
|
||||||
if impuesto.factor != 'T':
|
if impuesto.factor != 'T':
|
||||||
tipo_factor = 'Cuota'
|
tipo_factor = 'Cuota'
|
||||||
|
@ -4366,10 +4373,12 @@ class PreFacturas(BaseModel):
|
||||||
for tax in p.impuestos:
|
for tax in p.impuestos:
|
||||||
if tax_locales and tax.tipo == 'R' and tax.key == '000':
|
if tax_locales and tax.tipo == 'R' and tax.key == '000':
|
||||||
base = product['importe']
|
base = product['importe']
|
||||||
|
|
||||||
if tax_decimals:
|
if tax_decimals:
|
||||||
impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX)
|
impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX)
|
||||||
else:
|
else:
|
||||||
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
|
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
|
||||||
|
|
||||||
if tax.tipo == 'T' and tax.key != '000':
|
if tax.tipo == 'T' and tax.key != '000':
|
||||||
total_trasladados = (total_trasladados or 0) + impuesto_producto
|
total_trasladados = (total_trasladados or 0) + impuesto_producto
|
||||||
elif tax.tipo == 'R' and tax.key != '000':
|
elif tax.tipo == 'R' and tax.key != '000':
|
||||||
|
@ -6404,6 +6413,40 @@ class CfdiNomina(BaseModel):
|
||||||
# ~ cls._sync_xml(cls, obj)
|
# ~ cls._sync_xml(cls, obj)
|
||||||
return obj.xml, name
|
return obj.xml, name
|
||||||
|
|
||||||
|
def _get_not_in_xml(self, invoice, emisor):
|
||||||
|
values = {'is_nomina': True}
|
||||||
|
|
||||||
|
if invoice.version == '3.2':
|
||||||
|
return values
|
||||||
|
|
||||||
|
values['regimenfiscal'] = invoice.regimen_fiscal
|
||||||
|
values['usocfdi'] = invoice.uso_cfdi
|
||||||
|
values['receptor'] = {}
|
||||||
|
values['fechadof'] = None
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_pdf(cls, id, rfc, sync=True):
|
||||||
|
try:
|
||||||
|
emisor = Emisor.select()[0]
|
||||||
|
except IndexError:
|
||||||
|
return b'', 'sin_datos_de_emisor.pdf'
|
||||||
|
|
||||||
|
obj = CfdiNomina.get(CfdiNomina.id==id)
|
||||||
|
name = '{}{}_{}.pdf'.format(obj.serie, obj.folio, obj.empleado.rfc)
|
||||||
|
if obj.uuid is None:
|
||||||
|
return b'', name
|
||||||
|
|
||||||
|
values = cls._get_not_in_xml(cls, obj, emisor)
|
||||||
|
data = util.get_data_from_xml(obj, values)
|
||||||
|
doc = util.to_pdf(data, emisor.rfc)
|
||||||
|
|
||||||
|
# ~ if sync:
|
||||||
|
# ~ target = emisor.rfc + '/' + str(obj.fecha)[:7].replace('-', '/')
|
||||||
|
# ~ cls._sync_pdf(cls, doc, name, target)
|
||||||
|
return doc, name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_years(cls):
|
def filter_years(cls):
|
||||||
data = [{'id': -1, 'value': 'Todos'}]
|
data = [{'id': -1, 'value': 'Todos'}]
|
||||||
|
|
|
@ -54,6 +54,7 @@ var controllers = {
|
||||||
$$('txt_plantilla_factura_33j').attachEvent('onItemClick', txt_plantilla_factura_33j_click)
|
$$('txt_plantilla_factura_33j').attachEvent('onItemClick', txt_plantilla_factura_33j_click)
|
||||||
$$('txt_plantilla_ticket').attachEvent('onItemClick', txt_plantilla_ticket_click)
|
$$('txt_plantilla_ticket').attachEvent('onItemClick', txt_plantilla_ticket_click)
|
||||||
$$('txt_plantilla_donataria').attachEvent('onItemClick', txt_plantilla_donataria_click)
|
$$('txt_plantilla_donataria').attachEvent('onItemClick', txt_plantilla_donataria_click)
|
||||||
|
$$('txt_plantilla_nomina1233').attachEvent('onItemClick', txt_plantilla_nomina1233_click)
|
||||||
$$('chk_config_ocultar_metodo_pago').attachEvent('onItemClick', chk_config_item_click)
|
$$('chk_config_ocultar_metodo_pago').attachEvent('onItemClick', chk_config_item_click)
|
||||||
$$('chk_config_ocultar_condiciones_pago').attachEvent('onItemClick', chk_config_item_click)
|
$$('chk_config_ocultar_condiciones_pago').attachEvent('onItemClick', chk_config_item_click)
|
||||||
$$('chk_config_send_zip').attachEvent('onItemClick', chk_config_item_click)
|
$$('chk_config_send_zip').attachEvent('onItemClick', chk_config_item_click)
|
||||||
|
@ -1020,6 +1021,44 @@ function txt_plantilla_donataria_click(e){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function txt_plantilla_nomina1233_click(e){
|
||||||
|
|
||||||
|
var body_elements = [
|
||||||
|
{cols: [{width: 100}, {view: 'uploader', id: 'up_template',
|
||||||
|
autosend: true, link: 'lst_files', value: 'Seleccionar archivo',
|
||||||
|
upload: '/files/txt_plantilla_nomina1233', width: 200}, {width: 100}]},
|
||||||
|
{view: 'list', id: 'lst_files', type: 'uploader', autoheight:true,
|
||||||
|
borderless: true},
|
||||||
|
{},
|
||||||
|
{cols: [{}, {view: 'button', label: 'Cerrar', autowidth: true,
|
||||||
|
click:("$$('win_template').close();")}, {}]}
|
||||||
|
]
|
||||||
|
|
||||||
|
var w = webix.ui({
|
||||||
|
view: 'window',
|
||||||
|
id: 'win_template',
|
||||||
|
modal: true,
|
||||||
|
position: 'center',
|
||||||
|
head: 'Subir Plantilla Nómina',
|
||||||
|
body: {
|
||||||
|
view: 'form',
|
||||||
|
elements: body_elements,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
w.show()
|
||||||
|
|
||||||
|
$$('up_template').attachEvent('onUploadComplete', function(response){
|
||||||
|
if(response.ok){
|
||||||
|
$$('txt_plantilla_nomina1233').setValue(response.name)
|
||||||
|
msg_ok('Plantilla cargada correctamente')
|
||||||
|
}else{
|
||||||
|
msg_error(response.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function tab_options_change(nv, ov){
|
function tab_options_change(nv, ov){
|
||||||
var cv = {
|
var cv = {
|
||||||
tab_admin_templates: 'templates',
|
tab_admin_templates: 'templates',
|
||||||
|
|
|
@ -829,7 +829,6 @@ function calcular_impuestos(){
|
||||||
}else{
|
}else{
|
||||||
impuesto_producto = (impuesto.tasa * base).round(DECIMALES)
|
impuesto_producto = (impuesto.tasa * base).round(DECIMALES)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = table_totals.findOne({'tax': tax.tax})
|
tmp = table_totals.findOne({'tax': tax.tax})
|
||||||
if(tmp === null){
|
if(tmp === null){
|
||||||
table_totals.insert({'tax': tax.tax, 'importe': impuesto_producto})
|
table_totals.insert({'tax': tax.tax, 'importe': impuesto_producto})
|
||||||
|
|
|
@ -392,9 +392,9 @@ function grid_nomina_click(id, e, node){
|
||||||
var row = this.getItem(id)
|
var row = this.getItem(id)
|
||||||
|
|
||||||
if(id.column == 'xml'){
|
if(id.column == 'xml'){
|
||||||
location = '/doc/xmlnom/' + row.id
|
location = '/doc/nomxml/' + row.id
|
||||||
}else if(id.column == 'pdf'){
|
}else if(id.column == 'pdf'){
|
||||||
//~ get_momina_pdf(row.id)
|
window.open('/doc/nompdf/' + row.id, '_blank')
|
||||||
//~ }else if(id.column == 'email'){
|
//~ }else if(id.column == 'email'){
|
||||||
//~ enviar_correo(row)
|
//~ enviar_correo(row)
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,6 +569,11 @@ var options_templates = [
|
||||||
icon: 'file'},
|
icon: 'file'},
|
||||||
{}]},
|
{}]},
|
||||||
{maxHeight: 20},
|
{maxHeight: 20},
|
||||||
|
{cols: [{maxWidth: 15},
|
||||||
|
{view: 'search', id: 'txt_plantilla_nomina1233', name: 'plantilla_nomina1233',
|
||||||
|
label: 'Plantilla Nomina v1.2 - Cfdi 3.3 (ODS): ', labelPosition: 'top',
|
||||||
|
icon: 'file'}, {}]},
|
||||||
|
{maxHeight: 20},
|
||||||
{}]
|
{}]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue