Fix - Al generar complemento EDU

This commit is contained in:
Mauricio Baeza 2018-06-03 00:00:04 -05:00
parent 7348b1bbba
commit cf5517d1ab
14 changed files with 188 additions and 22 deletions

View File

@ -1,7 +1,16 @@
v 1.8.0 [03-jun-2018]
---------------------
- Se permiten 4 decimales en Tipo de cambio
- Se agrega el campo {total_cantidades} al generar el PDF
- Se agrega opción para generar respaldos de la BD en MV
- Fix: Al generar con complemento EDU
v 1.7.0 [23-may-2018]
---------------------
- Se agrega soporte para truncar impuestos locales, para las estulticias de los "ingenieros" de las dependencias de gobierno
v 1.6.1 [09-abr-2018]
---------------------
- Fix: Nómina con separación

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.8.0

View File

@ -124,6 +124,8 @@ class CFDI(object):
if datos['donativo']:
self._donativo = True
self._edu = datos['edu']
if datos['complementos']:
if 'ine' in datos['complementos']:
self._ine = True

View File

@ -17,7 +17,11 @@ class AppEmpresas(object):
def on_post(self, req, resp):
values = req.params
req.context['result'] = self._db.empresa_agregar(values)
opt = values.pop('opt', '1')
if opt == '1':
req.context['result'] = self._db.empresa_agregar(values)
elif opt == '2':
req.context['result'] = self._db.respaldar_dbs()
resp.status = falcon.HTTP_200
def on_delete(self, req, resp):

View File

@ -627,6 +627,7 @@ class LIBO(object):
self._sm = None
self._desktop = None
self._currency = 'MXN'
self._total_cantidades = 0
if self.is_running:
ctx = uno.getComponentContext()
service = 'com.sun.star.bridge.UnoUrlResolver'
@ -872,7 +873,7 @@ class LIBO(object):
col5.append((float(valor_unitario),))
col6.append((float(importe),))
col7.append((float(descuento),))
self._total_cantidades += float(cantidad)
if not count:
return
@ -934,6 +935,8 @@ class LIBO(object):
}
currency = data['moneda']
self._set_cell('{total_cantidades}', str(self._total_cantidades))
cell_title = self._set_cell('{subtotal.titulo}', 'SubTotal')
value = data['subtotal']
cell_value = self._set_cell('{subtotal}', value, value=True)
@ -1568,7 +1571,7 @@ def _comprobante(doc, options):
data['fechaformato'] = fecha.strftime('%A, %d de %B de %Y')
if 'tipocambio' in data:
data['tipocambio'] = 'Tipo de Cambio: $ {:0.2f}'.format(
data['tipocambio'] = 'Tipo de Cambio: $ {:0.4f}'.format(
float(data['tipocambio']))
data['notas'] = options['notas']
@ -3411,3 +3414,20 @@ def get_timbres(rfc, token):
def truncate(value):
return trunc(value * 100) / 100
def validate_path_bk():
path_bk = _join(str(Path.home()), DIR_FACTURAS)
if not os.path.isdir(path_bk):
msg = 'No existe la carpeta'
return {'ok': False, 'msg': msg}
return {'ok': True, 'msg': path_bk}
def respaldar_db(values, path_bk):
user = values[0].lower()
db = loads(values[1])['name']
path = _join(path_bk, '{}.bk'.format(user))
args = 'pg_dump -U postgres -Fc {} > "{}"'.format(db, path)
_call(args)
return

View File

@ -28,6 +28,9 @@ class StorageEngine(object):
def empresa_borrar(self, values):
return main.empresa_borrar(values['rfc'])
def respaldar_dbs(self):
return main.respaldar_dbs()
def _get_empresas(self, values):
return main.get_empresas()
@ -107,8 +110,8 @@ class StorageEngine(object):
def enviar_prefac(self, values):
return main.PreFacturas.enviar(values['id'])
def _get_cancelinvoice(self, values):
return main.Facturas.cancel(values['id'])
# ~ def _get_cancelinvoice(self, values):
# ~ return main.Facturas.cancel(values['id'])
def _get_statussat(self, values):
return main.Facturas.get_status_sat(values['id'])
@ -371,8 +374,8 @@ class StorageEngine(object):
def get_preinvoices(self, values):
return main.PreFacturas.get_(values)
def _get_timbrar(self, values):
return main.Facturas.timbrar(values)
# ~ def _get_timbrar(self, values):
# ~ return main.Facturas.timbrar(values)
def _get_anticipoegreso(self, values):
return main.Facturas.anticipo_egreso(int(values['id']))

View File

@ -18,7 +18,7 @@ from controllers import util
from settings import log, DEBUG, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \
INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS, DEFAULT_SAT_PRODUCTO, \
CANCEL_SIGNATURE, PUBLIC, DEFAULT_SERIE_TICKET, CURRENT_CFDI_NOMINA, \
DEFAULT_SAT_NOMINA, DECIMALES_TAX, TITLE_APP
DEFAULT_SAT_NOMINA, DECIMALES_TAX, TITLE_APP, MV
FORMAT = '{0:.2f}'
@ -3811,7 +3811,6 @@ class Facturas(BaseModel):
FacturasComplementos.create(**data)
return
def _get_serie(self, user, default_serie):
if user.sucursal is None:
return default_serie
@ -3828,7 +3827,7 @@ class Facturas(BaseModel):
emisor = Emisor.select()[0]
values['serie'] = cls._get_serie(cls, user, values['serie'])
values['folio'] = cls._get_folio(cls, values['serie'])
values['tipo_cambio'] = float(values['tipo_cambio'])
values['tipo_cambio'] = round(float(values['tipo_cambio']), 4)
values['lugar_expedicion'] = emisor.cp_expedicion or emisor.codigo_postal
values['anticipo'] = util.get_bool(values['anticipo'])
values['donativo'] = util.get_bool(values['donativo'])
@ -3850,6 +3849,9 @@ class Facturas(BaseModel):
obj.total_mn = totals['total_mn']
obj.save()
msg = 'G {}'.format(obj.id)
_save_log(user.usuario, msg, 'F')
msg = 'Factura guardada correctamente. Enviando a timbrar'
row = {
'id': obj.id,
@ -3859,6 +3861,7 @@ class Facturas(BaseModel):
'fecha': obj.fecha,
'tipo_comprobante': obj.tipo_comprobante,
'estatus': obj.estatus,
'paid': 'No',
'total_mn': obj.total_mn,
'cliente': obj.cliente.nombre,
}
@ -3897,7 +3900,7 @@ class Facturas(BaseModel):
comprobante['Moneda'] = invoice.moneda
comprobante['TipoCambio'] = '1'
if comprobante['Moneda'] != 'MXN':
comprobante['TipoCambio'] = FORMAT.format(invoice.tipo_cambio)
comprobante['TipoCambio'] = FORMAT_TAX.format(invoice.tipo_cambio)
comprobante['Total'] = FORMAT.format(invoice.total)
comprobante['TipoDeComprobante'] = invoice.tipo_comprobante
if invoice.metodo_pago:
@ -4190,7 +4193,7 @@ class Facturas(BaseModel):
return
@classmethod
def timbrar(cls, values):
def timbrar(cls, values, user):
id = int(values['id'])
update = util.loads(values.get('update', 'true'))
@ -4221,6 +4224,9 @@ class Facturas(BaseModel):
if update:
cls._update_inventory(cls, obj)
cls._sync(cls, id, auth)
m = 'T {}'.format(obj.id)
_save_log(user.usuario, m, 'F')
else:
msg = result['error']
obj.estatus = 'Error'
@ -4379,6 +4385,16 @@ class Facturas(BaseModel):
if args['opt'] == 'invoicepayed':
return cls._set_invoices_payed(cls, args['ids'], user)
if args['opt'] == 'timbrar':
return cls.timbrar(args, user)
if args['opt'] == 'cancel':
result = cls.cancel(args['id'])
if result['ok']:
m = 'C {}'.format(args['id'])
_save_log(user.usuario, m, 'F')
return result
return {'ok': False}
@ -7136,6 +7152,13 @@ class CfdiNominaRelacionados(BaseModel):
return [str(r.cfdi_origen.uuid) for r in query]
@util.run_in_thread
def _save_log(user, action, table):
data = {'usuario': user, 'accion': action, 'tabla': table}
Registro.add(data)
return
def authenticate(args):
respuesta = {'login': False, 'msg': 'No Autorizado', 'user': ''}
values = util.get_con(args['rfc'])
@ -7638,6 +7661,28 @@ def empresa_borrar(rfc):
return True
def respaldar_dbs():
if not MV:
msg = 'Solo MV'
return {'ok': False, 'msg': msg}
result = util.validate_path_bk()
if not result['ok']:
return result
path_bk = result['msg']
data = util.get_rfcs()
if not len(data):
msg = 'Sin bases de datos a respaldar'
return {'ok': False, 'msg': msg}
for row in data:
util.respaldar_db(row, path_bk)
msg = 'Bases de datos respaldadas correctamente'
return {'ok': True, 'msg': msg}
def _importar_valores(archivo='', rfc=''):
if not rfc:
rfc = input('Introduce el RFC: ').strip().upper()

View File

@ -31,8 +31,9 @@ except ImportError:
DEBUG = DEBUG
VERSION = '1.5.0'
VERSION = '1.8.0'
EMAIL_SUPPORT = ('soporte@empresalibre.net',)
TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION)
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

View File

@ -44,12 +44,14 @@ var invoices_controllers = {
$$('lst_moneda').attachEvent('onChange', lst_moneda_change)
$$('lst_tipo_comprobante').attachEvent('onChange', lst_tipo_comprobante_change)
$$('lst_serie').attachEvent('onChange', lst_serie_change)
$$('txt_tipo_cambio').attachEvent('onBlur', txt_tipo_cambio_lost_focus)
$$('cmd_cfdi_notes').attachEvent('onItemClick', cmd_cfdi_notes_click)
$$('cmd_admin_invoice_notes').attachEvent('onItemClick', cmd_admin_invoice_notes_click)
$$('cmd_import_invoice').attachEvent('onItemClick', cmd_import_invoice_click)
webix.extend($$('grid_invoices'), webix.ProgressBar)
focus('search_client_name')
}
}
@ -465,7 +467,8 @@ function generar_anticipo_egreso(id){
function send_timbrar(id){
webix.ajax().get('/values/timbrar', {id: id}, function(text, data){
//~ webix.ajax().get('/values/timbrar', {id: id}, function(text, data){
webix.ajax().post('invoices', {opt: 'timbrar', id: id}, function(text, data){
var values = data.json()
if(values.ok){
cmd_update_timbres_click()
@ -1026,7 +1029,7 @@ function grid_details_before_edit_stop(state, editor){
state.value = state.value.trim()
if(state.value.length != 21){
msg = 'El Pedimento debe ser de 21 caracteres, será '
msg += 'rechazado por el SAT. Edita estalo hasta que ya '
msg += 'rechazado por el SAT. Editalo hasta que ya '
msg += 'no veas este mensaje de error. <BR>'
msg += '<BR>Caracteres: ' + state.value.length
msg_error(msg)
@ -1051,6 +1054,12 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
cantidad = cantidad.round(DECIMALES)
grid.blockEvent()
state.value = cantidad
grid.unblockEvent()
var valor_unitario = parseFloat(row['valor_unitario'])
var descuento = parseFloat(row['descuento'])
}
@ -1065,13 +1074,16 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
if(cfg_invoice['with_taxes']){
var valor_unitario = price_without_taxes(parseFloat(state.value), row.id_product)
grid.blockEvent()
state.value = valor_unitario
grid.unblockEvent()
}else{
var valor_unitario = parseFloat(state.value).round(DECIMALES)
}
var valor_unitario = parseFloat(state.value)
grid.blockEvent()
state.value = valor_unitario
grid.unblockEvent()
var cantidad = parseFloat(row['cantidad'])
var descuento = parseFloat(row['descuento'])
}
@ -1087,6 +1099,8 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
descuento = descuento.round(DECIMALES)
var cantidad = parseFloat(row['cantidad'])
var valor_unitario = parseFloat(row['valor_unitario'])
@ -1099,6 +1113,11 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
grid.blockEvent()
state.value = descuento
grid.unblockEvent()
}
var precio_final = valor_unitario - descuento
@ -1316,7 +1335,8 @@ function grid_invoices_click(id, e, node){
function send_cancel(id){
webix.ajax().get('/values/cancelinvoice', {id: id}, function(text, data){
//~ webix.ajax().get('/values/cancelinvoice', {id: id}, function(text, data){
webix.ajax().post('invoices', {opt: 'cancel', id: id}, function(text, data){
var values = data.json()
if(values.ok){
msg_ok(values.msg)
@ -1532,6 +1552,21 @@ function lst_moneda_change(nv, ov){
$$('txt_tipo_cambio').config.readonly = false
}
$$('txt_tipo_cambio').refresh()
select_all('txt_tipo_cambio')
}
function txt_tipo_cambio_lost_focus(prev){
var tipo_cambio = $$('txt_tipo_cambio').getValue()
if(isNaN(tipo_cambio * 1)){
webix.UIManager.setFocus('txt_tipo_cambio')
msg = 'El Tipo de Cambio debe ser un valor númerico'
msg_error(msg)
$$('txt_tipo_cambio').setValue('1.00')
}else{
$$('txt_tipo_cambio').setValue(parseFloat(tipo_cambio).round(4))
}
}

View File

@ -531,7 +531,8 @@ function chk_is_invoice_day_change(new_value, old_value){
function send_timbrar_invoice(id){
webix.ajax().get('/values/timbrar', {id: id, update: false}, function(text, data){
//~ webix.ajax().get('/values/timbrar', {id: id, update: false}, function(text, data){
webix.ajax().post('invoices', {opt: 'timbrar', id: id, update: false}, function(text, data){
var values = data.json()
if(values.ok){
msg_ok(values.msg)

View File

@ -53,6 +53,12 @@ function focus(name){
}
function select_all(name){
focus(name)
$$(name).getInputNode().select()
}
function to_end(name){
focus(name)
var txt = $$(name)

View File

@ -16,6 +16,11 @@ var header = [
{view: 'button', type: 'icon', width: 40, css: 'app_button',
icon: 'home', click: 'window.location = "/"'},
]
var footer = [
{},
{view: 'button', value: 'Respaldar BD', click: 'cmd_respaldar_bd'},
{},
]
var grid_empresas_cols = [
@ -57,6 +62,7 @@ var ui_empresas = {
}
},
grid_empresas,
{view: 'toolbar', elements: footer},
]}, {}, ]
},
]

View File

@ -22,7 +22,7 @@ var grid_cols_students = [
sort: 'string'},
{id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust: 'data',
sort: 'string'},
{id: 'curp', header: ['CURP'], sort: 'string'},
{id: 'curp', header: ['CURP'], sort: 'string', adjust: 'data'},
]

View File

@ -42,6 +42,8 @@ function validate_nuevo_rfc(){
return
}
values['opt'] = 1
msg = '¿Estás seguro de agregar este nuevo emisor?'
webix.confirm({
title: 'Agregar Emisor',
@ -99,6 +101,37 @@ function grid_empresas_click(id, e, node){
}
function respaldar_bd(){
webix.ajax().post("/empresas", {'opt': 2}, function(text, data, xhr) {
var values = data.json();
if (values.ok) {
msg_ok(values.msg)
} else {
msg_error(values.msg)
}
})
}
function cmd_respaldar_bd(){
msg = '¿Estás seguro de respaldar las Bases de Datos?'
webix.confirm({
title: 'Respaldar BD',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
msg = 'Respaldando Bases de datos...'
msg_ok(msg)
respaldar_bd()
}
}
})
}
webix.ready(function(){
webix.ui(ui_empresas)
$$('grid_empresas').attachEvent('onItemClick', grid_empresas_click)