-- =============================================================
-- ARCHIVO: 99-rls-erp-modules.sql
-- DESCRIPCION: Row Level Security (RLS) Policies para modulos ERP
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-24
-- CREADO POR: TASK-028 Remediacion RLS
-- =============================================================

-- =====================================================
-- PRODUCTS MODULE - RLS Policies
-- =====================================================

-- product_categories
ALTER TABLE products.product_categories ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_product_categories ON products.product_categories;
CREATE POLICY tenant_isolation_product_categories ON products.product_categories
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- products
ALTER TABLE products.products ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_products ON products.products;
CREATE POLICY tenant_isolation_products ON products.products
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- INVENTORY MODULE - RLS Policies
-- =====================================================

-- warehouses
ALTER TABLE inventory.warehouses ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_warehouses ON inventory.warehouses;
CREATE POLICY tenant_isolation_warehouses ON inventory.warehouses
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- stock_levels
ALTER TABLE inventory.stock_levels ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_stock_levels ON inventory.stock_levels;
CREATE POLICY tenant_isolation_stock_levels ON inventory.stock_levels
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- stock_movements
ALTER TABLE inventory.stock_movements ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_stock_movements ON inventory.stock_movements;
CREATE POLICY tenant_isolation_stock_movements ON inventory.stock_movements
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- inventory_counts
ALTER TABLE inventory.inventory_counts ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_inventory_counts ON inventory.inventory_counts;
CREATE POLICY tenant_isolation_inventory_counts ON inventory.inventory_counts
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- transfer_orders
ALTER TABLE inventory.transfer_orders ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_transfer_orders ON inventory.transfer_orders;
CREATE POLICY tenant_isolation_transfer_orders ON inventory.transfer_orders
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- lots
ALTER TABLE inventory.lots ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_lots ON inventory.lots;
CREATE POLICY tenant_isolation_lots ON inventory.lots
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- pickings
ALTER TABLE inventory.pickings ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_pickings ON inventory.pickings;
CREATE POLICY tenant_isolation_pickings ON inventory.pickings
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- PARTNERS MODULE - RLS Policies
-- =====================================================

-- partners
ALTER TABLE partners.partners ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_partners ON partners.partners;
CREATE POLICY tenant_isolation_partners ON partners.partners
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- partner_segments
ALTER TABLE partners.partner_segments ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_partner_segments ON partners.partner_segments;
CREATE POLICY tenant_isolation_partner_segments ON partners.partner_segments
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- SALES MODULE - RLS Policies
-- =====================================================

-- quotations
ALTER TABLE sales.quotations ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_quotations ON sales.quotations;
CREATE POLICY tenant_isolation_quotations ON sales.quotations
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- sales_orders
ALTER TABLE sales.sales_orders ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_sales_orders ON sales.sales_orders;
CREATE POLICY tenant_isolation_sales_orders ON sales.sales_orders
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- PURCHASES MODULE - RLS Policies
-- =====================================================

-- purchase_orders
ALTER TABLE purchases.purchase_orders ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_purchase_orders ON purchases.purchase_orders;
CREATE POLICY tenant_isolation_purchase_orders ON purchases.purchase_orders
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- purchase_receipts
ALTER TABLE purchases.purchase_receipts ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_purchase_receipts ON purchases.purchase_receipts;
CREATE POLICY tenant_isolation_purchase_receipts ON purchases.purchase_receipts
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- BILLING MODULE - RLS Policies
-- =====================================================

-- invoices (billing schema)
ALTER TABLE billing.invoices ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_billing_invoices ON billing.invoices;
CREATE POLICY tenant_isolation_billing_invoices ON billing.invoices
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- payments (billing schema)
ALTER TABLE billing.payments ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_billing_payments ON billing.payments;
CREATE POLICY tenant_isolation_billing_payments ON billing.payments
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- FINANCIAL MODULE - RLS Policies
-- =====================================================

-- accounts
ALTER TABLE financial.accounts ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_accounts ON financial.accounts;
CREATE POLICY tenant_isolation_accounts ON financial.accounts
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- account_mappings
ALTER TABLE financial.account_mappings ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_account_mappings ON financial.account_mappings;
CREATE POLICY tenant_isolation_account_mappings ON financial.account_mappings
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- fiscal_years
ALTER TABLE financial.fiscal_years ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_fiscal_years ON financial.fiscal_years;
CREATE POLICY tenant_isolation_fiscal_years ON financial.fiscal_years
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- fiscal_periods
ALTER TABLE financial.fiscal_periods ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_fiscal_periods ON financial.fiscal_periods;
CREATE POLICY tenant_isolation_fiscal_periods ON financial.fiscal_periods
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- journals
ALTER TABLE financial.journals ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_journals ON financial.journals;
CREATE POLICY tenant_isolation_journals ON financial.journals
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- journal_entries
ALTER TABLE financial.journal_entries ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_journal_entries ON financial.journal_entries;
CREATE POLICY tenant_isolation_journal_entries ON financial.journal_entries
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- journal_entry_lines
ALTER TABLE financial.journal_entry_lines ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_journal_entry_lines ON financial.journal_entry_lines;
CREATE POLICY tenant_isolation_journal_entry_lines ON financial.journal_entry_lines
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- invoices (financial schema)
ALTER TABLE financial.invoices ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_financial_invoices ON financial.invoices;
CREATE POLICY tenant_isolation_financial_invoices ON financial.invoices
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- invoice_lines (financial schema)
ALTER TABLE financial.invoice_lines ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_invoice_lines ON financial.invoice_lines;
CREATE POLICY tenant_isolation_invoice_lines ON financial.invoice_lines
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- payments (financial schema)
ALTER TABLE financial.payments ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_financial_payments ON financial.payments;
CREATE POLICY tenant_isolation_financial_payments ON financial.payments
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- taxes
ALTER TABLE financial.taxes ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_taxes ON financial.taxes;
CREATE POLICY tenant_isolation_taxes ON financial.taxes
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- tax_groups
ALTER TABLE financial.tax_groups ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_tax_groups ON financial.tax_groups;
CREATE POLICY tenant_isolation_tax_groups ON financial.tax_groups
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- bank_statements
ALTER TABLE financial.bank_statements ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_bank_statements ON financial.bank_statements;
CREATE POLICY tenant_isolation_bank_statements ON financial.bank_statements
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- bank_statement_lines
ALTER TABLE financial.bank_statement_lines ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_bank_statement_lines ON financial.bank_statement_lines;
CREATE POLICY tenant_isolation_bank_statement_lines ON financial.bank_statement_lines
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- bank_reconciliation_rules
ALTER TABLE financial.bank_reconciliation_rules ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_bank_reconciliation_rules ON financial.bank_reconciliation_rules;
CREATE POLICY tenant_isolation_bank_reconciliation_rules ON financial.bank_reconciliation_rules
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- PROJECTS MODULE - RLS Policies
-- =====================================================

-- projects
ALTER TABLE projects.projects ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_projects ON projects.projects;
CREATE POLICY tenant_isolation_projects ON projects.projects
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- project_stages
ALTER TABLE projects.project_stages ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_project_stages ON projects.project_stages;
CREATE POLICY tenant_isolation_project_stages ON projects.project_stages
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- tasks
ALTER TABLE projects.tasks ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_tasks ON projects.tasks;
CREATE POLICY tenant_isolation_tasks ON projects.tasks
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- milestones
ALTER TABLE projects.milestones ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_milestones ON projects.milestones;
CREATE POLICY tenant_isolation_milestones ON projects.milestones
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- timesheets
ALTER TABLE projects.timesheets ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_timesheets ON projects.timesheets;
CREATE POLICY tenant_isolation_timesheets ON projects.timesheets
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- project_members
ALTER TABLE projects.project_members ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_project_members ON projects.project_members;
CREATE POLICY tenant_isolation_project_members ON projects.project_members
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- COMENTARIOS
-- =====================================================
COMMENT ON POLICY tenant_isolation_products ON products.products IS 'Aislamiento multi-tenant para productos';
COMMENT ON POLICY tenant_isolation_warehouses ON inventory.warehouses IS 'Aislamiento multi-tenant para almacenes';
COMMENT ON POLICY tenant_isolation_partners ON partners.partners IS 'Aislamiento multi-tenant para socios comerciales';
COMMENT ON POLICY tenant_isolation_journal_entries ON financial.journal_entries IS 'Aislamiento multi-tenant para polizas contables';
COMMENT ON POLICY tenant_isolation_projects ON projects.projects IS 'Aislamiento multi-tenant para proyectos';

-- =====================================================
-- NOTAS DE IMPLEMENTACION
-- =====================================================
--
-- 1. Las tablas hijas (ej: invoice_lines, order_items) heredan seguridad
--    via CASCADE DELETE en sus FK a tablas padre
--
-- 2. Tablas de catalogo sistema (account_types) no tienen tenant_id
--    porque son compartidas entre todos los tenants
--
-- 3. El setting 'app.current_tenant_id' debe configurarse en cada
--    sesion de BD via: SET app.current_tenant_id = 'uuid-here';
--
-- 4. El backend debe configurar este setting antes de cada query
--    Ver: backend/src/middleware/tenant.middleware.ts
--
-- =====================================================
