[PROP-CORE-004] feat: Add payment_terminals schema DDL
Propagated from erp-core v1.5.0: - 5 tables: configs, payments, webhook_events, retry_queue, payment_links - RLS policies for tenant isolation - Indexes for performance - Functions for retry backoff and expiration Priority: P0 (CRITICAL for POS operations) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8d2480864a
commit
05b2158a8d
441
init/04-payment-terminals.sql
Normal file
441
init/04-payment-terminals.sql
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
-- =============================================================
|
||||||
|
-- ARCHIVO: 04-payment-terminals.sql
|
||||||
|
-- DESCRIPCION: Terminales de pago TPV (MercadoPago, Clip)
|
||||||
|
-- VERSION: 1.0.0
|
||||||
|
-- PROYECTO: ERP-Retail
|
||||||
|
-- FECHA: 2026-01-25
|
||||||
|
-- PROPAGADO DESDE: erp-core v1.5.0 (PROP-CORE-004)
|
||||||
|
-- =============================================================
|
||||||
|
-- Basado en: erp-core/database/ddl/25-payment-terminals.sql
|
||||||
|
-- =============================================================
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- SCHEMA: payment_terminals
|
||||||
|
-- =====================
|
||||||
|
CREATE SCHEMA IF NOT EXISTS payment_terminals;
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- ENUMS
|
||||||
|
-- =====================
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'terminal_provider') THEN
|
||||||
|
CREATE TYPE payment_terminals.terminal_provider AS ENUM (
|
||||||
|
'mercadopago',
|
||||||
|
'clip',
|
||||||
|
'stripe_terminal'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END$$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'terminal_payment_status') THEN
|
||||||
|
CREATE TYPE payment_terminals.terminal_payment_status AS ENUM (
|
||||||
|
'pending',
|
||||||
|
'processing',
|
||||||
|
'approved',
|
||||||
|
'authorized',
|
||||||
|
'in_process',
|
||||||
|
'rejected',
|
||||||
|
'refunded',
|
||||||
|
'partially_refunded',
|
||||||
|
'cancelled',
|
||||||
|
'charged_back'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END$$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'payment_method_type') THEN
|
||||||
|
CREATE TYPE payment_terminals.payment_method_type AS ENUM (
|
||||||
|
'card',
|
||||||
|
'qr',
|
||||||
|
'link',
|
||||||
|
'cash',
|
||||||
|
'bank_transfer'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END$$;
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- TABLA: tenant_terminal_configs
|
||||||
|
-- Credenciales de proveedores por tenant (no por branch)
|
||||||
|
-- =====================
|
||||||
|
CREATE TABLE IF NOT EXISTS payment_terminals.tenant_terminal_configs (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Proveedor
|
||||||
|
provider payment_terminals.terminal_provider NOT NULL,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
|
||||||
|
-- Credenciales (encriptadas AES-256)
|
||||||
|
credentials JSONB NOT NULL DEFAULT '{}',
|
||||||
|
-- MercadoPago: { access_token, public_key, collector_id }
|
||||||
|
-- Clip: { api_key, secret_key, merchant_id }
|
||||||
|
|
||||||
|
-- Configuracion especifica del proveedor
|
||||||
|
config JSONB DEFAULT '{}',
|
||||||
|
-- MercadoPago: { statement_descriptor, notification_url }
|
||||||
|
-- Clip: { default_currency, webhook_secret }
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
is_verified BOOLEAN DEFAULT false,
|
||||||
|
verification_error TEXT,
|
||||||
|
verified_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Limites
|
||||||
|
daily_limit DECIMAL(12,2),
|
||||||
|
monthly_limit DECIMAL(12,2),
|
||||||
|
transaction_limit DECIMAL(12,2),
|
||||||
|
|
||||||
|
-- Webhook
|
||||||
|
webhook_url VARCHAR(500),
|
||||||
|
webhook_secret VARCHAR(255),
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
metadata JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
created_by UUID REFERENCES auth.users(id),
|
||||||
|
|
||||||
|
UNIQUE(tenant_id, provider, name)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- TABLA: terminal_payments
|
||||||
|
-- Transacciones procesadas por terminales TPV
|
||||||
|
-- =====================
|
||||||
|
CREATE TABLE IF NOT EXISTS payment_terminals.terminal_payments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Configuracion usada
|
||||||
|
config_id UUID REFERENCES payment_terminals.tenant_terminal_configs(id),
|
||||||
|
branch_terminal_id UUID, -- Referencia opcional a terminal de sucursal
|
||||||
|
|
||||||
|
-- Proveedor y referencia externa
|
||||||
|
provider payment_terminals.terminal_provider NOT NULL,
|
||||||
|
external_id VARCHAR(255),
|
||||||
|
external_status VARCHAR(50),
|
||||||
|
|
||||||
|
-- Monto
|
||||||
|
amount DECIMAL(12,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) DEFAULT 'MXN',
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status payment_terminals.terminal_payment_status DEFAULT 'pending',
|
||||||
|
|
||||||
|
-- Metodo de pago
|
||||||
|
payment_method payment_terminals.payment_method_type DEFAULT 'card',
|
||||||
|
|
||||||
|
-- Datos de tarjeta (parciales, no sensibles)
|
||||||
|
card_last_four VARCHAR(4),
|
||||||
|
card_brand VARCHAR(20),
|
||||||
|
card_type VARCHAR(20), -- credit, debit, prepaid
|
||||||
|
|
||||||
|
-- Cliente
|
||||||
|
customer_email VARCHAR(255),
|
||||||
|
customer_phone VARCHAR(20),
|
||||||
|
customer_name VARCHAR(200),
|
||||||
|
|
||||||
|
-- Descripcion
|
||||||
|
description TEXT,
|
||||||
|
statement_descriptor VARCHAR(50),
|
||||||
|
|
||||||
|
-- Referencia interna (orden, venta, etc.)
|
||||||
|
reference_type VARCHAR(50), -- sale, order, invoice
|
||||||
|
reference_id UUID,
|
||||||
|
|
||||||
|
-- Comisiones
|
||||||
|
fee_amount DECIMAL(10,4),
|
||||||
|
fee_details JSONB,
|
||||||
|
net_amount DECIMAL(12,2),
|
||||||
|
|
||||||
|
-- Reembolso
|
||||||
|
refunded_amount DECIMAL(12,2) DEFAULT 0,
|
||||||
|
refund_reason TEXT,
|
||||||
|
|
||||||
|
-- Respuesta del proveedor
|
||||||
|
provider_response JSONB,
|
||||||
|
|
||||||
|
-- Error
|
||||||
|
error_code VARCHAR(50),
|
||||||
|
error_message TEXT,
|
||||||
|
|
||||||
|
-- Timestamps
|
||||||
|
processed_at TIMESTAMPTZ,
|
||||||
|
refunded_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
metadata JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
created_by UUID REFERENCES auth.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- TABLA: terminal_webhook_events
|
||||||
|
-- Eventos de webhook recibidos
|
||||||
|
-- =====================
|
||||||
|
CREATE TABLE IF NOT EXISTS payment_terminals.terminal_webhook_events (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
||||||
|
|
||||||
|
-- Proveedor y evento
|
||||||
|
provider payment_terminals.terminal_provider NOT NULL,
|
||||||
|
event_type VARCHAR(100) NOT NULL,
|
||||||
|
event_id VARCHAR(255), -- ID del evento en el proveedor
|
||||||
|
|
||||||
|
-- Referencia
|
||||||
|
payment_id UUID REFERENCES payment_terminals.terminal_payments(id),
|
||||||
|
external_id VARCHAR(255),
|
||||||
|
|
||||||
|
-- Payload completo
|
||||||
|
payload JSONB NOT NULL,
|
||||||
|
headers JSONB,
|
||||||
|
|
||||||
|
-- Validacion de firma
|
||||||
|
signature_valid BOOLEAN,
|
||||||
|
|
||||||
|
-- Procesamiento
|
||||||
|
processed BOOLEAN DEFAULT false,
|
||||||
|
processed_at TIMESTAMPTZ,
|
||||||
|
processing_error TEXT,
|
||||||
|
retry_count INTEGER DEFAULT 0,
|
||||||
|
|
||||||
|
-- Idempotencia
|
||||||
|
idempotency_key VARCHAR(255),
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
UNIQUE(provider, event_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- TABLA: terminal_retry_queue
|
||||||
|
-- Cola de reintentos para operaciones fallidas
|
||||||
|
-- =====================
|
||||||
|
CREATE TABLE IF NOT EXISTS payment_terminals.terminal_retry_queue (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
||||||
|
|
||||||
|
-- Referencia
|
||||||
|
payment_id UUID REFERENCES payment_terminals.terminal_payments(id),
|
||||||
|
provider payment_terminals.terminal_provider NOT NULL,
|
||||||
|
|
||||||
|
-- Operacion
|
||||||
|
operation VARCHAR(50) NOT NULL, -- create_payment, refund, check_status
|
||||||
|
payload JSONB NOT NULL,
|
||||||
|
|
||||||
|
-- Reintentos
|
||||||
|
attempts INTEGER DEFAULT 0,
|
||||||
|
max_attempts INTEGER DEFAULT 5,
|
||||||
|
next_retry_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Error
|
||||||
|
last_error TEXT,
|
||||||
|
last_error_code VARCHAR(50),
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status VARCHAR(20) DEFAULT 'pending', -- pending, processing, completed, failed
|
||||||
|
completed_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- TABLA: terminal_payment_links
|
||||||
|
-- Links de pago generados
|
||||||
|
-- =====================
|
||||||
|
CREATE TABLE IF NOT EXISTS payment_terminals.terminal_payment_links (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
||||||
|
config_id UUID REFERENCES payment_terminals.tenant_terminal_configs(id),
|
||||||
|
|
||||||
|
-- Proveedor y referencia
|
||||||
|
provider payment_terminals.terminal_provider NOT NULL,
|
||||||
|
external_id VARCHAR(255),
|
||||||
|
|
||||||
|
-- URL del link
|
||||||
|
url VARCHAR(1000) NOT NULL,
|
||||||
|
short_url VARCHAR(500),
|
||||||
|
|
||||||
|
-- Monto
|
||||||
|
amount DECIMAL(12,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) DEFAULT 'MXN',
|
||||||
|
|
||||||
|
-- Descripcion
|
||||||
|
title VARCHAR(200),
|
||||||
|
description TEXT,
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status VARCHAR(30) DEFAULT 'active', -- active, paid, expired, cancelled
|
||||||
|
|
||||||
|
-- Pago asociado (cuando se paga)
|
||||||
|
payment_id UUID REFERENCES payment_terminals.terminal_payments(id),
|
||||||
|
|
||||||
|
-- Expiracion
|
||||||
|
expires_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Referencia interna
|
||||||
|
reference_type VARCHAR(50),
|
||||||
|
reference_id UUID,
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
metadata JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
created_by UUID REFERENCES auth.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- INDICES
|
||||||
|
-- =====================
|
||||||
|
|
||||||
|
-- tenant_terminal_configs
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_configs_tenant
|
||||||
|
ON payment_terminals.tenant_terminal_configs(tenant_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_configs_provider
|
||||||
|
ON payment_terminals.tenant_terminal_configs(provider);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_configs_active
|
||||||
|
ON payment_terminals.tenant_terminal_configs(is_active) WHERE is_active = true;
|
||||||
|
|
||||||
|
-- terminal_payments
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_tenant
|
||||||
|
ON payment_terminals.terminal_payments(tenant_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_provider
|
||||||
|
ON payment_terminals.terminal_payments(provider);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_status
|
||||||
|
ON payment_terminals.terminal_payments(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_external
|
||||||
|
ON payment_terminals.terminal_payments(external_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_reference
|
||||||
|
ON payment_terminals.terminal_payments(reference_type, reference_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_terminal_payments_created
|
||||||
|
ON payment_terminals.terminal_payments(created_at DESC);
|
||||||
|
|
||||||
|
-- terminal_webhook_events
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_webhook_events_tenant
|
||||||
|
ON payment_terminals.terminal_webhook_events(tenant_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_webhook_events_provider
|
||||||
|
ON payment_terminals.terminal_webhook_events(provider);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_webhook_events_processed
|
||||||
|
ON payment_terminals.terminal_webhook_events(processed, created_at)
|
||||||
|
WHERE processed = false;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_webhook_events_idempotency
|
||||||
|
ON payment_terminals.terminal_webhook_events(idempotency_key);
|
||||||
|
|
||||||
|
-- terminal_retry_queue
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_retry_queue_next
|
||||||
|
ON payment_terminals.terminal_retry_queue(next_retry_at)
|
||||||
|
WHERE status = 'pending';
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_retry_queue_tenant
|
||||||
|
ON payment_terminals.terminal_retry_queue(tenant_id);
|
||||||
|
|
||||||
|
-- terminal_payment_links
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_payment_links_tenant
|
||||||
|
ON payment_terminals.terminal_payment_links(tenant_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_payment_links_status
|
||||||
|
ON payment_terminals.terminal_payment_links(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_payment_links_expires
|
||||||
|
ON payment_terminals.terminal_payment_links(expires_at)
|
||||||
|
WHERE status = 'active';
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- RLS POLICIES
|
||||||
|
-- =====================
|
||||||
|
|
||||||
|
ALTER TABLE payment_terminals.tenant_terminal_configs ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE payment_terminals.terminal_payments ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE payment_terminals.terminal_webhook_events ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE payment_terminals.terminal_retry_queue ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE payment_terminals.terminal_payment_links ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- Politicas de aislamiento por tenant
|
||||||
|
CREATE POLICY tenant_configs_isolation ON payment_terminals.tenant_terminal_configs
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant', true)::UUID);
|
||||||
|
|
||||||
|
CREATE POLICY terminal_payments_isolation ON payment_terminals.terminal_payments
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant', true)::UUID);
|
||||||
|
|
||||||
|
CREATE POLICY webhook_events_isolation ON payment_terminals.terminal_webhook_events
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant', true)::UUID);
|
||||||
|
|
||||||
|
CREATE POLICY retry_queue_isolation ON payment_terminals.terminal_retry_queue
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant', true)::UUID);
|
||||||
|
|
||||||
|
CREATE POLICY payment_links_isolation ON payment_terminals.terminal_payment_links
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant', true)::UUID);
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- FUNCIONES
|
||||||
|
-- =====================
|
||||||
|
|
||||||
|
-- Funcion para calcular siguiente retry con backoff exponencial
|
||||||
|
CREATE OR REPLACE FUNCTION payment_terminals.calculate_next_retry(
|
||||||
|
p_attempts INTEGER,
|
||||||
|
p_base_delay_seconds INTEGER DEFAULT 60
|
||||||
|
) RETURNS TIMESTAMPTZ AS $$
|
||||||
|
BEGIN
|
||||||
|
RETURN NOW() + (p_base_delay_seconds * POWER(2, p_attempts)) * INTERVAL '1 second';
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Funcion para marcar pagos expirados
|
||||||
|
CREATE OR REPLACE FUNCTION payment_terminals.expire_old_pending_payments()
|
||||||
|
RETURNS INTEGER AS $$
|
||||||
|
DECLARE
|
||||||
|
affected_rows INTEGER;
|
||||||
|
BEGIN
|
||||||
|
UPDATE payment_terminals.terminal_payments
|
||||||
|
SET status = 'cancelled',
|
||||||
|
updated_at = NOW(),
|
||||||
|
error_message = 'Payment expired'
|
||||||
|
WHERE status = 'pending'
|
||||||
|
AND created_at < NOW() - INTERVAL '24 hours';
|
||||||
|
|
||||||
|
GET DIAGNOSTICS affected_rows = ROW_COUNT;
|
||||||
|
RETURN affected_rows;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Funcion para expirar links de pago
|
||||||
|
CREATE OR REPLACE FUNCTION payment_terminals.expire_payment_links()
|
||||||
|
RETURNS INTEGER AS $$
|
||||||
|
DECLARE
|
||||||
|
affected_rows INTEGER;
|
||||||
|
BEGIN
|
||||||
|
UPDATE payment_terminals.terminal_payment_links
|
||||||
|
SET status = 'expired',
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE status = 'active'
|
||||||
|
AND expires_at IS NOT NULL
|
||||||
|
AND expires_at < NOW();
|
||||||
|
|
||||||
|
GET DIAGNOSTICS affected_rows = ROW_COUNT;
|
||||||
|
RETURN affected_rows;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- =====================
|
||||||
|
-- COMENTARIOS
|
||||||
|
-- =====================
|
||||||
|
|
||||||
|
COMMENT ON SCHEMA payment_terminals IS 'Terminales de pago TPV (MercadoPago, Clip, Stripe Terminal) - Retail';
|
||||||
|
COMMENT ON TABLE payment_terminals.tenant_terminal_configs IS 'Configuracion de credenciales de proveedores TPV por tenant';
|
||||||
|
COMMENT ON TABLE payment_terminals.terminal_payments IS 'Transacciones procesadas por terminales TPV';
|
||||||
|
COMMENT ON TABLE payment_terminals.terminal_webhook_events IS 'Eventos de webhook recibidos de proveedores TPV';
|
||||||
|
COMMENT ON TABLE payment_terminals.terminal_retry_queue IS 'Cola de reintentos para operaciones fallidas';
|
||||||
|
COMMENT ON TABLE payment_terminals.terminal_payment_links IS 'Links de pago generados';
|
||||||
|
|
||||||
|
-- =============================================================
|
||||||
|
-- FIN DEL ARCHIVO
|
||||||
|
-- =============================================================
|
||||||
Loading…
Reference in New Issue
Block a user