Flujo de Negocio: Purchase (Compras)
Modulo: purchase
Modelo Principal: purchase.order
Aplica Workflow: Si
1. Estados de Orden de Compra (state)
| Estado |
Nombre UI |
Descripcion |
Siguiente |
| draft |
RFQ |
Solicitud de cotizacion inicial |
sent, to approve, purchase |
| sent |
RFQ Sent |
RFQ enviada al proveedor |
to approve, purchase |
| to approve |
To Approve |
Pendiente de aprobacion |
purchase, cancel |
| purchase |
Purchase Order |
Orden confirmada |
(cancel via unlock) |
| cancel |
Cancelled |
Orden cancelada |
draft |
2. Diagrama de Transiciones
┌──────────────────┐
│ DRAFT │
│ (RFQ) │
└────────┬─────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
action_rfq_send() button_confirm() button_confirm()
│ (sin aprobacion) (con aprobacion)
▼ │ │
┌──────────────────┐ │ │
│ SENT │ │ │
│ (RFQ Sent) │ │ │
└────────┬─────────┘ │ │
│ │ │
│ button_confirm() │ │
│ │ │
└───────────────────┼──────────────────┤
│ │
▼ ▼
(monto < limite) (monto >= limite)
│ │
│ ┌────────┴────────┐
│ │ TO APPROVE │
│ │ (Pendiente) │
│ └────────┬────────┘
│ │
│ button_approve()
│ │
└────────┬─────────┘
│
▼
┌──────────────────────────────┐
│ PURCHASE │
│ (Purchase Order) │
│ │
│ - Genera recepciones (stock)│
│ - Habilita facturacion │
│ - locked = True (opcional) │
└──────────────┬───────────────┘
│
button_cancel()
(requiere unlock)
│
▼
┌──────────────────┐
│ CANCEL │
│ (Cancelled) │
└────────┬─────────┘
│
button_draft()
│
▼
┌──────────────────┐
│ DRAFT │
│ (Reabierta) │
└──────────────────┘
3. Flujo Completo de Compra
1. CREACION (draft)
└─ Usuario crea purchase.order
└─ Selecciona proveedor (partner_id)
└─ Agrega lineas con productos y cantidades
└─ state = 'draft'
2. ENVIO RFQ (opcional)
└─ action_rfq_send()
└─ Envia correo al proveedor
└─ state = 'sent'
3. CONFIRMACION
└─ button_confirm() llamado
3a. SIN DOBLE VALIDACION:
└─ _approval_allowed() = True
└─ button_approve() ejecutado automatico
└─ state = 'purchase'
3b. CON DOBLE VALIDACION (monto > limite):
└─ _approval_allowed() = False
└─ state = 'to approve'
└─ Requiere gerente
4. APROBACION (si aplica)
└─ button_approve()
└─ Verifica permisos
└─ state = 'purchase'
└─ date_approve = now()
5. RECEPCION (integracion stock)
└─ Genera stock.picking automaticamente
└─ Operario recibe productos
└─ qty_received actualizado en lineas
6. FACTURACION
└─ Proveedor envia factura
└─ Vincula factura con PO
└─ qty_invoiced actualizado
└─ invoice_status = 'invoiced'
4. Metodos de Transicion
| Metodo |
De Estado |
A Estado |
Descripcion |
| button_confirm() |
draft/sent |
to approve/purchase |
Confirma orden |
| button_approve() |
to approve |
purchase |
Aprueba orden |
| button_cancel() |
* (no purchase locked) |
cancel |
Cancela |
| button_draft() |
cancel |
draft |
Vuelve a borrador |
| action_rfq_send() |
draft |
sent |
Envia RFQ |
| button_unlock() |
purchase |
purchase (unlocked) |
Desbloquea |
5. Reglas de Negocio
| ID |
Regla |
Validacion |
Mensaje |
| R1 |
Proveedor requerido |
partner_id presente |
Proveedor requerido |
| R2 |
Lineas requeridas |
order_line no vacio |
Agregue al menos una linea |
| R3 |
Producto valido |
product_id empresa compatible |
Producto de otra empresa |
| R4 |
Cantidad positiva |
product_qty > 0 |
Cantidad debe ser positiva |
| R5 |
Aprobacion limite |
amount_total vs limite |
Requiere aprobacion |
6. Flujo de Doble Validacion
CONFIGURACION (res.config.settings)
│
├─ po_lock = 'lock' | 'edit'
├─ po_double_validation = 'one_step' | 'two_step'
└─ po_double_validation_amount = monto_limite
│
│
EVALUACION EN button_confirm()
│
├─ _approval_allowed():
│ │
│ ├─ Si po_double_validation == 'one_step':
│ │ └─ return True (sin aprobacion)
│ │
│ └─ Si po_double_validation == 'two_step':
│ └─ return amount_total < limite
│ OR user tiene permiso manager
│
└─ Resultado:
├─ True → state = 'purchase'
└─ False → state = 'to approve'
7. Integracion con Stock
CONFIRMACION (state → purchase)
│
├─ Genera stock.picking automaticamente
│ └─ picking_type_id = Recepciones
│ └─ partner_id = Proveedor
│ └─ location_dest_id = Stock
│
├─ Por cada purchase.order.line:
│ └─ Crea stock.move
│ └─ product_id
│ └─ product_uom_qty = product_qty
│ └─ purchase_line_id = line.id
│
RECEPCION (en stock)
│
├─ Operario valida picking
├─ stock.move → done
└─ purchase.order.line.qty_received actualizado
8. Integracion con Facturacion
CREACION DE FACTURA
│
├─ Desde PO: action_create_invoice()
│ └─ Crea account.move tipo 'in_invoice'
│ └─ Vincula lineas de factura con POL
│
├─ Desde Factura entrante:
│ └─ purchase.bill.line.match
│ └─ Matching automatico o manual
│
ACTUALIZACION
│
├─ qty_invoiced calculado de lineas factura
├─ invoice_status recalculado:
│ ├─ 'no' = nada que facturar
│ ├─ 'to invoice' = pendiente
│ └─ 'invoiced' = todo facturado
9. Acciones Automaticas
| Trigger |
Accion |
Condicion |
| button_confirm |
Generar nombre secuencial |
Si name = 'New' |
| button_approve |
Establecer date_approve |
Siempre |
| button_approve |
Crear recepciones stock |
Si integracion activa |
| Linea modificada |
Recalcular totales |
Siempre |
| Recepcion stock |
Actualizar qty_received |
Automatico |
10. Permisos por Estado
| Estado |
Editable |
Grupos |
| draft |
Si |
purchase.group_purchase_user |
| sent |
Si |
purchase.group_purchase_user |
| to approve |
Parcial |
purchase.group_purchase_manager |
| purchase |
No (locked) |
purchase.group_purchase_manager (unlock) |
| cancel |
No |
purchase.group_purchase_user (reopen) |
11. Flujo de Estados de Facturacion
PO CONFIRMADA (state = purchase)
│
├─ invoice_status = 'no'
│ └─ Nada recibido aun
│
├─ Recepcion parcial:
│ └─ qty_received > 0
│ └─ invoice_status = 'to invoice'
│
├─ Factura parcial:
│ └─ qty_invoiced < qty_received
│ └─ invoice_status = 'to invoice'
│
└─ Todo facturado:
└─ qty_invoiced >= qty_received
└─ invoice_status = 'invoiced'
Referencias:
- purchase_order.py: button_confirm, button_approve, button_cancel
- Integracion stock: purchase_stock/
- Integracion account: account_move.py