Nivel código
Módulos del sistema
Dos repositorios, una arquitectura espejo: cada módulo de negocio existe como una app de Django en el backend y como un grupo de pantallas + un servicio en el frontend. Entender ese emparejamiento es entender el 90 % del código.
1. Mapa general
flowchart TB
subgraph FE["FRONTEND · lu-hermetica-comercial-webapp · React + TypeScript + Vite"]
direction TB
SH["src/components/screens/*
pantallas por módulo"]
SC["src/components/*_components
componentes de cada módulo"]
UI["src/components/ui
shadcn / Radix"]
SV["src/services/*Service.ts
una capa por dominio: fetch + tipos"]
ST["src/context · src/store (zustand) · src/hooks"]
PWA["src/sw.ts · vite-plugin-pwa
service worker, instalable"]
SH --> SC --> UI
SH --> ST
SH --> SV
SV --> PWA
end
API{{"HTTPS · JSON
Token de DRF en la cabecera Authorization"}}
SV --> API
subgraph BE["BACKEND · lu-hermetica-comercial-backend · Django + DRF"]
direction TB
URLS["hermetica_dir/urls.py
enrutador raíz de /api/*"]
APPS["Apps de dominio
models · serializers · views · urls"]
PERM["accounts
usuarios, grupos, GroupBasedPermission, push"]
CMD["management/commands
importaciones e ingestas"]
URLS --> APPS
APPS --> PERM
APPS --> CMD
end
API --> URLS
DB[("PostgreSQL")]
BUCK[("Cloud Storage")]
NIS[("Nisira")]
APPS --> DB
APPS --> BUCK
CMD --> NIS
classDef fe fill:#fdf0e3,stroke:#e08b2f,color:#7a4a10
classDef be fill:#e8f1fb,stroke:#4285f4,color:#0b3d78
classDef store fill:#eaf6ef,stroke:#34a853,color:#0d5228
classDef api fill:#111827,stroke:#111827,color:#ffffff
class SH,SC,UI,SV,ST,PWA fe
class URLS,APPS,PERM,CMD be
class DB,BUCK,NIS store
class API api
src/services en el frontend y por
hermetica_dir/urls.py en el backend. No hay fetch suelto en las
pantallas ni rutas fuera del enrutador raíz.2. Backend · apps de Django
Todas las apps siguen la misma estructura (models.py,
serializers.py, views.py, urls.py,
migrations/) y se montan bajo un prefijo de /api/.
| App | Ruta | Responsabilidad | Modelos principales |
|---|---|---|---|
commercial | /api/ |
Núcleo comercial y de servicios: clientes, plantas, productos, visitas, notas de servicio, técnicos, programación de servicios y reprogramaciones. | Client, Plant, Product, Visit,
ServiceNote, Technician, ScheduledService,
ReprogramacionRequest |
dispatch | /api/dispatch/ |
Espejo de las órdenes del ERP y su estado de despacho. Aloja la importación desde Nisira y las notificaciones de despacho. | SalesOrder, ProductionOrder,
NisiraProductionOrder, Group, ImportStatus,
DispatchNotification |
calendarapp | /api/calendar/ |
Calendario semanal de despachos: programación, arrastre entre días y despacho real. | Dispatch, RealDispatch |
cotizaciones | /api/cotizaciones/ |
Cotizador comercial completo: listas de precios, plantillas de descripción, accesorios, precios especiales, generación de Excel y PDF de propuesta. | Cotizacion, CotizacionItem, ListaPrecios,
PlantillaDescripcion, PrecioEspecial, Vendedor |
paom | /api/paom/ |
Planeamiento y optimización de material: planes de corte, aprovechamiento de retazos, fórmulas por tipo de puerta y requerimientos por OPR. | CuttingPlan, Offcut, Formula,
Requirement, Accessory, Rod |
mrp | /api/mrp/ |
Planificación de requerimientos de material: listas de materiales, demanda mensual y órdenes de compra derivadas. | Material, BOM, MonthlyDemand,
PurchaseOrder |
inventory | /api/inventory/ |
Inventario y programa de despacho por producto. | ProductData, DispatchProgram |
importsapp | /api/imports/ |
Seguimiento de importaciones de compra: proveedores, órdenes, pagos, documentos, historial y alertas. | PurchaseOrder, Payment, ImportDocument,
Alert |
portal_gerencial | /api/portal/ |
Portal de gerencia: áreas, tareas con vencimiento y eventos. Incluye el endpoint de cron para notificar tareas vencidas. | Area, Tarea, Evento |
analytics_chatanalytics_mcp | /api/analytics/ |
«Chat Nisira»: consulta en lenguaje natural sobre el datawarehouse, vía Claude con herramientas MCP, más transcripción y voz. | ChatConversation, ChatMessage |
dashboard | /api/dashboard/ |
Agregados e indicadores para las pantallas de tablero; carga de archivos de apoyo. | UploadedFile |
reports | /api/reports/ |
Generación de reportes y exportaciones (sin modelos propios). | — |
accounts | /api/push/ |
Transversal: perfiles, grupos de permisos (GroupBasedPermission) y
suscripciones a notificaciones push del navegador. |
PushSubscription |
hermetica_dir | — | Proyecto Django: settings.py, urls.py, WSGI/ASGI. Punto de
entrada de toda la configuración. |
— |
Permisos. El control de acceso es por grupo de Django, no por rol propio:
GroupBasedPermission compara el grupo del usuario contra el módulo solicitado. Los
grupos se administran desde /admin/.
3. Frontend · organización del código
| Carpeta | Contiene |
|---|---|
src/components/screens/ |
Una pantalla por vista de negocio: CalendarScreen,
OrdenProduccionScreen, ClientesScreen,
VisitasScreen, NotasServicioScreen,
ComercialDashboardScreen, LoginScreen, más subcarpetas por
módulo (paom/, mrp/, inventory/,
gerencia/, services/, accesorios/,
analytics-chat/, reportes/). |
src/components/*_components/ |
Componentes específicos de cada módulo: calendar_components,
cotizador_components, paom_components,
mrp_components, imports_components,
servicios_components, portal_gerencial_components,
dashboard_components. |
src/components/ui/ |
Librería de componentes base (shadcn sobre Radix UI) + Tailwind. No contiene lógica de negocio. |
src/services/ |
Única capa que habla con la API. Un archivo por dominio:
dispatchService, cotizacionService, paomService,
mrpService, clientService, serviceNoteService,
portalGerencialService, reportsService, etc. Aquí vive
fetchWithAuth, que adjunta el token y limpia la sesión ante un 401. |
src/context/ · src/store/ · src/hooks/ |
Estado global (AppContext, ProveedoresContext,
TecnicosContext), estado de UI con zustand y hooks reutilizables
(useDispatchDragDrop, useProductionOrders,
useAccesorios). |
src/sw.ts · src/lib/pwa.ts |
Service worker propio y registro de la PWA (Workbox). Es lo que permite instalar la app y lo que hay que tener en cuenta al desplegar: ver la nota de abajo. |
src/types/ · src/utils/ · src/lib/ |
Tipos TypeScript compartidos, utilidades y el algoritmo de optimización auxiliar
(optimization.ts) y el tour de onboarding (lib/tutorial). |
Trampa conocida de la PWA. Como la app precachea sus assets, tras un despliegue el navegador de un usuario con pestañas abiertas sigue sirviendo el bundle anterior: el service worker nuevo queda en estado waiting hasta que se cierran todas las pestañas del dominio. Un refresco forzado no basta. Es la causa más habitual del reporte «lo desplegaron pero no lo veo».
4. Correspondencia módulo ↔ pantalla ↔ API
| Módulo (menú lateral) | Frontend | Servicio | API |
|---|---|---|---|
| Despachos | screens/ + calendar_components | dispatchService | /api/dispatch/ |
| Calendario / Programación | CalendarScreen | dispatchService | /api/calendar/ |
| Cotizaciones | cotizador_components | cotizacionService, accesoriosService, priceListService | /api/cotizaciones/ |
| Comercial | ComercialDashboardScreen, ClientesScreen | clientService, salesOrderService | /api/ |
| Servicios | screens/services, servicios_components | serviceNoteService, serviceScheduleService, visitService | /api/ |
| PAOM | screens/paom, paom_components | paomService | /api/paom/ |
| MRP | screens/mrp, mrp_components | mrpService | /api/mrp/ |
| Inventario | screens/inventory | inventoryService | /api/inventory/ |
| Importaciones | imports_dashboard, imports_components | importService, supplierService | /api/imports/ |
| Portal Gerencial | screens/gerencia | portalGerencialService | /api/portal/ |
| Chat Nisira | screens/analytics-chat | — | /api/analytics/ |
| Directorio / Usuarios | screens/ | userService, pushService | /api/push/, /admin/ |
5. Stack y versiones
Backend
Python 3 · Django 5.2 · Django REST Framework · django-filter ·
django-storages (GCS) · whitenoise · psycopg ·
corsheaders · openpyxl y WeasyPrint para Excel y PDF.
Zona horaria America/Lima, idioma es-PE. Se sirve en contenedor
Docker sobre el puerto 8080.
Frontend
React 18 · TypeScript · Vite · Tailwind CSS · shadcn/ui sobre Radix · zustand ·
react-hook-form + zod · echarts y recharts · date-fns · @hello-pangea/dnd para
el arrastre del calendario · vite-plugin-pwa + Workbox.
Dos lockfiles en el frontend. El repositorio tiene package-lock.json
y pnpm-lock.yaml. Cloudflare instala con pnpm
(--frozen-lockfile), así que si se toca package.json y solo se
actualiza el lockfile de npm, toda la verificación local pasa y el despliegue real falla
con ERR_PNPM_OUTDATED_LOCKFILE. Regla: al tocar package.json, correr
npx pnpm@10.18.1 install --lockfile-only y commitear pnpm-lock.yaml
en el mismo commit. Se reconoce de un vistazo porque el build falla en ~20 s, cuando uno sano
tarda entre 1,5 y 3,5 minutos.