mirror of
https://github.com/cursos-uai/sap_tfi_2026.git
synced 2026-07-31 20:48:30 -03:00
feat(initial-iteration): primera iteración ICONIX del flujo venta→factura→pago
Documentación generada: - 7 casos de uso (CU-VEN-001, CU-VEN-004, CU-ENT-002, CU-ENT-004, CU-FAC-001, CU-FAC-002, CU-FAC-003) - Modelo de dominio inicial (12 conceptos, 9 reglas de negocio) - Arquitectura general (C4 contexto + contenedores) - Prototipo del formulario de presupuesto - 5 diagramas PlantUML (.puml): - Diagrama general de casos de uso - Modelo de dominio conceptual - Diagrama de robustez de CU-VEN-004 - Diagrama de secuencia de CU-VEN-004 - Diagrama de clases técnicas (integración Venta/Stock/Contabilidad) - Matriz de trazabilidad con 20 EV-COD y 22 EV-INF Odoo analizado: 19.0 Community (rama 19.0) Método: ingeniería inversa con verificación de código fuente Nota: NO pushear (gate S2). Ale debe revisar antes de merge a main.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
@startuml D-CLA-CON-GEN-001 — Modelo de Dominio (Conceptual)
|
||||
|
||||
title SAP-TFI-2026 — Modelo de Dominio Conceptual
|
||||
|
||||
skinparam shadowing false
|
||||
skinparam handwritten false
|
||||
skinparam defaultFontName Arial
|
||||
skinparam defaultFontSize 11
|
||||
skinparam linetype ortho
|
||||
skinparam backgroundColor white
|
||||
skinparam classAttributeIconSize 0
|
||||
|
||||
' ─── Conceptos del dominio (separados de clases técnicas Odoo) ───
|
||||
|
||||
class "Cliente" as C {
|
||||
+nombre: String
|
||||
+direccion: String
|
||||
+lista_precios: PriceList
|
||||
+condicion_pago: PaymentTerm
|
||||
}
|
||||
|
||||
class "Producto" as P {
|
||||
+nombre: String
|
||||
+descripcion: String
|
||||
+precio: Money
|
||||
+categoria: Category
|
||||
+impuestos: Tax*
|
||||
}
|
||||
|
||||
class "Presupuesto" as Q {
|
||||
+nombre: String
|
||||
+fecha: DateTime
|
||||
+estado: QuotationState
|
||||
+lineas: OrderLine*
|
||||
+total: Money
|
||||
}
|
||||
|
||||
class "PedidoVenta" as O {
|
||||
+nombre: String
|
||||
+fecha_confirmacion: DateTime
|
||||
+estado: OrderState
|
||||
+estado_facturacion: InvoiceStatus
|
||||
+estado_entrega: DeliveryStatus
|
||||
+lineas: OrderLine*
|
||||
+total: Money
|
||||
}
|
||||
|
||||
class "LineaPedido" as OL {
|
||||
+producto: Producto
|
||||
+cantidad: Float
|
||||
+unidad: Unit
|
||||
+precio_unitario: Money
|
||||
+descuento: Float
|
||||
+impuestos: Tax*
|
||||
+subtotal: Money
|
||||
}
|
||||
|
||||
class "Transferencia" as T {
|
||||
+nombre: String
|
||||
+estado: PickingState
|
||||
+origen: Warehouse
|
||||
+destino: Warehouse
|
||||
+lineas: MoveLine*
|
||||
}
|
||||
|
||||
class "LineaMovimiento" as ML {
|
||||
+producto: Producto
|
||||
+cantidad: Float
|
||||
+cantidad_reservada: Float
|
||||
+cantidad_entregada: Float
|
||||
+estado: MoveState
|
||||
}
|
||||
|
||||
class "Factura" as I {
|
||||
+numero: String
|
||||
+fecha: Date
|
||||
+estado: InvoiceState
|
||||
+estado_pago: PaymentState
|
||||
+cliente: Cliente
|
||||
+lineas: InvoiceLine*
|
||||
+total: Money
|
||||
}
|
||||
|
||||
class "LineaFactura" as IL {
|
||||
+producto: Producto
|
||||
+cantidad: Float
|
||||
+precio_unitario: Money
|
||||
+impuestos: Tax*
|
||||
+subtotal: Money
|
||||
+cuenta_contable: Account
|
||||
}
|
||||
|
||||
class "Pago" as Pm {
|
||||
+fecha: Date
|
||||
+monto: Money
|
||||
+metodo: PaymentMethod
|
||||
+diario: Journal
|
||||
+factura: Factura
|
||||
}
|
||||
|
||||
class "Almacen" as W {
|
||||
+nombre: String
|
||||
+codigo: String
|
||||
+direccion: String
|
||||
}
|
||||
|
||||
class "Ubicacion" as L {
|
||||
+nombre: String
|
||||
+almacen: Almacen
|
||||
+tipo: LocationType
|
||||
}
|
||||
|
||||
' ─── Relaciones ───
|
||||
|
||||
Cliente "1" --> "*" Presupuesto : solicita
|
||||
Cliente "1" --> "*" PedidoVenta : compra
|
||||
Cliente "1" --> "*" Factura : recibe
|
||||
Presupuesto "1" --> "0..1" PedidoVenta : se convierte en
|
||||
PedidoVenta "1" --> "*" LineaPedido : contiene
|
||||
PedidoVenta "1" --> "*" Transferencia : genera
|
||||
PedidoVenta "1" --> "*" Factura : origina
|
||||
Producto "1" --> "*" LineaPedido : aparece en
|
||||
LineaPedido "1" --> "*" LineaMovimiento : se convierte en
|
||||
Transferencia "1" --> "*" LineaMovimiento : contiene
|
||||
Almacen "1" --> "*" Ubicacion : tiene
|
||||
Transferencia "*" --> "2" Almacen : origen/destino
|
||||
Factura "1" --> "*" LineaFactura : contiene
|
||||
Factura "1" --> "*" Pago : recibe
|
||||
LineaPedido "1" --> "*" LineaFactura : se factura en
|
||||
|
||||
legend right
|
||||
Proyecto: SAP-TFI-2026
|
||||
Agente: saptfi2026
|
||||
Metodología: ICONIX
|
||||
Fuente: Ingeniería inversa de Odoo 19.0
|
||||
Modelo conceptual (separado del técnico)
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,111 @@
|
||||
@startuml D-CLA-INT-001 — Diagrama de Clases: Integración Venta/Stock/Contabilidad
|
||||
|
||||
title SAP-TFI-2026 — Diagrama de Clases Técnicas (Integración Venta/Stock/Contabilidad)
|
||||
|
||||
skinparam shadowing false
|
||||
skinparam handwritten false
|
||||
skinparam defaultFontName Arial
|
||||
skinparam defaultFontSize 11
|
||||
skinparam linetype ortho
|
||||
skinparam backgroundColor white
|
||||
|
||||
' ─── sale.order ───
|
||||
class "<sale.order>" as SO {
|
||||
+_name = "sale.order"
|
||||
+_inherit = ["portal.mixin", "mail.thread", ...]
|
||||
--
|
||||
+name: Char
|
||||
+partner_id: Many2one(res.partner)
|
||||
+state: Selection
|
||||
+invoice_status: Selection
|
||||
+amount_untaxed: Monetary
|
||||
+amount_total: Monetary
|
||||
--
|
||||
+action_confirm()
|
||||
+action_quotation_send()
|
||||
+_create_invoices()
|
||||
}
|
||||
|
||||
' ─── sale.order.line ───
|
||||
class "<sale.order.line>" as SOL {
|
||||
+_name = "sale.order.line"
|
||||
--
|
||||
+order_id: Many2one(sale.order)
|
||||
+product_id: Many2one(product.product)
|
||||
+product_uom_qty: Float
|
||||
+price_unit: Float
|
||||
+discount: Float
|
||||
+price_subtotal: Monetary
|
||||
}
|
||||
|
||||
' ─── stock.picking ───
|
||||
class "<stock.picking>" as SP {
|
||||
+_name = "stock.picking"
|
||||
+_inherit = ["mail.thread"]
|
||||
--
|
||||
+name: Char
|
||||
+partner_id: Many2one(res.partner)
|
||||
+state: Selection
|
||||
+picking_type_id: Many2one(stock.picking.type)
|
||||
--
|
||||
+action_confirm()
|
||||
+action_assign()
|
||||
+button_validate()
|
||||
}
|
||||
|
||||
' ─── stock.move ───
|
||||
class "<stock.move>" as SM {
|
||||
+_name = "stock.move"
|
||||
--
|
||||
+picking_id: Many2one(stock.picking)
|
||||
+product_id: Many2one(product.product)
|
||||
+product_uom_qty: Float
|
||||
+state: Selection
|
||||
--
|
||||
+action_confirm()
|
||||
}
|
||||
|
||||
' ─── account.move ───
|
||||
class "<account.move>" as AM {
|
||||
+_name = "account.move"
|
||||
--
|
||||
+name: Char
|
||||
+partner_id: Many2one(res.partner)
|
||||
+move_type: Selection
|
||||
+state: Selection
|
||||
+invoice_date: Date
|
||||
+payment_state: Selection
|
||||
--
|
||||
+action_post()
|
||||
+action_register_payment()
|
||||
}
|
||||
|
||||
' ─── account.move.line ───
|
||||
class "<account.move.line>" as AML {
|
||||
+_name = "account.move.line"
|
||||
--
|
||||
+move_id: Many2one(account.move)
|
||||
+product_id: Many2one(product.product)
|
||||
+quantity: Float
|
||||
+price_unit: Float
|
||||
+price_subtotal: Monetary
|
||||
}
|
||||
|
||||
' ─── Relaciones ───
|
||||
SO "1" *-- "*" SOL : order_line
|
||||
SO "1" *-- "*" AM : invoice_ids
|
||||
SP "*" --> "1" SO : sale_id
|
||||
SP "1" *-- "*" SM : move_ids
|
||||
SM "*" --> "1" SOL : sale_line_id
|
||||
AM "1" *-- "*" AML : line_ids
|
||||
AM "*" --> "1" SOL : invoice_line_ids
|
||||
|
||||
legend right
|
||||
Proyecto: SAP-TFI-2026
|
||||
Agente: saptfi2026
|
||||
Metodología: ICONIX
|
||||
Fuente: Ingeniería inversa de Odoo 19.0
|
||||
Solo campos y métodos relevantes para el flujo de venta
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,57 @@
|
||||
@startuml D-CU-GEN-001 — Diagrama General de Casos de Uso
|
||||
|
||||
title SAP-TFI-2026 — Casos de Uso del Flujo Principal
|
||||
|
||||
skinparam shadowing false
|
||||
skinparam handwritten false
|
||||
skinparam defaultFontName Arial
|
||||
skinparam defaultFontSize 12
|
||||
skinparam linetype ortho
|
||||
skinparam backgroundColor white
|
||||
|
||||
left to right direction
|
||||
skinparam actorStyle awesome
|
||||
|
||||
actor "Vendedor" as V
|
||||
actor "Operario\nde Almacén" as OA
|
||||
actor "Facturador" as F
|
||||
|
||||
rectangle "Módulo sale" {
|
||||
usecase "CU-VEN-001\nCrear presupuesto" as CU1
|
||||
usecase "CU-VEN-004\nConfirmar pedido" as CU4
|
||||
}
|
||||
|
||||
rectangle "Módulo stock" {
|
||||
usecase "CU-ENT-002\nReservar productos" as CU2
|
||||
usecase "CU-ENT-004\nValidar entrega" as CU3
|
||||
}
|
||||
|
||||
rectangle "Módulo account" {
|
||||
usecase "CU-FAC-001\nCrear factura" as CU5
|
||||
usecase "CU-FAC-002\nPublicar factura" as CU6
|
||||
usecase "CU-FAC-003\nRegistrar pago" as CU7
|
||||
}
|
||||
|
||||
V --> CU1
|
||||
V --> CU4
|
||||
OA --> CU2
|
||||
OA --> CU3
|
||||
F --> CU5
|
||||
F --> CU6
|
||||
F --> CU7
|
||||
|
||||
CU1 ..> CU4 : <<flujo>>
|
||||
CU4 ..> CU2 : <<dispara>>
|
||||
CU2 ..> CU3 : <<precondición>>
|
||||
CU3 ..> CU5 : <<opcionalmente>>
|
||||
CU5 ..> CU6 : <<flujo>>
|
||||
CU6 ..> CU7 : <<flujo>>
|
||||
|
||||
legend right
|
||||
Proyecto: SAP-TFI-2026
|
||||
Agente: saptfi2026
|
||||
Metodología: ICONIX
|
||||
Fuente: Ingeniería inversa de Odoo 19.0
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,60 @@
|
||||
@startuml D-ROB-VEN-004 — Diagrama de Robustez: Confirmar Pedido
|
||||
|
||||
title SAP-TFI-2026 — Diagrama de Robustez: Confirmar Pedido de Venta (CU-VEN-004)
|
||||
|
||||
skinparam shadowing false
|
||||
skinparam handwritten false
|
||||
skinparam defaultFontName Arial
|
||||
skinparam defaultFontSize 12
|
||||
skinparam linetype ortho
|
||||
skinparam backgroundColor white
|
||||
|
||||
' Boundary = vistas, formularios
|
||||
' Control = coordinadores
|
||||
' Entity = objetos persistentes
|
||||
|
||||
actor "Vendedor" as V
|
||||
|
||||
boundary "view_sale_order_form\n(form de pedido)" as B_Form
|
||||
boundary "Wiz. Validación" as B_Wiz
|
||||
|
||||
control "SaleOrder\n(action_confirm)" as C_SO
|
||||
control "Validator\n(_confirmation_error_message)" as C_Val
|
||||
control "Confirmation\nValues\n(_prepare_confirmation_values)" as C_CV
|
||||
control "Stock\n(_action_confirm)" as C_Stk
|
||||
control "Invoice\n(_create_invoices)" as C_Inv
|
||||
|
||||
entity "sale.order" as E_SO
|
||||
entity "sale.order.line" as E_Line
|
||||
entity "stock.picking" as E_Pick
|
||||
entity "account.move" as E_Move
|
||||
|
||||
V --> B_Form : 1. Click "Confirmar"
|
||||
B_Form --> C_SO : 2. Invoca action_confirm
|
||||
C_SO --> C_Val : 3. Valida pedido
|
||||
C_Val --> E_SO : 4. Lee estado y líneas
|
||||
C_Val --> E_Line : 5. Lee líneas
|
||||
C_Val --> C_SO : 6. OK / error
|
||||
|
||||
alt Si OK
|
||||
C_SO --> C_CV : 7. Prepara valores
|
||||
C_CV --> E_SO : 8. Write state='sale', date_order
|
||||
C_SO --> C_Stk : 9. _action_confirm (stock)
|
||||
C_Stk --> E_Pick : 10. Crea picking
|
||||
C_SO --> C_Inv : 11. _create_invoices (opcional)
|
||||
C_Inv --> E_Move : 12. Crea factura
|
||||
C_SO --> B_Form : 13. Retorna OK
|
||||
else Si error
|
||||
C_Val --> B_Form : 6b. Muestra error
|
||||
end
|
||||
|
||||
B_Form --> V : 14. Muestra resultado (estado actualizado)
|
||||
|
||||
legend right
|
||||
Proyecto: SAP-TFI-2026
|
||||
Agente: saptfi2026
|
||||
Metodología: ICONIX
|
||||
Fuente: Ingeniería inversa de Odoo 19.0
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,80 @@
|
||||
@startuml D-SEC-VEN-004 — Diagrama de Secuencia: Confirmar Pedido
|
||||
|
||||
title SAP-TFI-2026 — Diagrama de Secuencia: Confirmar Pedido de Venta (CU-VEN-004)
|
||||
|
||||
skinparam shadowing false
|
||||
skinparam handwritten false
|
||||
skinparam defaultFontName Arial
|
||||
skinparam defaultFontSize 12
|
||||
skinparam linetype ortho
|
||||
skinparam backgroundColor white
|
||||
|
||||
actor "Vendedor" as V
|
||||
participant "Form\n(view_sale_order_form)" as Form
|
||||
participant "SaleOrder\n(action_confirm)" as SO
|
||||
participant "Validator\n(_confirmation_error_message)" as Val
|
||||
participant "Conf. Values\n(_prepare_confirmation_values)" as CV
|
||||
participant "Stock Layer\n(_action_confirm)" as Stock
|
||||
participant "Invoice Layer\n(_create_invoices)" as Inv
|
||||
database "PostgreSQL" as DB
|
||||
|
||||
V -> Form : 1. Click "Confirmar"
|
||||
activate Form
|
||||
|
||||
Form -> SO : 2. action_confirm()
|
||||
activate SO
|
||||
|
||||
SO -> Val : 3. _confirmation_error_message()
|
||||
activate Val
|
||||
Val -> DB : 4. SELECT state, lines
|
||||
DB --> Val : 5. estado + líneas
|
||||
alt Si estado OK y líneas OK
|
||||
Val --> SO : 6a. error_msg = None (OK)
|
||||
else Si error
|
||||
Val --> SO : 6b. error_msg (UserError)
|
||||
SO --> Form : 7b. raise UserError
|
||||
Form --> V : 8b. Muestra error
|
||||
end
|
||||
deactivate Val
|
||||
|
||||
SO -> DB : 9. SELECT order_line for analytic validation
|
||||
DB --> SO : 10. líneas
|
||||
|
||||
SO -> CV : 11. _prepare_confirmation_values()
|
||||
activate CV
|
||||
CV --> SO : 12. {'state': 'sale', 'date_order': now}
|
||||
deactivate CV
|
||||
|
||||
SO -> DB : 13. UPDATE sale.order SET state='sale', date_order=...
|
||||
DB --> SO : 14. OK
|
||||
|
||||
SO -> Stock : 15. _action_confirm()
|
||||
activate Stock
|
||||
Stock -> DB : 16. INSERT stock.picking, stock.move
|
||||
DB --> Stock : 17. OK
|
||||
Stock --> SO : 18. pickings creados
|
||||
deactivate Stock
|
||||
|
||||
opt Si auto-factura configurada
|
||||
SO -> Inv : 19. _create_invoices()
|
||||
activate Inv
|
||||
Inv -> DB : 20. INSERT account.move
|
||||
DB --> Inv : 21. OK
|
||||
Inv --> SO : 22. factura creada
|
||||
deactivate Inv
|
||||
end
|
||||
|
||||
SO --> Form : 23. return True
|
||||
deactivate SO
|
||||
|
||||
Form --> V : 24. Estado actualizado a "sale"
|
||||
deactivate Form
|
||||
|
||||
legend right
|
||||
Proyecto: SAP-TFI-2026
|
||||
Agente: saptfi2026
|
||||
Metodología: ICONIX
|
||||
Fuente: Ingeniería inversa de Odoo 19.0
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
Reference in New Issue
Block a user