Skip to main content

Product Model

The Producto model represents items in your inventory with the following fields:
integer
Unique product identifier (auto-generated)
integer
Foreign key to the owner User (admin who created the product)
string
Barcode identifier (unique per user, max 50 characters)
string
Product name (max 100 characters, required)
string
Product category (max 50 characters, optional)
decimal
Purchase cost (10 digits, 2 decimals, default: 0.00)
decimal
Selling price (10 digits, 2 decimals)
integer
Available quantity (positive integer, default: 0)
datetime
Timestamp when product was created (auto-generated)
datetime
Timestamp of last update (auto-updated)

List Products

Requires authentication. Returns products owned by the authenticated user (admin) or their creator (vendedor).

Query Parameters

string
Filter products by category (case-insensitive exact match)
string
default:"nombre"
Sort field. Options: nombre, precio, stock, categoria, -precio (descending)
integer
default:"1"
Page number for pagination (7 items per page)

Example: Filter and Sort

Response

Returns rendered HTML template with paginated product list. See products_lista.html template.

Create Product

Requires authentication and admin role. Vendedor users cannot create products.

Request Parameters

string
required
Product name (max 100 characters)
string
Barcode (must be unique per user, max 50 characters)
string
Product category (max 50 characters)
decimal
default:"0.00"
Purchase cost (e.g., “1200.00”)
decimal
Selling price (e.g., “1500.00”)
integer
default:"0"
Initial stock quantity

Response

Success (HTTP 302):
  • Redirects to /productos/
  • Flash message: “Producto agregado correctamente.”
Validation Error (HTTP 200):
  • Re-renders form with error messages
  • Flash message: “Revisa los campos marcados en el formulario.”
Permission Denied (HTTP 403):
  • Redirects to error page (vendedor users)

Validation Rules

  • nombre is required
  • codigo_de_barras must be unique within user’s products (constraint: unique_together=('codigo_de_barras', 'usuario'))
  • precio_compra and precio must be non-negative decimals
  • stock must be non-negative integer

Update Product

Requires authentication and admin role. Only the product owner can update.

URL Parameters

integer
required
Product ID to update

Request Parameters

Same as Create Product - all fields are editable.

Response

Success (HTTP 302):
  • Redirects to /productos/
  • Flash message: “Producto actualizado correctamente.”
Not Found (HTTP 404):
  • Product doesn’t exist or doesn’t belong to authenticated user
Validation Error (HTTP 200):
  • Re-renders form with error messages

Delete Product

Requires authentication and admin role. Cannot delete products referenced in sales (PROTECT constraint).

URL Parameters

integer
required
Product ID to delete

Response

Success (HTTP 302):
  • Product deleted
  • Redirects to /productos/
  • Flash message: “Producto eliminado correctamente.”
Protected Error (HTTP 302):
  • Cannot delete due to foreign key constraint (product has sales)
  • Redirects to /productos/
  • Error message: “No se puede eliminar el producto '' porque está relacionado con una venta. Para eliminar este producto, primero debes eliminar la(s) venta(s) asociada(s).”
Not Found (HTTP 404):
  • Product doesn’t exist or doesn’t belong to user

GET Request

Accessing the delete URL via GET shows confirmation page:
Renders producto_confirmar_eliminar.html template.

Business Logic

Stock Management

Product stock is automatically decremented when:
  • Sale created: producto.stock -= cantidad
  • Sale detail updated: producto.stock -= (new_cantidad - old_cantidad)
Stock is restored when:
  • Sale deleted: producto.stock += cantidad
  • Sale detail deleted: producto.stock += cantidad
See Sales API for details.

Purchase Integration

When products are purchased:
  • Stock incremented: producto.stock += cantidad_comprada
  • Purchase price updated: producto.precio_compra = precio_compra_detalle
  • Optionally, selling price updated: producto.precio = precio_venta_detalle
See Purchases API for details.

Multi-Tenancy

Products are isolated per user:
  • Admin users see only their own products
  • Vendedor users see products owned by their creado_por admin
  • Enforced at database level: usuario foreign key
  • Enforced in views: Producto.objects.filter(usuario=request.user)

Barcode Uniqueness

The unique_together constraint allows:
  • Same barcode for different users (multi-tenant isolation)
  • Different products with unique barcodes per user
Example:

Example Workflow

Create Product with Stock

  • Sales API - Product selection in sales
  • Purchases API - Product stock replenishment
  • See applications/productos/views.py source: /home/daytona/workspace/source/applications/productos/views.py