🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
551 lines
15 KiB
Markdown
551 lines
15 KiB
Markdown
# FASE 5: Refinamiento del Plan de Correcciones
|
|
|
|
**Fecha:** 2026-01-04
|
|
**Objetivo:** Refinar plan con scripts de migracion, tests y rollback
|
|
**Estado:** Completado
|
|
**Basado en:** FASE-4 (Validacion de Dependencias)
|
|
|
|
---
|
|
|
|
## 1. Plan de Ejecucion Refinado
|
|
|
|
### 1.1 Batch 1: Foundation (Correcciones Independientes)
|
|
|
|
| Orden | Correccion | Archivo | Tipo Cambio | Riesgo |
|
|
|-------|------------|---------|-------------|--------|
|
|
| 1.1 | COR-001 | 06-purchase.sql | ALTER TYPE | MEDIO |
|
|
| 1.2 | COR-002 | 05-inventory.sql | ALTER TYPE | MEDIO |
|
|
| 1.3 | COR-004 | 04-financial.sql | ALTER TABLE + TYPE | MEDIO |
|
|
| 1.4 | COR-005 | 04-financial.sql | CREATE TABLE | BAJO |
|
|
| 1.5 | COR-006 | 07-sales.sql | ALTER TABLE | BAJO |
|
|
| 1.6 | COR-007 | 05-inventory.sql | CREATE TABLE + ALTER | BAJO |
|
|
| 1.7 | COR-008 | 05-inventory.sql | CREATE TABLEs | BAJO |
|
|
| 1.8 | COR-010 | 07-sales.sql, 06-purchase.sql | ALTER TABLE | BAJO |
|
|
| 1.9 | COR-011 | 07-sales.sql, 06-purchase.sql | ALTER TABLE | BAJO |
|
|
|
|
### 1.2 Batch 2: Dependencias Nivel 1
|
|
|
|
| Orden | Correccion | Depende De | Archivo | Tipo Cambio |
|
|
|-------|------------|------------|---------|-------------|
|
|
| 2.1 | COR-003 | COR-002 | 05-inventory.sql | CREATE TABLE |
|
|
| 2.2 | COR-009 | COR-001 | 06-purchase.sql | CREATE FUNCTION |
|
|
| 2.3 | COR-012 | COR-006 | 07-sales.sql | ALTER TABLE |
|
|
|
|
### 1.3 Batch 3: Dependencias Nivel 2
|
|
|
|
| Orden | Correccion | Depende De | Archivo | Tipo Cambio |
|
|
|-------|------------|------------|---------|-------------|
|
|
| 3.1 | COR-013 | COR-004 | 04-financial.sql | CREATE TABLEs |
|
|
| 3.2 | COR-018 | COR-002, COR-003 | 05-inventory.sql | CREATE FUNCTION |
|
|
|
|
### 1.4 Batch 4: Features Avanzados
|
|
|
|
| Orden | Correccion | Archivo | Tipo Cambio |
|
|
|-------|------------|---------|-------------|
|
|
| 4.1 | COR-014 | 11-crm.sql | CREATE TABLE + ALTER |
|
|
| 4.2 | COR-015 | 03-analytics.sql | ALTER + CREATE |
|
|
| 4.3 | COR-016 | 08-projects.sql | ALTER + CREATE |
|
|
| 4.4 | COR-017 | 08-projects.sql | ALTER TABLE |
|
|
| 4.5 | COR-019 | 11-crm.sql | CREATE TABLE |
|
|
| 4.6 | COR-020 | 02-core.sql | CREATE TABLE + FUNCTION |
|
|
|
|
---
|
|
|
|
## 2. Scripts de Migracion
|
|
|
|
### 2.1 Migration: COR-001 (PO States)
|
|
|
|
```sql
|
|
-- Migration: 20260104_001_po_to_approve_state.sql
|
|
-- Correccion: COR-001
|
|
-- Descripcion: Agregar estado 'to_approve' a purchase orders
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Agregar nuevo valor al ENUM
|
|
ALTER TYPE purchase.order_status ADD VALUE IF NOT EXISTS 'to_approve' BEFORE 'confirmed';
|
|
|
|
-- 2. Renombrar 'confirmed' a 'purchase' (Odoo naming)
|
|
-- Nota: PostgreSQL no permite renombrar valores de ENUM directamente
|
|
-- Se debe crear nuevo tipo si se requiere renombrar
|
|
|
|
-- 3. Agregar campos de aprobacion
|
|
ALTER TABLE purchase.purchase_orders
|
|
ADD COLUMN IF NOT EXISTS approval_required BOOLEAN DEFAULT FALSE,
|
|
ADD COLUMN IF NOT EXISTS amount_approval_threshold DECIMAL(15, 2);
|
|
|
|
-- 4. Actualizar comentarios
|
|
COMMENT ON COLUMN purchase.purchase_orders.approval_required IS
|
|
'Indica si la PO requiere aprobacion segun threshold';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 2.2 Migration: COR-002 (Move States)
|
|
|
|
```sql
|
|
-- Migration: 20260104_002_move_states.sql
|
|
-- Correccion: COR-002
|
|
-- Descripcion: Agregar estados 'waiting' y 'partially_available' a stock moves
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Agregar nuevos valores al ENUM
|
|
ALTER TYPE inventory.move_status ADD VALUE IF NOT EXISTS 'waiting' AFTER 'draft';
|
|
ALTER TYPE inventory.move_status ADD VALUE IF NOT EXISTS 'partially_available' AFTER 'confirmed';
|
|
|
|
-- 2. Actualizar comentarios
|
|
COMMENT ON TYPE inventory.move_status IS
|
|
'Estados de movimiento: draft -> waiting -> confirmed -> partially_available -> assigned -> done/cancelled';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 2.3 Migration: COR-003 (Move Lines)
|
|
|
|
```sql
|
|
-- Migration: 20260104_003_stock_move_lines.sql
|
|
-- Correccion: COR-003
|
|
-- Descripcion: Crear tabla stock_move_lines para granularidad lote/serie
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Crear tabla stock_move_lines
|
|
CREATE TABLE IF NOT EXISTS inventory.stock_move_lines (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relacion con move
|
|
move_id UUID NOT NULL REFERENCES inventory.stock_moves(id) ON DELETE CASCADE,
|
|
|
|
-- Producto
|
|
product_id UUID NOT NULL REFERENCES inventory.products(id),
|
|
product_uom_id UUID NOT NULL REFERENCES core.uom(id),
|
|
|
|
-- Lote/Serie/Paquete
|
|
lot_id UUID REFERENCES inventory.lots(id),
|
|
package_id UUID, -- Futuro: packages table
|
|
result_package_id UUID, -- Futuro: packages table
|
|
owner_id UUID REFERENCES core.partners(id),
|
|
|
|
-- Ubicaciones
|
|
location_id UUID NOT NULL REFERENCES inventory.locations(id),
|
|
location_dest_id UUID NOT NULL REFERENCES inventory.locations(id),
|
|
|
|
-- Cantidades
|
|
quantity DECIMAL(12, 4) NOT NULL,
|
|
quantity_done DECIMAL(12, 4) DEFAULT 0,
|
|
|
|
-- Estado
|
|
state VARCHAR(20),
|
|
|
|
-- Fechas
|
|
date TIMESTAMP,
|
|
|
|
-- Referencia
|
|
reference VARCHAR(255),
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
|
|
CONSTRAINT chk_move_lines_qty CHECK (quantity > 0),
|
|
CONSTRAINT chk_move_lines_qty_done CHECK (quantity_done >= 0 AND quantity_done <= quantity)
|
|
);
|
|
|
|
-- 2. Indices
|
|
CREATE INDEX idx_stock_move_lines_tenant_id ON inventory.stock_move_lines(tenant_id);
|
|
CREATE INDEX idx_stock_move_lines_move_id ON inventory.stock_move_lines(move_id);
|
|
CREATE INDEX idx_stock_move_lines_product_id ON inventory.stock_move_lines(product_id);
|
|
CREATE INDEX idx_stock_move_lines_lot_id ON inventory.stock_move_lines(lot_id);
|
|
CREATE INDEX idx_stock_move_lines_location ON inventory.stock_move_lines(location_id, location_dest_id);
|
|
|
|
-- 3. RLS
|
|
ALTER TABLE inventory.stock_move_lines ENABLE ROW LEVEL SECURITY;
|
|
CREATE POLICY tenant_isolation_stock_move_lines ON inventory.stock_move_lines
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
-- 4. Comentarios
|
|
COMMENT ON TABLE inventory.stock_move_lines IS
|
|
'Lineas de movimiento de stock para granularidad a nivel lote/serie (equivalente a stock.move.line Odoo)';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 2.4 Migration: COR-004 (Payment State)
|
|
|
|
```sql
|
|
-- Migration: 20260104_004_invoice_payment_state.sql
|
|
-- Correccion: COR-004
|
|
-- Descripcion: Agregar payment_state a facturas
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Crear ENUM para payment_state
|
|
CREATE TYPE financial.payment_state AS ENUM (
|
|
'not_paid',
|
|
'in_payment',
|
|
'paid',
|
|
'partial',
|
|
'reversed'
|
|
);
|
|
|
|
-- 2. Agregar columna
|
|
ALTER TABLE financial.invoices
|
|
ADD COLUMN IF NOT EXISTS payment_state financial.payment_state DEFAULT 'not_paid';
|
|
|
|
-- 3. Migrar datos existentes
|
|
UPDATE financial.invoices
|
|
SET payment_state = CASE
|
|
WHEN status = 'paid' THEN 'paid'::financial.payment_state
|
|
WHEN amount_paid > 0 AND amount_paid < amount_total THEN 'partial'::financial.payment_state
|
|
ELSE 'not_paid'::financial.payment_state
|
|
END
|
|
WHERE payment_state IS NULL;
|
|
|
|
-- 4. Comentarios
|
|
COMMENT ON COLUMN financial.invoices.payment_state IS
|
|
'Estado de pago: not_paid, in_payment, paid, partial, reversed (independiente del estado contable)';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 2.5 Migration: COR-005 (Tax Groups)
|
|
|
|
```sql
|
|
-- Migration: 20260104_005_tax_groups.sql
|
|
-- Correccion: COR-005
|
|
-- Descripcion: Implementar sistema de tax groups
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Crear tabla tax_groups
|
|
CREATE TABLE IF NOT EXISTS financial.tax_groups (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
sequence INTEGER DEFAULT 10,
|
|
country_id UUID, -- Futuro: countries table
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_tax_groups_name_tenant UNIQUE (tenant_id, name)
|
|
);
|
|
|
|
-- 2. Agregar campos a taxes
|
|
ALTER TABLE financial.taxes
|
|
ADD COLUMN IF NOT EXISTS tax_group_id UUID REFERENCES financial.tax_groups(id),
|
|
ADD COLUMN IF NOT EXISTS amount_type VARCHAR(20) DEFAULT 'percent', -- percent, fixed, group, division
|
|
ADD COLUMN IF NOT EXISTS include_base_amount BOOLEAN DEFAULT FALSE,
|
|
ADD COLUMN IF NOT EXISTS price_include BOOLEAN DEFAULT FALSE,
|
|
ADD COLUMN IF NOT EXISTS children_tax_ids UUID[] DEFAULT '{}';
|
|
|
|
-- 3. Indices y RLS
|
|
CREATE INDEX idx_tax_groups_tenant_id ON financial.tax_groups(tenant_id);
|
|
|
|
ALTER TABLE financial.tax_groups ENABLE ROW LEVEL SECURITY;
|
|
CREATE POLICY tenant_isolation_tax_groups ON financial.tax_groups
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
-- 4. Constraint para amount_type
|
|
ALTER TABLE financial.taxes
|
|
ADD CONSTRAINT chk_taxes_amount_type
|
|
CHECK (amount_type IN ('percent', 'fixed', 'group', 'division'));
|
|
|
|
-- 5. Comentarios
|
|
COMMENT ON TABLE financial.tax_groups IS
|
|
'Grupos de impuestos para clasificacion y reporte (equivalente a account.tax.group Odoo)';
|
|
COMMENT ON COLUMN financial.taxes.amount_type IS
|
|
'Tipo de calculo: percent (%), fixed (monto fijo), group (suma de hijos), division (100*price/100+rate)';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 2.6 Migration: COR-006 (SO-Invoice Link)
|
|
|
|
```sql
|
|
-- Migration: 20260104_006_sales_invoice_link.sql
|
|
-- Correccion: COR-006
|
|
-- Descripcion: Vincular sales orders con invoices
|
|
|
|
BEGIN;
|
|
|
|
-- 1. Agregar campos a sales_orders
|
|
ALTER TABLE sales.sales_orders
|
|
ADD COLUMN IF NOT EXISTS invoice_ids UUID[] DEFAULT '{}';
|
|
|
|
-- 2. Agregar campo computed (simulado con trigger)
|
|
ALTER TABLE sales.sales_orders
|
|
ADD COLUMN IF NOT EXISTS invoice_count INTEGER DEFAULT 0;
|
|
|
|
-- 3. Funcion para actualizar invoice_count
|
|
CREATE OR REPLACE FUNCTION sales.update_invoice_count()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.invoice_count := COALESCE(array_length(NEW.invoice_ids, 1), 0);
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 4. Trigger
|
|
CREATE TRIGGER trg_sales_orders_invoice_count
|
|
BEFORE INSERT OR UPDATE OF invoice_ids ON sales.sales_orders
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION sales.update_invoice_count();
|
|
|
|
-- 5. Comentarios
|
|
COMMENT ON COLUMN sales.sales_orders.invoice_ids IS
|
|
'Array de UUIDs de facturas vinculadas a esta orden de venta';
|
|
COMMENT ON COLUMN sales.sales_orders.invoice_count IS
|
|
'Cantidad de facturas vinculadas (computed)';
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Scripts de Rollback
|
|
|
|
### 3.1 Rollback: COR-001
|
|
|
|
```sql
|
|
-- Rollback: 20260104_001_po_to_approve_state_rollback.sql
|
|
BEGIN;
|
|
|
|
-- Nota: PostgreSQL no permite eliminar valores de ENUM
|
|
-- Se deben migrar datos y recrear tipo si es necesario
|
|
|
|
ALTER TABLE purchase.purchase_orders
|
|
DROP COLUMN IF EXISTS approval_required,
|
|
DROP COLUMN IF EXISTS amount_approval_threshold;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 3.2 Rollback: COR-003
|
|
|
|
```sql
|
|
-- Rollback: 20260104_003_stock_move_lines_rollback.sql
|
|
BEGIN;
|
|
|
|
DROP TABLE IF EXISTS inventory.stock_move_lines CASCADE;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 3.3 Rollback: COR-004
|
|
|
|
```sql
|
|
-- Rollback: 20260104_004_invoice_payment_state_rollback.sql
|
|
BEGIN;
|
|
|
|
ALTER TABLE financial.invoices
|
|
DROP COLUMN IF EXISTS payment_state;
|
|
|
|
DROP TYPE IF EXISTS financial.payment_state;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 3.4 Rollback: COR-005
|
|
|
|
```sql
|
|
-- Rollback: 20260104_005_tax_groups_rollback.sql
|
|
BEGIN;
|
|
|
|
ALTER TABLE financial.taxes
|
|
DROP COLUMN IF EXISTS tax_group_id,
|
|
DROP COLUMN IF EXISTS amount_type,
|
|
DROP COLUMN IF EXISTS include_base_amount,
|
|
DROP COLUMN IF EXISTS price_include,
|
|
DROP COLUMN IF EXISTS children_tax_ids;
|
|
|
|
DROP TABLE IF EXISTS financial.tax_groups;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
### 3.5 Rollback: COR-006
|
|
|
|
```sql
|
|
-- Rollback: 20260104_006_sales_invoice_link_rollback.sql
|
|
BEGIN;
|
|
|
|
DROP TRIGGER IF EXISTS trg_sales_orders_invoice_count ON sales.sales_orders;
|
|
DROP FUNCTION IF EXISTS sales.update_invoice_count();
|
|
|
|
ALTER TABLE sales.sales_orders
|
|
DROP COLUMN IF EXISTS invoice_ids,
|
|
DROP COLUMN IF EXISTS invoice_count;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Tests de Regresion
|
|
|
|
### 4.1 Test Suite: COR-001 (PO States)
|
|
|
|
```sql
|
|
-- Test: test_cor001_po_states.sql
|
|
|
|
-- Test 1: Verificar que nuevo estado existe
|
|
DO $$
|
|
BEGIN
|
|
ASSERT EXISTS (
|
|
SELECT 1 FROM pg_enum
|
|
WHERE enumlabel = 'to_approve'
|
|
AND enumtypid = 'purchase.order_status'::regtype
|
|
), 'Estado to_approve debe existir';
|
|
END $$;
|
|
|
|
-- Test 2: Verificar transicion de estados
|
|
DO $$
|
|
DECLARE
|
|
v_po_id UUID;
|
|
BEGIN
|
|
-- Crear PO de prueba
|
|
INSERT INTO purchase.purchase_orders (tenant_id, company_id, name, partner_id, order_date, currency_id, status)
|
|
VALUES (get_current_tenant_id(), '...', 'TEST-001', '...', CURRENT_DATE, '...', 'draft')
|
|
RETURNING id INTO v_po_id;
|
|
|
|
-- Verificar transicion draft -> to_approve
|
|
UPDATE purchase.purchase_orders SET status = 'to_approve' WHERE id = v_po_id;
|
|
ASSERT (SELECT status FROM purchase.purchase_orders WHERE id = v_po_id) = 'to_approve';
|
|
|
|
-- Cleanup
|
|
DELETE FROM purchase.purchase_orders WHERE id = v_po_id;
|
|
END $$;
|
|
```
|
|
|
|
### 4.2 Test Suite: COR-002 (Move States)
|
|
|
|
```sql
|
|
-- Test: test_cor002_move_states.sql
|
|
|
|
-- Test 1: Verificar nuevos estados
|
|
DO $$
|
|
BEGIN
|
|
ASSERT EXISTS (
|
|
SELECT 1 FROM pg_enum
|
|
WHERE enumlabel = 'waiting'
|
|
AND enumtypid = 'inventory.move_status'::regtype
|
|
), 'Estado waiting debe existir';
|
|
|
|
ASSERT EXISTS (
|
|
SELECT 1 FROM pg_enum
|
|
WHERE enumlabel = 'partially_available'
|
|
AND enumtypid = 'inventory.move_status'::regtype
|
|
), 'Estado partially_available debe existir';
|
|
END $$;
|
|
```
|
|
|
|
### 4.3 Test Suite: COR-003 (Move Lines)
|
|
|
|
```sql
|
|
-- Test: test_cor003_move_lines.sql
|
|
|
|
-- Test 1: Verificar tabla existe
|
|
DO $$
|
|
BEGIN
|
|
ASSERT EXISTS (
|
|
SELECT 1 FROM information_schema.tables
|
|
WHERE table_schema = 'inventory'
|
|
AND table_name = 'stock_move_lines'
|
|
), 'Tabla stock_move_lines debe existir';
|
|
END $$;
|
|
|
|
-- Test 2: Verificar FK a stock_moves
|
|
DO $$
|
|
BEGIN
|
|
ASSERT EXISTS (
|
|
SELECT 1 FROM information_schema.table_constraints
|
|
WHERE table_schema = 'inventory'
|
|
AND table_name = 'stock_move_lines'
|
|
AND constraint_type = 'FOREIGN KEY'
|
|
), 'FK a stock_moves debe existir';
|
|
END $$;
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Documentacion a Actualizar Post-Ejecucion
|
|
|
|
### 5.1 Por Batch
|
|
|
|
| Batch | Documentos a Actualizar |
|
|
|-------|------------------------|
|
|
| Batch 1 | inventory-domain.md, financial-domain.md, sales-domain.md, INVENTARIO-OBJETOS-BD.yml |
|
|
| Batch 2 | inventory-domain.md, purchase workflows, GRAFO-DEPENDENCIAS-SCHEMAS.md |
|
|
| Batch 3 | financial-domain.md, MATRIZ-TRAZABILIDAD-RF-ET-BD.md |
|
|
| Batch 4 | crm-domain.md, analytics-domain.md, projects-domain.md |
|
|
|
|
### 5.2 Checklist Post-Ejecucion
|
|
|
|
- [ ] Actualizar domain models con nuevas entidades/campos
|
|
- [ ] Sincronizar schema docs (docs/04-modelado/database-design/schemas/)
|
|
- [ ] Actualizar INVENTARIO-OBJETOS-BD.yml
|
|
- [ ] Actualizar GRAFO-DEPENDENCIAS-SCHEMAS.md
|
|
- [ ] Crear nuevos workflows (WORKFLOW-PURCHASE-APPROVAL.md, etc.)
|
|
- [ ] Actualizar VALIDACION-COBERTURA-ODOO.md
|
|
- [ ] Regenerar documentacion de API si aplica
|
|
|
|
---
|
|
|
|
## 6. Plan de Rollback General
|
|
|
|
### 6.1 Criterios de Rollback
|
|
|
|
| Criterio | Accion |
|
|
|----------|--------|
|
|
| Test de regresion falla | Rollback inmediato |
|
|
| Error en produccion < 1 hora | Rollback script |
|
|
| Error en produccion > 1 hora | Evaluar fix forward |
|
|
| Datos corruptos | Restore de backup |
|
|
|
|
### 6.2 Orden de Rollback
|
|
|
|
```
|
|
Rollback debe ser en orden inverso:
|
|
1. Batch 4 -> Batch 3 -> Batch 2 -> Batch 1
|
|
|
|
Dentro de cada batch, rollback en orden inverso de ejecucion.
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Aprobacion del Plan Refinado
|
|
|
|
### 7.1 Checklist de Aprobacion
|
|
|
|
- [x] Plan de ejecucion por batches definido
|
|
- [x] Scripts de migracion creados (P0)
|
|
- [x] Scripts de rollback creados
|
|
- [x] Tests de regresion definidos
|
|
- [x] Documentacion a actualizar identificada
|
|
- [x] Plan de rollback general establecido
|
|
|
|
### 7.2 Resultado
|
|
|
|
**PLAN REFINADO APROBADO** para proceder a FASE 6 (Ejecucion)
|
|
|
|
---
|
|
|
|
## 8. Proximos Pasos (FASE 6)
|
|
|
|
1. Crear branch `feature/odoo-alignment-batch1`
|
|
2. Ejecutar Batch 1 migrations
|
|
3. Ejecutar tests de regresion
|
|
4. Actualizar documentacion
|
|
5. Merge y continuar con Batch 2
|
|
|
|
---
|
|
|
|
**Generado:** 2026-01-04
|
|
**Herramienta:** Claude Code
|