# -*- encoding: utf-8 -*-
import datetime
from decimal import Decimal
from django.db import models
from django.conf import settings
#from reservas_abm.models import CentroCosto, Proveedor
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.utils.translation import gettext as _
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator

# Create your models here.
MESES_CHOICES = (
    ('1', 'Enero'),
    ('2', 'Febrero'),
    ('3', 'Marzo'),
    ('4', 'Abril'),
    ('5', 'Mayo'),
    ('6', 'Junio'),
    ('7', 'Julio'),
    ('8', 'Agosto'),
    ('9', 'Septiembre'),
    ('10', 'Octubre'),
    ('11', 'Noviembre'),
    ('12', 'Diciembre'),
)

IVA_CHOICES = (
    ('10.5', '10.5%'),
    ('21.0', '21%'),
    ('27.0', '27%'),
    ('EXENTO', 'EXENTO'),
)

TIPO_FACTURA_CHOICES = (
    ('A', 'A'),
    ('B', 'B'),
    ('C', 'C'),
)

MONEDA_CHOICE = (
    ('D', u'U$S'),
    ('P', u'$ARG'),
    ('CL', u'$CL'),
    ('S', u'Soles'),
)

PERTENECE_CHOICES = (
    ('S', 'SERVICIOS'),
    ('V', 'VENTAS'),
)

TIPO_GASTO_CHOICE = (
    ('P', u'Proveedores'),
    ('V', u'Viaticos'),
    ('A', u'A Rendir'),
    ('H', u'Honorarios'),
    ('O', u'Otros'),
)

TIPO_PROVINCIA_CHOICE = (
    ('CB', u'Capital Federal'),
    ('BA', u'Buenos Aires'),
    ('EN', 'Entre Rios'),
    ('CR', 'Corrientes'),
    ('MI', 'Misiones'),
    ('FO', 'Formosa'),
    ('CH', 'Chaco'),
    ('SF', 'Santa Fe'),
    ('CO', 'Cordoba'),
    ('SE', 'Santiago del Estero'),
    ('SA', 'Salta'),
    ('JU', 'Jujuy'),
    ('TU', 'Tucuman'),
    ('CA', 'Catamarca'),
    ('LR', 'La Rioja'),
    ('SJ', 'San Juan'),
    ('SL', 'San Luis'),
    ('LP', 'La Pampa'),
    ('NE', 'Neuquen'),
    ('RN', 'Rio Negro'),
    ('CH', 'Chubut'),
    ('SC', 'Santa Cruz'),
    ('TF', 'Tierra del Fuego'),
)


class ClaseConURL(object):
    def get_absolute_url(self):
        return urlresolvers.reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.module_name), args=[self.id])


class DetalleFacturaInmo(models.Model):
    factura = models.ForeignKey('FacturaInmo')
    orden_pago = models.ForeignKey(
        'OrdenPagoInmo', blank=True, null=True, editable=False)
    porcentaje_iva = models.CharField('Porcentaje IVA', max_length=15, choices=IVA_CHOICES,
                                      blank=True, null=True)
    importe_neto = models.DecimalField('Importe Neto', max_digits=15,
                                       decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    iva = models.DecimalField('IVA', max_digits=15, decimal_places=2,
                              validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iva = models.DecimalField('Ret IVA', max_digits=15, decimal_places=2,
                                  validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iibb_caba = models.DecimalField('Ret IIBB CABA', max_digits=15, decimal_places=2,
                                        validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iibb_bsas = models.DecimalField('Ret IIBB BSAS', max_digits=15, decimal_places=2,
                                        validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iva = models.DecimalField('Percep IVA', max_digits=15, decimal_places=2,
                                     validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iibb_caba = models.DecimalField('Percep IIBB CABA', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iibb_bsas = models.DecimalField('Percep IIBB BSAS', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)

    class Meta:
        verbose_name = ('Detalle Factura')
        verbose_name_plural = ('Detalles Facturas')

    def __unicode__(self):
        return '%s | %s' % (self.factura, self.orden_pago)

    def save(self, force_insert=True, force_update=True, *args, **kwargs):
        super(DetalleFacturaInmo, self).save(*args, **kwargs)
        if self.factura.tipo_factura == 'A':
            iva_compras = IVA_Compras_Inmo()
            iva_compras.fecha = self.factura.fecha_factura
            iva_compras.tipo_comprobante = self.factura.tipo_factura
            iva_compras.nro_comprobante = self.factura.nrofactura
            iva_compras.cuit = self.factura.proveedorinmo.cuit
            iva_compras.razonsocial = self.factura.proveedorinmo.razonsocial
            if self.porcentaje_iva == 'EXENTO':
                iva_compras.exento = True
            elif self.porcentaje_iva == '21.0':
                iva_compras.grabado_21 = self.factura.importe_neto_total
                iva_compras.iva_21 = self.iva
            elif self.porcentaje_iva == '10.5':
                iva_compras.grabado_105 = self.factura.importe_neto_total
                iva_compras.iva_105 = self.iva
            elif self.porcentaje_iva == '27.0':
                iva_compras.grabado_27 = self.factura.importe_neto_total
                iva_compras.iva_27 = self.iva
            iva_compras.ret_iva = self.ret_iva
            iva_compras.percep_iva = self.percep_iva
            iva_compras.percep_iibb_caba = self.percep_iibb_caba
            iva_compras.percep_iibb_bsas = self.percep_iibb_bsas
            iva_compras.ret_iibb_caba = self.ret_iibb_caba
            iva_compras.ret_iibb_bsas = self.ret_iibb_bsas
            iva_compras.importe_total = self.factura.importe_total
            iva_compras.save()


class FacturaInmo(models.Model):
    orden_pago = models.ForeignKey(
        'OrdenPagoInmo', blank=True, null=True, editable=False)
    nrofactura = models.CharField('Nro. Factura', max_length=25)
    concepto = models.CharField(
        'Concepto', max_length=60, blank=True, null=True)
    importe_neto_total = models.DecimalField('Imp. Neto Total', max_digits=15,
                                             decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    importe_total = models.DecimalField('Importe Total', max_digits=15,
                                        decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    tipo_factura = models.CharField(
        'Tipo', max_length=2, choices=TIPO_FACTURA_CHOICES)
    proveedorinmo = models.ForeignKey('ordenes_de_pago.Proveedor')
    fecha_factura = models.DateField(
        'Fecha Factura', default=datetime.date.today())
    pendiente = models.BooleanField('Pendiente')  # editable=False)

    def __unicode__(self):
        return '%s | %s | %s | $ %s' % (self.proveedorinmo.cuit, self.fecha_factura, self.nrofactura, self.importe_total)

    class Meta:
        verbose_name = ('Factura Inmo San Martín')
        verbose_name_plural = ('Facturas Inmo San Martín')


class IVA_Compras_Inmo(models.Model):
    fecha = models.DateField('Fecha', default=datetime.date.today())
    tipo_comprobante = models.CharField(
        'Tipo', max_length=2, choices=TIPO_FACTURA_CHOICES)
    nro_comprobante = models.CharField('Nro. Comprobante', max_length=25)
    cuit = models.CharField('CUIT', max_length=11)
    razonsocial = models.CharField('Razon Social', max_length=50)
    grabado_21 = models.DecimalField('Grabado 21%', max_digits=15,
                                     decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    grabado_105 = models.DecimalField('Grabado 10.5%', max_digits=15,
                                      decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    grabado_27 = models.DecimalField('Grabado 27%', max_digits=15,
                                     decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    exento = models.BooleanField('Exento', default=False)
    iva_21 = models.DecimalField('IVA 21%', max_digits=15,
                                 decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    iva_105 = models.DecimalField('IVA 10.5%', max_digits=15,
                                  decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    iva_27 = models.DecimalField('IVA 27%', max_digits=15,
                                 decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    ret_iva = models.DecimalField('Ret IVA', max_digits=15, decimal_places=2,
                                  validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iva = models.DecimalField('Percep IVA', max_digits=15, decimal_places=2,
                                     validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_gcias = models.DecimalField('Ret Gcias', max_digits=15, decimal_places=2,
                                    validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iibb_caba = models.DecimalField('Percep IIBB CABA', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'),
                                           blank=True, null=True)
    percep_iibb_bsas = models.DecimalField('Percep IIBB BSAS', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'),
                                           blank=True, null=True)
    ret_iibb_caba = models.DecimalField('Ret IIBB CABA', max_digits=15, decimal_places=2,
                                        validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iibb_bsas = models.DecimalField('Ret IIBB BSAS', max_digits=15, decimal_places=2,
                                        validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    importe_total = models.DecimalField('Importe Total', max_digits=15,
                                        decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))

    def __unicode__(self):
        return '%s | %s | $ %s' % (self.fecha, self.nro_comprobante, self.importe_total)

    class Meta:
        verbose_name = ('IVA Compra Inmo San Martín')
        verbose_name_plural = ('IVA Compras Inmo San Martín')


class DetalleNotaCreditoInmo(models.Model):
    notacredito = models.ForeignKey('NotaCreditoInmo')
    orden_pago = models.ForeignKey(
        'OrdenPagoInmo', blank=True, null=True, editable=False)
    porcentaje_iva = models.CharField(
        'Porcentaje IVA', max_length=15, choices=IVA_CHOICES, blank=True, null=True)
    importe_neto = models.DecimalField('Importe Neto', max_digits=15,
                                       decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    iva = models.DecimalField('IVA', max_digits=15, decimal_places=2,
                              validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iva = models.DecimalField('Ret IVA', max_digits=15, decimal_places=2,
                                  validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    ret_iibb = models.DecimalField('Ret IIBB', max_digits=15, decimal_places=2,
                                   validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iva = models.DecimalField('Percep IVA', max_digits=15, decimal_places=2,
                                     validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iibb_caba = models.DecimalField('Percep IIBB CABA', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    percep_iibb_bsas = models.DecimalField('Percep IIBB BSAS', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)

    class Meta:
        verbose_name = ('Detalle Nota Credito')
        verbose_name_plural = ('Detalles Notas Creditos')


class NotaCreditoInmo(models.Model):
    orden_pago = models.ForeignKey(
        'OrdenPagoInmo', blank=True, null=True, editable=False)
    nronotacredito = models.CharField('Nro. Nota Credito', max_length=25)
    concepto = models.CharField(
        'Concepto', max_length=60, blank=True, null=True)
    importe_neto_total = models.DecimalField('Importe Neto Total', max_digits=15,
                                             decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    importe_total = models.DecimalField('Importe Total', max_digits=15,
                                        decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    tipo_nota_credito = models.CharField(
        'Tipo', max_length=2, choices=TIPO_FACTURA_CHOICES)
    proveedorinmo = models.ForeignKey('ordenes_de_pago.Proveedor')
    fecha_nota_credito = models.DateField(
        'Fecha Nota Credito', default=datetime.date.today())
    pendiente = models.BooleanField('Pendiente')  # , editable=False)

    def __unicode__(self):
        return '%s | %s | %s | $ %s' % (self.proveedorinmo.cuit, self.fecha_nota_credito, self.nronotacredito, self.importe_total)

    class Meta:
        verbose_name = ('Nota Credito Inmo San Martín')
        verbose_name_plural = ('Notas Creditos Inmo San Martín')


class OrdenPagoInmo(models.Model):
    nro_orden_pago = models.AutoField('Nro Orden Pago', primary_key=True)
    proveedorinmo = models.ForeignKey('ordenes_de_pago.Proveedor')
    fecha_orden_pago = models.DateField('Fecha', default=datetime.date.today())
    moneda = models.CharField('Moneda', max_length=4,
                              choices=MONEDA_CHOICE, blank=True, null=True)
    total_a_pagar = models.DecimalField(u'Total a Pagar', max_digits=15,
                                        decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'))
    descripcion = models.CharField(
        'Descripcion', max_length=50, blank=True, null=True)

    def __unicode__(self):
        return '%s' % (self.nro_orden_pago,)

    class Meta:
        verbose_name = ('Orden de Pago Inmo San Martín')
        verbose_name_plural = ('Ordenes de Pago Inmo San Martín')


class DetalleOrdenPagoInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo')
    banco = models.ForeignKey('reservas_abm.banco')
    forma_pago = models.ForeignKey('reservas_abm.formapago')
    tipo_gasto = models.CharField('Tipo Gasto', max_length=2,
                                  choices=TIPO_GASTO_CHOICE, blank=True, null=True)
    nro_cheque = models.CharField(u'Nº Cheque', max_length=20, default=0,
                                  blank=True, null=True)

    def __unicode__(self):
        return '%s' % (self.get_tipo_gasto_display(),)

    class Meta:
        verbose_name = ('Detalle Orden de Pago')
        verbose_name_plural = ('Detalles Ordenes de Pago')


class DetalleOrdenPagoCCInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo')
    centro_costo = models.ForeignKey('ordenes_de_pago.CentroCosto')
    porcentaje_aplicacion = models.DecimalField(u'% Aplic', max_digits=6,
                                                decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('100.00'))

    def __unicode__(self):
        return '%s' % (self.orden_pago,)

    class Meta:
        verbose_name = ('Detalle Orden de Pago Centro Costo')
        verbose_name_plural = ('Detalles Ordenes de Pago Centro Costo')


class DetalleOrdenPagoNCInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo')
    notacredito = models.ForeignKey('NotaCreditoInmo')

    def __unicode__(self):
        return '%s' % (self.orden_pago,)

    class Meta:
        verbose_name = ('Detalle Orden de Pago NC')
        verbose_name_plural = ('Detalles Ordenes de Pago NC')

    def save(self, force_insert=True, force_update=True, *args, **kwargs):
        super(DetalleOrdenPagoNCInmo, self).save(*args, **kwargs)
        self.notacredito.pendiente = True
        self.notacredito.save()
        imp_facturas = 0
        imp_notacredito = 0
        imp_iibb = 0
        imp_gan = 0
        for fac in self.orden_pago.detalleordenpagofacinmo_set.all():
            imp_facturas += fac.factura.importe_total
        try:
            for nc in self.orden_pago.detalleordenpagoncinmo_set.all():
                imp_notacredito += nc.notacredito.importe_total
        except:
            imp_notacredito = 0
        try:
            for ret in self.detalleordenpagoretinmo_set.all():
                imp_iibb += ret.importe_ret_iibb
        except:
            imp_iibb = 0
        try:
            for retgan in self.detalleordenpagoretinmo_set.all():
                imp_gan += retgan.importe_ret_ganancias
        except:
            imp_gan = 0

        self.orden_pago.total_a_pagar = (
            imp_facturas - imp_notacredito - imp_iibb - imp_gan)
        self.orden_pago.save()
        super(DetalleOrdenPagoNCInmo, self).save(*args, **kwargs)


class DetalleOrdenPagoFACInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo')
    factura = models.ForeignKey('FacturaInmo')

    def __unicode__(self):
        return '%s' % (self.orden_pago,)

    class Meta:
        verbose_name = ('Detalle Orden de Pago Factura')
        verbose_name_plural = ('Detalles Ordenes de Pago Facturas')

    def save(self, *args, **kwargs):
        super(DetalleOrdenPagoFACInmo, self).save(*args, **kwargs)
        self.factura.pendiente = True
        self.factura.save()
        imp_facturas = 0
        imp_notacredito = 0
        imp_iibb = 0
        imp_gan = 0
        for fac in self.orden_pago.detalleordenpagofacinmo_set.all():
            imp_facturas += fac.factura.importe_total
        try:
            for nc in self.orden_pago.detalleordenpagoncinmo_set.all():
                imp_notacredito += nc.notacredito.importe_total
        except:
            imp_notacredito = 0
        try:
            for ret in self.detalleordenpagoretinmo_set.all():
                imp_iibb += ret.importe_ret_iibb
        except:
            imp_iibb = 0
        try:
            for retgan in self.detalleordenpagoretinmo_set.all():
                imp_gan += retgan.importe_ret_iibb
        except:
            imp_gan = 0
        self.orden_pago.total_a_pagar = (
            imp_facturas - imp_notacredito - imp_iibb - imp_gan)
        self.orden_pago.save()
        super(DetalleOrdenPagoFACInmo, self).save(*args, **kwargs)


class DetalleOrdenPagoRetInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo')
    importe_ret_iibb = models.DecimalField('Ret IIBB', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    nro_ret_iibb = models.CharField(
        'Nro', max_length=18, blank=True, null=True)
    importe_ret_ganancias = models.DecimalField('Ret GAN', max_digits=15,
                                                decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'), blank=True, null=True)
    nro_ret_ganancias = models.CharField(
        'Nro', max_length=15, blank=True, null=True)

    def save(self, force_insert=True, force_update=True, *args, **kwargs):
        super(DetalleOrdenPagoRetInmo, self).save(*args, **kwargs)
        total_importe_facturas = 0
        total_importe_neto_facturas = 0
        total_importe_notacredito = 0
        for importe_factura in DetalleOrdenPagoFACInmo.objects.filter(orden_pago=self.orden_pago.pk):
            total_importe_facturas = total_importe_facturas + \
                importe_factura.factura.importe_total
        for importe_neto_factura in DetalleOrdenPagoFACInmo.objects.filter(orden_pago=self.orden_pago.pk):
            total_importe_neto_facturas = total_importe_neto_facturas + \
                importe_neto_factura.factura.importe_neto_total
        for importe_notacredito in DetalleOrdenPagoNCInmo.objects.filter(orden_pago=self.orden_pago.pk):
            total_importe_notacredito = total_importe_notacredito + \
                importe_notacredito.notacredito.importe_neto_total
        if (self.orden_pago.proveedor.porcentaje_ret == None) or (self.orden_pago.proveedorinmo.porcentaje_ret == 0):
            self.importe_ret_iibb = 0
        else:
            if self.pk:
                try:
                    iibb_servicios = self.ingresosbrutos
                except:
                    iibb_servicios = IngresosBrutosInmo()
            self.importe_ret_iibb = (
                (total_importe_neto_facturas - total_importe_notacredito) * self.orden_pago.proveedorinmo.porcentaje_ret)/100
        self.orden_pago.total_a_pagar = (
            total_importe_facturas - total_importe_notacredito - self.importe_ret_iibb - self.importe_ret_ganancias)
        self.orden_pago.save()
        if not self.importe_ret_iibb == 0:
            iibb_servicios.orden_pago = self.orden_pago
            iibb_servicios.pertenece = 'S'
            iibb_servicios.proveedor = self.orden_pago.proveedor
            iibb_servicios.importe_pagado = (
                total_importe_neto_facturas - total_importe_notacredito)
            iibb_servicios.importe_retenido = self.importe_ret_iibb
            iibb_servicios.save()
            self.nro_ret_iibb = iibb_servicios.nro_certificado
        super(DetalleOrdenPagoRetInmo, self).save(*args, **kwargs)


class IngresosBrutosInmo(models.Model):
    orden_pago = models.ForeignKey('OrdenPagoInmo', blank=True, null=True)
    nro_certificado = models.CharField(
        'Nro. Cert', max_length=18, blank=True, null=True)
    proveedorinmo = models.ForeignKey('ordenes_de_pago.Proveedor')
    fecha_iibb = models.DateField('Fecha', default=datetime.date.today(),
                                  blank=True, null=True)
    importe_pagado = models.DecimalField(u'Importe Pagado', max_digits=15,
                                         decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'),
                                         blank=True, null=True)
    importe_retenido = models.DecimalField(u'Importe Ret', max_digits=15,
                                           decimal_places=2, validators=[MinValueValidator(0)], default=Decimal('0.00'),
                                           blank=True, null=True)
    pertenece = models.CharField('Pertenece a', max_length=1, choices=PERTENECE_CHOICES,
                                 blank=True, null=True)

    def __unicode__(self):
        return '%s | %s' % (self.orden_pago, self.orden_pago_venta)

    class Meta:
        verbose_name_plural = ('Ingresos Brutos Inmo San Martín')

    def clean(self):
        mascara = '0001-' + str(datetime.date.today().year) + '-'
        nro_id = str('%08d' % (self.id))
        self.nro_certificado = mascara + nro_id
        if self.orden_pago == None:
            self.pertenece = 'V'
        else:
            self.pertenece = 'S'

    def save(self, force_insert=True, force_update=True, *args, **kwargs):
        super(IngresosBrutosInmo, self).save(*args, **kwargs)
        mascara = '0001-' + str(datetime.date.today().year) + '-'
        nro_id = str('%08d' % (self.id))
        self.nro_certificado = mascara + nro_id
        if self.orden_pago == None:
            self.pertenece = 'V'
        else:
            self.pertenece = 'S'
        super(IngresosBrutosInmo, self).save(*args, **kwargs)
