Flujo de Negocio: Sale (Ventas)
Modulo: sale
Modelo Principal: sale.order
Aplica Workflow: Si
1. Estados de Orden de Venta (state)
| Estado |
Nombre UI |
Descripcion |
Siguiente |
| draft |
Quotation |
Cotizacion inicial |
sent, sale |
| sent |
Quotation Sent |
Cotizacion enviada al cliente |
sale, cancel |
| sale |
Sales Order |
Orden confirmada |
cancel |
| cancel |
Cancelled |
Orden cancelada |
draft |
2. Diagrama de Transiciones
┌──────────────────┐
│ DRAFT │
│ (Quotation) │
└────────┬─────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
action_quotation_send() │ action_confirm()
│ │ │
▼ │ │
┌──────────────────┐ │ │
│ SENT │ │ │
│ (Quotation Sent) │ │ │
└────────┬─────────┘ │ │
│ │ │
│ action_confirm() │ │
│ (firma/pago opt) │ │
│ │ │
└───────────────────┴──────────────────┘
│
▼
┌───────────────────────────────────────┐
│ │
│ SALE │
│ (Sales Order) │
│ │
│ - Genera entregas (sale_stock) │
│ - Habilita facturacion │
│ - locked = True (opcional) │
│ │
└───────────────────┬───────────────────┘
│
action_cancel()
(requiere unlock)
│
▼
┌──────────────────┐
│ CANCEL │
│ (Cancelled) │
└────────┬─────────┘
│
action_draft()
│
▼
┌──────────────────┐
│ DRAFT │
│ (Reabierta) │
└──────────────────┘
3. Flujo Completo de Venta
1. CREACION (draft)
└─ Usuario crea sale.order
└─ Selecciona cliente (partner_id)
└─ Sistema calcula direcciones (invoice/shipping)
└─ Agrega lineas con productos
└─ state = 'draft'
2. ENVIO COTIZACION (opcional)
└─ action_quotation_send()
└─ Envia correo al cliente
└─ state = 'sent'
└─ Cliente puede ver en portal
3. VALIDACION PRE-CONFIRMACION (si configurado)
3a. FIRMA ONLINE (require_signature = True):
└─ Cliente firma en portal
└─ signature, signed_by, signed_on guardados
3b. PAGO ONLINE (require_payment = True):
└─ Cliente paga anticipo (prepayment_percent)
└─ payment.transaction creada
└─ amount_paid actualizado
4. CONFIRMACION
└─ action_confirm()
└─ _action_confirm() ejecutado
└─ state = 'sale'
└─ date_order = now() (si era draft)
└─ name genera secuencia si 'New'
5. ENTREGA (integracion sale_stock)
└─ Genera stock.picking automaticamente
└─ Operario prepara y envia
└─ qty_delivered actualizado en lineas
6. FACTURACION
└─ _create_invoices()
└─ account.move creado tipo 'out_invoice'
└─ invoice_status actualizado
4. Metodos de Transicion
| Metodo |
De Estado |
A Estado |
Descripcion |
| action_confirm() |
draft/sent |
sale |
Confirma orden |
| action_cancel() |
* |
cancel |
Cancela orden |
| action_draft() |
cancel |
draft |
Vuelve a borrador |
| action_quotation_send() |
draft |
sent |
Envia cotizacion |
| action_lock() |
sale |
sale (locked) |
Bloquea |
| action_unlock() |
sale (locked) |
sale |
Desbloquea |
5. Reglas de Negocio
| ID |
Regla |
Validacion |
Mensaje |
| R1 |
Cliente requerido |
partner_id presente |
Cliente requerido |
| R2 |
Lineas requeridas |
order_line no vacio |
Agregue productos |
| R3 |
Fecha confirmacion |
date_order si state='sale' |
Fecha requerida |
| R4 |
Productos activos |
Sin productos archivados |
Producto archivado |
| R5 |
Firma requerida |
signature si require_signature |
Firma pendiente |
| R6 |
Pago requerido |
amount_paid >= prepayment si require_payment |
Pago pendiente |
6. Flujo de Firma y Pago Online
COTIZACION ENVIADA (state = sent)
│
├─ require_signature = True?
│ │
│ ├─ SI: Cliente debe firmar en portal
│ │ └─ /my/orders/<id>/accept
│ │ └─ POST con firma en base64
│ │ └─ sale.order.signature = firma
│ │
│ └─ NO: Continua sin firma
│
├─ require_payment = True?
│ │
│ ├─ SI: Cliente debe pagar anticipo
│ │ └─ /my/orders/<id>/transaction
│ │ └─ prepayment_percent del total
│ │ └─ payment.transaction creada
│ │ └─ Estado: done/authorized
│ │
│ └─ NO: Continua sin pago
│
└─ Condiciones cumplidas:
└─ action_confirm() disponible
└─ O confirmacion automatica
7. Integracion con Inventario (sale_stock)
CONFIRMACION (state → sale)
│
├─ sale_stock genera stock.picking
│ └─ picking_type_id = Envios
│ └─ partner_id = Cliente
│ └─ location_dest_id = Customer Location
│
├─ Por cada sale.order.line:
│ └─ Crea stock.move
│ └─ product_id
│ └─ product_uom_qty
│ └─ sale_line_id = line.id
│
ENVIO (en stock)
│
├─ Operario prepara picking
├─ stock.move → done
└─ sale.order.line.qty_delivered actualizado
8. Flujo de Facturacion
CREAR FACTURA
│
├─ Wizard: sale.advance.payment.inv
│ │
│ ├─ advance_payment_method = 'delivered':
│ │ └─ Factura por cantidades entregadas
│ │ └─ qty_to_invoice = qty_delivered - qty_invoiced
│ │
│ ├─ advance_payment_method = 'percentage':
│ │ └─ Factura anticipo (% del total)
│ │ └─ Linea tipo downpayment
│ │
│ └─ advance_payment_method = 'fixed':
│ └─ Factura anticipo (monto fijo)
│ └─ Linea tipo downpayment
│
├─ _create_invoices()
│ └─ account.move tipo 'out_invoice'
│ └─ Lineas vinculadas a sale.order.line
│
ACTUALIZACION ESTADO
│
├─ invoice_status recalculado:
│ ├─ 'no' = nada que facturar
│ ├─ 'to invoice' = pendiente
│ ├─ 'invoiced' = todo facturado
│ └─ 'upselling' = oportunidad upselling
9. Acciones Automaticas
| Trigger |
Accion |
Condicion |
| action_confirm |
Generar nombre secuencial |
Si name = 'New' |
| action_confirm |
Establecer date_order |
Si era draft |
| action_confirm |
Crear entregas |
Si sale_stock instalado |
| Linea modificada |
Recalcular totales |
Siempre |
| Entrega completada |
Actualizar qty_delivered |
Automatico |
| Pago autorizado |
Confirmar orden |
Si autoconfirm |
10. Permisos por Estado
| Estado |
Editable |
Grupos |
| draft |
Si |
sales_team.group_sale_salesman |
| sent |
Si |
sales_team.group_sale_salesman |
| sale |
No (locked) |
sales_team.group_sale_manager (unlock) |
| cancel |
No |
sales_team.group_sale_salesman (reopen) |
11. Flujo de Estados de Facturacion
SO CONFIRMADA (state = sale)
│
├─ invoice_status = 'no'
│ └─ Nada entregado aun
│ └─ O productos sin factura (service invoice='manual')
│
├─ Entrega realizada:
│ └─ qty_delivered > 0
│ └─ invoice_status = 'to invoice'
│
├─ Upselling detectado:
│ └─ qty_delivered > qty_invoiced
│ └─ Politica = 'order'
│ └─ invoice_status = 'upselling'
│
├─ Factura parcial:
│ └─ qty_invoiced < qty_delivered
│ └─ invoice_status = 'to invoice'
│
└─ Todo facturado:
└─ qty_invoiced >= qty_to_invoice
└─ invoice_status = 'invoiced'
12. Constraint de Base de Datos
-- Orden confirmada requiere fecha
CHECK(
(state = 'sale' AND date_order IS NOT NULL)
OR state != 'sale'
)
Referencias:
- sale_order.py: action_confirm, action_cancel, _create_invoices
- Integracion stock: sale_stock/
- Wizard factura: sale_make_invoice_advance.py