from datetime import datetime 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 def get_upload_path(instance, filename): return os.path.join(str(type(instance).__name__), filename) 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)]) valor_carencia = DecimalField( _('valor da carência'), default=0, max_digits=25, decimal_places=2) porcentagem_carencia = DecimalField( _('porcentagem da carência'), default=0, max_digits=8, decimal_places=4) periodicidade_boletos = CharField( _(u'periodicidade dos boletos'), default="30", choices=PERIODICIDADE, max_length=3) usuarios_bloqueados = BooleanField( _(u"usuários bloqueados?"), default=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 = _('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()