cobro_discriminado.py 14.1 KB
# -*- coding: utf-8 -*-
###############################################################################
#    License, author and contributors information in:                         #
#    __manifest__.py file at the root folder of this module.                  #
###############################################################################

from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError, Warning
import datetime

class hgt_cobro_multiple(models.TransientModel):
    _name = 'hgt.cobro_multiple'
    _description = 'Cobro multiple avanzado'
    _inherit = ['asw.action.manager']

    # Informacion pago
    pcw_cliente = fields.Many2one(
        comodel_name='asw.cliente', 
        string='Cliente',
        readonly=True,
        compute='_compute_cliente',
    )

    caja_efectivo = fields.Many2one(
        comodel_name='asw.caja', 
        string='Caja Efectivo',
    )

    caja_cheque = fields.Many2one(
        comodel_name='asw.caja', 
        string='Caja Cheques',
    )
    
    nota = fields.Text(string='nota',readonly=True)
    
    pcw_referencia = fields.Char(
        string=u'Referencia',
    )    

    pcw_efectivo = fields.Monetary(
        string='Efectivo', 
        currency_field='cli_moneda_empresa'
    )

    pcw_retencion_recibida = fields.Monetary(
        string='Retención', 
        currency_field='cli_moneda_empresa'
    )
    
    pcw_cli_razon_social = fields.Char(
        string='Razon Social',
        related='pcw_cliente.cli_razon_social'
    )

    # Currency field
    cli_moneda_empresa = fields.Many2one(
        string=u'Moneda del saldo',
        comodel_name='res.currency',
        ondelete='set null', 
        related='pcw_cliente.create_uid.company_id.currency_id',        
    )

    # Formas de pago
    pcw_che_recibidos = fields.Many2many(
        comodel_name='asw.cheque', 
        relation='pago_cliente_chq_recibido', 
        column1='asw_cheque_id', 
        column2='asw_cliente_id', 
        string='Cheques Recibidos'
    )

    pcw_chq_emitidos = fields.Many2many(
        comodel_name='asw.cheque', 
        relation='pago_cliente_chq_emitido', 
        column1='asw_cheque_id', 
        column2='asw_cliente_id', 
        string='Cheques Emitidos'
    )

    pcw_chq_resiv2 = fields.Many2many(
        comodel_name='asw.cheque', 
        relation='pago_cliente_chq_emitido_nuevo123', 
        column1='asw_cheque_id', 
        column2='asw_cliente_id', 
        string='Cheques Emitidos'
    )

    pcw_transferencias_recibidas = fields.Many2many(
        comodel_name='asw.valores', 
        relation='pago_cliente_transferencia_recibida', 
        column1='pago_cliente_id', 
        column2='asw_valores_id', 
        string='Transferencias Recibidas'
    )

    pcw_transferencias_emitidas = fields.Many2many(
        comodel_name='asw.valores', 
        relation='pago_cliente_transferencia_emitida', 
        column1='pago_cliente_id', 
        column2='asw_valores_id', 
        string='Transferencias Emitidas'
    )

    #pcw_tarjetas = fields.Many2many(
    #    comodel_name='asw.valores', 
    #    relation='pago_cliente_tarjeta', 
    #    column1='pago_cliente_id', 
    #    column2='asw_valores_id', 
    #    string='Tarjetas'
    #)

    pcw_tarjetas = fields.Many2many(
        comodel_name='asw.valores', 
        relation='hgt_pago_cliente_tarjeta', 
        column1='pago_cliente_id', 
        column2='asw_valores_id', 
        string='Tarjetas'
    )

    pcw_retenciones = fields.Many2many(
        comodel_name='asw.valores', 
        relation='pago_cliente_retencion', 
        column1='pago_cliente_id', 
        column2='asw_valores_id', 
        string='Retenciones'
    )
    # Total de pago
    pcw_total = fields.Monetary(
        string='Total Recibido',
        compute='_calcular_total',
        currency_field='cli_moneda_empresa'
    )

    pcw_recibo = fields.Many2one(
        string='Recibo',
        comodel_name='asw.comprobante'
    )
###########################################Validaciones y calculos ######################################

    @api.depends('pcw_total')
    def _compute_cliente(self):
        if not len(self.pcw_cliente) == 0:
            return(None)
        context = self.env.context
        active_ids = context.get('active_ids')
        facturas = self.env['asw.comprobante'].search([('id', 'in', active_ids)])
        idc = []
        Texto = "Facturas que se abonaran:"
        Total = 0
        for factura in facturas:
            if not factura.comp_cliente.id in idc:
                idc.append(factura.comp_cliente.id)
            if not factura.comp_adeudado > 0:
                raise UserError(f"Factura {factura.display_name} ya esta pagada o valor nulo")
            if factura.comp_estado in ["b","c"]:
                raise UserError(f"Factura {factura.display_name} en estado invalido para cobrar")
            #if (factura.comp_talonario.tal_tipo == "e"):
            #    raise UserError(f"El comprobante {factura.display_name} no es de venta")
            Total = Total + factura.comp_adeudado
            Texto = f"{Texto}\n{factura.display_name}    {factura.comp_adeudado}"
        if not len(idc) == 1:
            raise UserError("Solo se puede cobrar a un cliente a la vez, cierre la ventana y seleccione de vuelta los comprobantes a operar")
        Texto = f"{Texto}\nTotal {Total}".replace(".",self.PuntoDecimal())
        self.pcw_cliente = idc[0]
        self.nota = Texto



    @api.depends('pcw_efectivo', 'pcw_che_recibidos', 'pcw_transferencias_recibidas', 'pcw_tarjetas', 'pcw_chq_resiv2', 'pcw_transferencias_emitidas', 'pcw_retencion_recibida','pcw_retenciones')
    def _calcular_total(self):
        total = 0
        for record in self.pcw_chq_resiv2:
            total = total + record.che_monto
        for record in self.pcw_transferencias_recibidas:
            total = total + record.val_monto
        for record in self.pcw_chq_emitidos:
            total = total + record.che_monto
        for record in self.pcw_transferencias_emitidas:
            total = total + record.val_monto
        for record in self.pcw_tarjetas:
            total = total + record.val_monto
        for record in self.pcw_retenciones:
            total = total + record.val_monto
        self.pcw_total = total + self.pcw_efectivo + self.pcw_retencion_recibida


    #################################              LOGICA DE PAGO                            #################

    @api.multi
    def pago_facturas_masivo(self):
        context = self.env.context
        active_ids = context.get('active_ids')
        facturas = self.env['asw.comprobante'].search([('id', 'in', active_ids)],order="id asc")
        if len(facturas) == 0:#no hay facturas seleccionadas
            raise Warning("No se seleccionaron facturas")
        resivo = self.CrearValidarResivoMultiple()
        if self.pcw_total != resivo.comp_total:
            raise Warning("Error al procesar el pago informar a soporte")
        total = self.pcw_total
        for factura in facturas:
            if factura.comp_estado in ["c","b"]:
                raise Warning(f"Factura {factura.display_name} esta cancelada o sin validar no se puede Cobrar")
            if not factura.comp_adeudado > 0:
                raise Warning(f"Factura {factura.display_name} en cero revisar")
            if(not factura.comp_talonario.tal_genera_cta_cte):
                raise Warning(f"Factura {factura.display_name} no mueve cuenta corriente no puedo manejarla")
            total = self.LogicaFacturas(factura,resivo,total)
            #obserbacion = f"""{obserbacion}\n{factura.display_name}"""
        resivo.aumentar_numeracion_talonario()
        resivo.comp_fecha_validacion = fields.Datetime.now()
        resivo.generar_monto_adeudado()
        resivo.validar_nro_comprobante()
        self.ArmarObservaciones(facturas,resivo)
        resivo.generar_monto_adeudado()#a prueba
        return(resivo)

    def ArmarObservaciones(self,facturas,resivo):
        obserbacion = "\nFacturas Afectadas     | Total | Saldo"  
        for factura in facturas:
            obserbacion = f"""{obserbacion}\n{factura.display_name} | {factura.comp_total} | {factura.comp_adeudado}""".replace(".",self.PuntoDecimal())
        resivo.comp_observaciones = obserbacion 


    @api.multi
    def generar_recibo(self):
        resivo = self.pago_facturas_masivo()
        self.ValoresEnCajas(resivo)
        return {
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'asw.comprobante',
                'type': 'ir.actions.act_window',
                'target': 'self',
                'res_id': resivo.id,
            }

    def LogicaFacturas(self,factura,resivo,total):
        #print(f"factura {factura.display_name},adeudado {factura.comp_adeudado}, total {total}")
        tmp = total
        total = total - factura.comp_adeudado
        if tmp >= 0.0:
            self.MovimientoCuentaCorriente(factura,resivo,tmp)
        #if total < 0.0:
        #    total = 0.0
        return(total)

    #Nombre heredado no me gusto pero bue....
    def MovimientoCuentaCorriente(self,factura,resivo,total):
        #Total = total
        #diff = total - factura.comp_adeudado
        movimiento = factura.comp_adeudado
        if factura.comp_adeudado >= total: #diff < 0.0:
            movimiento = total
        #print( movimiento, factura.display_name)
        if movimiento < 0.0: 
            raise Warning("debug")
        cta_cte = self.env['asw.cta_cte'].create({
            'cc_cliente' : resivo.comp_cliente.id,
            'cc_comprobante' : resivo.id,
            'cc_moneda' : resivo.comp_moneda.id,
            'cc_monto' : movimiento
        })
        cta_cte.afectar(factura.id)
        resivo.generar_monto_adeudado()
        print()


    def CrearValidarResivoMultiple(self,tipo="e"):
        talonario = self.env['asw.talonario'].search([('tal_menu','=','rec'),('tal_tipo','=',tipo),('tal_mov_caja', '!=', 'sn')], limit=1)
        self.pcw_recibo = self.env['asw.comprobante'].generar_comprobante(
            talonario,
            self.pcw_cliente, 
            self.pcw_total, 
            self.pcw_referencia
        )
        self.agregar_efectivo()
        self.agregar_retencion()
        self.agregar_cheques_recibidos()
        self.agregar_transferencias_recibidas()
        self.agregar_tarjetas()
        self.pcw_recibo._onchange_comp_linea_facturas()
        self.pcw_recibo.realizar_validaciones()
        self.pcw_recibo._onchange_talonario()
        return(self.pcw_recibo)

    #################################################LOGICA CREACION RESIVO##################################################
    def agregar_efectivo(self):
        if self.pcw_efectivo != 0:
            efectivo = self.env['asw.tipos_valores'].search([('tv_tipo', '=', 'ef')])
            self.pcw_recibo.agregar_valor(self.pcw_efectivo, efectivo, self.caja_efectivo.id)

    def agregar_retencion(self):
        if(len(self.pcw_retenciones) == 0):
            return(None)#Si no hay alguna retencion
        for linea in self.pcw_retenciones:
            self.pcw_recibo.agregar_valor(linea.val_monto, linea.val_tipo, False)

    def agregar_cheques_recibidos(self):
        if(len(self.pcw_chq_resiv2) > 0):
            cheque_recibido = self.env['asw.tipos_valores'].search([('tv_tipo', '=', 'chr')])
            for cheque in self.pcw_chq_resiv2: 
                self.pcw_recibo.agregar_cheque(cheque, cheque_recibido, self.caja_cheque.id)

    def agregar_transferencias_recibidas(self):
        transferencia_recibida = self.env['asw.tipos_valores'].search([('tv_tipo','=','trr')])
        
        self.pcw_transferencias_recibidas.write({'val_comprobante' : self.pcw_recibo.id, 'val_tipo' : transferencia_recibida.id})

    def agregar_tarjetas(self):
        tarjeta_credito = self.env['asw.tipos_valores'].search([('tv_tipo','=','ta'),('tv_descripcion','ilike','credito')])
        tarjeta_debito = self.env['asw.tipos_valores'].search([('tv_tipo','=','ta'),('tv_descripcion','ilike','débito')])

        for record in self.pcw_tarjetas:
            if(record.val_tipo.tv_descripcion == 'Tarjeta de Credito'):
                record.write({'val_comprobante' : self.pcw_recibo.id, 'val_tipo' : tarjeta_credito.id})
            if(record.val_tipo.tv_descripcion == 'Tarjeta de Débito'):
                record.write({'val_comprobante' : self.pcw_recibo.id, 'val_tipo' : tarjeta_debito.id})


    ########################################LOGICA GESTION DE VALORES Y CAJAS ######################################################

    def ValoresEnCajas(self,resivo):
        #Clasifico el tipo de valor
        efectivo = []
        cheques = []
        transferencias = []
        tarjetas = []
        for valor in resivo.comp_valores:
            if valor.val_tipo.tv_tipo == "ef":
                efectivo.append(valor)
            if valor.val_tipo.tv_tipo == "chr":
                cheques.append(valor)
            if valor.val_tipo.tv_tipo == "trr":
                transferencias.append(valor)
            if valor.val_tipo.tv_tipo == "ta":
                tarjetas.append(valor)
        #Asocio segun el tipo de valor
        self.MoverValores(efectivo, self.caja_efectivo.id)
        self.MoverValores(cheques, self.caja_cheque.id)
        self.MoverValores(transferencias)
        self.MoverValores(tarjetas)
        

    def MoverValores(self, valores, caja_destino_id=True):
        """mueve los valores de los recivos segun se configure"""
        for valor in valores:
            if caja_destino_id == True:
                caja_destino_id = valor.valor_caja_id.id
            if  caja_destino_id == False:
                raise Warning("No esta definida una de las cajas, todos los valores deven tener cajas asignadas") 
            valor.valor_caja_id.caja_valor_ids = [(3,valor.id,)]#elimino el valor de la caja actual
            valor.valor_caja_id = caja_destino_id #cambio la caja en el valor
            valor.valor_caja_id.caja_valor_ids = [(4,valor.id,)]#agrego el valor a la caja destino


    def PuntoDecimal(self):
        """devuelve si es coma o punto segun la configuracion del sistema"""
        idioma = self.env.user.lang
        res_lang = self.env["res.lang"].sudo().search([["code","=",idioma]])
        decimal = res_lang.decimal_point
        #print(decimal)
        return(decimal)