class PrecioUnidadInventario(RegistroModel): unidad_inventario = models.ForeignKey('almacenes.UnidadInventario', on_delete=models.CASCADE, related_name='precios') base_imponible = models.DecimalField(max_digits=10, decimal_places=2) margen_ganancia = models.DecimalField(max_digits=10, decimal_places=1, blank=True, null=True, verbose_name='margen de ganancia') porcentaje_impuesto = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name='porcentaje de impuesto') impuesto = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name='impuesto') precio_venta_publico = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='precio final') exento = models.BooleanField(default=False) objects = RegistroQuerySet.as_manager() def almacen(self): return self.unidad_inventario.almacen() almacen.short_description = 'almacén' def producto(self): return self.unidad_inventario.producto() def codigo_lote(self): if self.unidad_inventario.lote_produccion: return self.unidad_inventario.lote_produccion.codigo return 'Ninguno' codigo_lote.short_description = 'código de lote/serie' def __str__(self): return str(self.precio_venta_publico)+'_'+str(self.unidad_inventario) search_fields = ('unidad_inventario__control_stock__almacen__tienda__nombre', 'unidad_inventario__control_stock__almacen__nombre', 'unidad_inventario__control_stock__almacen__direccion', 'unidad_inventario__control_stock__producto__codigo_venta', 'unidad_inventario__control_stock__producto__descripcion', 'unidad_inventario__lote_produccion__codigo') class Meta(RegistroModel.Meta): db_table = 'precio_unidad_inventario' verbose_name = 'precio' verbose_name_plural = 'precios'
class AtributoCategoria(RegistroModel): nombre = models.CharField(max_length=255) categoria = models.ForeignKey('productos.CategoriaProducto', on_delete=models.CASCADE, related_name='atributos') objects = RegistroQuerySet.as_manager() def __str__(self): return self.nombre + '_' + str(self.categoria) class Meta(RegistroModel.Meta): db_table = 'atributo_categoria'
class Fabricacion(RegistroModel): lote_produccion = models.OneToOneField('almacenes.LoteProduccion', on_delete=models.CASCADE, related_name='fabricacion') unidad_inventario = models.ForeignKey('almacenes.UnidadInventario', on_delete=models.CASCADE, related_name='fabricacion') cantidad_produccion = models.DecimalField(null=True, max_digits=10, decimal_places=4, verbose_name='cantidad') objects = RegistroQuerySet.as_manager() def save(self, *args, **kwargs): super(Fabricacion, self).save(*args, **kwargs) self.unidad_inventario.actualizar_cantidad_producto() def producto(self): return self.lote_produccion.producto.descripcion def almacen_produccion(self): return self.unidad_inventario.almacen() almacen_produccion.short_description = 'almacén' def codigo_lote(self): return self.lote_produccion.codigo codigo_lote.short_description = 'código de lote/serie' def fecha_produccion(self): return self.lote_produccion.fecha_produccion fecha_produccion.short_description = 'fecha de producción' def fecha_vencimiento(self): return self.lote_produccion.fecha_vencimiento fecha_vencimiento.short_description = 'fecha de vencimiento' search_fields = ('unidad_inventario__control_stock__almacen__nombre', 'unidad_inventario__control_stock__almacen__direccion', 'lote_produccion__producto__codigo_venta', 'lote_produccion__producto__descripcion', 'lote_produccion__codigo') class Meta(RegistroModel.Meta): db_table = 'fabricacion' verbose_name = 'fabricación' permissions = (('view_fabricacion', 'Can see fabricacion'), )
class CompraProducto(RegistroModel): unidad_inventario = models.ForeignKey('almacenes.UnidadInventario', on_delete=models.CASCADE, related_name='compras') proveedor = models.ForeignKey('personas.Persona', on_delete=models.CASCADE, related_name='compras_proveedor') cantidad = models.DecimalField(max_digits=10, decimal_places=4) costo_unidad = models.DecimalField(max_digits=10, decimal_places=2) objects = RegistroQuerySet.as_manager() def save(self, *args, **kwargs): super(CompraProducto, self).save(*args, **kwargs) self.unidad_inventario.actualizar_cantidad_producto() def almacen(self): return self.unidad_inventario.almacen() almacen.short_description = 'almacén' def producto(self): return self.unidad_inventario.producto() def codigo_lote(self): if self.unidad_inventario.lote_produccion: return self.unidad_inventario.lote_produccion.codigo return 'Ninguno' codigo_lote.short_description = 'código de lote/serie' @property def costo_adicional(self): return self.costos.filter(activo=True).aggregate( models.Sum('cantidad'))['cantidad__sum'] search_fields = ( 'unidad_inventario__control_stock__producto__descripcion', 'unidad_inventario__control_stock__producto__codigo_venta', 'proveedor__nombre', 'proveedor__apellido', 'proveedor__numero_identificacion', 'unidad_inventario__control_stock__almacen__nombre', 'unidad_inventario__control_stock__almacen__direccion', 'unidad_inventario__lote_produccion__codigo') class Meta(RegistroModel.Meta): db_table = 'compra_producto' verbose_name = 'compra' verbose_name_plural = 'compras' permissions = (('view_compraproducto', 'Can see compras producto'), )
class Venta(RegistroModel): class Estado(ChoiceEnum): EN_PROCESO = 1, 'en proceso' FINALIZADA = 2, 'finalizada' PAUSADA = 3, 'pausada' CANCELADA = 4, 'cancelada' estado = models.IntegerField(choices=Estado.choices()) objects = RegistroQuerySet.as_manager() def estado_str(self): return str(self.Estado(self.estado)) class Meta(RegistroModel.Meta): db_table = 'venta'
class LoteProduccion(RegistroModel): codigo = models.CharField(max_length=255) producto = models.ForeignKey('productos.Producto', on_delete=models.CASCADE, related_name='lotes_produccion') fecha_produccion = models.DateField(null=True) fecha_vencimiento = models.DateField(null=True) objects = RegistroQuerySet.as_manager() def __str__(self): return self.codigo class Meta(RegistroModel.Meta): db_table = 'lote_produccion' permissions = ( ('view_loteproduccion', 'Can see lotes produccion'), )
class Unidad(RegistroModel): nombre = models.CharField(max_length=255) descripcion = models.CharField(max_length=255) objects = RegistroQuerySet.as_manager() def __str__(self): return self.nombre search_fields = ('nombre', 'descripcion') class Meta(RegistroModel.Meta): db_table = 'unidad' verbose_name_plural = 'unidades' ordering = ('nombre', ) permissions = (('view_unidad', 'Can see unidades'), )
class AtributoProducto(RegistroModel): producto = models.ForeignKey('productos.Producto', on_delete=models.CASCADE, related_name='atributos') atributo_categoria = models.ForeignKey('productos.AtributoCategoria', on_delete=models.CASCADE, related_name='productos') valor = models.CharField(max_length=255) objects = RegistroQuerySet.as_manager() def __str__(self): return str(self.producto) + '_' + str(self.atributo_categoria) class Meta(RegistroModel.Meta): db_table = 'atributo_producto'
class ComponenteProducto(RegistroModel): producto_base = models.ForeignKey('productos.Producto', on_delete=models.CASCADE, related_name='componentes_producto') producto_componente = models.ForeignKey('productos.Producto', on_delete=models.CASCADE, related_name='compuestos') cantidad_componente = models.DecimalField(max_digits=10, decimal_places=4) objects = RegistroQuerySet.as_manager() def __str__(self): return str(self.producto_base) + '_' + str(self.producto_componente) class Meta(RegistroModel.Meta): db_table = 'componente_producto'
class CategoriaProducto(RegistroModel): nombre = models.CharField(max_length=255) slug = models.SlugField(unique=True) objects = RegistroQuerySet.as_manager() @property def atributos_actuales(self): return self.atributos.filter(activo=True) @property def productos_actuales(self): return Producto.objects.actuales().filter( id__in=AtributoProducto.objects.actuales().filter( atributo_categoria__categoria=self, atributo_categoria__activo=True).values_list( 'producto', flat=True)).distinct() def get_absolute_url(self): return reverse("productos:detalle_categoria", kwargs={'slug': self.slug}) def get_unique_slug(self): slug = slugify(self.nombre) unique_slug = slug num = CategoriaProducto.objects.filter(slug=unique_slug).count() if num > 0: unique_slug = '{}-{}'.format(slug, num) return unique_slug def __str__(self): return self.nombre search_fields = ('nombre', ) class Meta(RegistroModel.Meta): db_table = 'categoria_producto' verbose_name = 'categoría' verbose_name_plural = 'categorías' ordering = ('nombre', ) permissions = (('view_categoriaproducto', 'Can see categorías productos'), )
class AjusteInventarioProducto(RegistroModel): unidad_inventario = models.ForeignKey('almacenes.UnidadInventario', on_delete=models.CASCADE, related_name='ajustes') cantidad = models.DecimalField(max_digits=10, decimal_places=4) descripcion = models.CharField(max_length=100, blank=True, null=True) objects = RegistroQuerySet.as_manager() def save(self, *args, **kwargs): super(AjusteInventarioProducto, self).save(*args, **kwargs) self.unidad_inventario.actualizar_cantidad_producto() def almacen(self): return self.unidad_inventario.almacen() almacen.short_description = 'almacén' def producto(self): return self.unidad_inventario.producto() def codigo_lote(self): if self.unidad_inventario.lote_produccion: return self.unidad_inventario.lote_produccion.codigo return 'Ninguno' codigo_lote.short_description = 'código de lote/serie' fabricacion = models.ForeignKey('movimientos.Fabricacion', null=True, on_delete=models.CASCADE, related_name='ajustes') search_fields = ('unidad_inventario__control_stock__almacen__nombre', 'unidad_inventario__control_stock__producto__descripcion', 'unidad_inventario__lote_produccion__codigo') class Meta(RegistroModel.Meta): db_table = 'ajuste_inventario_producto' verbose_name = 'ajuste' verbose_name_plural = 'ajustes' permissions = (('view_ajusteinventarioproducto', 'Can see ajustes inventario producto'), )
class Tienda(RegistroModel): nombre = models.CharField(max_length=255) direccion = models.CharField(max_length=255, verbose_name='dirección') objects = RegistroQuerySet.as_manager() search_fields = ('nombre', 'direccion') def is_authenticated(self): return True def __str__(self): if Tienda.objects.actuales().filter(nombre=self.nombre).count() > 1: return '{} {}'.format(self.id, self.nombre) return self.nombre class Meta(RegistroModel.Meta): db_table = 'tienda' permissions = (('view_tienda', 'Can see tiendas'), )
class Persona(RegistroModel): usuario = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, related_name='persona', blank=True, null=True) nombre = models.CharField(max_length=45) apellido = models.CharField(max_length=45, blank=True, null=True) tipo = models.CharField(max_length=1, verbose_name='tipo de identificación') numero_identificacion = models.CharField( max_length=45, verbose_name='número de identificación') direccion = models.CharField(max_length=100, blank=True, null=True, verbose_name='dirección') telefono = models.CharField(max_length=45, blank=True, null=True, verbose_name='teléfono') email = models.EmailField(verbose_name='dirección de correo electrónico', blank=True, null=True) twitter = models.CharField( max_length=15, blank=True, null=True, validators=[ RegexValidator(r'^[0-9a-zA-Z_]*$', "Solo se permiten caracteres alfanuméricos y '_'.") ]) instagram = models.CharField( max_length=30, blank=True, null=True, validators=[ RegexValidator( r'^[0-9a-zA-Z_\.]*$', "Solo se permiten caracteres alfanuméricos, '.' y '_'.") ]) facebook = models.CharField( max_length=50, blank=True, null=True, validators=[ MinLengthValidator(5), RegexValidator(r'^[0-9a-zA-Z\.]*$', "Solo se permiten caracteres alfanuméricos y '.'.") ]) representante = models.ForeignKey('personas.Persona', on_delete=models.SET_NULL, blank=True, null=True) objects = RegistroQuerySet.as_manager() def identificacion(self): return self.tipo + '-' + self.numero_identificacion identificacion.short_description = 'identificación' def __str__(self): string = self.nombre if self.apellido: string += ' ' + self.apellido return string + '. ' + self.tipo + '-' + self.numero_identificacion search_fields = ('nombre', 'apellido', 'tipo', 'numero_identificacion') class Meta(RegistroModel.Meta): db_table = 'persona' permissions = (('view_persona', 'Can see personas'), )