8.6 KiB
MODELO DE DOMINIO: Ventas
Módulos: MGN-007 (Ventas Básico) Fecha: 2025-11-24 Referencia Odoo: sale Referencia Gamilit: sales_management schema
Diagrama de Entidades (Texto UML)
[SaleOrder]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- partner_id: UUID (FK)
- name: String
- order_date: Date
- validity_date: Date
- expected_date: Date
- status: ENUM (draft, sent, sale, done, cancelled)
- amount_total: Decimal
- amount_invoiced: Decimal
- invoice_status: ENUM (to_invoice, invoiced)
- delivery_status: ENUM (to_deliver, delivered)
1 <----> * [SaleOrderLine]
1 <----> * [Invoice]
1 <----> * [Picking]
[SaleOrderLine]
- id: UUID (PK)
- order_id: UUID (FK)
- product_id: UUID (FK)
- description: String
- quantity: Decimal
- price_unit: Decimal
- discount: Decimal
- tax_ids: UUID[]
- subtotal: Decimal
- total: Decimal
- analytic_account_id: UUID (FK)
- qty_delivered: Decimal
- qty_invoiced: Decimal
[Quotation]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- partner_id: UUID (FK)
- name: String
- date: Date
- validity_date: Date
- status: ENUM (draft, sent, approved, rejected, converted)
- amount_total: Decimal
- terms_conditions: Text
- signature: String (base64)
- signature_date: Timestamp
1 <----> * [SaleOrder] (conversión)
[PaymentTerm]
- id: UUID (PK)
- tenant_id: UUID (FK)
- name: String
- days: Integer
- description: Text
[PriceList]
- id: UUID (PK)
- tenant_id: UUID (FK)
- name: String
- currency_id: UUID (FK)
- active: Boolean
1 <----> * [PriceListItem]
[PriceListItem]
- id: UUID (PK)
- pricelist_id: UUID (FK)
- product_id: UUID (FK)
- price: Decimal
- min_quantity: Decimal
Entidades Principales
1. SaleOrder (Orden de Venta)
Descripción: Orden de venta confirmada a cliente.
Atributos:
id: UUIDpartner_id: Clientename: Número de orden (ej: "SO001")order_date: Fecha de ordenvalidity_date: Fecha de validez (opcional)expected_date: Fecha esperada de entregastatus: draft, sent, sale, done, cancelledamount_total: Monto totalinvoice_status: to_invoice, invoiceddelivery_status: to_deliver, delivered
Relaciones:
- 1 SaleOrder → N SaleOrderLines
- 1 SaleOrder → N Invoices
- 1 SaleOrder → N Pickings
Patrón Odoo: sale.order Estados:
- draft: Borrador (editable)
- sent: Enviada a cliente
- sale: Confirmada (genera picking)
- done: Completada (entregada y facturada)
- cancelled: Cancelada
2. SaleOrderLine (Línea de Orden de Venta)
Descripción: Línea de producto/servicio en orden de venta.
Atributos:
id: UUIDorder_id: Orden propietariaproduct_id: Productodescription: Descripciónquantity: Cantidad ordenadaprice_unit: Precio unitariodiscount: Descuento (%)tax_ids: Impuestos aplicadossubtotal: Subtotal sin impuestostotal: Total con impuestosqty_delivered: Cantidad entregadaqty_invoiced: Cantidad facturada
Relaciones:
- N SaleOrderLines → 1 SaleOrder
Patrón Odoo: sale.order.line Cálculo: total = ((quantity * price_unit) * (1 - discount/100)) + taxes
3. Quotation (Cotización)
Descripción: Cotización enviada a cliente (pre-orden).
Atributos:
id: UUIDpartner_id: Cliente potencialname: Número de cotizacióndate: Fecha de emisiónvalidity_date: Fecha de expiraciónstatus: draft, sent, approved, rejected, convertedamount_total: Monto totalterms_conditions: Términos y condicionessignature: Firma electrónica (base64)signature_date: Fecha/hora de firma
Relaciones:
- 1 Quotation → 1 SaleOrder (conversión)
Patrón Odoo: sale.order (state=draft/sent) Flujo:
- Crear quotation
- Enviar a cliente (sent)
- Cliente aprueba/firma (approved)
- Convertir a sale order (converted)
4. PaymentTerm (Término de Pago)
Descripción: Condiciones de pago para cliente.
Atributos:
id: UUIDname: Nombre (ej: "30 días")days: Días de plazodescription: Descripción
Relaciones:
- 1 PaymentTerm → N SaleOrders
Patrón Odoo: account.payment.term Términos comunes:
- Inmediato (0 días)
- 15 días
- 30 días
- 60 días
5. PriceList (Lista de Precios)
Descripción: Lista de precios por cliente o segmento.
Atributos:
id: UUIDname: Nombre (ej: "Precio Distribuidor")currency_id: Monedaactive: Activa/Inactiva
Relaciones:
- 1 PriceList → N PriceListItems
- 1 PriceList → N Partners
Patrón Odoo: product.pricelist Uso: Precios diferenciados por tipo de cliente
6. PriceListItem (Item de Lista de Precios)
Descripción: Precio específico de producto en lista.
Atributos:
id: UUIDpricelist_id: Lista propietariaproduct_id: Productoprice: Preciomin_quantity: Cantidad mínima
Relaciones:
- N PriceListItems → 1 PriceList
Patrón Odoo: product.pricelist.item
Reglas de Negocio
RN-SAL-001: Flujo de Estados
- Orden solo puede confirmarse (sale) desde draft o sent
- Una vez en 'sale', no puede volver a draft
- Cancelación posible desde cualquier estado excepto 'done'
RN-SAL-002: Generación Automática de Picking
- Al confirmar orden (status=sale), generar Picking de entrega
- Picking tipo 'outgoing'
- Solo para productos tipo 'storable'
RN-SAL-003: Facturación
- Facturar después de entrega (delivery → invoice)
- Facturar antes de entrega (invoice → delivery)
- Facturación parcial permitida
RN-SAL-004: Control de Cantidades
- qty_delivered: actualizada desde Picking
- qty_invoiced: actualizada desde Invoice
- delivery_status: 'delivered' cuando qty_delivered = quantity
- invoice_status: 'invoiced' cuando qty_invoiced = quantity
RN-SAL-005: Cotización con Firma
- Cotización aprobada requiere firma electrónica
- Firma incluye: canvas signature, timestamp, IP, user_agent
- Firma es inmutable
RN-SAL-006: Validez de Cotización
- Cotización con validity_date vencida no puede confirmarse
- Sistema alerta si cotización está por vencer
RN-SAL-007: Descuentos
- Descuento por línea (0-100%)
- Descuento aplicado antes de impuestos
- Subtotal = (quantity * price_unit) * (1 - discount/100)
Casos de Uso Principales
- UC-SAL-001: Usuario crea cotización y envía a cliente
- UC-SAL-002: Cliente aprueba cotización online (portal)
- UC-SAL-003: Cliente firma cotización electrónicamente
- UC-SAL-004: Usuario convierte cotización a orden de venta
- UC-SAL-005: Sistema genera picking al confirmar orden
- UC-SAL-006: Usuario valida entrega de productos
- UC-SAL-007: Usuario crea factura desde orden
- UC-SAL-008: Usuario consulta reporte de ventas por cliente
Validaciones y Constraints
-- Sale order name único por company
UNIQUE (tenant_id, company_id, name)
-- Cantidades > 0
CHECK (quantity > 0)
CHECK (price_unit >= 0)
-- Descuento entre 0 y 100
CHECK (discount >= 0 AND discount <= 100)
-- qty_delivered <= quantity
CHECK (qty_delivered <= quantity)
-- qty_invoiced <= quantity
CHECK (qty_invoiced <= quantity)
-- validity_date >= date (cotización)
CHECK (validity_date >= date)
Índices Requeridos
CREATE INDEX idx_sale_orders_partner_id ON sales.sale_orders(partner_id);
CREATE INDEX idx_sale_orders_status ON sales.sale_orders(status);
CREATE INDEX idx_sale_orders_order_date ON sales.sale_orders(order_date);
CREATE INDEX idx_sale_order_lines_order_id ON sales.sale_order_lines(order_id);
CREATE INDEX idx_sale_order_lines_product_id ON sales.sale_order_lines(product_id);
CREATE INDEX idx_quotations_partner_id ON sales.quotations(partner_id);
CREATE INDEX idx_quotations_status ON sales.quotations(status);
CREATE INDEX idx_quotations_validity_date ON sales.quotations(validity_date);
Integración con Otros Módulos
Con MGN-005 (Inventario)
- Confirmar SO → genera Picking (outgoing)
- Validar Picking → actualiza qty_delivered
Con MGN-004 (Financiero)
- Crear factura desde SO → copia líneas de SO
- Validar factura → actualiza qty_invoiced
Con MGN-008 (Analítica)
- Líneas de SO pueden tener analytic_account_id
- Al facturar, genera líneas analíticas
Con MGN-009 (CRM)
- Lead convertido → crea Quotation
- Quotation vinculada a Opportunity
Con MGN-013 (Portal)
- Cliente ve quotations en portal
- Cliente aprueba/firma desde portal