forked from elmau/empresa-libre
Cancelar CFDI de pago
This commit is contained in:
parent
e5a389a9dd
commit
0ec7989c75
|
@ -1858,6 +1858,12 @@ class MovimientosBanco(BaseModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
def add(cls, values):
|
def add(cls, values):
|
||||||
ids = values.pop('ids', '')
|
ids = values.pop('ids', '')
|
||||||
|
|
||||||
|
if ids and not Facturas.validate_count_partners(util.loads(ids)):
|
||||||
|
msg = 'Facturas relacionadas a diferentes clientes'
|
||||||
|
data = {'ok': False, 'msg': msg}
|
||||||
|
return data
|
||||||
|
|
||||||
actualizar = False
|
actualizar = False
|
||||||
if 'saldo' in values:
|
if 'saldo' in values:
|
||||||
saldo = values['saldo']
|
saldo = values['saldo']
|
||||||
|
@ -3220,6 +3226,17 @@ class Facturas(BaseModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
order_by = ('fecha',)
|
order_by = ('fecha',)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate_count_partners(cls, ids):
|
||||||
|
filters = (Facturas.id.in_(tuple(ids.keys())))
|
||||||
|
partners = (Facturas.select(fn.COUNT(Facturas.cliente))
|
||||||
|
.where(filters)
|
||||||
|
.group_by(Facturas.cliente)
|
||||||
|
.order_by(Facturas.cliente).tuples())
|
||||||
|
if len(partners) > 1:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cancel(cls, id):
|
def cancel(cls, id):
|
||||||
obj = Facturas.get(Facturas.id==id)
|
obj = Facturas.get(Facturas.id==id)
|
||||||
|
@ -5279,6 +5296,7 @@ class CfdiPagos(BaseModel):
|
||||||
notas = TextField(default='')
|
notas = TextField(default='')
|
||||||
error = TextField(default='')
|
error = TextField(default='')
|
||||||
cancelada = BooleanField(default=False)
|
cancelada = BooleanField(default=False)
|
||||||
|
fecha_cancelacion = DateTimeField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
order_by = ('movimiento',)
|
order_by = ('movimiento',)
|
||||||
|
@ -5288,6 +5306,46 @@ class CfdiPagos(BaseModel):
|
||||||
opt = values.pop('opt')
|
opt = values.pop('opt')
|
||||||
return getattr(cls, '_{}'.format(opt))(cls, values)
|
return getattr(cls, '_{}'.format(opt))(cls, values)
|
||||||
|
|
||||||
|
def _cancel(self, values):
|
||||||
|
id_mov = int(values['id_mov'])
|
||||||
|
|
||||||
|
filters = (
|
||||||
|
(CfdiPagos.movimiento==id_mov) &
|
||||||
|
(CfdiPagos.cancelada==False)
|
||||||
|
)
|
||||||
|
last = CfdiPagos.select().where(filters)
|
||||||
|
if not last:
|
||||||
|
msg = 'El depósito no tiene facturas de pago activas'
|
||||||
|
data = {'ok': False, 'msg': msg}
|
||||||
|
return data
|
||||||
|
|
||||||
|
if len(last) > 1:
|
||||||
|
msg = 'Hay más de una factura activa para este depósito'
|
||||||
|
data = {'ok': False, 'msg': msg}
|
||||||
|
return data
|
||||||
|
|
||||||
|
last = last[0]
|
||||||
|
if not last.uuid:
|
||||||
|
msg = 'La factura no esta timbrada'
|
||||||
|
data = {'ok': False, 'msg': msg}
|
||||||
|
return data
|
||||||
|
|
||||||
|
auth = Emisor.get_auth()
|
||||||
|
cert = Certificado.get_cert()
|
||||||
|
|
||||||
|
data, result = util.cancel_xml(auth, last.uuid, cert)
|
||||||
|
if data['ok']:
|
||||||
|
last.estatus = 'Cancelada'
|
||||||
|
last.error = ''
|
||||||
|
last.cancelada = True
|
||||||
|
last.fecha_cancelacion = result['Fecha']
|
||||||
|
msg = 'Factura cancelada correctamente'
|
||||||
|
else:
|
||||||
|
last.error = msg = data['msg']
|
||||||
|
last.save()
|
||||||
|
|
||||||
|
return {'ok': data['ok'], 'msg': msg, 'id': last.id}
|
||||||
|
|
||||||
def _get_folio(self, serie):
|
def _get_folio(self, serie):
|
||||||
folio = int(Configuracion.get_('txt_config_cfdipay_folio') or '0')
|
folio = int(Configuracion.get_('txt_config_cfdipay_folio') or '0')
|
||||||
start = (CfdiPagos
|
start = (CfdiPagos
|
||||||
|
@ -5341,9 +5399,19 @@ class CfdiPagos(BaseModel):
|
||||||
data = {'ok': True, 'new': False}
|
data = {'ok': True, 'new': False}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
fields = {}
|
||||||
|
filters = (
|
||||||
|
(CfdiPagos.movimiento==id_mov) &
|
||||||
|
(CfdiPagos.cancelada==True)
|
||||||
|
)
|
||||||
|
previous = CfdiPagos.select().where(filters).order_by(CfdiPagos.id.desc())
|
||||||
|
if previous:
|
||||||
|
previous = previous[0]
|
||||||
|
fields['tipo_relacion'] = DEFAULT_CFDIPAY['TYPE_RELATION']
|
||||||
|
fields['uuid_relacionado'] = previous.uuid
|
||||||
|
|
||||||
emisor = Emisor.select()[0]
|
emisor = Emisor.select()[0]
|
||||||
serie = Configuracion.get_('txt_config_cfdipay_serie') or DEFAULT_CFDIPAY['SERIE']
|
serie = Configuracion.get_('txt_config_cfdipay_serie') or DEFAULT_CFDIPAY['SERIE']
|
||||||
fields = {}
|
|
||||||
fields['movimiento'] = id_mov
|
fields['movimiento'] = id_mov
|
||||||
fields['socio'] = partner
|
fields['socio'] = partner
|
||||||
fields['serie'] = serie
|
fields['serie'] = serie
|
||||||
|
@ -5417,7 +5485,7 @@ class CfdiPagos(BaseModel):
|
||||||
if invoice.tipo_relacion:
|
if invoice.tipo_relacion:
|
||||||
related = {
|
related = {
|
||||||
'tipo': invoice.tipo_relacion,
|
'tipo': invoice.tipo_relacion,
|
||||||
'cfdis': (invoice.uuid_relacionado,),
|
'cfdis': (str(invoice.uuid_relacionado),),
|
||||||
}
|
}
|
||||||
|
|
||||||
emisor = {
|
emisor = {
|
||||||
|
@ -7958,6 +8026,10 @@ def _migrate_tables():
|
||||||
migrations.append(migrator.drop_column('cfdipagos', 'cancelado'))
|
migrations.append(migrator.drop_column('cfdipagos', 'cancelado'))
|
||||||
migrations.append(migrator.add_column('cfdipagos', 'cancelada', cancelada))
|
migrations.append(migrator.add_column('cfdipagos', 'cancelada', cancelada))
|
||||||
|
|
||||||
|
if not 'fecha_cancelacion' in columns:
|
||||||
|
fecha_cancelacion = DateTimeField(null=True)
|
||||||
|
migrations.append(migrator.add_column('cfdipagos', 'fecha_cancelacion', fecha_cancelacion))
|
||||||
|
|
||||||
if migrations:
|
if migrations:
|
||||||
with database_proxy.atomic() as txn:
|
with database_proxy.atomic() as txn:
|
||||||
migrate(*migrations)
|
migrate(*migrations)
|
||||||
|
|
|
@ -164,6 +164,7 @@ DEFAULT_CFDIPAY = {
|
||||||
'KEYSAT': '84111506',
|
'KEYSAT': '84111506',
|
||||||
'UNITKEY': 'ACT',
|
'UNITKEY': 'ACT',
|
||||||
'DESCRIPTION': 'Pago',
|
'DESCRIPTION': 'Pago',
|
||||||
|
'TYPE_RELATION': '04',
|
||||||
}
|
}
|
||||||
DIR_FACTURAS = 'facturas'
|
DIR_FACTURAS = 'facturas'
|
||||||
USAR_TOKEN = False
|
USAR_TOKEN = False
|
||||||
|
|
|
@ -893,6 +893,43 @@ function cmd_pay_stamp_click(){
|
||||||
|
|
||||||
|
|
||||||
function cmd_pay_cancel_click(){
|
function cmd_pay_cancel_click(){
|
||||||
|
var form = $$('form_bank_pay')
|
||||||
|
var values = form.getValues()
|
||||||
|
var data = {'opt': 'cancel', 'id_mov': values.id_mov}
|
||||||
|
|
||||||
|
var grid = $$('grid_cfdi_pay')
|
||||||
|
if(grid.count() == 0){
|
||||||
|
msg_error('El depósito no tiene facturas de pago activas')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = '¿Estás seguro de cancelar esta factura?\n\nESTA ACCIÓN NO SE PUEDE DESHACER'
|
||||||
|
webix.confirm({
|
||||||
|
title: 'Cancelar Factura',
|
||||||
|
ok: 'Si',
|
||||||
|
cancel: 'No',
|
||||||
|
type: 'confirm-error',
|
||||||
|
text: msg,
|
||||||
|
callback:function(result){
|
||||||
|
if(result){
|
||||||
|
webix.ajax().post('/cfdipay', data, {
|
||||||
|
error:function(text, data, XmlHttpRequest){
|
||||||
|
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||||
|
msg_error(msg)
|
||||||
|
},
|
||||||
|
success:function(text, data, XmlHttpRequest){
|
||||||
|
values = data.json();
|
||||||
|
if(values.ok){
|
||||||
|
grid.updateItem(values.id, {'estatus': 'Cancelada'})
|
||||||
|
msg_ok(values.msg)
|
||||||
|
}else{
|
||||||
|
msg_error(values.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue