from datetime import datetime from django.contrib.auth.models import AbstractUser from django.core.validators import MinValueValidator from django.db.models import CASCADE, PROTECT, Q, BooleanField, CharField, DateField, DateTimeField, DecimalField, FileField, ForeignKey, IntegerField, ManyToManyField, Model, PositiveIntegerField, TextField from django.utils.translation import ugettext_lazy as _ import os from django.core.exceptions import PermissionDenied def get_upload_path(instance, filename): return os.path.join(str(type(instance).__name__), filename) class User(AbstractUser): def delete(self): if self.pk != 1: self.delete() else: raise PermissionDenied class Estado(Model): nome = CharField(_('nome'), max_length=60) sigla = CharField(_('sigla'), max_length=2) class Meta: verbose_name = _('Estado') verbose_name_plural = _('Estados') ordering = ['nome'] def __str__(self): return self.nome class Cidade(Model): nome = CharField(_('nome'), max_length=60) estado = ForeignKey(Estado, verbose_name=_('estado'), related_name='cidades', on_delete=PROTECT) ibge = CharField(_(u'código IBGE'), max_length=7) class Meta: verbose_name = _('Cidade') verbose_name_plural = _('Cidades') ordering = ['nome'] @property def label(self): return u'{city}-{state}'.format( city=self.nome, state=self.estado.sigla ) def __str__(self): return self.label class Pessoa(Model): SITUACAO = ( ("A", "Ativo"), ("I", "Inativo"), ) nome = CharField(_(u'nome'), max_length=255) cpf = CharField('CPF', max_length=14, unique=True, blank=True, null=True) data_nascimento = DateField(_('data de nascimento'), blank=True, null=True) ativo = BooleanField(_("ativo"), default=True) situacao = CharField(_(u'situação'), max_length=1, choices=SITUACAO, default='A') criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Pessoa') verbose_name_plural = _('Pessoas') ordering = ['nome'] def __str__(self): return self.nome @property def label(self): return u'{nome} - {cpf}'.format( nome=self.nome, cpf=self.cpf ) class Endereco(Model): pessoa = ForeignKey(Pessoa, related_name='enderecos', on_delete=CASCADE) endereco = CharField(_(u'endereço'), max_length=60, blank=True, null=True) numero = IntegerField(_(u'número'), blank=True, null=True) complemento = CharField( _('complemento'), max_length=20, blank=True, null=True) bairro = CharField(_('bairro'), max_length=60, blank=True, null=True) cep = CharField(_('CEP'), max_length=9, blank=True, null=True) cidade = ForeignKey(Cidade, verbose_name=_('cidade'), on_delete=PROTECT, related_name='pessoa_%(class)ss', blank=True, null=True) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Endereço') verbose_name_plural = _('Endereços') ordering = ['endereco'] class Telefone(Model): TYPES = ( ('F', _('Fixo')), ('M', _('Celular')), ('C', _('Comercial')), ) ddd = CharField(_('DDD'), max_length=2) numero = CharField(_('número'), max_length=10) tipo = CharField(_('tipo'), max_length=1, choices=TYPES, blank=True) principal = BooleanField(_('principal'), default=False) pessoa = ForeignKey(Pessoa, related_name='telefones', on_delete=CASCADE) telegram = BooleanField(default=False) whatsapp = BooleanField(default=False) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Telefone') verbose_name_plural = _('Telefones') ordering = ['tipo'] def __str__(self): return f'({self.ddd}) {self.numero}' class Email(Model): email = CharField(_('email'), max_length=255) pessoa = ForeignKey(Pessoa, related_name='emails', on_delete=CASCADE) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Email') verbose_name_plural = _('Emails') ordering = ['email'] class Notas(Model): nota = TextField(_('nota')) pessoa = ForeignKey(Pessoa, related_name='notas', on_delete=CASCADE) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Nota') verbose_name_plural = _('Notas') ordering = ['modificado'] class Cliente(Model): SITUACAO = ( ('E', 'Em dia'), ('A', 'Atrasado'), ('I', 'Inadimplente'), ) DESCONTOS = ( ('P', 'Porcentagem'), ('V', 'Valor Fixo'), ) PERIODICIDADE = ( ("1", u'Diário'), ("7", 'Semanal'), ("30", 'Mensal'), ("60", 'Bimestral'), ("90", 'Trimestral'), ("120", 'Semestral'), ("360", 'Anual'), ) razao_social = CharField(_(u'razão social'), max_length=255) nome_fantasia = CharField(_(u'nome fantasia'), max_length=255) cnpj = CharField('CNPJ', max_length=18, unique=True, blank=True, null=True) ie = CharField('inscrição estadual', max_length=20, unique=True, blank=True, null=True) im = CharField('inscrição municipal', max_length=20, unique=True, blank=True, null=True) ativo = BooleanField(_("ativo"), default=True) situacao = CharField(_(u'situação'), max_length=1, choices=SITUACAO, default='E') endereco = CharField(_(u'endereço matriz'), max_length=60, blank=True, null=True) numero = IntegerField(_(u'nº matriz'), blank=True, null=True) complemento = CharField( _('complemento matriz'), max_length=20, blank=True, null=True) bairro = CharField(_('bairro matriz'), max_length=60, blank=True, null=True) cep = CharField(_('CEP matriz'), max_length=9, blank=True, null=True) cidade = ForeignKey(Cidade, verbose_name=_('cidade matriz'), on_delete=PROTECT, related_name='cliente_%(class)ss', blank=True, null=True) responsaveis = ManyToManyField(Pessoa, verbose_name=_( 'responsaveis'), related_name='eh_responsavel') socios = ManyToManyField(Pessoa, verbose_name=_( 'socios'), related_name='eh_socio') retaguarda = CharField(_(u'endereço da retaguarda'), max_length=255) nome_banco_dados = CharField(_(u'nome do banco de dados'), max_length=255) contrato = FileField(_('contrato'), upload_to=get_upload_path) data_adesao = DateField(verbose_name=_('data de adesão')) data_de_vencimento = DateField(verbose_name=_('data do vencimento')) valor_base_contrato = DecimalField( _('valor base do contrato'), max_digits=25, decimal_places=2) indice_reajuste = DecimalField( _(u'índice de reajuste'), max_digits=8, decimal_places=4) qtd_pdvs = IntegerField(_(u'nº de pdvs'), validators=[MinValueValidator(1)]) tipo_desconto = CharField(_(u'tipo de desconto'), max_length=1, choices=DESCONTOS, default='P') carencia = BooleanField(_(u'carência'), default=False) periodo_carencia = PositiveIntegerField( _(u'período de carência (em meses)'), default=0, validators=[MinValueValidator(0)], blank=True, null=True) valor_carencia = DecimalField( _('valor da carência'), default=0, max_digits=25, decimal_places=2, blank=True, null=True) porcentagem_carencia = DecimalField( _('porcentagem da carência'), default=0, max_digits=8, decimal_places=4, blank=True, null=True) periodicidade_boletos = CharField( _(u'periodicidade dos boletos'), default="30", choices=PERIODICIDADE, max_length=3) usuarios_bloqueados = BooleanField( _(u"usuários bloqueados?"), default=False) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Cliente') verbose_name_plural = _('Cliente') ordering = ['razao_social'] def __str__(self): return f'{self.razao_social[0:20]} - {self.cnpj}' @property def atrasado(self): return self.boletos.filter(Q(situacao='A'), Q(data_vencimento__lt=datetime.today().date())).count() > 0 class TelefoneCliente(Model): TYPES = ( ('F', _('Fixo')), ('M', _('Celular')), ('C', _('Comercial')), ) ddd = CharField(_('DDD'), max_length=2) numero = CharField(_('número'), max_length=10) tipo = CharField(_('tipo'), max_length=1, choices=TYPES, blank=True) principal = BooleanField(_('principal'), default=False) cliente = ForeignKey(Cliente, related_name='telefones', on_delete=CASCADE) telegram = BooleanField(default=False) whatsapp = BooleanField(default=False) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Telefone') verbose_name_plural = _('Telefones') ordering = ['tipo'] def __str__(self): return f'({self.ddd}) {self.numero}' class Boleto(Model): SITUACAO = ( ('A', 'Aberto'), ('B', 'Baixado'), ) cliente = ForeignKey(Cliente, related_name='boletos', on_delete=CASCADE) nosso_numero = CharField( _(u'nosso número'), max_length=255, blank=True, null=True) numero_boleto = CharField(_(u'número do boleto'), max_length=255) data_vencimento = DateField(_('data de vencimento')) data_geracao = DateField(_(u'data de geração')) situacao = CharField(_(u'situação'), max_length=1, choices=SITUACAO, default='A', blank=True) valor = DecimalField( _('valor do boleto'), max_digits=25, decimal_places=2) criado = DateTimeField(auto_now_add=True, editable=False, verbose_name=_('cadastrado em'), null=True) modificado = DateTimeField( auto_now=True, editable=False, verbose_name=_('alterado em'), null=True) class Meta: verbose_name = _('Boleto') verbose_name_plural = _('Boletos') ordering = ['numero_boleto'] @property def atrasado(self): return self.data_vencimento < datetime.today().date() def save(self, *args, **kwargs): super(Boleto, self).save(*args, **kwargs) if not self.cliente.atrasado: self.cliente.situacao = 'E' self.cliente.save()