Documentation Index
Fetch the complete documentation index at: https://mintlify.com/YonAnn99/Acrylitec/llms.txt
Use this file to discover all available pages before exploring further.
All routes are defined in gestion/urls.py and mounted at the project root via path('', include('gestion.urls')) in core/urls.py, meaning every path listed below is served from the site root with no additional prefix. Access control is enforced at the view level using the @login_required decorator and @user_passes_test(es_admin, login_url='/sin-permiso/') for admin-only views. Unauthenticated users are redirected to /login/; authenticated non-admins who attempt to reach an admin view are redirected to /sin-permiso/.
Authentication
These routes handle user session management and access denial. No authentication is required to reach them.
GET / — Home / Root
| Field | Value |
|---|
| Methods | GET |
| Auth | None |
| View | login_view |
The root path '' is mapped to login_view. If the requesting user is already authenticated and belongs to the Administrador group (or is a superuser), they are immediately redirected to /dashboard/. Otherwise the login form is rendered.
GET /login/ and POST /login/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | None |
| View | login_view |
GET renders the login form (gestion/login.html). POST reads username and password from the request body, calls Django’s authenticate(), and on success calls login() then redirects:
- Admins →
/dashboard/
- Non-admins →
/ventas/ (the sales list, which all authenticated users can access)
On failed authentication, the form is re-rendered with an error context value of "Usuario o contraseña incorrectos.".
GET /logout/
| Field | Value |
|---|
| Methods | GET |
| Auth | None |
| View | logout_view |
Calls Django’s logout() then flushes the entire session with request.session.flush() before redirecting to /login/.
GET /sin-permiso/
| Field | Value |
|---|
| Methods | GET |
| Auth | None |
| View | sin_permiso |
Renders gestion/sin_permiso.html. Used as the login_url redirect target for @user_passes_test(es_admin, ...) so that authenticated non-admin users see a friendly access-denied page rather than a 403.
Dashboard
GET /dashboard/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required, admin only |
| View | dashboard |
Decorated with both @login_required and @user_passes_test(es_admin). Renders gestion/dashboard.html with:
- KPIs: current-month revenue, current-month sale count, all-time revenue, all-time sale count, total clients, and current-month quotation count.
- Revenue charts: monthly, weekly, and yearly series as JSON, segmented by year for the picker UI.
- Active orders: sales with status
pendiente or en_produccion, enriched with resolved client and product names.
Clients
GET /clientes/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required |
| View | lista_clientes |
Lists all Clientes records. Accepts an optional ?q= query parameter to filter by nombre, telefono, or email (case-insensitive). Renders gestion/clientes_list.html.
GET /clientes/nuevo/ and POST /clientes/nuevo/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | crear_cliente |
GET renders gestion/cliente_form.html. POST reads nombre, telefono, email, and direccion from the form body, creates a new Clientes record, and redirects to /clientes/.
Materials
GET /materiales/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required |
| View | lista_materiales |
Lists all Materiales records. Supports ?q= filtering on descripcion. Computes a materiales_bajos count — the number of materials whose stock_actual is at or below stock_minimo — and passes it to the template to display a low-stock badge.
GET /materiales/nuevo/ and POST /materiales/nuevo/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | crear_material |
GET renders gestion/material_form.html. POST creates a new Materiales record using descripcion, largo, ancho, stock (mapped to stock_actual), and stock_minimo, then redirects to /materiales/.
GET /materiales/eliminar/<int:id>/ and POST /materiales/eliminar/<int:id>/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | eliminar_material |
GET renders a confirmation screen (gestion/material_confirm_delete.html) showing how many Cotizaciones and DetalleVenta records reference this material. POST checks for those references:
- If any references exist, a Django
messages.error is set and the user is redirected to /materiales/ without deleting.
- If no references exist, the material is deleted and a success message is set.
Products
GET /productos/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required |
| View | lista_productos |
Lists all Productos records. Accepts ?q= to filter by nombre or detalle (case-insensitive, OR’d). Renders gestion/productos_list.html.
GET /productos/nuevo/ and POST /productos/nuevo/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | crear_producto |
GET renders gestion/producto_form.html with accion='Crear'. POST reads nombre, detalle, porcentaje_utilidad (defaults to 40 if blank), and optional precio_fijo. If a file is present in request.FILES['foto'], it is saved via default_storage to productos/<uuid><ext> and the path is stored on the model. Redirects to /productos/ on success.
GET /productos/<int:pk>/editar/ and POST /productos/<int:pk>/editar/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | editar_producto |
GET renders the product form pre-populated with the existing record. POST updates all fields; if a new photo is uploaded, the old file is deleted from storage before saving the new one. Redirects to /productos/ on success.
POST /productos/<int:pk>/eliminar/
| Field | Value |
|---|
| Methods | POST |
| Auth | Login required |
| View | eliminar_producto |
Deletes the product and its associated photo file from storage (silently ignores storage errors). Redirects to /productos/.
This endpoint only accepts POST. A GET request to this URL will render a confirmation page (gestion/producto_confirm_delete.html) — it does not delete the product.
Orders and Sales
GET /pedidos/nuevo/ and POST /pedidos/nuevo/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required |
| View | nuevo_pedido |
The POS multi-item order screen. GET renders gestion/venta_directa.html with all clients, products, materials, tabulador entries, and the current laser tariff.
POST with Content-Type: application/json triggers order creation: parses the cart from the request body, creates a Ventas master record, creates one DetalleVenta per cart item, decrements each material’s stock_actual by the item quantity, and returns JSON. See the AJAX API reference for the full request/response schema.
GET /ventas/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required |
| View | lista_ventas |
Lists all Ventas records ordered by fecha_venta descending. Computes a resumen context with:
total_ventas — total sale count
total_ingresos — sum of totals for sales with status pagada or entregada
pendientes, en_produccion, entregadas — per-status counts
Each sale is annotated with resolved cliente_nombre, producto_nombre, and total_calculado values for display.
GET /ventas/<int:pk>/
| Field | Value |
|---|
| Methods | GET |
| Auth | Login required |
| View | detalle_venta |
Fetches a single Ventas record with related Cotizaciones, Clientes, Productos, and Materiales data and renders gestion/venta_detalle.html. Returns 404 if the sale does not exist.
POST /ventas/<int:pk>/estatus/
| Field | Value |
|---|
| Methods | POST |
| Auth | Login required |
| View | actualizar_estatus_venta |
Updates the estatus and/or fecha_entrega fields on a Ventas record. Valid status values are pendiente, en_produccion, pagada, and entregada. Redirects to /ventas/<int:pk>/ after saving.
POST /ventas/<int:pk>/abono/
| Field | Value |
|---|
| Methods | POST |
| Auth | Login required |
| View | actualizar_abono_venta |
Updates monto_abonado on a Ventas record with a new Decimal value. Sets a messages.error if the value cannot be parsed. Redirects to /ventas/<int:pk>/ after the operation.
Pricing Configuration
GET /configuracion/ and POST /configuracion/
| Field | Value |
|---|
| Methods | GET, POST |
| Auth | Login required, admin only |
| View | configuracion_precios |
Decorated with @login_required and @user_passes_test(es_admin). GET renders gestion/configuracion_precios.html with the global ConfiguracionPrecios instance, all Productos, and all TabuladorCostos rows ordered by espesor_mm.
POST dispatches on the accion field:
accion value | Effect |
|---|
tarifa_laser | Updates ConfiguracionPrecios.tarifa_laser_minuto |
utilidad_producto | Updates Productos.porcentaje_utilidad for one product |
factor_costo | Updates TabuladorCostos.factor_costo for one tabulador row |
nuevo_tabulador | Creates a new TabuladorCostos row |
All actions redirect back to /configuracion/ after saving.
AJAX Endpoints
| Path | View | Description |
|---|
POST /ajax/calcular/ | calcular_precio_ajax | Real-time price calculation |
POST /ajax/crear-cliente/ | crear_cliente_ajax | Inline client creation from POS screen |
See the AJAX API reference for full request and response schemas for these endpoints.
In DEBUG mode, urlpatterns is extended with static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) so that uploaded product photos are served by Django’s development server. In production (e.g. Railway), Django does not serve media files this way — configure an external object store (such as Amazon S3 or Cloudinary) or a reverse-proxy rule to serve the MEDIA_ROOT directory.