erp-core/orchestration/01-analisis/FASE-5-REFINAMIENTO-PLAN.md
rckrdmrd 4c4e27d9ba feat: Documentation and orchestration updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:35:20 -06:00

15 KiB

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)

-- 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)

-- 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)

-- 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)

-- 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)

-- 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;
-- 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

-- 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

-- Rollback: 20260104_003_stock_move_lines_rollback.sql
BEGIN;

DROP TABLE IF EXISTS inventory.stock_move_lines CASCADE;

COMMIT;

3.3 Rollback: COR-004

-- 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

-- 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

-- 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)

-- 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)

-- 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)

-- 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

  • Plan de ejecucion por batches definido
  • Scripts de migracion creados (P0)
  • Scripts de rollback creados
  • Tests de regresion definidos
  • Documentacion a actualizar identificada
  • 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