The Procurement Calendar uses PostgreSQL via Supabase with a normalized relational schema. The database consists of catalog tables, a main requisitions table, an audit history table, and user profiles.
All tables use UUID primary keys generated with the uuid-ossp extension.
CREATE TABLE proveedores ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
CREATE TABLE productos ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, descripcion TEXT, activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
CREATE TABLE presentaciones ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
Warehouse locations or production lines where products are delivered.
CREATE TABLE destinos ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
Requisition status values with color coding for UI display.
CREATE TABLE estatus ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, color_hex TEXT NOT NULL DEFAULT '#6366F1', activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
Measurement units for quantities (kg, L, pzs, etc.).
CREATE TABLE unidades ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nombre TEXT NOT NULL, abreviatura TEXT NOT NULL, activo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());
CREATE OR REPLACE FUNCTION handle_new_user()RETURNS TRIGGER AS $$BEGIN INSERT INTO public.profiles (id, nombre_completo, rol) VALUES ( NEW.id, COALESCE(NEW.raw_user_meta_data->>'nombre_completo', NEW.email), COALESCE((NEW.raw_user_meta_data->>'rol')::user_role, 'consulta') ); RETURN NEW;END;$$ LANGUAGE plpgsql SECURITY DEFINER;CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION handle_new_user();
CREATE INDEX idx_requisiciones_fecha ON requisiciones(fecha_recepcion);CREATE INDEX idx_requisiciones_proveedor ON requisiciones(proveedor_id);CREATE INDEX idx_requisiciones_estatus ON requisiciones(estatus_id);CREATE INDEX idx_requisiciones_destino ON requisiciones(destino_id);
Indexes are created on frequently queried columns to optimize filtering and sorting operations.
The updated_at field is automatically maintained via trigger:
CREATE OR REPLACE FUNCTION update_updated_at()RETURNS TRIGGER AS $$BEGIN NEW.updated_at = NOW(); RETURN NEW;END;$$ LANGUAGE plpgsql;CREATE TRIGGER trg_requisiciones_updated_at BEFORE UPDATE ON requisiciones FOR EACH ROW EXECUTE FUNCTION update_updated_at();
Tracks all changes made to requisitions for audit purposes.
CREATE TABLE requisiciones_historial ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), requisicion_id UUID NOT NULL REFERENCES requisiciones(id) ON DELETE CASCADE, campo_modificado TEXT NOT NULL, valor_anterior TEXT, valor_nuevo TEXT, usuario_id UUID NOT NULL REFERENCES auth.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());CREATE INDEX idx_historial_requisicion ON requisiciones_historial(requisicion_id);