-- ============================================================================= -- MICHANGARRITO - 14 CODI/SPEI -- ============================================================================= -- Pagos CoDi (Cobro Digital) y SPEI (Sistema de Pagos Electronicos) -- ============================================================================= -- Cuentas virtuales SPEI (CLABE por tenant) CREATE TABLE IF NOT EXISTS sales.virtual_accounts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, provider VARCHAR(20) NOT NULL DEFAULT 'stp', -- stp, arcus, conekta, openpay clabe VARCHAR(18) UNIQUE NOT NULL, beneficiary_name VARCHAR(100), status VARCHAR(20) DEFAULT 'active', -- active, suspended, closed metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_virtual_accounts_tenant ON sales.virtual_accounts(tenant_id); CREATE INDEX idx_virtual_accounts_clabe ON sales.virtual_accounts(clabe); CREATE TRIGGER update_virtual_accounts_updated_at BEFORE UPDATE ON sales.virtual_accounts FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Transacciones CoDi CREATE TABLE IF NOT EXISTS sales.codi_transactions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, sale_id UUID REFERENCES sales.sales(id), qr_data TEXT NOT NULL, qr_image_url TEXT, amount DECIMAL(10,2) NOT NULL, reference VARCHAR(50), description VARCHAR(200), status VARCHAR(20) DEFAULT 'pending', -- pending, confirmed, expired, cancelled expires_at TIMESTAMPTZ NOT NULL, confirmed_at TIMESTAMPTZ, provider_transaction_id VARCHAR(100), provider_response JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_codi_transactions_tenant ON sales.codi_transactions(tenant_id); CREATE INDEX idx_codi_transactions_sale ON sales.codi_transactions(sale_id); CREATE INDEX idx_codi_transactions_status ON sales.codi_transactions(status); CREATE INDEX idx_codi_transactions_reference ON sales.codi_transactions(reference); CREATE TRIGGER update_codi_transactions_updated_at BEFORE UPDATE ON sales.codi_transactions FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Transacciones SPEI CREATE TABLE IF NOT EXISTS sales.spei_transactions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, virtual_account_id UUID REFERENCES sales.virtual_accounts(id), sale_id UUID REFERENCES sales.sales(id), amount DECIMAL(10,2) NOT NULL, sender_clabe VARCHAR(18), sender_name VARCHAR(100), sender_rfc VARCHAR(13), sender_bank VARCHAR(50), reference VARCHAR(50), description VARCHAR(200), tracking_key VARCHAR(50), status VARCHAR(20) DEFAULT 'received', -- received, reconciled, disputed received_at TIMESTAMPTZ NOT NULL, reconciled_at TIMESTAMPTZ, provider_data JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_spei_transactions_tenant ON sales.spei_transactions(tenant_id); CREATE INDEX idx_spei_transactions_account ON sales.spei_transactions(virtual_account_id); CREATE INDEX idx_spei_transactions_sale ON sales.spei_transactions(sale_id); CREATE INDEX idx_spei_transactions_tracking ON sales.spei_transactions(tracking_key); CREATE TRIGGER update_spei_transactions_updated_at BEFORE UPDATE ON sales.spei_transactions FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Configuracion CoDi/SPEI por tenant CREATE TABLE IF NOT EXISTS sales.payment_config ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, codi_enabled BOOLEAN DEFAULT false, codi_provider VARCHAR(20), codi_merchant_id VARCHAR(100), codi_qr_expiry_minutes INTEGER DEFAULT 5, spei_enabled BOOLEAN DEFAULT false, spei_provider VARCHAR(20), spei_auto_reconcile BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(tenant_id) ); CREATE TRIGGER update_payment_config_updated_at BEFORE UPDATE ON sales.payment_config FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Funcion para generar referencia unica de CoDi CREATE OR REPLACE FUNCTION generate_codi_reference(p_tenant_id UUID) RETURNS TEXT AS $$ DECLARE ref TEXT; BEGIN -- Generar referencia: MCH + 6 digitos aleatorios + timestamp ref := 'MCH' || to_char(now(), 'YYMMDDHH24MISS') || substr(md5(random()::text), 1, 4); RETURN upper(ref); END; $$ LANGUAGE plpgsql; -- Funcion para obtener resumen de pagos CoDi/SPEI del dia CREATE OR REPLACE FUNCTION get_codi_spei_summary(p_tenant_id UUID, p_date DATE DEFAULT CURRENT_DATE) RETURNS TABLE ( codi_count INTEGER, codi_total DECIMAL(10,2), spei_count INTEGER, spei_total DECIMAL(10,2) ) AS $$ BEGIN RETURN QUERY SELECT (SELECT COUNT(*)::INTEGER FROM sales.codi_transactions WHERE tenant_id = p_tenant_id AND status = 'confirmed' AND DATE(confirmed_at) = p_date) as codi_count, (SELECT COALESCE(SUM(amount), 0) FROM sales.codi_transactions WHERE tenant_id = p_tenant_id AND status = 'confirmed' AND DATE(confirmed_at) = p_date) as codi_total, (SELECT COUNT(*)::INTEGER FROM sales.spei_transactions WHERE tenant_id = p_tenant_id AND DATE(received_at) = p_date) as spei_count, (SELECT COALESCE(SUM(amount), 0) FROM sales.spei_transactions WHERE tenant_id = p_tenant_id AND DATE(received_at) = p_date) as spei_total; END; $$ LANGUAGE plpgsql;