-- Los Libros Contables - FELDMAN v2.0 -- Tablas para milestones, bloques y validaciones -- MILESTONES CREATE TABLE IF NOT EXISTS milestones ( id BIGSERIAL PRIMARY KEY, h_milestone VARCHAR(64) NOT NULL UNIQUE, h_instancia VARCHAR(64) NOT NULL, secuencia BIGINT NOT NULL, hash_previo VARCHAR(64), hash_contenido VARCHAR(64) NOT NULL, alias VARCHAR(200) NOT NULL, tipo_item VARCHAR(50) NOT NULL, descripcion TEXT, datos JSONB DEFAULT '{}', etiqueta_principal VARCHAR(64), proyecto_tag VARCHAR(64), id_padre_milestone BIGINT REFERENCES milestones(id), id_bloque_asociado BIGINT, blockchain_pending BOOLEAN DEFAULT TRUE, blockchain_tx_ref VARCHAR(128), notario_batch_id VARCHAR(64), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(64), CONSTRAINT milestone_secuencia_unica UNIQUE (h_instancia, secuencia) ); -- BLOQUES CREATE TABLE IF NOT EXISTS bloques ( id BIGSERIAL PRIMARY KEY, h_bloque VARCHAR(64) NOT NULL UNIQUE, h_instancia VARCHAR(64) NOT NULL, secuencia BIGINT NOT NULL, hash_previo VARCHAR(64), hash_contenido VARCHAR(64) NOT NULL, alias VARCHAR(200) NOT NULL, tipo_accion VARCHAR(50) NOT NULL, descripcion TEXT, datos JSONB DEFAULT '{}', evidencia_hash VARCHAR(64) NOT NULL, evidencia_url VARCHAR(500) NOT NULL, evidencia_tipo VARCHAR(50) NOT NULL, etiqueta_principal VARCHAR(64), proyecto_tag VARCHAR(64), id_padre_bloque BIGINT REFERENCES bloques(id), id_milestone_asociado BIGINT REFERENCES milestones(id), blockchain_pending BOOLEAN DEFAULT TRUE, blockchain_tx_ref VARCHAR(128), notario_batch_id VARCHAR(64), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(64), CONSTRAINT bloque_secuencia_unica UNIQUE (h_instancia, secuencia) ); -- COLA DE VALIDACION CREATE TABLE IF NOT EXISTS feldman_cola ( id BIGSERIAL PRIMARY KEY, h_entrada VARCHAR(64) NOT NULL UNIQUE, h_instancia VARCHAR(64) NOT NULL, origen VARCHAR(50) NOT NULL, h_origen VARCHAR(64), tipo_destino VARCHAR(20) NOT NULL, datos JSONB NOT NULL, estado VARCHAR(20) DEFAULT 'pendiente', error_mensaje TEXT, intentos INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, processed_at TIMESTAMP ); -- VALIDACIONES CREATE TABLE IF NOT EXISTS feldman_validaciones ( id BIGSERIAL PRIMARY KEY, h_entrada VARCHAR(64) NOT NULL, validacion_ok BOOLEAN NOT NULL, reglas_aplicadas JSONB NOT NULL, tipo_registro VARCHAR(20), h_registro VARCHAR(64), validated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- INDICES CREATE INDEX IF NOT EXISTS idx_milestones_pending ON milestones(blockchain_pending) WHERE blockchain_pending = TRUE; CREATE INDEX IF NOT EXISTS idx_bloques_pending ON bloques(blockchain_pending) WHERE blockchain_pending = TRUE; CREATE INDEX IF NOT EXISTS idx_milestones_proyecto ON milestones(proyecto_tag); CREATE INDEX IF NOT EXISTS idx_bloques_proyecto ON bloques(proyecto_tag); CREATE INDEX IF NOT EXISTS idx_feldman_estado ON feldman_cola(estado); CREATE INDEX IF NOT EXISTS idx_feldman_instancia ON feldman_cola(h_instancia); -- FUNCIONES CREATE OR REPLACE FUNCTION get_ultimo_hash_milestone(p_h_instancia VARCHAR) RETURNS VARCHAR AS $$ DECLARE v_hash VARCHAR; BEGIN SELECT hash_contenido INTO v_hash FROM milestones WHERE h_instancia = p_h_instancia ORDER BY secuencia DESC LIMIT 1; RETURN COALESCE(v_hash, 'GENESIS'); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION get_ultimo_hash_bloque(p_h_instancia VARCHAR) RETURNS VARCHAR AS $$ DECLARE v_hash VARCHAR; BEGIN SELECT hash_contenido INTO v_hash FROM bloques WHERE h_instancia = p_h_instancia ORDER BY secuencia DESC LIMIT 1; RETURN COALESCE(v_hash, 'GENESIS'); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION get_siguiente_secuencia_milestone(p_h_instancia VARCHAR) RETURNS BIGINT AS $$ BEGIN RETURN (SELECT COALESCE(MAX(secuencia), 0) + 1 FROM milestones WHERE h_instancia = p_h_instancia); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION get_siguiente_secuencia_bloque(p_h_instancia VARCHAR) RETURNS BIGINT AS $$ BEGIN RETURN (SELECT COALESCE(MAX(secuencia), 0) + 1 FROM bloques WHERE h_instancia = p_h_instancia); END; $$ LANGUAGE plpgsql;