HerméticaDocumentación técnica

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
Todo el tráfico entre capas pasa por 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/.

AppRutaResponsabilidadModelos 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_chat
analytics_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

CarpetaContiene
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)FrontendServicioAPI
Despachosscreens/ + calendar_componentsdispatchService/api/dispatch/
Calendario / ProgramaciónCalendarScreendispatchService/api/calendar/
Cotizacionescotizador_componentscotizacionService, accesoriosService, priceListService/api/cotizaciones/
ComercialComercialDashboardScreen, ClientesScreenclientService, salesOrderService/api/
Serviciosscreens/services, servicios_componentsserviceNoteService, serviceScheduleService, visitService/api/
PAOMscreens/paom, paom_componentspaomService/api/paom/
MRPscreens/mrp, mrp_componentsmrpService/api/mrp/
Inventarioscreens/inventoryinventoryService/api/inventory/
Importacionesimports_dashboard, imports_componentsimportService, supplierService/api/imports/
Portal Gerencialscreens/gerenciaportalGerencialService/api/portal/
Chat Nisirascreens/analytics-chat/api/analytics/
Directorio / Usuariosscreens/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.