From 08362c5677abaf4f4713a55cee771637204d14a0 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Thu, 11 Jun 2026 09:02:14 +0000 Subject: [PATCH] docs: FASES_IMPLEMENTADAS + MULTI_BRANCH + GLOBAL_INVOICE - Actualiza FASES_IMPLEMENTADAS.md con Fase 7 (precios proveedor, multi-sucursal, factura global) - Agrega docs/MULTI_BRANCH.md con arquitectura y endpoints - Agrega docs/GLOBAL_INVOICE.md con requerimiento SAT y flujo de uso --- docs/FASES_IMPLEMENTADAS.md | 42 +++++++++++++++++-- docs/GLOBAL_INVOICE.md | 82 +++++++++++++++++++++++++++++++++++++ docs/MULTI_BRANCH.md | 52 +++++++++++++++++++++++ 3 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 docs/GLOBAL_INVOICE.md create mode 100644 docs/MULTI_BRANCH.md diff --git a/docs/FASES_IMPLEMENTADAS.md b/docs/FASES_IMPLEMENTADAS.md index 148aa55..b8272c9 100644 --- a/docs/FASES_IMPLEMENTADAS.md +++ b/docs/FASES_IMPLEMENTADAS.md @@ -1,8 +1,9 @@ # Nexus POS — Resumen de Fases Implementadas -**Fecha:** 2026-04-29 -**Versión DB:** v3.2 +**Fecha:** 2026-06-11 +**Versión DB:** v4.1 **Tests:** 73/73 pasando (pytest) +**Commit:** `2b73c2c` --- @@ -200,6 +201,41 @@ METABASE_URL=http://localhost:3000 | — | **nexus-pos.service systemd** | 2026-04-29 | `c766571` | | — | **QWEN 3.6 AI Vehicle Fitment** | 2026-04-29 | `623c57b` | +## FASE 7: Precios de Proveedor + Multi-sucursal + Factura Global + +**Commit:** `2b73c2c` (2026-06-11) + +### 7.1 Lista de Precios de Proveedor + +| Feature | Archivos | Capacidades | +|---------|----------|-------------| +| **Precios por proveedor** | `supplier_catalog_prices` (master DB) | Precio, moneda, vigencia (effective_from/to), activo/inactivo | +| **Upload masivo** | `supplier_catalog_bp.py` | CSV/Excel con supplier_name, sku, price, currency | +| **Visualización** | `catalog.js`, `catalog_service.py` | `supplier_price` + `supplier_currency` en tarjetas y búsqueda | +| **Endpoints** | `supplier_catalog_bp.py` | `GET/POST/PUT/DELETE /pos/api/supplier-catalog/prices/*` | + +### 7.2 Multi-sucursal Completo + +| Feature | Archivos | Capacidades | +|---------|----------|-------------| +| **Schema migration v4.0** | `v4.0_multi_branch.sql` | `inventory.branch_id=NULL` (catálogo compartido), tabla `inventory_stock` | +| **Datos fiscales por sucursal** | `branches` (tenant DB) | `rfc`, `razon_social`, `regimen_fiscal`, `codigo_postal`, `serie_cfdi`, `folio_inicial`, `licencia_fiscal`, `certificado_pem`, `llave_pem`, `is_main` | +| **Sincronización de stock** | Trigger `trg_update_inventory_stock` | `inventory_operations` → `inventory_stock` automático | +| **Backend branches** | `config_bp.py` | CRUD completo con campos fiscales, validación de única sucursal `is_main` | +| **Backend inventario** | `inventory_bp.py`, `inventory_engine.py`, `pos_bp.py` | Stock por sucursal vía `inventory_stock`, catálogo compartido, verificación de stock en POS | +| **Backend facturación** | `invoicing_bp.py` | CFDI usa datos fiscales de la sucursal de la venta (`_get_issuer_config`) | +| **Frontend config** | `config.html`, `config.js` | Modal de sucursal expandido con todos los campos fiscales, edición inline | + +### 7.3 Factura Global Mensual + +| Feature | Archivos | Capacidades | +|---------|----------|-------------| +| **Schema migration v4.1** | `v4.1_global_invoice.sql` | `global_invoice_sales`, `sales.global_invoiced_at` | +| **Builder CFDI global** | `cfdi_builder.py` | `build_global_invoice_xml()` con `InformacionGlobal` SAT-compliant (`Periodicidad="04"`) | +| **Servicio** | `global_invoice.py` | Agrupa ventas PUE ≤$2,000 sin CFDI individual del mes/año solicitado | +| **Endpoints** | `invoicing_bp.py` | `POST /global-invoice`, `GET /global-invoice/`, `GET /global-invoice/eligible-sales` | +| **Frontend** | `invoicing.html`, `invoicing.js` | Botón "Factura Global" con modal de año/mes + vista previa de ventas elegibles | + --- ## Mejoras Pendientes (Roadmap Actualizado) @@ -215,7 +251,7 @@ METABASE_URL=http://localhost:3000 | 1 | **WhatsApp Business API (Meta Cloud) real** | Migrar de Baileys a Meta Cloud API. Requiere verificación de cuenta Meta, Business Manager, número de teléfono verificado. | 2-3 semanas | Stub creado (`whatsapp_cloud_bp.py`) | | 2 | **BNPL real** | Integrar APLAZO/Kueski/Clip con credenciales de sandbox/producción. | 2 semanas | Stub creado (`bnpl_bp.py`) | | 3 | **ERP Sync real** | Conectar Aspel/CONTPAQi/SAP/Odoo vía API o archivos de intercambio. | 2-3 semanas | Stub creado (`erp_bp.py`) | -| 4 | **Mercado Libre / Amazon sync** | Publicar inventario de bodegas en marketplaces. API de ML Seller + Amazon SP-API. | 3 semanas | No iniciado | +| 4 | **Mercado Libre / Amazon sync** | Publicar inventario de bodegas en marketplaces. API de ML Seller + Amazon SP-API. | 3 semanas | En progreso (ML Seller API vinculada) | ### 🟡 Medio — Diferenciadores diff --git a/docs/GLOBAL_INVOICE.md b/docs/GLOBAL_INVOICE.md new file mode 100644 index 0000000..25a2017 --- /dev/null +++ b/docs/GLOBAL_INVOICE.md @@ -0,0 +1,82 @@ +# Factura Global Mensual — Documentación Técnica + +**Versión DB:** v4.1 +**Commit:** `2b73c2c` + +--- + +## Requerimiento SAT + +El SAT permite agrupar tickets de contado (menores a $2,000) en una sola factura mensual tipo **Ingreso** con `InformacionGlobal`. + +## Criterios de elegibilidad + +Una venta es elegible para factura global si: +1. `metodo_pago_sat = 'PUE'` (pagado al momento) +2. `total <= $2,000` +3. `status = 'completed'` +4. No tiene CFDI individual timbrado (`cfdi_queue.status = 'stamped'`) +5. No está ya en una factura global (`sales.global_invoiced_at IS NULL`) +6. Fecha dentro del mes/año solicitado + +## Arquitectura + +### Tablas +- `global_invoice_sales (global_invoice_id, sale_id)` — relación N:M +- `sales.global_invoiced_at` — marca de inclusión + +### XML +- `build_global_invoice_xml()` en `cfdi_builder.py` +- `InformacionGlobal Periodicidad="04"` (mensual) +- Receptor: `PUBLICO EN GENERAL` (RFC XAXX010101000) + +--- + +## Endpoints + +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| `GET` | `/pos/api/invoicing/global-invoice/eligible-sales?year=&month=&branch_id=` | Preview de ventas elegibles | +| `POST` | `/pos/api/invoicing/global-invoice` | Genera factura global | +| `GET` | `/pos/api/invoicing/global-invoice/` | Estado y ventas vinculadas | + +### POST body +```json +{ + "year": 2026, + "month": 6, + "branch_id": 1 +} +``` + +### Response +```json +{ + "id": 42, + "status": "pending", + "sales_count": 15, + "total": 18450.00, + "provisional_folio": "PRE-00042", + "xml": "" +} +``` + +--- + +## Flujo de uso (Frontend) + +1. Ir a **Facturación** +2. Clic en botón **Factura Global** +3. Seleccionar año y mes +4. Clic en **Vista previa** para ver ventas elegibles +5. Clic en **Generar** para crear y encolar el CFDI +6. Procesar cola de timbrado normalmente + +--- + +## Timbrado + +La factura global entra en la cola `cfdi_queue` con: +- `type = 'ingreso'` +- `sale_id = NULL` +- Se timbra igual que cualquier otro CFDI vía Horux360 diff --git a/docs/MULTI_BRANCH.md b/docs/MULTI_BRANCH.md new file mode 100644 index 0000000..7c5a52f --- /dev/null +++ b/docs/MULTI_BRANCH.md @@ -0,0 +1,52 @@ +# Multi-sucursal — Documentación Técnica + +**Versión DB:** v4.0 +**Commit:** `2b73c2c` + +--- + +## Arquitectura + +### Catálogo compartido +- `inventory.branch_id` es siempre `NULL` (catálogo compartido a nivel tenant). +- `part_number` tiene unique index `idx_inventory_part_unique`. +- Productos duplicados por `part_number` en múltiples sucursales fueron consolidados en la migración v4.0. + +### Stock por sucursal +- Tabla `inventory_stock (inventory_id, branch_id, stock, location)`. +- Trigger `trg_update_inventory_stock` en `inventory_operations` mantiene `inventory_stock` sincronizado automáticamente. +- `inventory_stock_summary` sigue existiendo como stock total agregado (sin `branch_id`). + +### Datos fiscales por sucursal +- Tabla `branches` incluye: `rfc`, `razon_social`, `regimen_fiscal`, `codigo_postal`, `serie_cfdi`, `folio_inicial`, `licencia_fiscal`, `certificado_pem`, `llave_pem`, `is_main`. +- Solo una sucursal puede ser `is_main = true`. +- Al facturar, `_get_issuer_config(cur, branch_id)` usa datos de la sucursal de la venta; fallback a config global del tenant. + +--- + +## Endpoints + +### Config +- `GET /pos/api/config/branches` — lista sucursales (sin PEM) +- `GET /pos/api/config/branches/` — detalle completo (con PEM) +- `POST /pos/api/config/branches` — crear +- `PUT /pos/api/config/branches/` — editar + +### Inventario +- `GET /pos/api/inventory/items` — acepta `?branch_id=` para mostrar stock por sucursal +- Stock se lee de `inventory_stock` cuando se filtra por sucursal + +### POS +- Ventas verifican stock vía `get_stock(conn, inventory_id, branch_id)` +- `inventory_operations` registra `branch_id` de la venta + +--- + +## Migración + +```bash +cd /home/Autopartes/pos +python3 migrations/runner.py +``` + +Archivo: `pos/migrations/v4.0_multi_branch.sql`