- Create customer_credit_accounts table - Create fiados table for credit sales - Create fiado_payments table for payment tracking - Add view v_customer_credit_summary - Add indexes and RLS policies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
191 lines
8.2 KiB
SQL
191 lines
8.2 KiB
SQL
-- ===========================================
|
|
-- MECANICAS DIESEL - Fiados (Credit) Schema
|
|
-- ===========================================
|
|
-- Sistema de crédito para clientes
|
|
-- Tracking de ventas a crédito y pagos
|
|
|
|
SET search_path TO service_management, public;
|
|
|
|
-- -------------------------------------------
|
|
-- CUSTOMER_CREDIT_ACCOUNTS - Cuentas de crédito
|
|
-- -------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS service_management.customer_credit_accounts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
customer_id UUID NOT NULL REFERENCES service_management.customers(id),
|
|
|
|
-- Límites de crédito
|
|
credit_limit DECIMAL(12,2) DEFAULT 0 CHECK (credit_limit >= 0),
|
|
credit_days INTEGER DEFAULT 30 CHECK (credit_days >= 0),
|
|
|
|
-- Balances
|
|
current_balance DECIMAL(12,2) DEFAULT 0, -- Puede ser positivo (debe) o negativo (a favor)
|
|
|
|
-- Estadísticas
|
|
total_credit_given DECIMAL(14,2) DEFAULT 0,
|
|
total_payments_received DECIMAL(14,2) DEFAULT 0,
|
|
overdue_amount DECIMAL(12,2) DEFAULT 0,
|
|
|
|
-- Estado
|
|
is_active BOOLEAN DEFAULT true,
|
|
is_frozen BOOLEAN DEFAULT false, -- Congelar crédito si hay problemas
|
|
frozen_reason TEXT,
|
|
frozen_at TIMESTAMP WITH TIME ZONE,
|
|
frozen_by UUID,
|
|
|
|
-- Audit
|
|
created_by UUID,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_customer_credit_account UNIQUE (tenant_id, customer_id)
|
|
);
|
|
|
|
CREATE INDEX idx_credit_accounts_tenant ON service_management.customer_credit_accounts(tenant_id);
|
|
CREATE INDEX idx_credit_accounts_customer ON service_management.customer_credit_accounts(customer_id);
|
|
CREATE INDEX idx_credit_accounts_balance ON service_management.customer_credit_accounts(tenant_id, current_balance) WHERE current_balance > 0;
|
|
CREATE INDEX idx_credit_accounts_overdue ON service_management.customer_credit_accounts(tenant_id, overdue_amount) WHERE overdue_amount > 0;
|
|
|
|
CREATE TRIGGER trg_credit_accounts_updated_at
|
|
BEFORE UPDATE ON service_management.customer_credit_accounts
|
|
FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at();
|
|
|
|
-- RLS
|
|
SELECT create_tenant_rls_policies('service_management', 'customer_credit_accounts');
|
|
|
|
-- -------------------------------------------
|
|
-- FIADOS - Ventas a crédito
|
|
-- -------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS service_management.fiados (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
|
|
-- Relaciones
|
|
customer_id UUID NOT NULL REFERENCES service_management.customers(id),
|
|
credit_account_id UUID NOT NULL REFERENCES service_management.customer_credit_accounts(id),
|
|
order_id UUID REFERENCES service_management.service_orders(id),
|
|
|
|
-- Identificación
|
|
fiado_number VARCHAR(20) NOT NULL,
|
|
|
|
-- Monto
|
|
original_amount DECIMAL(12,2) NOT NULL CHECK (original_amount > 0),
|
|
remaining_amount DECIMAL(12,2) NOT NULL CHECK (remaining_amount >= 0),
|
|
|
|
-- Fechas
|
|
issued_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
due_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
paid_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Estado
|
|
status VARCHAR(20) DEFAULT 'pending'
|
|
CHECK (status IN ('pending', 'partial', 'paid', 'overdue', 'cancelled', 'written_off')),
|
|
|
|
-- Descripción
|
|
description TEXT,
|
|
notes TEXT,
|
|
|
|
-- Audit
|
|
created_by UUID,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_fiado_number UNIQUE (tenant_id, fiado_number)
|
|
);
|
|
|
|
CREATE INDEX idx_fiados_tenant ON service_management.fiados(tenant_id);
|
|
CREATE INDEX idx_fiados_customer ON service_management.fiados(customer_id);
|
|
CREATE INDEX idx_fiados_account ON service_management.fiados(credit_account_id);
|
|
CREATE INDEX idx_fiados_order ON service_management.fiados(order_id);
|
|
CREATE INDEX idx_fiados_status ON service_management.fiados(tenant_id, status);
|
|
CREATE INDEX idx_fiados_due ON service_management.fiados(due_at) WHERE status IN ('pending', 'partial');
|
|
CREATE INDEX idx_fiados_overdue ON service_management.fiados(tenant_id, due_at) WHERE status = 'overdue';
|
|
|
|
CREATE TRIGGER trg_fiados_updated_at
|
|
BEFORE UPDATE ON service_management.fiados
|
|
FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at();
|
|
|
|
-- RLS
|
|
SELECT create_tenant_rls_policies('service_management', 'fiados');
|
|
|
|
-- -------------------------------------------
|
|
-- FIADO_PAYMENTS - Pagos/Abonos a fiados
|
|
-- -------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS service_management.fiado_payments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
|
|
-- Relaciones
|
|
customer_id UUID NOT NULL REFERENCES service_management.customers(id),
|
|
credit_account_id UUID NOT NULL REFERENCES service_management.customer_credit_accounts(id),
|
|
fiado_id UUID REFERENCES service_management.fiados(id), -- NULL si es pago general a cuenta
|
|
|
|
-- Identificación
|
|
payment_number VARCHAR(20) NOT NULL,
|
|
|
|
-- Monto
|
|
amount DECIMAL(12,2) NOT NULL CHECK (amount > 0),
|
|
|
|
-- Método de pago
|
|
payment_method VARCHAR(20) NOT NULL
|
|
CHECK (payment_method IN ('cash', 'card', 'transfer', 'check', 'other')),
|
|
payment_reference VARCHAR(100), -- Referencia de transferencia, número de cheque, etc.
|
|
|
|
-- Descripción
|
|
notes TEXT,
|
|
|
|
-- Audit
|
|
received_by UUID,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_payment_number UNIQUE (tenant_id, payment_number)
|
|
);
|
|
|
|
CREATE INDEX idx_fiado_payments_tenant ON service_management.fiado_payments(tenant_id);
|
|
CREATE INDEX idx_fiado_payments_customer ON service_management.fiado_payments(customer_id);
|
|
CREATE INDEX idx_fiado_payments_account ON service_management.fiado_payments(credit_account_id);
|
|
CREATE INDEX idx_fiado_payments_fiado ON service_management.fiado_payments(fiado_id);
|
|
CREATE INDEX idx_fiado_payments_date ON service_management.fiado_payments(created_at DESC);
|
|
|
|
-- RLS
|
|
SELECT create_tenant_rls_policies('service_management', 'fiado_payments');
|
|
|
|
-- -------------------------------------------
|
|
-- COMMENTS
|
|
-- -------------------------------------------
|
|
COMMENT ON TABLE service_management.customer_credit_accounts IS 'Cuentas de crédito de clientes';
|
|
COMMENT ON COLUMN service_management.customer_credit_accounts.current_balance IS 'Saldo actual: positivo = cliente debe, negativo = saldo a favor';
|
|
COMMENT ON COLUMN service_management.customer_credit_accounts.is_frozen IS 'Crédito congelado por morosidad u otra razón';
|
|
|
|
COMMENT ON TABLE service_management.fiados IS 'Ventas a crédito (fiados) individuales';
|
|
COMMENT ON COLUMN service_management.fiados.fiado_number IS 'Número único de fiado (F-001, F-002, etc.)';
|
|
COMMENT ON COLUMN service_management.fiados.remaining_amount IS 'Monto pendiente de pago';
|
|
COMMENT ON COLUMN service_management.fiados.due_at IS 'Fecha de vencimiento basada en credit_days del cliente';
|
|
|
|
COMMENT ON TABLE service_management.fiado_payments IS 'Pagos/abonos recibidos para fiados';
|
|
COMMENT ON COLUMN service_management.fiado_payments.fiado_id IS 'NULL si el pago se aplica a la cuenta general, no a un fiado específico';
|
|
|
|
-- -------------------------------------------
|
|
-- VIEW: Customer Credit Summary
|
|
-- -------------------------------------------
|
|
CREATE OR REPLACE VIEW service_management.v_customer_credit_summary AS
|
|
SELECT
|
|
ca.tenant_id,
|
|
ca.customer_id,
|
|
c.name AS customer_name,
|
|
c.phone AS customer_phone,
|
|
ca.credit_limit,
|
|
ca.credit_days,
|
|
ca.current_balance,
|
|
ca.credit_limit - ca.current_balance AS available_credit,
|
|
ca.overdue_amount,
|
|
ca.is_active,
|
|
ca.is_frozen,
|
|
(SELECT COUNT(*) FROM service_management.fiados f WHERE f.credit_account_id = ca.id AND f.status IN ('pending', 'partial', 'overdue')) AS pending_fiados_count,
|
|
(SELECT COALESCE(SUM(f.remaining_amount), 0) FROM service_management.fiados f WHERE f.credit_account_id = ca.id AND f.status = 'overdue') AS overdue_fiados_amount,
|
|
(SELECT MAX(fp.created_at) FROM service_management.fiado_payments fp WHERE fp.credit_account_id = ca.id) AS last_payment_at
|
|
FROM service_management.customer_credit_accounts ca
|
|
JOIN service_management.customers c ON c.id = ca.customer_id;
|
|
|
|
COMMENT ON VIEW service_management.v_customer_credit_summary IS 'Resumen de crédito por cliente con estadísticas';
|