primer commit
This commit is contained in:
1 parent
ab3c613165
commit
b2fb4e2d0a
18 files changed
+1291
-277
No files matched your search
@@ -0,0 +1,169 @@
|
||||
# Flujo de Procesamiento — Documentos de Marketing (Ventas / Compras)
|
||||
|
||||
Cubre los documentos comerciales de SAP Business One que la app gestiona: Órdenes de Venta, Facturas de Venta, Órdenes de Compra y Facturas de Proveedor. Los cuatro comparten un único formulario genérico (`MarketingDocumentForm.tsx`) parametrizado por vista.
|
||||
|
||||
## Arquitectura General
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Frontend React (sap-frontend)"
|
||||
OL[OrdersList.tsx]
|
||||
O[Orders.tsx]
|
||||
IL[InvoicesList.tsx]
|
||||
I[Invoices.tsx]
|
||||
POL[PurchaseOrdersList.tsx]
|
||||
PO[PurchaseOrders.tsx]
|
||||
PIL[PurchaseInvoicesList.tsx]
|
||||
PI[PurchaseInvoices.tsx]
|
||||
FORM[MarketingDocumentForm.tsx]
|
||||
COPY[CopyFromModal.tsx]
|
||||
SEARCH[ModalSearchTemplate.tsx]
|
||||
BADGE[StatusBadge.tsx]
|
||||
LVT[ListViewTemplate.tsx]
|
||||
TYPES[types/sapMarketing.ts]
|
||||
API[api.ts]
|
||||
end
|
||||
|
||||
subgraph "Backend FastAPI (mini-backend)"
|
||||
SALES[routers/sales.py]
|
||||
PURCH[routers/purchases.py]
|
||||
CORE[core/sap.py]
|
||||
end
|
||||
|
||||
subgraph "SAP Business One"
|
||||
SL[Service Layer<br/>Orders / Invoices / PurchaseOrders / PurchaseInvoices]
|
||||
end
|
||||
|
||||
OL --> LVT
|
||||
IL --> LVT
|
||||
POL --> LVT
|
||||
PIL --> LVT
|
||||
LVT --> BADGE
|
||||
|
||||
O --> FORM
|
||||
I --> FORM
|
||||
PO --> FORM
|
||||
PI --> FORM
|
||||
FORM --> COPY
|
||||
FORM --> SEARCH
|
||||
FORM --> TYPES
|
||||
FORM --> API
|
||||
|
||||
API -->|GET/POST/PATCH| SALES
|
||||
API -->|GET/POST/PATCH| PURCH
|
||||
SALES --> CORE
|
||||
PURCH --> CORE
|
||||
CORE --> SL
|
||||
```
|
||||
|
||||
Cada vista de mantenimiento (`Orders.tsx`, `Invoices.tsx`, `PurchaseOrders.tsx`, `PurchaseInvoices.tsx`) es una capa delgada: mantiene el estado del documento (`doc`, tipado como `MarketingDocument` en `types/sapMarketing.ts`) y le pasa a `MarketingDocumentForm` la configuración específica de ese tipo de documento — el componente de formulario en sí no sabe si está editando una orden o una factura, solo renderiza lo que recibe por props.
|
||||
|
||||
## Cómo un solo formulario sirve a los 4 documentos
|
||||
|
||||
`MarketingDocumentForm` recibe por props todo lo que varía entre documentos:
|
||||
|
||||
| Prop | Qué controla | Ejemplo |
|
||||
|---|---|---|
|
||||
| `endpoint` | Endpoint del backend a consultar/enviar (`GET/POST/PATCH /api/{endpoint}`) | `"Orders"`, `"Invoices"`, `"PurchaseOrders"`, `"PurchaseInvoices"` |
|
||||
| `tipoDocumento` | Etiqueta tipada (`OrdenVenta`, `FacturaVenta`, `OrdenCompra`, `FacturaProveedor`) declarada en `DocumentConfigProps` | — no se usa dentro de la lógica del propio formulario en el código leído; parece ser solo metadata para quien lo invoca |
|
||||
| `titulo` | Encabezado visible del formulario | `"Factura de Ventas (OINV)"` |
|
||||
| `headerExtraFields` | Campos de cabecera exclusivos de ese documento | Facturas: `FolioPrefixString`, `FolioNumber`, `GroupNum` |
|
||||
| `lineColumns` | Columnas de la grilla de líneas, cada una con un `show(doc)` opcional para ocultar/mostrar según `DocType` | Compras oculta `ItemCode`/`Almacén` si `DocType` es de servicio |
|
||||
| `copyFromSources` | Documentos origen habilitados para el botón "📋 Copiar de" | Facturas de Venta: Orden de Venta y Entrega; Facturas de Proveedor: Orden de Compra |
|
||||
| `retencionConfig` / `detraccionConfig` | Solo presentes en `PurchaseInvoices.tsx` — habilitan los bloques de Retención (3%/6%) y Detracción (SUNAT) en el resumen de totales | No se pasan en Órdenes ni en Facturas de Venta |
|
||||
| `onBuscarSocio`, `onBuscarArticulos`, `onCellSearch` | Callbacks que abren los `ModalSearchTemplate` de Socios, Artículos, Almacén y Código de Impuesto | Cada vista instancia sus propios modales y decide qué endpoint/filtro usar |
|
||||
|
||||
El cálculo de totales (subtotal, impuesto 18% fijo, retención, detracción, total general) vive dentro del propio `MarketingDocumentForm`, no en las vistas.
|
||||
|
||||
## Flujo: Crear una Factura de Venta copiando una Orden
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor User as Usuario
|
||||
participant List as InvoicesList
|
||||
participant View as Invoices.tsx
|
||||
participant Form as MarketingDocumentForm
|
||||
participant Copy as CopyFromModal
|
||||
participant API as api.ts
|
||||
participant Backend as backend sales.py
|
||||
participant SAP as SAP Service Layer
|
||||
|
||||
User->>List: /ventas/facturas → "Nueva Factura"
|
||||
List->>View: navigate("/ventas/facturas/mantenimiento")
|
||||
View->>Form: <MarketingDocumentForm endpoint="Invoices" copyFromSources=[Orden, Entrega] />
|
||||
Form->>API: GET /api/Currencies
|
||||
API->>Backend: fetch
|
||||
Backend->>SAP: GET Currencies
|
||||
SAP-->>Form: lista de monedas
|
||||
|
||||
User->>Form: busca y selecciona Cliente (🔍)
|
||||
Form->>View: onBuscarSocio() abre ModalSearchTemplate(BusinessPartners)
|
||||
View-->>Form: setDoc({CardCode, CardName})
|
||||
|
||||
User->>Form: clic "📋 Copiar de" → "Orden de Venta"
|
||||
Form->>Copy: <CopyFromModal source={Orden} cardCode docType />
|
||||
Copy->>API: GET /api/Orders?filtro por CardCode/BaseType
|
||||
API->>Backend: fetch
|
||||
Backend->>SAP: GET Orders
|
||||
SAP-->>Copy: documentos abiertos del cliente
|
||||
User->>Copy: selecciona una orden
|
||||
Copy-->>Form: onConfirm(lines, sourceLabel)
|
||||
Note over Form: Si ya hay líneas, confirm() pregunta reemplazar o agregar
|
||||
Form->>Form: setDoc({DocumentLines: lines}) — cada línea trae BaseType/BaseEntry/BaseLine
|
||||
|
||||
User->>Form: clic "Crear Documento"
|
||||
Form->>API: POST /api/Invoices (doc + DocumentLines, sin BaseRef)
|
||||
API->>Backend: fetch POST
|
||||
Backend->>SAP: POST Invoices (con líneas BaseEntry → SAP cierra la orden origen)
|
||||
SAP-->>Backend: 201 Created
|
||||
Backend-->>Form: ok
|
||||
Form-->>User: "Documento creado exitosamente en SAP"
|
||||
```
|
||||
|
||||
El mismo patrón aplica a Facturas de Proveedor copiando desde Órdenes de Compra, solo cambian `endpoint` y `copyFromSources`.
|
||||
|
||||
## Árbol de Componentes
|
||||
|
||||
```
|
||||
App.tsx (BrowserRouter)
|
||||
└── / (ProtectedRoute → MainLayout)
|
||||
├── /ventas
|
||||
│ ├── /ordenes → OrdersList.tsx → ListViewTemplate → StatusBadge
|
||||
│ ├── /ordenes/mantenimiento → Orders.tsx → MarketingDocumentForm
|
||||
│ ├── /entrega → stub "Entregas / Guías" (sin vista real, ver Hallazgos)
|
||||
│ └── /facturas
|
||||
│ ├── (lista) → InvoicesList.tsx → ListViewTemplate → StatusBadge
|
||||
│ └── /mantenimiento → Invoices.tsx → MarketingDocumentForm
|
||||
└── /compras
|
||||
├── /ordenes → PurchaseOrdersList.tsx → ListViewTemplate → StatusBadge
|
||||
├── /ordenes/mantenimiento → PurchaseOrders.tsx → MarketingDocumentForm
|
||||
├── /recepcion → stub "Recepciones de Compra" (sin vista real, ver Hallazgos)
|
||||
└── /facturas
|
||||
├── (lista) → PurchaseInvoicesList.tsx → ListViewTemplate → StatusBadge
|
||||
└── /mantenimiento → PurchaseInvoices.tsx → MarketingDocumentForm (+ Retención/Detracción)
|
||||
|
||||
MarketingDocumentForm.tsx
|
||||
├── FormattedField.tsx / SelectField.tsx (cabecera)
|
||||
├── CopyFromModal.tsx (botón "Copiar de")
|
||||
└── (por vista) ModalSearchTemplate.tsx ×4 (Socios, Artículos, Almacén, Código de Impuesto)
|
||||
```
|
||||
|
||||
## Archivos Clave
|
||||
|
||||
| Archivo | Ruta | Propósito |
|
||||
|---|---|---|
|
||||
| `MarketingDocumentForm.tsx` | `src/components/` | Formulario genérico: cabecera, grilla de líneas, totales, copiar-de, submit GET/POST/PATCH |
|
||||
| `Orders.tsx` / `Invoices.tsx` | `src/views/ventas/` | Configuran el formulario para Órdenes y Facturas de venta |
|
||||
| `PurchaseOrders.tsx` / `PurchaseInvoices.tsx` | `src/views/compras/` | Configuran el formulario para Compras; Facturas agrega retención/detracción |
|
||||
| `OrdersList.tsx`, `InvoicesList.tsx`, `PurchaseOrdersList.tsx`, `PurchaseInvoicesList.tsx` | `src/views/ventas/`, `src/views/compras/` | Listados vía `ListViewTemplate`, con `StatusBadge` por estado del documento |
|
||||
| `CopyFromModal.tsx` | `src/components/ui/` | Modal para copiar líneas desde un documento base (Orden→Entrega→Factura) |
|
||||
| `ModalSearchTemplate.tsx` | `src/components/ui/` | Modal de búsqueda genérico reutilizado para Socios, Artículos, Almacenes, Códigos de Impuesto |
|
||||
| `sapMarketing.ts` | `src/types/` | `MarketingDocument`, `DocumentLine`, `DocumentConfigProps`, `CopyFromSource`, `LineColumnConfig` |
|
||||
| `sunat.ts` | `src/utils/` | `DETRACCION_CODIGOS` (porcentajes SUNAT usados en Facturas de Proveedor) |
|
||||
| `sales.py` / `purchases.py` | `mini-backend/routers/` | Endpoints REST que proxean a SAP Service Layer |
|
||||
|
||||
## Hallazgos (código tal cual está hoy, sin corregir)
|
||||
|
||||
- **`ventas/entrega` y `compras/recepcion` son stubs**: en `App.tsx` son componentes en línea que solo muestran un título ("Entregas / Guías" / "Recepciones de Compra"), sin listado ni formulario real todavía.
|
||||
- **`DeliveryNotesList.tsx` existe pero no está enrutado**: el archivo `src/views/ventas/DeliveryNotesList.tsx` está escrito pero ninguna ruta en `App.tsx` lo importa o lo usa — no es alcanzable desde la navegación actual.
|
||||
- El endpoint `PurchaseDeliveryNotes` (documentado en `mini-backend/docs/api-reference.md`) tampoco tiene vista de frontend correspondiente todavía.
|
||||
Reference in new issue
Block a user