Aplicacion :

 USERS

from django.db import models

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
#
from .managers import UserManager

class User(AbstractBaseUser, PermissionsMixin):
    # TIPO DE USUARIOS
    ADMINISTRADOR = '0'
    ALMACEN = '1'
    VENTAS = '2'
    # GENEROS
    VARON = 'M'
    MUJER = 'F'
    OTRO = 'O'
    #
    OCUPATION_CHOICES = [
        (ADMINISTRADOR, 'Administrador'),
        (ALMACEN, 'Almacen'),
        (VENTAS, 'Ventas'),
    ]

    GENDER_CHOICES = [
        (VARON, 'Masculino'),
        (MUJER, 'Femenino'),
        (OTRO, 'Otros'),
    ]

    email = models.EmailField(unique=True)
    full_name = models.CharField('Nombres', max_length=100)
    ocupation = models.CharField(max_length=1, choices=OCUPATION_CHOICES, blank=True)
    genero = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
    date_birth = models.DateField('Fecha de nacimiento', blank=True,null=True)
    #
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'

    REQUIRED_FIELDS = ['full_name']

    objects = UserManager()

    def get_short_name(self):
        return self.email

    def get_full_name(self):
        return self.full_name

 

CAJA

from django.db import models
from django.conf import settings

#
from model_utils.models import TimeStampedModel

# local apps
from applications.producto.models import Product

#
# from .managers import SaleDetailManager

class CloseBox(TimeStampedModel):

    date_close = models.DateTimeField('Fecha de Cierre',)
    count = models.PositiveIntegerField('Cantidad de ventas')
    amount = models.DecimalField('Monto total en ventas',max_digits=10,decimal_places=2)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,verbose_name='cajero',
        related_name="close_user",)

    class Meta:
        verbose_name = 'Cierre Caja'
        verbose_name_plural = 'Cirres de Caja'

    def __str__(self):
        return str(self.user.full_name) + ' - ' + str(self.date_close)

PRODUCTO

# third-party
from model_utils.models import TimeStampedModel
# Django
from django.db import models
# local
from .managers import ProductManager

class Marca(TimeStampedModel):

    name = models.CharField('Nombre', max_length=30)

    class Meta:
        verbose_name = 'Marca'
        verbose_name_plural = 'Marcas'

    def __str__(self):
        return self.name

class Provider(TimeStampedModel):

    name = models.CharField('Razon Social',max_length=100)
    email = models.EmailField(blank=True,null=True)
    phone = models.CharField('telefonos',max_length=40,blank=True,)
    web = models.URLField('sitio web',blank=True,)

    class Meta:
        verbose_name = 'Proveedor'
        verbose_name_plural = 'Proveedores'

    def __str__(self):
        return self.name

class Product(TimeStampedModel):

    UNIT_CHOICES = (
        ('0', 'Kilogramos'),
        ('1', 'Litros'),
        ('2', 'Unidades'),
    )

    barcode = models.CharField(max_length=13,unique=True)
    name = models.CharField('Nombre',max_length=40)
    provider = models.ForeignKey(Provider,on_delete=models.CASCADE)
    marca = models.ForeignKey(Marca,on_delete=models.CASCADE)
    due_date = models.DateField('fehca de vencimiento',blank=True,null=True)
    description = models.TextField('descripcion del producto',blank=True,)
    unit = models.CharField('unidad de medida',max_length=1,choices=UNIT_CHOICES,)
    count = models.PositiveIntegerField('cantidad en almacen',default=0)
    purchase_price = models.DecimalField('precio compra',max_digits=7,decimal_places=2)
    sale_price = models.DecimalField('precio venta',max_digits=7,decimal_places=2)
    num_sale = models.PositiveIntegerField('numero de ventas',default=0)
    anulate = models.BooleanField('eliminado',default=False)
    #
    objects = ProductManager()

    class Meta:
        verbose_name = 'Producto'
        verbose_name_plural = 'Productos'

    def __str__(self):
        return self.name

VENTA

from django.db import models
from django.conf import settings
from django.db.models.signals import pre_delete, post_save
#
from model_utils.models import TimeStampedModel

# local apps
from applications.producto.models import Product

#
from .managers import SaleManager, SaleDetailManager, CarShopManager
from .signals import update_stok_ventas_producto

class Sale(TimeStampedModel):
    """Modelo que representa a una Venta Global"""
    # tipo recibo constantes
    BOLETA = '0'
    FACTURA = '1'
    SIN_COMPROBANTE = '2'
    # tipo pago constantes
    TARJETA = '0'
    CASH = '1'
    BONO = '2'
    OTRO = '3'
    #
    TIPO_INVOCE_CHOICES = [
        (BOLETA, 'Boleta'),
        (FACTURA, 'Factura'),
        (SIN_COMPROBANTE, 'Sin Comprobante'),
    ]

    TIPO_PAYMENT_CHOICES = [
        (TARJETA, 'Tarjeta'),
        (CASH, 'Cash'),
        (BONO, 'Bono'),
        (OTRO, 'Otro'),
    ]

    date_sale = models.DateTimeField('Fecha de Venta',)
    count = models.PositiveIntegerField('Cantidad de Productos')
    amount = models.DecimalField('Monto',max_digits=10,decimal_places=2)
    type_invoce = models.CharField('TIPO',max_length=2,choices=TIPO_INVOCE_CHOICES)
    type_payment = models.CharField('TIPO PAGO',max_length=2,choices=TIPO_PAYMENT_CHOICES)
    close = models.BooleanField('Venta cerrada',default=False)
    anulate = models.BooleanField('Venta Anulada',default=False,)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,verbose_name='cajero',
        related_name="user_venta",)

    objects = SaleManager()

    class Meta:
        verbose_name = 'Venta'
        verbose_name_plural = 'ventas'

    def __str__(self):
        return 'Nº [' + str(self.id) + '] - ' + str(self.date_sale)


class SaleDetail(TimeStampedModel):
    """Modelo que representa a una venta en detalle"""
    product = models.ForeignKey(Product,on_delete=models.CASCADE,verbose_name='producto',
        related_name='product_sale')
    sale = models.ForeignKey(Sale,on_delete=models.CASCADE,verbose_name='Codigo de Venta',
        related_name='detail_sale')
    count = models.PositiveIntegerField('Cantidad')
    price_purchase = models.DecimalField('Precio Compra',max_digits=10,decimal_places=3)
    price_sale = models.DecimalField('Precio Venta',max_digits=10,decimal_places=2)
    tax = models.DecimalField('Impuesto',max_digits=5,decimal_places=2)
    anulate = models.BooleanField(default=False)
    #

    objects = SaleDetailManager()

    class Meta:
        verbose_name = 'Producto Vendido'
        verbose_name_plural = 'Productos vendidos'

    def __str__(self):
        return str(self.sale.id) + ' - ' + str(self.product.name)

class CarShop(TimeStampedModel):
    """Modelo que representa a un carrito de compras"""
    barcode = models.CharField(max_length=13,unique=True)
    product = models.ForeignKey(Product,on_delete=models.CASCADE,verbose_name='producto',
        related_name='product_car')
    count = models.PositiveIntegerField('Cantidad')

    objects = CarShopManager()

    class Meta:
        verbose_name = 'Carrito de compras'
        verbose_name_plural = 'Carrito de compras'
        ordering = ['-created']

    def __str__(self):
        return str(self.product.name)


# signals for venta
post_save.connect(update_stok_ventas_producto, sender=SaleDetail)