You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
12 KiB
317 lines
12 KiB
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()
|