cfdi-admin/source/main/models.py

162 lines
6.8 KiB
Python

import re
from datetime import datetime
from django.db import models
from django.core.validators import MinLengthValidator
from django.core.exceptions import ValidationError
from django.utils.timezone import now
def validate_rfc(value):
l = 4
if len(value)==12:
l = 3
s = value[0:l]
r = re.match('[A-ZÑ&]{%s}' % l, s)
if not r:
raise ValidationError('Caracteres inválidos al inicio del RFC')
s = value[-3:]
r = re.match('[A-Z0-9]{3}', s)
if not r:
raise ValidationError('Caracteres inválidos al final del RFC')
s = value[l:l+6]
r = re.match('[0-9]{6}', s)
msg = 'Fecha inválida en el RFC'
if not r:
raise ValidationError(msg)
try:
datetime.strptime(s,"%y%m%d")
except:
raise ValidationError(msg)
class RFCField(models.CharField):
description = 'Field to RFC of México'
default_validators = [MinLengthValidator(12), validate_rfc]
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 13
super().__init__(*args, **kwargs)
def to_python(self, value):
return value.upper()
class Clients(models.Model):
rfc = RFCField('RFC', unique=True)
name = models.CharField('Razón Social', max_length=500)
key = models.TextField('Key', default='', blank=True)
cer = models.TextField('Cer', default='', blank=True)
serial_number = models.CharField('Fiel Serie', default='', blank=True, max_length=100)
date_from = models.DateTimeField('Desde', null=True, blank=True)
date_to = models.DateTimeField('Hasta', null=True, blank=True)
class Meta:
ordering = ['name']
verbose_name = 'Cliente'
verbose_name_plural = 'Clientes'
def __str__(self):
return self.name
class Cfdi(models.Model):
uuid = models.UUIDField('UUID', unique=True)
version = models.CharField('Version', max_length=10)
version_nomina = models.CharField('Ver. Nom.', max_length=10, default='', blank=True)
serie = models.CharField('Serie', max_length=50, default='', blank=True)
folio = models.CharField('Folio', max_length=50, default='', blank=True)
date_cfdi = models.DateTimeField('Fecha CFDI')
date_stamp = models.DateTimeField('Fecha Timbrado')
date_cancel = models.DateTimeField('Fecha Cancelada', null=True)
type_cfdi = models.CharField('Tipo', max_length=100, default='', blank=True)
no_cert = models.CharField('No. Certificado', max_length=50, default='', blank=True)
no_cert_sat = models.CharField('Cert. SAT', max_length=50, default='', blank=True)
place_expedition = models.CharField('Lugar Expedición', max_length=200, default='', blank=True)
currency = models.CharField('Moneda', max_length=100, default='MXN', blank=True)
type_change = models.DecimalField('T.C.', max_digits=19, decimal_places=6, null=True)
way_pay = models.CharField('Forma de pago', max_length=100, default='', blank=True)
method_pay = models.CharField('Método de pago', max_length=100, default='', blank=True)
subtotal = models.DecimalField('Subtotal', max_digits=19, decimal_places=6)
discount = models.DecimalField('Descuento', max_digits=19, decimal_places=6, null=True)
tax_trasladados = models.DecimalField('I. Trasladados', max_digits=19, decimal_places=6, null=True)
tax_retenidos = models.DecimalField('I. Retenidos', max_digits=19, decimal_places=6, null=True)
tax_others = models.DecimalField('Otros I.', max_digits=19, decimal_places=6, null=True)
total = models.DecimalField('Total', max_digits=19, decimal_places=6)
emisor_rfc = RFCField('Emisor RFC')
emisor = models.CharField('Emisor', max_length=500, default='', blank=True)
regimen_fiscal = models.CharField('Regimen Fiscal', max_length=10, default='', blank=True)
registro_patronal = models.CharField('Registro Patronal', max_length=50, default='', blank=True)
receptor_rfc = RFCField('Receptor RFC')
receptor = models.CharField('Receptor', max_length=500, default='', blank=True)
uso_cfdi = models.CharField('Uso CFDI', max_length=50, default='', blank=True)
rfc_pac = models.CharField('RFC PAC', max_length=15, default='', blank=True)
status_sat = models.CharField('Estatus SAT', max_length=100, default='', blank=True)
xml = models.TextField('XML')
class Meta:
ordering = ['-date_cfdi']
verbose_name = 'Cfdi'
verbose_name_plural = 'Cfdis'
def __str__(self):
return str(self.uuid)
class Taxes(models.Model):
TYPES = [
('T', 'Traslado'),
('R', 'Retención'),
]
cfdi = models.ForeignKey(Cfdi,
related_name='cfdi_taxes', on_delete=models.CASCADE)
type_tax = models.CharField('Tipo', max_length=1, choices=TYPES)
key_sat = models.CharField('Clave SAT', max_length=5, default='', blank=True)
importe = models.DecimalField('Importe', max_digits=19, decimal_places=6)
type_factor = models.CharField('Tipo Factor', max_length=10, default='', blank=True)
rate = models.DecimalField('Tasa', max_digits=19, decimal_places=6, null=True)
class Meta:
verbose_name = 'Impuesto'
verbose_name_plural = 'Impuestos'
class CfdiDetails(models.Model):
cfdi = models.ForeignKey(Cfdi,
related_name='cfdi_details', on_delete=models.CASCADE)
key = models.CharField('Clave', max_length=15, default='', blank=True)
key_sat = models.CharField('Clave SAT', max_length=15, default='', blank=True)
key_unit = models.CharField('Clave Unidad', max_length=15, default='', blank=True)
unit = models.CharField('Unidad', max_length=100, default='', blank=True)
description = models.CharField('Descripción', max_length=5000, default='', blank=True)
cant = models.DecimalField('Cantidad', max_digits=19, decimal_places=6)
value = models.DecimalField('Valor Unitario', max_digits=19, decimal_places=6)
discount = models.DecimalField('Descuento', max_digits=19, decimal_places=6, null=True)
importe = models.DecimalField('Importe', max_digits=19, decimal_places=6)
class Meta:
verbose_name = 'Concepto'
verbose_name_plural = 'Conceptos'
class DetailTaxes(models.Model):
TYPES = [
('T', 'Traslado'),
('R', 'Retención'),
]
detail = models.ForeignKey(CfdiDetails,
related_name='detail', on_delete=models.CASCADE)
type_tax = models.CharField('Tipo', max_length=1, choices=TYPES)
key_sat = models.CharField('Clave SAT', max_length=5, default='', blank=True)
base = models.DecimalField('Base', max_digits=19, decimal_places=6)
importe = models.DecimalField('Importe', max_digits=19, decimal_places=6)
type_factor = models.CharField('Tipo Factor', max_length=10, default='', blank=True)
rate = models.DecimalField('Tasa', max_digits=19, decimal_places=6, null=True)
class Meta:
verbose_name = 'Impuesto'
verbose_name_plural = 'Impuestos'