🎉 Initial commit - Hazard Odoo 16 project
- Custom modules: hazard_shopify, hazard_inventory_report, hazard_website - Third-party modules: bi_sql_editor, query_deluxe, sql_request_abstract, l10n_mx_sat_sync_itadmin_ee - Docker setup: Odoo 16 + PostgreSQL 17 - Utility scripts: backup_hazard.sh, update_module.py - Agent configuration: .agents/AGENTS.md - Security: Enterprise modules, credentials, backups and production data excluded via .gitignore
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# Documentación: Flujo Custom (B2B / Mayoreo) y Subcontratación en Odoo
|
||||
|
||||
*Este documento consolida las decisiones, configuraciones y la arquitectura implementada para manejar el flujo B2B y maquila, manteniéndolo 100% aislado de Shopify.*
|
||||
|
||||
## 1. El Problema a Resolver
|
||||
El cliente (Hazard) necesita manejar un flujo donde:
|
||||
- Se venden productos a la medida (ej. Camisas para Club de Golf) a clientes B2B.
|
||||
- Hazard no fabrica la ropa directamente. Proveen los insumos (telas, botones, cierres) a fábricas externas (maquileras, muchas en China).
|
||||
- Ocasionalmente, compran el producto ya terminado a la fábrica.
|
||||
- Piden cotizaciones a diferentes fábricas y manejan anticipos.
|
||||
- **Regla Crítica:** Todo este inventario (Insumos y Ropa a la Medida) debe estar separado lógicamente de la tienda en línea (Shopify), aunque físicamente compartan el almacén. El conector no debe sincronizar estos productos.
|
||||
|
||||
---
|
||||
|
||||
## 2. Solución y Arquitectura en Odoo
|
||||
|
||||
Para resolver esto utilizando funciones nativas de Odoo y código a prueba de errores, activamos la siguiente arquitectura:
|
||||
|
||||
### A. Fabricación y Subcontratación (MRP)
|
||||
Se activó la **Subcontratación**.
|
||||
- **Cómo funciona:** Cuando se crea la "Camisa Custom", se le asigna una **Lista de Materiales (BoM)** de tipo *Subcontratación*.
|
||||
- **La magia:** Al crearle una Orden de Compra a la fábrica china por las camisas, Odoo automáticamente genera un movimiento de inventario (Resuministro de subcontratista) que **descuenta la tela de nuestro almacén principal** y la transfiere a una bodega virtual de la fábrica. Al recibir la camisa terminada, la tela se consume oficialmente.
|
||||
|
||||
### B. Compras y Licitaciones (Purchase Agreements)
|
||||
Se activaron los **Acuerdos de Compra**.
|
||||
- Esto permite crear una *Licitación* o *Requisición*. Se puede pedir cotización a 3 fábricas chinas distintas al mismo tiempo, compararlas en Odoo y elegir la ganadora para generar la Orden de Compra definitiva.
|
||||
- **Anticipos:** Se resuelven registrando una factura de proveedor por "Anticipo" vinculada a la Orden de Compra, lo que crea un saldo a favor en la cuenta de la fábrica.
|
||||
|
||||
### C. Ventas B2B (CRM / Sales)
|
||||
Se creó el **Equipo de Ventas `Custom / B2B`**.
|
||||
- Los vendedores usan Odoo (recomendado usar el CRM Kanban de Odoo en lugar de Notion para evitar doble trabajo) para hacer las cotizaciones (Quotations) directamente.
|
||||
|
||||
---
|
||||
|
||||
## 3. El Blindaje contra Shopify (Código Personalizado)
|
||||
|
||||
Para garantizar que el inventario no se mezcle con Shopify, se crearon dos categorías de producto exclusivas:
|
||||
1. `Insumos / Materia Prima`
|
||||
2. `Producto Final Custom`
|
||||
|
||||
**La medida de seguridad:**
|
||||
Se modificó el módulo custom `hazard_shopify` (específicamente en `models/product_template.py`). Se añadió un `@api.constrains` que actúa como escudo protector:
|
||||
```python
|
||||
@api.constrains('shopify_published', 'categ_id')
|
||||
def _check_shopify_published_category(self):
|
||||
for record in self:
|
||||
if record.shopify_published and record.categ_id:
|
||||
if 'Custom' in record.categ_id.name or 'Insumo' in record.categ_id.name:
|
||||
raise UserError("Los productos de la categoría Custom o Insumos no pueden ser publicados en Shopify.")
|
||||
```
|
||||
**Resultado:** Incluso si un usuario intenta forzar la sincronización (marcando la casilla "Publicado en Shopify" o haciendo clic en el botón de push), el sistema lanzará un error y bloqueará la acción. La separación está garantizada por código.
|
||||
|
||||
*(Nota: Los códigos de barra automáticos EAN13 siguen generándose para estos productos gracias a la lógica del sistema, lo cual es útil para escaneos internos en bodega).*
|
||||
|
||||
---
|
||||
|
||||
## 4. Guía de Prueba Rápida (Walkthrough)
|
||||
|
||||
Se inyectaron datos de prueba (`setup_test_data.py`) para validar el flujo. Los pasos para una demo son:
|
||||
|
||||
1. **Cotizar al Cliente Final:** Confirmar la Cotización (SO) para el cliente `Club de Golf Test` por 5 unidades de `Camisa Custom Club de Golf (Test)`.
|
||||
2. **Mandar a Maquilar:** Confirmar la Orden de Compra (PO) a `Fábrica China Test`.
|
||||
3. **Validar Envío de Insumo:** Ir a *Inventario > Operaciones > Resuministro de Subcontratista* y validar la entrega de 7.5 metros de `Tela Azul Premium` hacia la fábrica.
|
||||
4. **Recibir el Producto Final:** Volver a la Orden de Compra y recibir las 5 camisas.
|
||||
5. **Entregar al Cliente Final:** Volver a la Cotización original (SO) y validar la entrega al cliente.
|
||||
|
||||
*Durante todo este flujo, Shopify permanece 100% aislado.*
|
||||
Reference in New Issue
Block a user