diff --git a/migrations/0004_lucky_skreet.sql b/migrations/0004_lucky_skreet.sql new file mode 100644 index 0000000..c9d164f --- /dev/null +++ b/migrations/0004_lucky_skreet.sql @@ -0,0 +1,31 @@ +CREATE TYPE "public"."scenario_variable_name" AS ENUM('siteCount', 'deliveriesPerWeek', 'instructionalWeeks');--> statement-breakpoint +CREATE TYPE "public"."exception_consequence" AS ENUM('price_delta', 'withdrawal', 'unquantified');--> statement-breakpoint +CREATE TYPE "public"."unpriced_reason" AS ENUM('shape_unsupported', 'input_missing', 'line_incomplete', 'withdrawal_conditioned');--> statement-breakpoint +CREATE TABLE "scenario_variable" ( + "scenario_id" uuid NOT NULL, + "name" "scenario_variable_name" NOT NULL, + "value" numeric(14, 3) NOT NULL, + CONSTRAINT "scenario_variable_scenario_id_name_pk" PRIMARY KEY("scenario_id","name") +); +--> statement-breakpoint +ALTER TABLE "scenario_variable" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "derived_cost" ALTER COLUMN "amount" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "evaluation_scenario" ADD COLUMN "monthly_weights" integer[];--> statement-breakpoint +ALTER TABLE "price_line" ADD COLUMN "required" boolean DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "reason" "unpriced_reason";--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "amount_if_declined" numeric(16, 2);--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "reason_if_declined" "unpriced_reason";--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "breakdown" jsonb NOT NULL;--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "evaluator_version" integer NOT NULL;--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "inputs_hash" text NOT NULL;--> statement-breakpoint +ALTER TABLE "derived_cost" ADD COLUMN "voided_by_amendment_id" uuid;--> statement-breakpoint +ALTER TABLE "exception" ADD COLUMN "target_section" text;--> statement-breakpoint +ALTER TABLE "exception" ADD COLUMN "labelled" boolean NOT NULL;--> statement-breakpoint +ALTER TABLE "exception" ADD COLUMN "consequence" "exception_consequence" NOT NULL;--> statement-breakpoint +ALTER TABLE "exception" ADD COLUMN "amount_if_declined" numeric(14, 2);--> statement-breakpoint +ALTER TABLE "price_quote" ADD COLUMN "attachment_document_id" uuid;--> statement-breakpoint +ALTER TABLE "scenario_variable" ADD CONSTRAINT "scenario_variable_scenario_id_evaluation_scenario_id_fk" FOREIGN KEY ("scenario_id") REFERENCES "public"."evaluation_scenario"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "price_quote" ADD CONSTRAINT "price_quote_attachment_document_id_response_document_id_fk" FOREIGN KEY ("attachment_document_id") REFERENCES "public"."response_document"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +CREATE POLICY "scenario_variable_read" ON "scenario_variable" AS PERMISSIVE FOR SELECT TO public USING (class_released(release_level_for_solicitation( + (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id) + ), 'scenario_quantity')); \ No newline at end of file diff --git a/migrations/0005_petite_selene.sql b/migrations/0005_petite_selene.sql new file mode 100644 index 0000000..01a6b25 --- /dev/null +++ b/migrations/0005_petite_selene.sql @@ -0,0 +1 @@ +ALTER TABLE "exception" DROP COLUMN "price_delta"; \ No newline at end of file diff --git a/migrations/meta/0004_snapshot.json b/migrations/meta/0004_snapshot.json new file mode 100644 index 0000000..3e7bb62 --- /dev/null +++ b/migrations/meta/0004_snapshot.json @@ -0,0 +1,3206 @@ +{ + "id": "a9fe26ae-065d-49b1-9ab2-791e76db9e70", + "prevId": "69fe6962-32d6-460e-8144-0055a2e84401", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.actor": { + "name": "actor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "actor_email_unique": { + "name": "actor_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.membership": { + "name": "membership", + "schema": "", + "columns": { + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "membership_actor_id_actor_id_fk": { + "name": "membership_actor_id_actor_id_fk", + "tableFrom": "membership", + "tableTo": "actor", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "membership_org_id_organization_id_fk": { + "name": "membership_org_id_organization_id_fk", + "tableFrom": "membership", + "tableTo": "organization", + "columnsFrom": [ + "org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "membership_actor_id_org_id_pk": { + "name": "membership_actor_id_org_id_pk", + "columns": [ + "actor_id", + "org_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.org_capability": { + "name": "org_capability", + "schema": "", + "columns": { + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "capability": { + "name": "capability", + "type": "capability", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "granted_at": { + "name": "granted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "org_capability_org_id_organization_id_fk": { + "name": "org_capability_org_id_organization_id_fk", + "tableFrom": "org_capability", + "tableTo": "organization", + "columnsFrom": [ + "org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "org_capability_org_id_capability_pk": { + "name": "org_capability_org_id_capability_pk", + "columns": [ + "org_id", + "capability" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "legal_name": { + "name": "legal_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.roster_entry": { + "name": "roster_entry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "contact_email": { + "name": "contact_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duns": { + "name": "duns", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claimed_vendor_org_id": { + "name": "claimed_vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "roster_entry_retailer_org_id_organization_id_fk": { + "name": "roster_entry_retailer_org_id_organization_id_fk", + "tableFrom": "roster_entry", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "roster_entry_claimed_vendor_org_id_organization_id_fk": { + "name": "roster_entry_claimed_vendor_org_id_organization_id_fk", + "tableFrom": "roster_entry", + "tableTo": "organization", + "columnsFrom": [ + "claimed_vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roster_entry_retailer_org_id_name_unique": { + "name": "roster_entry_retailer_org_id_name_unique", + "nullsNotDistinct": false, + "columns": [ + "retailer_org_id", + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.category_change_event": { + "name": "category_change_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "kind": { + "name": "kind", + "type": "category_change_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_ids": { + "name": "from_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true + }, + "to_ids": { + "name": "to_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "performed_by": { + "name": "performed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "performed_at": { + "name": "performed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "category_change_event_retailer_org_id_organization_id_fk": { + "name": "category_change_event_retailer_org_id_organization_id_fk", + "tableFrom": "category_change_event", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eligibility": { + "name": "eligibility", + "schema": "", + "columns": { + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "local_category_id": { + "name": "local_category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provenance": { + "name": "provenance", + "type": "grant_provenance", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "provenance_event_id": { + "name": "provenance_event_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "granted_at": { + "name": "granted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "eligibility_retailer_org_id_organization_id_fk": { + "name": "eligibility_retailer_org_id_organization_id_fk", + "tableFrom": "eligibility", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "eligibility_vendor_org_id_organization_id_fk": { + "name": "eligibility_vendor_org_id_organization_id_fk", + "tableFrom": "eligibility", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "eligibility_local_category_id_local_category_id_fk": { + "name": "eligibility_local_category_id_local_category_id_fk", + "tableFrom": "eligibility", + "tableTo": "local_category", + "columnsFrom": [ + "local_category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "eligibility_retailer_org_id_vendor_org_id_local_category_id_pk": { + "name": "eligibility_retailer_org_id_vendor_org_id_local_category_id_pk", + "columns": [ + "retailer_org_id", + "vendor_org_id", + "local_category_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.local_category": { + "name": "local_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "spine_leaf_id": { + "name": "spine_leaf_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "valid_from": { + "name": "valid_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "valid_to": { + "name": "valid_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "superseded_by": { + "name": "superseded_by", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "local_category_retailer_org_id_organization_id_fk": { + "name": "local_category_retailer_org_id_organization_id_fk", + "tableFrom": "local_category", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "local_category_spine_leaf_id_spine_node_id_fk": { + "name": "local_category_spine_leaf_id_spine_node_id_fk", + "tableFrom": "local_category", + "tableTo": "spine_node", + "columnsFrom": [ + "spine_leaf_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.spine_node": { + "name": "spine_node", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "unspsc_families": { + "name": "unspsc_families", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "valid_from": { + "name": "valid_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "valid_to": { + "name": "valid_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "superseded_by": { + "name": "superseded_by", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.criterion": { + "name": "criterion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "max_points": { + "name": "max_points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "weight": { + "name": "weight", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "scale_anchors": { + "name": "scale_anchors", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "criterion_solicitation_id_solicitation_id_fk": { + "name": "criterion_solicitation_id_solicitation_id_fk", + "tableFrom": "criterion", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "criterion_parent_id_criterion_id_fk": { + "name": "criterion_parent_id_criterion_id_fk", + "tableFrom": "criterion", + "tableTo": "criterion", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.criterion_requirement": { + "name": "criterion_requirement", + "schema": "", + "columns": { + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "frozen_at": { + "name": "frozen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "criterion_requirement_criterion_id_criterion_id_fk": { + "name": "criterion_requirement_criterion_id_criterion_id_fk", + "tableFrom": "criterion_requirement", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "criterion_requirement_requirement_id_requirement_id_fk": { + "name": "criterion_requirement_requirement_id_requirement_id_fk", + "tableFrom": "criterion_requirement", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "criterion_requirement_criterion_id_requirement_id_pk": { + "name": "criterion_requirement_criterion_id_requirement_id_pk", + "columns": [ + "criterion_id", + "requirement_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.evaluation_scenario": { + "name": "evaluation_scenario", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "declared_at": { + "name": "declared_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "monthly_weights": { + "name": "monthly_weights", + "type": "integer[]", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "evaluation_scenario_solicitation_id_solicitation_id_fk": { + "name": "evaluation_scenario_solicitation_id_solicitation_id_fk", + "tableFrom": "evaluation_scenario", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.price_line": { + "name": "price_line", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "unit": { + "name": "unit", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": {}, + "foreignKeys": { + "price_line_solicitation_id_solicitation_id_fk": { + "name": "price_line_solicitation_id_solicitation_id_fk", + "tableFrom": "price_line", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.requirement": { + "name": "requirement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ordinal": { + "name": "ordinal", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "requirement_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "response_obligation": { + "name": "response_obligation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provenance_document_id": { + "name": "provenance_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provenance_page": { + "name": "provenance_page", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provenance_span": { + "name": "provenance_span", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "determinable_from_response": { + "name": "determinable_from_response", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "confirmation_state": { + "name": "confirmation_state", + "type": "confirmation_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'unconfirmed'" + }, + "confirmed_by": { + "name": "confirmed_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "confirmed_at": { + "name": "confirmed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "requirement_solicitation_id_solicitation_id_fk": { + "name": "requirement_solicitation_id_solicitation_id_fk", + "tableFrom": "requirement", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "requirement_provenance_document_id_solicitation_document_id_fk": { + "name": "requirement_provenance_document_id_solicitation_document_id_fk", + "tableFrom": "requirement", + "tableTo": "solicitation_document", + "columnsFrom": [ + "provenance_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.scenario_quantity": { + "name": "scenario_quantity", + "schema": "", + "columns": { + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "price_line_id": { + "name": "price_line_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "numeric(14, 3)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "scenario_quantity_scenario_id_evaluation_scenario_id_fk": { + "name": "scenario_quantity_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "scenario_quantity", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "scenario_quantity_price_line_id_price_line_id_fk": { + "name": "scenario_quantity_price_line_id_price_line_id_fk", + "tableFrom": "scenario_quantity", + "tableTo": "price_line", + "columnsFrom": [ + "price_line_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "scenario_quantity_scenario_id_price_line_id_pk": { + "name": "scenario_quantity_scenario_id_price_line_id_pk", + "columns": [ + "scenario_id", + "price_line_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": { + "scenario_quantity_read": { + "name": "scenario_quantity_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_solicitation(\n (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id)\n ), 'scenario_quantity')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.scenario_variable": { + "name": "scenario_variable", + "schema": "", + "columns": { + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "scenario_variable_name", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "numeric(14, 3)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "scenario_variable_scenario_id_evaluation_scenario_id_fk": { + "name": "scenario_variable_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "scenario_variable", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "scenario_variable_scenario_id_name_pk": { + "name": "scenario_variable_scenario_id_name_pk", + "columns": [ + "scenario_id", + "name" + ] + } + }, + "uniqueConstraints": {}, + "policies": { + "scenario_variable_read": { + "name": "scenario_variable_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_solicitation(\n (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id)\n ), 'scenario_quantity')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.solicitation": { + "name": "solicitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issuer_org_id": { + "name": "issuer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "local_category_id": { + "name": "local_category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stage": { + "name": "stage", + "type": "solicitation_stage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "issued_at": { + "name": "issued_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "responses_due_at": { + "name": "responses_due_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "acknowledgement_required": { + "name": "acknowledgement_required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "volume_band": { + "name": "volume_band", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_issuer_org_id_organization_id_fk": { + "name": "solicitation_issuer_org_id_organization_id_fk", + "tableFrom": "solicitation", + "tableTo": "organization", + "columnsFrom": [ + "issuer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "solicitation_local_category_id_local_category_id_fk": { + "name": "solicitation_local_category_id_local_category_id_fk", + "tableFrom": "solicitation", + "tableTo": "local_category", + "columnsFrom": [ + "local_category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.solicitation_amendment": { + "name": "solicitation_amendment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "class": { + "name": "class", + "type": "amendment_class", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requirement_ids": { + "name": "requirement_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deadline_extended_to": { + "name": "deadline_extended_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_at": { + "name": "authored_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_amendment_solicitation_id_solicitation_id_fk": { + "name": "solicitation_amendment_solicitation_id_solicitation_id_fk", + "tableFrom": "solicitation_amendment", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.solicitation_document": { + "name": "solicitation_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_document_solicitation_id_solicitation_id_fk": { + "name": "solicitation_document_solicitation_id_solicitation_id_fk", + "tableFrom": "solicitation_document", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.answer": { + "name": "answer", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "coverage": { + "name": "coverage", + "type": "coverage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provenance_document_id": { + "name": "provenance_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provenance_page": { + "name": "provenance_page", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provenance_span": { + "name": "provenance_span", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "vendor_attested": { + "name": "vendor_attested", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "reopened_by_amendment_id": { + "name": "reopened_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "answer_response_id_response_id_fk": { + "name": "answer_response_id_response_id_fk", + "tableFrom": "answer", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "answer_requirement_id_requirement_id_fk": { + "name": "answer_requirement_id_requirement_id_fk", + "tableFrom": "answer", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "answer_provenance_document_id_response_document_id_fk": { + "name": "answer_provenance_document_id_response_document_id_fk", + "tableFrom": "answer", + "tableTo": "response_document", + "columnsFrom": [ + "provenance_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "answer_read": { + "name": "answer_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'answer_text')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.derived_cost": { + "name": "derived_cost", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "amount": { + "name": "amount", + "type": "numeric(16, 2)", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "unpriced_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "amount_if_declined": { + "name": "amount_if_declined", + "type": "numeric(16, 2)", + "primaryKey": false, + "notNull": false + }, + "reason_if_declined": { + "name": "reason_if_declined", + "type": "unpriced_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "breakdown": { + "name": "breakdown", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "evaluator_version": { + "name": "evaluator_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "inputs_hash": { + "name": "inputs_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "voided_by_amendment_id": { + "name": "voided_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "computed_at": { + "name": "computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "derived_cost_response_id_response_id_fk": { + "name": "derived_cost_response_id_response_id_fk", + "tableFrom": "derived_cost", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "derived_cost_scenario_id_evaluation_scenario_id_fk": { + "name": "derived_cost_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "derived_cost", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "derived_cost_read": { + "name": "derived_cost_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'derived_cost')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.exception": { + "name": "exception", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_section": { + "name": "target_section", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "labelled": { + "name": "labelled", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "consequence": { + "name": "consequence", + "type": "exception_consequence", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "amount_if_declined": { + "name": "amount_if_declined", + "type": "numeric(14, 2)", + "primaryKey": false, + "notNull": false + }, + "price_delta": { + "name": "price_delta", + "type": "numeric(14, 2)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "exception_response_id_response_id_fk": { + "name": "exception_response_id_response_id_fk", + "tableFrom": "exception", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "exception_requirement_id_requirement_id_fk": { + "name": "exception_requirement_id_requirement_id_fk", + "tableFrom": "exception", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "exception_read": { + "name": "exception_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'exception_text')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.participation": { + "name": "participation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "participation_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'invited'" + }, + "acknowledged_at": { + "name": "acknowledged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "participation_solicitation_id_solicitation_id_fk": { + "name": "participation_solicitation_id_solicitation_id_fk", + "tableFrom": "participation", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "participation_vendor_org_id_organization_id_fk": { + "name": "participation_vendor_org_id_organization_id_fk", + "tableFrom": "participation", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.price_quote": { + "name": "price_quote", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "price_line_id": { + "name": "price_line_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rate_structure": { + "name": "rate_structure", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "attachment_document_id": { + "name": "attachment_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "price_quote_response_id_response_id_fk": { + "name": "price_quote_response_id_response_id_fk", + "tableFrom": "price_quote", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "price_quote_price_line_id_price_line_id_fk": { + "name": "price_quote_price_line_id_price_line_id_fk", + "tableFrom": "price_quote", + "tableTo": "price_line", + "columnsFrom": [ + "price_line_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "price_quote_attachment_document_id_response_document_id_fk": { + "name": "price_quote_attachment_document_id_response_document_id_fk", + "tableFrom": "price_quote", + "tableTo": "response_document", + "columnsFrom": [ + "attachment_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "price_quote_read": { + "name": "price_quote_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'price_quote')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.response": { + "name": "response", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "submitted_at": { + "name": "submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "attested_by": { + "name": "attested_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "attested_at": { + "name": "attested_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "response_solicitation_id_solicitation_id_fk": { + "name": "response_solicitation_id_solicitation_id_fk", + "tableFrom": "response", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "response_vendor_org_id_organization_id_fk": { + "name": "response_vendor_org_id_organization_id_fk", + "tableFrom": "response", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.response_document": { + "name": "response_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "response_document_response_id_response_id_fk": { + "name": "response_document_response_id_response_id_fk", + "tableFrom": "response_document", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.gate_result": { + "name": "gate_result", + "schema": "", + "columns": { + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "passed": { + "name": "passed", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "computed_at": { + "name": "computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "gate_result_response_id_response_id_fk": { + "name": "gate_result_response_id_response_id_fk", + "tableFrom": "gate_result", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "gate_result_requirement_id_requirement_id_fk": { + "name": "gate_result_requirement_id_requirement_id_fk", + "tableFrom": "gate_result", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.rubric_amendment": { + "name": "rubric_amendment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "voided_score_ids": { + "name": "voided_score_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_at": { + "name": "authored_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.score": { + "name": "score", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "points": { + "name": "points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "committed_by": { + "name": "committed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "committed_at": { + "name": "committed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "derived_from_suggestion_id": { + "name": "derived_from_suggestion_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "voided_by_amendment_id": { + "name": "voided_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "score_response_id_response_id_fk": { + "name": "score_response_id_response_id_fk", + "tableFrom": "score", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "score_criterion_id_criterion_id_fk": { + "name": "score_criterion_id_criterion_id_fk", + "tableFrom": "score", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "score_derived_from_suggestion_id_suggestion_id_fk": { + "name": "score_derived_from_suggestion_id_suggestion_id_fk", + "tableFrom": "score", + "tableTo": "suggestion", + "columnsFrom": [ + "derived_from_suggestion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "score_read": { + "name": "score_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'own_scoring')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.suggestion": { + "name": "suggestion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "proposed_points": { + "name": "proposed_points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": false + }, + "anchor_matched": { + "name": "anchor_matched", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "citations": { + "name": "citations", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "confidence": { + "name": "confidence", + "type": "numeric(4, 3)", + "primaryKey": false, + "notNull": false + }, + "model_version": { + "name": "model_version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "no_evidence_found": { + "name": "no_evidence_found", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "suggestion_response_id_response_id_fk": { + "name": "suggestion_response_id_response_id_fk", + "tableFrom": "suggestion", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "suggestion_criterion_id_criterion_id_fk": { + "name": "suggestion_criterion_id_criterion_id_fk", + "tableFrom": "suggestion", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.export_event": { + "name": "export_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "capability": { + "name": "capability", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "classes": { + "name": "classes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "row_count": { + "name": "row_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "at": { + "name": "at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release_matrix": { + "name": "release_matrix", + "schema": "", + "columns": { + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "class": { + "name": "class", + "type": "disclosure_class", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "level": { + "name": "level", + "type": "release_level", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "released": { + "name": "released", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "effective_from": { + "name": "effective_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "release_matrix_version_class_level_pk": { + "name": "release_matrix_version_class_level_pk", + "columns": [ + "version", + "class", + "level" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.document_type": { + "name": "document_type", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiry_rule": { + "name": "expiry_rule", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.retailer_acceptance": { + "name": "retailer_acceptance", + "schema": "", + "columns": { + "document_id": { + "name": "document_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "accepted_at": { + "name": "accepted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "vendor_disclosed_name": { + "name": "vendor_disclosed_name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "retailer_acceptance_document_id_vault_document_id_fk": { + "name": "retailer_acceptance_document_id_vault_document_id_fk", + "tableFrom": "retailer_acceptance", + "tableTo": "vault_document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "retailer_acceptance_retailer_org_id_organization_id_fk": { + "name": "retailer_acceptance_retailer_org_id_organization_id_fk", + "tableFrom": "retailer_acceptance", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "retailer_acceptance_document_id_retailer_org_id_pk": { + "name": "retailer_acceptance_document_id_retailer_org_id_pk", + "columns": [ + "document_id", + "retailer_org_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.vault_document": { + "name": "vault_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type_id": { + "name": "type_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "expiry_state": { + "name": "expiry_state", + "type": "expiry_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'current'" + }, + "expiry_computed_at": { + "name": "expiry_computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "vault_document_vendor_org_id_organization_id_fk": { + "name": "vault_document_vendor_org_id_organization_id_fk", + "tableFrom": "vault_document", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vault_document_type_id_document_type_id_fk": { + "name": "vault_document_type_id_document_type_id_fk", + "tableFrom": "vault_document", + "tableTo": "document_type", + "columnsFrom": [ + "type_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.entitlement": { + "name": "entitlement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "beneficiary_org_id": { + "name": "beneficiary_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "payer_org_id": { + "name": "payer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tier": { + "name": "tier", + "type": "tier", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "lapsed_at": { + "name": "lapsed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "entitlement_beneficiary_org_id_organization_id_fk": { + "name": "entitlement_beneficiary_org_id_organization_id_fk", + "tableFrom": "entitlement", + "tableTo": "organization", + "columnsFrom": [ + "beneficiary_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "entitlement_payer_org_id_organization_id_fk": { + "name": "entitlement_payer_org_id_organization_id_fk", + "tableFrom": "entitlement", + "tableTo": "organization", + "columnsFrom": [ + "payer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.confirmation_event": { + "name": "confirmation_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "confirmed_by": { + "name": "confirmed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "corrected": { + "name": "corrected", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "at": { + "name": "at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "confirmation_event_requirement_id_requirement_id_fk": { + "name": "confirmation_event_requirement_id_requirement_id_fk", + "tableFrom": "confirmation_event", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sweep_finding": { + "name": "sweep_finding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "sweep_finding_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "page": { + "name": "page", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "span": { + "name": "span", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "quoted_text": { + "name": "quoted_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resolved_by_requirement_id": { + "name": "resolved_by_requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "dismissed_by": { + "name": "dismissed_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "dismissed_at": { + "name": "dismissed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sweep_finding_solicitation_id_solicitation_id_fk": { + "name": "sweep_finding_solicitation_id_solicitation_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "sweep_finding_document_id_solicitation_document_id_fk": { + "name": "sweep_finding_document_id_solicitation_document_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "solicitation_document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "sweep_finding_resolved_by_requirement_id_requirement_id_fk": { + "name": "sweep_finding_resolved_by_requirement_id_requirement_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "requirement", + "columnsFrom": [ + "resolved_by_requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.vendor_omission_report": { + "name": "vendor_omission_report", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reported_at": { + "name": "reported_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "acted_on_at": { + "name": "acted_on_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "acted_on_by": { + "name": "acted_on_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "vendor_omission_report_solicitation_id_solicitation_id_fk": { + "name": "vendor_omission_report_solicitation_id_solicitation_id_fk", + "tableFrom": "vendor_omission_report", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.capability": { + "name": "capability", + "schema": "public", + "values": [ + "issuer", + "vendor" + ] + }, + "public.category_change_kind": { + "name": "category_change_kind", + "schema": "public", + "values": [ + "split", + "merge", + "retire", + "remap" + ] + }, + "public.grant_provenance": { + "name": "grant_provenance", + "schema": "public", + "values": [ + "manual", + "split_event", + "merge_event" + ] + }, + "public.amendment_class": { + "name": "amendment_class", + "schema": "public", + "values": [ + "substantive", + "clarification" + ] + }, + "public.confirmation_state": { + "name": "confirmation_state", + "schema": "public", + "values": [ + "unconfirmed", + "confirmed", + "corrected" + ] + }, + "public.requirement_kind": { + "name": "requirement_kind", + "schema": "public", + "values": [ + "mandatory_gate", + "scored_criterion", + "certification_form", + "compliance_schedule", + "pricing", + "narrative" + ] + }, + "public.scenario_variable_name": { + "name": "scenario_variable_name", + "schema": "public", + "values": [ + "siteCount", + "deliveriesPerWeek", + "instructionalWeeks" + ] + }, + "public.solicitation_stage": { + "name": "solicitation_stage", + "schema": "public", + "values": [ + "draft", + "open", + "evaluating", + "finalists", + "awarded", + "cancelled" + ] + }, + "public.coverage": { + "name": "coverage", + "schema": "public", + "values": [ + "answered", + "not_answered", + "indeterminate" + ] + }, + "public.exception_consequence": { + "name": "exception_consequence", + "schema": "public", + "values": [ + "price_delta", + "withdrawal", + "unquantified" + ] + }, + "public.participation_state": { + "name": "participation_state", + "schema": "public", + "values": [ + "invited", + "opened", + "acknowledged", + "intends_to_bid", + "submitted", + "withdrawn" + ] + }, + "public.unpriced_reason": { + "name": "unpriced_reason", + "schema": "public", + "values": [ + "shape_unsupported", + "input_missing", + "line_incomplete", + "withdrawal_conditioned" + ] + }, + "public.disclosure_class": { + "name": "disclosure_class", + "schema": "public", + "values": [ + "vendor_identity", + "participation_signal", + "scenario_quantity", + "answer_text", + "exception_text", + "price_quote", + "derived_cost", + "vault_document", + "own_scoring" + ] + }, + "public.release_level": { + "name": "release_level", + "schema": "public", + "values": [ + "none", + "invited", + "acknowledged", + "submitted", + "open", + "evaluating", + "finalist", + "awarded" + ] + }, + "public.expiry_state": { + "name": "expiry_state", + "schema": "public", + "values": [ + "current", + "expiring_soon", + "expired" + ] + }, + "public.tier": { + "name": "tier", + "schema": "public", + "values": [ + "base", + "pro", + "enterprise" + ] + }, + "public.sweep_finding_kind": { + "name": "sweep_finding_kind", + "schema": "public", + "values": [ + "asserted_obligation", + "uncovered_span" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/0005_snapshot.json b/migrations/meta/0005_snapshot.json new file mode 100644 index 0000000..f53afc1 --- /dev/null +++ b/migrations/meta/0005_snapshot.json @@ -0,0 +1,3200 @@ +{ + "id": "cb16ceca-3055-4e26-ab0a-d2d0f11de639", + "prevId": "a9fe26ae-065d-49b1-9ab2-791e76db9e70", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.actor": { + "name": "actor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "actor_email_unique": { + "name": "actor_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.membership": { + "name": "membership", + "schema": "", + "columns": { + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "membership_actor_id_actor_id_fk": { + "name": "membership_actor_id_actor_id_fk", + "tableFrom": "membership", + "tableTo": "actor", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "membership_org_id_organization_id_fk": { + "name": "membership_org_id_organization_id_fk", + "tableFrom": "membership", + "tableTo": "organization", + "columnsFrom": [ + "org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "membership_actor_id_org_id_pk": { + "name": "membership_actor_id_org_id_pk", + "columns": [ + "actor_id", + "org_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.org_capability": { + "name": "org_capability", + "schema": "", + "columns": { + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "capability": { + "name": "capability", + "type": "capability", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "granted_at": { + "name": "granted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "org_capability_org_id_organization_id_fk": { + "name": "org_capability_org_id_organization_id_fk", + "tableFrom": "org_capability", + "tableTo": "organization", + "columnsFrom": [ + "org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "org_capability_org_id_capability_pk": { + "name": "org_capability_org_id_capability_pk", + "columns": [ + "org_id", + "capability" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "legal_name": { + "name": "legal_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.roster_entry": { + "name": "roster_entry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "contact_email": { + "name": "contact_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duns": { + "name": "duns", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claimed_vendor_org_id": { + "name": "claimed_vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "roster_entry_retailer_org_id_organization_id_fk": { + "name": "roster_entry_retailer_org_id_organization_id_fk", + "tableFrom": "roster_entry", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "roster_entry_claimed_vendor_org_id_organization_id_fk": { + "name": "roster_entry_claimed_vendor_org_id_organization_id_fk", + "tableFrom": "roster_entry", + "tableTo": "organization", + "columnsFrom": [ + "claimed_vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roster_entry_retailer_org_id_name_unique": { + "name": "roster_entry_retailer_org_id_name_unique", + "nullsNotDistinct": false, + "columns": [ + "retailer_org_id", + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.category_change_event": { + "name": "category_change_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "kind": { + "name": "kind", + "type": "category_change_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_ids": { + "name": "from_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true + }, + "to_ids": { + "name": "to_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "performed_by": { + "name": "performed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "performed_at": { + "name": "performed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "category_change_event_retailer_org_id_organization_id_fk": { + "name": "category_change_event_retailer_org_id_organization_id_fk", + "tableFrom": "category_change_event", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eligibility": { + "name": "eligibility", + "schema": "", + "columns": { + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "local_category_id": { + "name": "local_category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provenance": { + "name": "provenance", + "type": "grant_provenance", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "provenance_event_id": { + "name": "provenance_event_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "granted_at": { + "name": "granted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "eligibility_retailer_org_id_organization_id_fk": { + "name": "eligibility_retailer_org_id_organization_id_fk", + "tableFrom": "eligibility", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "eligibility_vendor_org_id_organization_id_fk": { + "name": "eligibility_vendor_org_id_organization_id_fk", + "tableFrom": "eligibility", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "eligibility_local_category_id_local_category_id_fk": { + "name": "eligibility_local_category_id_local_category_id_fk", + "tableFrom": "eligibility", + "tableTo": "local_category", + "columnsFrom": [ + "local_category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "eligibility_retailer_org_id_vendor_org_id_local_category_id_pk": { + "name": "eligibility_retailer_org_id_vendor_org_id_local_category_id_pk", + "columns": [ + "retailer_org_id", + "vendor_org_id", + "local_category_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.local_category": { + "name": "local_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "spine_leaf_id": { + "name": "spine_leaf_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "valid_from": { + "name": "valid_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "valid_to": { + "name": "valid_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "superseded_by": { + "name": "superseded_by", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "local_category_retailer_org_id_organization_id_fk": { + "name": "local_category_retailer_org_id_organization_id_fk", + "tableFrom": "local_category", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "local_category_spine_leaf_id_spine_node_id_fk": { + "name": "local_category_spine_leaf_id_spine_node_id_fk", + "tableFrom": "local_category", + "tableTo": "spine_node", + "columnsFrom": [ + "spine_leaf_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.spine_node": { + "name": "spine_node", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "unspsc_families": { + "name": "unspsc_families", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "valid_from": { + "name": "valid_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "valid_to": { + "name": "valid_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "superseded_by": { + "name": "superseded_by", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.criterion": { + "name": "criterion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "max_points": { + "name": "max_points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "weight": { + "name": "weight", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "scale_anchors": { + "name": "scale_anchors", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "criterion_solicitation_id_solicitation_id_fk": { + "name": "criterion_solicitation_id_solicitation_id_fk", + "tableFrom": "criterion", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "criterion_parent_id_criterion_id_fk": { + "name": "criterion_parent_id_criterion_id_fk", + "tableFrom": "criterion", + "tableTo": "criterion", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.criterion_requirement": { + "name": "criterion_requirement", + "schema": "", + "columns": { + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "frozen_at": { + "name": "frozen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "criterion_requirement_criterion_id_criterion_id_fk": { + "name": "criterion_requirement_criterion_id_criterion_id_fk", + "tableFrom": "criterion_requirement", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "criterion_requirement_requirement_id_requirement_id_fk": { + "name": "criterion_requirement_requirement_id_requirement_id_fk", + "tableFrom": "criterion_requirement", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "criterion_requirement_criterion_id_requirement_id_pk": { + "name": "criterion_requirement_criterion_id_requirement_id_pk", + "columns": [ + "criterion_id", + "requirement_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.evaluation_scenario": { + "name": "evaluation_scenario", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "declared_at": { + "name": "declared_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "monthly_weights": { + "name": "monthly_weights", + "type": "integer[]", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "evaluation_scenario_solicitation_id_solicitation_id_fk": { + "name": "evaluation_scenario_solicitation_id_solicitation_id_fk", + "tableFrom": "evaluation_scenario", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.price_line": { + "name": "price_line", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "unit": { + "name": "unit", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": {}, + "foreignKeys": { + "price_line_solicitation_id_solicitation_id_fk": { + "name": "price_line_solicitation_id_solicitation_id_fk", + "tableFrom": "price_line", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.requirement": { + "name": "requirement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ordinal": { + "name": "ordinal", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "requirement_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "response_obligation": { + "name": "response_obligation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provenance_document_id": { + "name": "provenance_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provenance_page": { + "name": "provenance_page", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provenance_span": { + "name": "provenance_span", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "determinable_from_response": { + "name": "determinable_from_response", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "confirmation_state": { + "name": "confirmation_state", + "type": "confirmation_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'unconfirmed'" + }, + "confirmed_by": { + "name": "confirmed_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "confirmed_at": { + "name": "confirmed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "requirement_solicitation_id_solicitation_id_fk": { + "name": "requirement_solicitation_id_solicitation_id_fk", + "tableFrom": "requirement", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "requirement_provenance_document_id_solicitation_document_id_fk": { + "name": "requirement_provenance_document_id_solicitation_document_id_fk", + "tableFrom": "requirement", + "tableTo": "solicitation_document", + "columnsFrom": [ + "provenance_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.scenario_quantity": { + "name": "scenario_quantity", + "schema": "", + "columns": { + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "price_line_id": { + "name": "price_line_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "numeric(14, 3)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "scenario_quantity_scenario_id_evaluation_scenario_id_fk": { + "name": "scenario_quantity_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "scenario_quantity", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "scenario_quantity_price_line_id_price_line_id_fk": { + "name": "scenario_quantity_price_line_id_price_line_id_fk", + "tableFrom": "scenario_quantity", + "tableTo": "price_line", + "columnsFrom": [ + "price_line_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "scenario_quantity_scenario_id_price_line_id_pk": { + "name": "scenario_quantity_scenario_id_price_line_id_pk", + "columns": [ + "scenario_id", + "price_line_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": { + "scenario_quantity_read": { + "name": "scenario_quantity_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_solicitation(\n (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id)\n ), 'scenario_quantity')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.scenario_variable": { + "name": "scenario_variable", + "schema": "", + "columns": { + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "scenario_variable_name", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "numeric(14, 3)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "scenario_variable_scenario_id_evaluation_scenario_id_fk": { + "name": "scenario_variable_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "scenario_variable", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "scenario_variable_scenario_id_name_pk": { + "name": "scenario_variable_scenario_id_name_pk", + "columns": [ + "scenario_id", + "name" + ] + } + }, + "uniqueConstraints": {}, + "policies": { + "scenario_variable_read": { + "name": "scenario_variable_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_solicitation(\n (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id)\n ), 'scenario_quantity')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.solicitation": { + "name": "solicitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issuer_org_id": { + "name": "issuer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "local_category_id": { + "name": "local_category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stage": { + "name": "stage", + "type": "solicitation_stage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "issued_at": { + "name": "issued_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "responses_due_at": { + "name": "responses_due_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "acknowledgement_required": { + "name": "acknowledgement_required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "volume_band": { + "name": "volume_band", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_issuer_org_id_organization_id_fk": { + "name": "solicitation_issuer_org_id_organization_id_fk", + "tableFrom": "solicitation", + "tableTo": "organization", + "columnsFrom": [ + "issuer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "solicitation_local_category_id_local_category_id_fk": { + "name": "solicitation_local_category_id_local_category_id_fk", + "tableFrom": "solicitation", + "tableTo": "local_category", + "columnsFrom": [ + "local_category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.solicitation_amendment": { + "name": "solicitation_amendment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "class": { + "name": "class", + "type": "amendment_class", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requirement_ids": { + "name": "requirement_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deadline_extended_to": { + "name": "deadline_extended_to", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_at": { + "name": "authored_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_amendment_solicitation_id_solicitation_id_fk": { + "name": "solicitation_amendment_solicitation_id_solicitation_id_fk", + "tableFrom": "solicitation_amendment", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.solicitation_document": { + "name": "solicitation_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "solicitation_document_solicitation_id_solicitation_id_fk": { + "name": "solicitation_document_solicitation_id_solicitation_id_fk", + "tableFrom": "solicitation_document", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.answer": { + "name": "answer", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "coverage": { + "name": "coverage", + "type": "coverage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provenance_document_id": { + "name": "provenance_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provenance_page": { + "name": "provenance_page", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provenance_span": { + "name": "provenance_span", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "vendor_attested": { + "name": "vendor_attested", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "reopened_by_amendment_id": { + "name": "reopened_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "answer_response_id_response_id_fk": { + "name": "answer_response_id_response_id_fk", + "tableFrom": "answer", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "answer_requirement_id_requirement_id_fk": { + "name": "answer_requirement_id_requirement_id_fk", + "tableFrom": "answer", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "answer_provenance_document_id_response_document_id_fk": { + "name": "answer_provenance_document_id_response_document_id_fk", + "tableFrom": "answer", + "tableTo": "response_document", + "columnsFrom": [ + "provenance_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "answer_read": { + "name": "answer_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'answer_text')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.derived_cost": { + "name": "derived_cost", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scenario_id": { + "name": "scenario_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "amount": { + "name": "amount", + "type": "numeric(16, 2)", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "unpriced_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "amount_if_declined": { + "name": "amount_if_declined", + "type": "numeric(16, 2)", + "primaryKey": false, + "notNull": false + }, + "reason_if_declined": { + "name": "reason_if_declined", + "type": "unpriced_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "breakdown": { + "name": "breakdown", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "evaluator_version": { + "name": "evaluator_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "inputs_hash": { + "name": "inputs_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "voided_by_amendment_id": { + "name": "voided_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "computed_at": { + "name": "computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "derived_cost_response_id_response_id_fk": { + "name": "derived_cost_response_id_response_id_fk", + "tableFrom": "derived_cost", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "derived_cost_scenario_id_evaluation_scenario_id_fk": { + "name": "derived_cost_scenario_id_evaluation_scenario_id_fk", + "tableFrom": "derived_cost", + "tableTo": "evaluation_scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "derived_cost_read": { + "name": "derived_cost_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'derived_cost')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.exception": { + "name": "exception", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_section": { + "name": "target_section", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "labelled": { + "name": "labelled", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "consequence": { + "name": "consequence", + "type": "exception_consequence", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "amount_if_declined": { + "name": "amount_if_declined", + "type": "numeric(14, 2)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "exception_response_id_response_id_fk": { + "name": "exception_response_id_response_id_fk", + "tableFrom": "exception", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "exception_requirement_id_requirement_id_fk": { + "name": "exception_requirement_id_requirement_id_fk", + "tableFrom": "exception", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "exception_read": { + "name": "exception_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'exception_text')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.participation": { + "name": "participation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "participation_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'invited'" + }, + "acknowledged_at": { + "name": "acknowledged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "participation_solicitation_id_solicitation_id_fk": { + "name": "participation_solicitation_id_solicitation_id_fk", + "tableFrom": "participation", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "participation_vendor_org_id_organization_id_fk": { + "name": "participation_vendor_org_id_organization_id_fk", + "tableFrom": "participation", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.price_quote": { + "name": "price_quote", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "price_line_id": { + "name": "price_line_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rate_structure": { + "name": "rate_structure", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "attachment_document_id": { + "name": "attachment_document_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "price_quote_response_id_response_id_fk": { + "name": "price_quote_response_id_response_id_fk", + "tableFrom": "price_quote", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "price_quote_price_line_id_price_line_id_fk": { + "name": "price_quote_price_line_id_price_line_id_fk", + "tableFrom": "price_quote", + "tableTo": "price_line", + "columnsFrom": [ + "price_line_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "price_quote_attachment_document_id_response_document_id_fk": { + "name": "price_quote_attachment_document_id_response_document_id_fk", + "tableFrom": "price_quote", + "tableTo": "response_document", + "columnsFrom": [ + "attachment_document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "price_quote_read": { + "name": "price_quote_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'price_quote')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.response": { + "name": "response", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "submitted_at": { + "name": "submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "attested_by": { + "name": "attested_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "attested_at": { + "name": "attested_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "response_solicitation_id_solicitation_id_fk": { + "name": "response_solicitation_id_solicitation_id_fk", + "tableFrom": "response", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "response_vendor_org_id_organization_id_fk": { + "name": "response_vendor_org_id_organization_id_fk", + "tableFrom": "response", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.response_document": { + "name": "response_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "response_document_response_id_response_id_fk": { + "name": "response_document_response_id_response_id_fk", + "tableFrom": "response_document", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.gate_result": { + "name": "gate_result", + "schema": "", + "columns": { + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "passed": { + "name": "passed", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "computed_at": { + "name": "computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "gate_result_response_id_response_id_fk": { + "name": "gate_result_response_id_response_id_fk", + "tableFrom": "gate_result", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "gate_result_requirement_id_requirement_id_fk": { + "name": "gate_result_requirement_id_requirement_id_fk", + "tableFrom": "gate_result", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.rubric_amendment": { + "name": "rubric_amendment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "voided_score_ids": { + "name": "voided_score_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "authored_by": { + "name": "authored_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authored_at": { + "name": "authored_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.score": { + "name": "score", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "points": { + "name": "points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true + }, + "committed_by": { + "name": "committed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "committed_at": { + "name": "committed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "derived_from_suggestion_id": { + "name": "derived_from_suggestion_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "voided_by_amendment_id": { + "name": "voided_by_amendment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "score_response_id_response_id_fk": { + "name": "score_response_id_response_id_fk", + "tableFrom": "score", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "score_criterion_id_criterion_id_fk": { + "name": "score_criterion_id_criterion_id_fk", + "tableFrom": "score", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "score_derived_from_suggestion_id_suggestion_id_fk": { + "name": "score_derived_from_suggestion_id_suggestion_id_fk", + "tableFrom": "score", + "tableTo": "suggestion", + "columnsFrom": [ + "derived_from_suggestion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": { + "score_read": { + "name": "score_read", + "as": "PERMISSIVE", + "for": "SELECT", + "to": [ + "public" + ], + "using": "class_released(release_level_for_response(response_id), 'own_scoring')" + } + }, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.suggestion": { + "name": "suggestion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "criterion_id": { + "name": "criterion_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "proposed_points": { + "name": "proposed_points", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": false + }, + "anchor_matched": { + "name": "anchor_matched", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "citations": { + "name": "citations", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "confidence": { + "name": "confidence", + "type": "numeric(4, 3)", + "primaryKey": false, + "notNull": false + }, + "model_version": { + "name": "model_version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "no_evidence_found": { + "name": "no_evidence_found", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "suggestion_response_id_response_id_fk": { + "name": "suggestion_response_id_response_id_fk", + "tableFrom": "suggestion", + "tableTo": "response", + "columnsFrom": [ + "response_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "suggestion_criterion_id_criterion_id_fk": { + "name": "suggestion_criterion_id_criterion_id_fk", + "tableFrom": "suggestion", + "tableTo": "criterion", + "columnsFrom": [ + "criterion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.export_event": { + "name": "export_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "capability": { + "name": "capability", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "classes": { + "name": "classes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "row_count": { + "name": "row_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "at": { + "name": "at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release_matrix": { + "name": "release_matrix", + "schema": "", + "columns": { + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "class": { + "name": "class", + "type": "disclosure_class", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "level": { + "name": "level", + "type": "release_level", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "released": { + "name": "released", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "effective_from": { + "name": "effective_from", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "release_matrix_version_class_level_pk": { + "name": "release_matrix_version_class_level_pk", + "columns": [ + "version", + "class", + "level" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.document_type": { + "name": "document_type", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiry_rule": { + "name": "expiry_rule", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.retailer_acceptance": { + "name": "retailer_acceptance", + "schema": "", + "columns": { + "document_id": { + "name": "document_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "retailer_org_id": { + "name": "retailer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "accepted_at": { + "name": "accepted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "vendor_disclosed_name": { + "name": "vendor_disclosed_name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "retailer_acceptance_document_id_vault_document_id_fk": { + "name": "retailer_acceptance_document_id_vault_document_id_fk", + "tableFrom": "retailer_acceptance", + "tableTo": "vault_document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "retailer_acceptance_retailer_org_id_organization_id_fk": { + "name": "retailer_acceptance_retailer_org_id_organization_id_fk", + "tableFrom": "retailer_acceptance", + "tableTo": "organization", + "columnsFrom": [ + "retailer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "retailer_acceptance_document_id_retailer_org_id_pk": { + "name": "retailer_acceptance_document_id_retailer_org_id_pk", + "columns": [ + "document_id", + "retailer_org_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.vault_document": { + "name": "vault_document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type_id": { + "name": "type_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "blob_ref": { + "name": "blob_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "expiry_state": { + "name": "expiry_state", + "type": "expiry_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'current'" + }, + "expiry_computed_at": { + "name": "expiry_computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "vault_document_vendor_org_id_organization_id_fk": { + "name": "vault_document_vendor_org_id_organization_id_fk", + "tableFrom": "vault_document", + "tableTo": "organization", + "columnsFrom": [ + "vendor_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vault_document_type_id_document_type_id_fk": { + "name": "vault_document_type_id_document_type_id_fk", + "tableFrom": "vault_document", + "tableTo": "document_type", + "columnsFrom": [ + "type_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.entitlement": { + "name": "entitlement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "beneficiary_org_id": { + "name": "beneficiary_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "payer_org_id": { + "name": "payer_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tier": { + "name": "tier", + "type": "tier", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "lapsed_at": { + "name": "lapsed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "entitlement_beneficiary_org_id_organization_id_fk": { + "name": "entitlement_beneficiary_org_id_organization_id_fk", + "tableFrom": "entitlement", + "tableTo": "organization", + "columnsFrom": [ + "beneficiary_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "entitlement_payer_org_id_organization_id_fk": { + "name": "entitlement_payer_org_id_organization_id_fk", + "tableFrom": "entitlement", + "tableTo": "organization", + "columnsFrom": [ + "payer_org_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.confirmation_event": { + "name": "confirmation_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "requirement_id": { + "name": "requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "confirmed_by": { + "name": "confirmed_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "corrected": { + "name": "corrected", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "at": { + "name": "at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "confirmation_event_requirement_id_requirement_id_fk": { + "name": "confirmation_event_requirement_id_requirement_id_fk", + "tableFrom": "confirmation_event", + "tableTo": "requirement", + "columnsFrom": [ + "requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sweep_finding": { + "name": "sweep_finding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "sweep_finding_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "page": { + "name": "page", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "span": { + "name": "span", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "quoted_text": { + "name": "quoted_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resolved_by_requirement_id": { + "name": "resolved_by_requirement_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "dismissed_by": { + "name": "dismissed_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "dismissed_at": { + "name": "dismissed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sweep_finding_solicitation_id_solicitation_id_fk": { + "name": "sweep_finding_solicitation_id_solicitation_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "sweep_finding_document_id_solicitation_document_id_fk": { + "name": "sweep_finding_document_id_solicitation_document_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "solicitation_document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "sweep_finding_resolved_by_requirement_id_requirement_id_fk": { + "name": "sweep_finding_resolved_by_requirement_id_requirement_id_fk", + "tableFrom": "sweep_finding", + "tableTo": "requirement", + "columnsFrom": [ + "resolved_by_requirement_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.vendor_omission_report": { + "name": "vendor_omission_report", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "solicitation_id": { + "name": "solicitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "vendor_org_id": { + "name": "vendor_org_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reported_at": { + "name": "reported_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "acted_on_at": { + "name": "acted_on_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "acted_on_by": { + "name": "acted_on_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "vendor_omission_report_solicitation_id_solicitation_id_fk": { + "name": "vendor_omission_report_solicitation_id_solicitation_id_fk", + "tableFrom": "vendor_omission_report", + "tableTo": "solicitation", + "columnsFrom": [ + "solicitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.capability": { + "name": "capability", + "schema": "public", + "values": [ + "issuer", + "vendor" + ] + }, + "public.category_change_kind": { + "name": "category_change_kind", + "schema": "public", + "values": [ + "split", + "merge", + "retire", + "remap" + ] + }, + "public.grant_provenance": { + "name": "grant_provenance", + "schema": "public", + "values": [ + "manual", + "split_event", + "merge_event" + ] + }, + "public.amendment_class": { + "name": "amendment_class", + "schema": "public", + "values": [ + "substantive", + "clarification" + ] + }, + "public.confirmation_state": { + "name": "confirmation_state", + "schema": "public", + "values": [ + "unconfirmed", + "confirmed", + "corrected" + ] + }, + "public.requirement_kind": { + "name": "requirement_kind", + "schema": "public", + "values": [ + "mandatory_gate", + "scored_criterion", + "certification_form", + "compliance_schedule", + "pricing", + "narrative" + ] + }, + "public.scenario_variable_name": { + "name": "scenario_variable_name", + "schema": "public", + "values": [ + "siteCount", + "deliveriesPerWeek", + "instructionalWeeks" + ] + }, + "public.solicitation_stage": { + "name": "solicitation_stage", + "schema": "public", + "values": [ + "draft", + "open", + "evaluating", + "finalists", + "awarded", + "cancelled" + ] + }, + "public.coverage": { + "name": "coverage", + "schema": "public", + "values": [ + "answered", + "not_answered", + "indeterminate" + ] + }, + "public.exception_consequence": { + "name": "exception_consequence", + "schema": "public", + "values": [ + "price_delta", + "withdrawal", + "unquantified" + ] + }, + "public.participation_state": { + "name": "participation_state", + "schema": "public", + "values": [ + "invited", + "opened", + "acknowledged", + "intends_to_bid", + "submitted", + "withdrawn" + ] + }, + "public.unpriced_reason": { + "name": "unpriced_reason", + "schema": "public", + "values": [ + "shape_unsupported", + "input_missing", + "line_incomplete", + "withdrawal_conditioned" + ] + }, + "public.disclosure_class": { + "name": "disclosure_class", + "schema": "public", + "values": [ + "vendor_identity", + "participation_signal", + "scenario_quantity", + "answer_text", + "exception_text", + "price_quote", + "derived_cost", + "vault_document", + "own_scoring" + ] + }, + "public.release_level": { + "name": "release_level", + "schema": "public", + "values": [ + "none", + "invited", + "acknowledged", + "submitted", + "open", + "evaluating", + "finalist", + "awarded" + ] + }, + "public.expiry_state": { + "name": "expiry_state", + "schema": "public", + "values": [ + "current", + "expiring_soon", + "expired" + ] + }, + "public.tier": { + "name": "tier", + "schema": "public", + "values": [ + "base", + "pro", + "enterprise" + ] + }, + "public.sweep_finding_kind": { + "name": "sweep_finding_kind", + "schema": "public", + "values": [ + "asserted_obligation", + "uncovered_span" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json index 7bad668..f2e43bc 100644 --- a/migrations/meta/_journal.json +++ b/migrations/meta/_journal.json @@ -29,6 +29,20 @@ "when": 1785797388491, "tag": "0003_criterion_nesting_and_determinability", "breakpoints": true + }, + { + "idx": 4, + "version": "7", + "when": 1785825133701, + "tag": "0004_lucky_skreet", + "breakpoints": true + }, + { + "idx": 5, + "version": "7", + "when": 1785825144805, + "tag": "0005_petite_selene", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package.json b/package.json index 0f758c8..6ff068f 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,14 @@ "version": "0.0.0", "private": true, "type": "module", - "description": "Retail RFP transmission system — v1 code layout", + "description": "Retail RFP transmission system \u2014 v1 code layout", "scripts": { "typecheck": "tsc --noEmit", "generate": "drizzle-kit generate", "generate:custom": "drizzle-kit generate --custom", "migrate": "drizzle-kit migrate", - "seams": "grep -rn 'new Seam(' src/ --include=*.ts" + "seams": "grep -rn 'new Seam(' src/ --include=*.ts", + "check:pricing": "tsx src/pricing/corpus-check.ts" }, "dependencies": { "drizzle-orm": "^0.45.2", @@ -18,6 +19,7 @@ "devDependencies": { "@types/node": "^22.10.0", "drizzle-kit": "^0.31.10", + "tsx": "^4.23.5", "typescript": "^5.7.0" } } diff --git a/src/db/schema/response.ts b/src/db/schema/response.ts index 00a8bb5..428e5ef 100644 --- a/src/db/schema/response.ts +++ b/src/db/schema/response.ts @@ -2,6 +2,8 @@ import { sql } from 'drizzle-orm' import { boolean, integer, jsonb, numeric, pgEnum, pgPolicy, pgTable, text, timestamp, uuid, } from 'drizzle-orm/pg-core' +import type { Derivation } from '../../pricing/evaluate.js' +import type { RateStructure } from '../../pricing/rate.js' import { organization } from './org.js' import { evaluationScenario, priceLine, requirement, solicitation } from './solicitation.js' @@ -66,13 +68,42 @@ export const answer = pgTable('answer', { }), ]).enableRLS() +/** + * The consequence of an exception being DECLINED. Closed by #29. + * + * A nullable price delta was the obvious model and the wrong one. Anacostia + * labels three exceptions; two carry deltas, and the third says that if + * declined the vendor cannot bid produce at all. A nullable delta reads that + * third one as "no cost impact" — the inverse of the truth, on the most + * consequential of the three. + */ +export const exceptionConsequence = pgEnum('exception_consequence', [ + 'price_delta', 'withdrawal', 'unquantified', +]) + /** Simultaneously a risk flag and a pricing line (#22). */ export const exception = pgTable('exception', { id: uuid('id').primaryKey().defaultRandom(), responseId: uuid('response_id').notNull().references(() => response.id), requirementId: uuid('requirement_id').references(() => requirement.id), + /** + * Set when the exception targets a document section the extractor never + * enumerated as a requirement — Anacostia's EX-3 points at C.3, which the + * truth file does not carry. That makes exceptions a completeness signal + * feeding #16's sweep, not merely a response field. + */ + targetSection: text('target_section'), text: text('text').notNull(), - priceDelta: numeric('price_delta', { precision: 14, scale: 2 }), + /** + * False = found in prose with no heading and no delta, like Chesapeake's + * polite request inside the Pricing section. Detecting it is valuable; + * PRICING it would be a model deciding (#15), so an unlabelled exception + * never moves arithmetic — it routes to a human as a finding. + */ + labelled: boolean('labelled').notNull(), + consequence: exceptionConsequence('consequence').notNull(), + /** Set only for `price_delta`. */ + amountIfDeclined: numeric('amount_if_declined', { precision: 14, scale: 2 }), }, () => [ pgPolicy('exception_read', { for: 'select', @@ -88,7 +119,15 @@ export const priceQuote = pgTable('price_quote', { id: uuid('id').primaryKey().defaultRandom(), responseId: uuid('response_id').notNull().references(() => response.id), priceLineId: uuid('price_line_id').notNull().references(() => priceLine.id), - rateStructure: jsonb('rate_structure').notNull(), + /** + * One base schedule plus closed modifiers — see src/pricing/rate.ts. Money + * leaves are nullable ON PURPOSE: Chesapeake's shape is fully supported and + * its unit price simply is not in the document, and "supported shape, + * missing field" is recoverable in a way "unrepresentable shape" is not. + */ + rateStructure: jsonb('rate_structure').$type().notNull(), + /** Set when no supported shape represents this quote; the document stands in its place. */ + attachmentDocumentId: uuid('attachment_document_id').references(() => responseDocument.id), }, () => [ pgPolicy('price_quote_read', { for: 'select', @@ -101,11 +140,51 @@ export const priceQuote = pgTable('price_quote', { * Requirements contracts carry estimate-only quantities (#22), so anything * presenting this as contract value misrepresents comparability (#15). */ +export const unpricedReason = pgEnum('unpriced_reason', [ + 'shape_unsupported', 'input_missing', 'line_incomplete', 'withdrawal_conditioned', +]) + export const derivedCost = pgTable('derived_cost', { id: uuid('id').primaryKey().defaultRandom(), responseId: uuid('response_id').notNull().references(() => response.id), scenarioId: uuid('scenario_id').notNull().references(() => evaluationScenario.id), - amount: numeric('amount', { precision: 16, scale: 2 }).notNull(), + /** + * NULLABLE, and that is the decision. A price that cannot be computed is not + * zero — zero silently disqualifies on arithmetic — and it is not the + * vendor's own stated figure either. Chesapeake states the lowest number in + * the field, unverifiable, on the bid that fails two gates. It abstains and + * routes to a human, rendered achromatic and dashed like any indeterminate + * (#36). Null here is never a partial sum: if any required line abstains the + * whole total is withheld (#29, and #37's roll-up bug in money). + */ + amount: numeric('amount', { precision: 16, scale: 2 }), + reason: unpricedReason('reason'), + /** As-if-exceptions-declined. Shown beside `amount`; NEVER ranks (#29). */ + amountIfDeclined: numeric('amount_if_declined', { precision: 16, scale: 2 }), + reasonIfDeclined: unpricedReason('reason_if_declined'), + /** + * The evidentiary half. A bare scalar can only assert; a protest asks WHY + * this bid ranked here, and the per-line derivation — band chosen, seasonal + * factor, each modifier's contribution, floor if it bound — is what answers. + */ + breakdown: jsonb('breakdown').$type().notNull(), + /** + * Recorded so a divergence found years later is explainable rather than + * merely alarming. Recomputation on read is a CHECK, not the authority: the + * stored number stays authoritative and a mismatch surfaces as a finding. + * This is not a promise that old evaluator versions stay runnable. + */ + evaluatorVersion: integer('evaluator_version').notNull(), + /** Covers the rate structures and the published scenario. Detects input drift. */ + inputsHash: text('inputs_hash').notNull(), + /** + * A substantive amendment to the scenario VOIDS derived costs rather than + * recomputing them (#29, consistent with #16 and #37). Every figure here was + * computed against assumptions that no longer hold, and a quietly recomputed + * price is the silent recompute #15 forbids — more dangerous here than in + * scoring, because nobody watches arithmetic the way they watch a rubric. + */ + voidedByAmendmentId: uuid('voided_by_amendment_id'), computedAt: timestamp('computed_at', { withTimezone: true }).notNull().defaultNow(), }, () => [ pgPolicy('derived_cost_read', { diff --git a/src/db/schema/solicitation.ts b/src/db/schema/solicitation.ts index 2329fbf..927ebd5 100644 --- a/src/db/schema/solicitation.ts +++ b/src/db/schema/solicitation.ts @@ -146,15 +146,60 @@ export const priceLine = pgTable('price_line', { solicitationId: uuid('solicitation_id').notNull().references(() => solicitation.id), label: text('label').notNull(), unit: text('unit').notNull(), + /** + * A required line that cannot be priced withholds the whole bid total (#29). + * An optional one does not, which is the only reason this column exists. + */ + required: boolean('required').notNull().default(true), }) -/** Published with the RFP so price is bindable up front (#10). */ +/** + * Published with the RFP so price is bindable up front (#10). + * + * `monthlyWeights` is relative volume per month, index 0 = January, in any + * consistent unit — instructional days, for a school food contract. WEIGHTS, + * not normalised shares: #29 found that rounding twelve shares to basis points + * quantizes a seasonal factor by enough to matter on a six-figure line, and + * #22 is emphatic that rounding erases results. Integers here, ratio taken in + * the evaluator, nothing rounded until the final total. + */ export const evaluationScenario = pgTable('evaluation_scenario', { id: uuid('id').primaryKey().defaultRandom(), solicitationId: uuid('solicitation_id').notNull().references(() => solicitation.id), declaredAt: timestamp('declared_at', { withTimezone: true }).notNull().defaultNow(), + monthlyWeights: integer('monthly_weights').array(), }) +/** + * The closed scenario vocabulary (#29). A rate structure may read only these, + * and one reading a variable this RFP never published is rejected at + * submission — while the vendor can still fix it — rather than resolving to a + * null months later when nobody can act on it. + * + * Curated the way the category spine is (#26): extending it is a schema change + * on purpose. Free-form keys would let two bids in one field be priced against + * different assumptions, which is the single thing derived cost exists to + * prevent. + */ +export const scenarioVariableName = pgEnum('scenario_variable_name', [ + 'siteCount', 'deliveriesPerWeek', 'instructionalWeeks', +]) + +/** Same disclosure class as the basket — these are the assumptions, and equally sensitive. */ +export const scenarioVariable = pgTable('scenario_variable', { + scenarioId: uuid('scenario_id').notNull().references(() => evaluationScenario.id), + name: scenarioVariableName('name').notNull(), + value: numeric('value', { precision: 14, scale: 3 }).notNull(), +}, (t) => [ + primaryKey({ columns: [t.scenarioId, t.name] }), + pgPolicy('scenario_variable_read', { + for: 'select', + using: sql`class_released(release_level_for_solicitation( + (SELECT solicitation_id FROM evaluation_scenario WHERE id = scenario_id) + ), 'scenario_quantity')`, + }), +]).enableRLS() + /** * The exact basket. Sits behind the acknowledgement gate (#14 decision 4) — * this is the sensitive half of the scenario, and its own disclosure class. diff --git a/src/pricing/corpus-check.ts b/src/pricing/corpus-check.ts new file mode 100644 index 0000000..8199ee0 --- /dev/null +++ b/src/pricing/corpus-check.ts @@ -0,0 +1,314 @@ +/** + * The corpus assertions for #29. `npm run check:pricing` + * + * This ticket is unusually verifiable: the Friendship PCS response set carries + * three rate structures with hand-computed ground truth, so the evaluator is + * falsifiable rather than merely reviewable. Stated figures are read from the + * truth files rather than typed here, so editing the corpus breaks this check + * instead of quietly diverging from it — the same discipline validate-truth.py + * applies to the RFP side. + * + * The three vendors exercise three different failure surfaces on purpose: + * Potomac the arithmetic is checkable AND THE DOCUMENT IS WRONG + * Chesapeake the shape is supported and the input is absent + * Anacostia cost depends on WHEN, and assuming flat flatters the bid + * + * NOTE what this does not cover: translating a PDF into these structures is + * extraction (#16), unbuilt. The structures below are transcribed by hand from + * the truth files, so this checks the EVALUATOR, not the extractor. + */ +import { readFileSync } from 'node:fs' +import { evaluateBid, evaluateLine, type LineDerivation } from './evaluate.js' +import { applyExceptions, type ResponseException } from './exception.js' +import type { RateStructure } from './rate.js' +import type { Scenario } from './scenario.js' + +const CORPUS = 'corpus/friendship-pcs/responses' +const truth = (f: string) => JSON.parse(readFileSync(`${CORPUS}/${f}.truth.json`, 'utf8')) + +const dollars = (minor: number) => `$${(minor / 100).toLocaleString('en-US', { minimumFractionDigits: 2 })}` + +let failures = 0 +function check(label: string, ok: boolean, detail = '') { + console.log(` ${ok ? 'ok ' : 'FAIL'} ${label}${detail ? ` ${detail}` : ''}`) + if (!ok) failures++ +} + +/* ── the school calendar ─────────────────────────────────────────────────── */ + +/** Instructional days by month, Jan..Dec. 180 days, none in July or August. */ +const DAYS = [19, 18, 21, 18, 21, 10, 0, 0, 20, 22, 17, 14] +const TOTAL_DAYS = DAYS.reduce((a, b) => a + b, 0) + +// Published as raw day counts. An earlier draft normalised these to +// basis-point shares and the factor assertion below failed by 3e-5 — about $19 +// on this line. That was the SCENARIO quantizing, not the evaluator, and the +// fix was to stop quantizing: weights are exact, ratios are taken last. +const CALENDAR = DAYS + +/* ── Potomac: volume-banded, whole basket ────────────────────────────────── */ + +console.log('\nPotomac Provisions — volume_banded, whole_basket') + +const potomacTruth = truth('potomac-provisions') +const POTOMAC_VOLUME: number = potomacTruth.priceQuote.statedAtScenarioVolume +const POTOMAC_STATED: number = potomacTruth.priceQuote.statedBaseYearTotal + +const potomac: RateStructure = { + base: { + kind: 'volume_banded', + application: 'whole_basket', + measuredBy: 'line_quantity', + bands: [ + { from: 0, to: 11_999, unitPrice: 2840 }, + { from: 12_000, to: 23_999, unitPrice: 2755 }, + { from: 24_000, to: 35_999, unitPrice: 2684 }, + { from: 36_000, to: null, unitPrice: 2627 }, + ], + }, + modifiers: [], +} + +const potomacScenario: Scenario = { quantities: { food: POTOMAC_VOLUME }, scalars: {} } +const p = evaluateLine('food', potomac, potomacScenario) + +check( + 'computes the band total exactly', + p.amount === 58_957_000, + `${dollars(p.amount ?? 0)} at ${POTOMAC_VOLUME} cases`, +) + +// The planted trap. #15 decision 2 puts price arithmetic in code precisely so +// a vendor's stated total is never trusted over a computed one. +check( + 'does NOT reproduce the stated total', + p.amount !== POTOMAC_STATED * 100, + `stated ${dollars(POTOMAC_STATED * 100)}, computed ${dollars(p.amount ?? 0)}, ` + + `divergence ${dollars(Math.abs((p.amount ?? 0) - POTOMAC_STATED * 100))}`, +) + +// One word of data, thousands of dollars. If this ever passes, the flag has +// stopped being load-bearing and something is defaulting. +const marginal = evaluateLine( + 'food', + { ...potomac, base: { ...potomac.base, application: 'marginal' } as typeof potomac.base }, + potomacScenario, +) +check( + 'marginal application yields a different number', + marginal.amount !== null && marginal.amount !== p.amount, + `whole_basket ${dollars(p.amount ?? 0)} vs marginal ${dollars(marginal.amount ?? 0)}`, +) + +// 12,000 units at the first band plus 9,400 at the second is exactly the +// 21,400 bid. An off-by-one at the band seam is invisible in the total and +// wrong in the record. +check( + 'marginal prices every unit exactly once', + marginal.amount === 12_000 * 2840 + 9_400 * 2755, + dollars(marginal.amount ?? 0), +) + +check('evaluation is deterministic', evaluateLine('food', potomac, potomacScenario).amount === p.amount) + +/* ── Chesapeake: supported shape, absent input ───────────────────────────── */ + +console.log('\nChesapeake Food Service — flat_unit + per_event_charge, unit price absent') + +const chesapeakeTruth = truth('chesapeake-food-service') +const CH_ASSUMED: { deliveriesPerWeek: number; sites: number } = chesapeakeTruth.priceQuote.statedAssumptions + +const chesapeake: RateStructure = { + base: { kind: 'flat_unit', unitPrice: null }, // lives in the Excel sheet we never got (KM-1) + modifiers: [ + { + kind: 'per_event_charge', + count: { product: ['siteCount', 'deliveriesPerWeek', 'instructionalWeeks'] }, + rate: { + steppedBy: 'deliveriesPerWeek', + steps: [ + { at: 2, charge: 3400 }, + { at: 3, charge: 2850 }, + { at: 4, charge: 2400 }, + ], + }, + }, + ], +} + +const chesapeakeScenario: Scenario = { + quantities: { food: 21_400 }, + scalars: { + siteCount: CH_ASSUMED.sites, + deliveriesPerWeek: CH_ASSUMED.deliveriesPerWeek, + instructionalWeeks: 36, + }, +} + +const c = evaluateLine('food', chesapeake, chesapeakeScenario) + +check('abstains rather than returning a number', c.amount === null) +check('reason is input_missing, not shape_unsupported', c.reason === 'input_missing', String(c.reason)) +check( + 'names the field to ask the vendor for', + c.missing.includes('base.unitPrice'), + c.missing.join(', '), +) +// The lowest number in the field belongs to the bid that fails two gates. If a +// null cost ever falls back to the stated figure, the demo ranks a number +// nobody checked. +check( + 'the stated total never substitutes for the computed one', + c.amount !== chesapeakeTruth.priceQuote.statedBaseYearTotal * 100, + `stated ${dollars(chesapeakeTruth.priceQuote.statedBaseYearTotal * 100)} is the cheapest in the field`, +) + +/* ── Anacostia: seasonal, and the calendar that decides it ───────────────── */ + +console.log('\nAnacostia Farm Collective — flat_unit + seasonal_multiplier') + +const anacostiaTruth = truth('anacostia-farm-collective') +const BASE_CASE_PRICE = Math.round(anacostiaTruth.priceQuote.rateStructure.baseProduceCasePrice * 100) +const PRODUCE_CASES = 20_000 + +const anacostia: RateStructure = { + base: { kind: 'flat_unit', unitPrice: BASE_CASE_PRICE }, + modifiers: [ + { + kind: 'seasonal_multiplier', + periods: [ + { months: [6, 7, 8, 9, 10], multiplier: 8800 }, + { months: [4, 5, 11], multiplier: 10_000 }, + { months: [12, 1, 2, 3], multiplier: 11_900 }, + ], + }, + ], +} + +const noCalendar: Scenario = { quantities: { produce: PRODUCE_CASES }, scalars: {} } +const a0 = evaluateLine('produce', anacostia, noCalendar) + +check('abstains when the calendar is not published', a0.amount === null) +check( + 'names monthlyWeights as the missing input', + a0.missing.includes('scenario.monthlyWeights'), + a0.missing.join(', '), +) + +const withCalendar: Scenario = { ...noCalendar, monthlyWeights: CALENDAR } +const a1 = evaluateLine('produce', anacostia, withCalendar) + +const flat = BASE_CASE_PRICE * PRODUCE_CASES +check('prices once the calendar exists', a1.amount !== null, dollars(a1.amount ?? 0)) + +// The vendor says this themselves: the 180-day calendar falls disproportionately +// OUTSIDE the peak band. A flat assumption would have understated the bid. +check( + 'the calendar makes this bid more expensive, not less', + (a1.amount ?? 0) > flat, + `flat would be ${dollars(flat)}, calendar-weighted is ${dollars(a1.amount ?? 0)}`, +) + +// Independent arithmetic — float, weighted by raw day counts rather than by the +// apportioned bp shares the evaluator uses. Agreement to six figures means the +// traversal is right, not merely self-consistent. +const expectedFactor = + (52 * 0.88 + 56 * 1.0 + 72 * 1.19) / TOTAL_DAYS // peak / shoulder / out-of-region days +const actualFactor = (a1.amount ?? 0) / flat +check( + 'the weighted factor matches an independent computation', + Math.abs(actualFactor - expectedFactor) < 1e-9, + `${actualFactor.toFixed(9)} vs ${expectedFactor.toFixed(9)}`, +) + +/* ── the exception with no price ─────────────────────────────────────────── */ + +console.log('\nAnacostia exceptions — two priceable, one not') + +const rawExceptions: { + id: string + labelled: boolean + requirementId: string | null + targetSection?: string + priceDeltaIfDeclined: number | null + isBidWithdrawalCondition?: boolean +}[] = anacostiaTruth.exceptions + +const exceptions: ResponseException[] = rawExceptions.map((e) => ({ + id: e.id, + labelled: e.labelled, + targetRequirementId: e.requirementId, + targetSection: e.targetSection ?? null, + consequence: e.isBidWithdrawalCondition + ? { kind: 'withdrawal' } + : e.priceDeltaIfDeclined !== null + ? { kind: 'price_delta', amountIfDeclined: e.priceDeltaIfDeclined * 100 } + : { kind: 'unquantified' }, +})) + +const bid = evaluateBid([{ priceLineId: 'produce', rate: anacostia, required: true }], withCalendar) +const adjusted = applyExceptions(bid, exceptions) + +check('as-bid is the figure that ranks', adjusted.asBid === a1.amount) +check( + 'the withdrawal exception makes as-if-declined undefined', + adjusted.asIfDeclined === null && adjusted.asIfDeclinedReason === 'withdrawal_conditioned', + `not ${dollars(anacostiaTruth.priceQuote.statedTotalIfExceptionsDeclined * 100)}, which omits EX-3`, +) +check( + 'the exception pointing at an unenumerated section surfaces as a finding', + adjusted.findings.some((f) => f.targetSection === 'C.3'), + adjusted.findings.map((f) => f.id).join(', '), +) + +/* ── Chesapeake's unlabelled exception never moves arithmetic ────────────── */ + +const chesapeakeExceptions: ResponseException[] = (chesapeakeTruth.exceptions as { id: string }[]).map((e) => ({ + id: e.id, + labelled: false, + targetRequirementId: null, + targetSection: null, + consequence: { kind: 'unquantified' }, +})) +const chBid = evaluateBid([{ priceLineId: 'food', rate: chesapeake, required: true }], chesapeakeScenario) +const chAdjusted = applyExceptions(chBid, chesapeakeExceptions) + +console.log('\nChesapeake exception — unlabelled, hidden in the Pricing section') +check( + 'an unlabelled exception is a finding, never an adjustment', + chAdjusted.findings.length === chesapeakeExceptions.length && chAdjusted.asIfDeclined === chBid.amount, + chAdjusted.findings.map((f) => f.id).join(', '), +) + +/* ── a partial sum is never a total ──────────────────────────────────────── */ + +console.log('\nBid-level roll-up') + +const mixed = evaluateBid( + [ + { priceLineId: 'produce', rate: anacostia, required: true }, + { priceLineId: 'grocery', rate: { base: { kind: 'flat_unit', unitPrice: 1500 }, modifiers: [] }, required: true }, + { priceLineId: 'dairy', rate: { base: { kind: 'flat_unit', unitPrice: 900 }, modifiers: [] }, required: true }, + { priceLineId: 'protein', rate: chesapeake, required: true }, + ], + { + ...withCalendar, + quantities: { produce: PRODUCE_CASES, grocery: 4000, dairy: 3000, protein: 2000 }, + scalars: chesapeakeScenario.scalars, + }, +) + +check('three of four lines price', mixed.linesPriced === 3, `${mixed.linesPriced}/${mixed.lineCount}`) +check('the bid total is withheld, not partial', mixed.amount === null && mixed.reason === 'line_incomplete') + +const partial = mixed.lines.reduce((s: number, l: LineDerivation) => s + (l.amount ?? 0), 0) +check( + 'the partial sum is a real number that must never be shown as a total', + partial > 0, + `${dollars(partial)} — arithmetically correct, and not this bid's price`, +) + +/* ── */ + +console.log(failures === 0 ? '\nPRICING OK' : `\n${failures} FAILED`) +process.exit(failures === 0 ? 0 : 1) diff --git a/src/pricing/evaluate.ts b/src/pricing/evaluate.ts new file mode 100644 index 0000000..0698490 --- /dev/null +++ b/src/pricing/evaluate.ts @@ -0,0 +1,424 @@ +import { + BP_ONE, + MONTHLY_WEIGHTS, + type BaseSchedule, + type Minor, + type Modifier, + type RateStructure, +} from './rate.js' +import { assertWellFormed, type Scenario } from './scenario.js' + +/** + * Rate evaluation. Closed by #29. + * + * Three properties this file exists to hold, all of them protest-facing: + * + * 1. ABSTENTION IS TYPED, NEVER ZERO. A cost that cannot be computed is null + * with a reason. Zero silently disqualifies on arithmetic; dropping the bid + * does it more quietly still. Neither is a decision the system may make + * (#15) — "this bid has no price" routes to a human, rendered achromatic + * and dashed like any other indeterminate (#36). + * + * 2. A PARTIAL SUM IS NEVER A TOTAL. If any required line abstains, the bid + * total is null and the surface shows `3/4 lines priced`. This is the + * roll-up bug #37 caught in the prototype — arithmetically correct, reads + * as a total, is not one. Same fix: one predicate, applied at the top. + * + * 3. ONE ROUNDING POINT. #22 banned rounding in scores because 82.15 and 81.90 + * decide a contest; money is worse, because it is float by default. A line + * accumulates as an exact rational in bigint — numerator and denominator, + * never divided — and rounds once at the end, half-up. Nothing quantizes on + * the way through, which is what lets the seasonal factor be a ratio of + * published integers rather than a rounded multiplier. + */ + +/** + * Bump on ANY change to the arithmetic. Recorded on every derivation so a + * divergence found years later is explainable rather than merely alarming. + * This is not a promise that old versions stay runnable — see the recompute + * rule in derivation storage (#29, and handed to #21). + */ +export const EVALUATOR_VERSION = 1 + +export type UnpricedReason = + /** No supported shape represents this. Permanent — the quote lives as an attachment. */ + | 'shape_unsupported' + /** Shape is supported, a field is absent. RECOVERABLE: ask the vendor. */ + | 'input_missing' + /** Bid-level only: at least one required line abstained. */ + | 'line_incomplete' + /** An exception makes performance conditional, so the if-declined figure is undefined. */ + | 'withdrawal_conditioned' + +export interface Step { + readonly label: string + readonly amount: Minor | null + readonly detail?: string +} + +export interface LineDerivation { + readonly priceLineId: string + readonly amount: Minor | null + readonly reason: UnpricedReason | null + /** Field paths that were absent. This is the clarification-request payload. */ + readonly missing: readonly string[] + readonly steps: readonly Step[] +} + +/** + * The stored record. The scalar alone is unfalsifiable — a protest asks WHY a + * bid ranked where it did, and a bare number can only assert. `steps` is what + * answers it. + */ +export interface Derivation { + readonly evaluatorVersion: number + readonly amount: Minor | null + readonly reason: UnpricedReason | null + readonly lines: readonly LineDerivation[] + readonly linesPriced: number + readonly lineCount: number +} + +/* ── exact arithmetic ────────────────────────────────────────────────────── */ + +/** Quantities carry 3 decimals — numeric(14,3) in the schema. */ +const QTY_SCALE = 1_000n + +/** + * An exact rational in minor units. Never divided until `resolve`. + * Kept as a plain pair rather than reduced: the numbers here are small enough + * that bigint growth is irrelevant, and not reducing keeps the arithmetic + * obvious to whoever reads this during a challenge. + */ +interface Rational { + n: bigint + d: bigint +} + +function roundHalfUp({ n, d }: Rational): number { + const neg = n < 0n + const a = neg ? -n : n + const q = (2n * a + d) / (2n * d) + return Number(neg ? -q : q) +} + +function addMinor(r: Rational, amount: Minor): void { + r.n += BigInt(amount) * r.d +} + +function compareMinor(r: Rational, amount: Minor): number { + const lhs = r.n + const rhs = BigInt(amount) * r.d + return lhs < rhs ? -1 : lhs > rhs ? 1 : 0 +} + +/* ── base schedule ───────────────────────────────────────────────────────── */ + +interface BaseResult { + readonly value: Rational | null + readonly missing: readonly string[] + readonly steps: readonly Step[] +} + +function evaluateBase(base: BaseSchedule, quantity: number): BaseResult { + const qty = BigInt(Math.round(quantity * Number(QTY_SCALE))) + + if (base.kind === 'flat_unit') { + if (base.unitPrice === null) { + return { value: null, missing: ['base.unitPrice'], steps: [] } + } + return { + value: { n: qty * BigInt(base.unitPrice), d: QTY_SCALE }, + missing: [], + steps: [{ label: 'Unit price', amount: base.unitPrice, detail: `flat, x ${quantity} units` }], + } + } + + if (base.application === 'whole_basket') { + // Potomac: a retroactive year-end rebate reprices EVERY unit at the band + // reached. The band is not knowable at order time, only at year end — + // which is exactly why derived cost is computed against the DECLARED + // scenario volume rather than anything observed. + const idx = base.bands.findIndex( + (b) => quantity >= b.from && (b.to === null || quantity <= b.to), + ) + const band = base.bands[idx] + if (band === undefined) { + return { value: null, missing: [`base.bands (no band covers ${quantity})`], steps: [] } + } + if (band.unitPrice === null) { + return { value: null, missing: [`base.bands[${idx}].unitPrice`], steps: [] } + } + return { + value: { n: qty * BigInt(band.unitPrice), d: QTY_SCALE }, + missing: [], + steps: [ + { + label: 'Band unit price', + amount: band.unitPrice, + detail: `whole-basket band ${idx} [${band.from}, ${band.to ?? '∞'}] at ${quantity} units`, + }, + ], + } + } + + // Marginal: each band prices only the volume falling inside it. + // + // The upper bound here is the NEXT band's `from`, not this band's `to`. + // `to` is inclusive and exists for whole-basket SELECTION, where bands read + // naturally as [0, 11999] then [12000, 23999]. Subtracting those bounds + // directly loses the unit between them — silently, since it is one unit out + // of tens of thousands. Marginal treats the ladder as half-open, the only + // reading that both totals correctly and survives fractional quantities. + // `bandsContiguous` is what keeps the two readings in agreement. + const missing: string[] = [] + base.bands.forEach((b, i) => { + if (b.unitPrice === null) missing.push(`base.bands[${i}].unitPrice`) + }) + if (missing.length > 0) return { value: null, missing, steps: [] } + + const value: Rational = { n: 0n, d: QTY_SCALE } + const steps: Step[] = [] + for (const [i, b] of base.bands.entries()) { + const next = base.bands[i + 1] + const lo = Math.max(b.from, 0) + const hi = next === undefined ? quantity : Math.min(next.from, quantity) + const inBand = Math.max(0, hi - lo) + if (inBand === 0) continue + value.n += BigInt(Math.round(inBand * Number(QTY_SCALE))) * BigInt(b.unitPrice!) + steps.push({ + label: `Band ${i}`, + amount: b.unitPrice, + detail: `marginal, ${inBand} units in [${lo}, ${next === undefined ? '∞' : next.from})`, + }) + } + return { value, missing: [], steps } +} + +/* ── structure validation ────────────────────────────────────────────────── */ + +/** + * Bands must ascend and not overlap, and each closed `to` must sit directly + * below the next `from`. Whole-basket reads `to`; marginal reads the next + * `from`. If those two disagree the same ladder prices two different ways + * depending on a flag, which is not something to discover during a protest. + */ +function bandsContiguous(bands: readonly { from: number; to: number | null }[]): boolean { + for (const [i, b] of bands.entries()) { + const next = bands[i + 1] + if (next === undefined) continue + if (b.to === null) return false // only the last band may be open-ended + if (next.from <= b.from) return false + if (next.from - b.to !== 1) return false + } + return true +} + +function coversTwelveMonthsExactly(m: Extract): boolean { + const seen = new Set() + for (const p of m.periods) { + for (const month of p.months) { + if (month < 1 || month > 12 || seen.has(month)) return false + seen.add(month) + } + } + return seen.size === 12 +} + +/* ── seasonal ────────────────────────────────────────────────────────────── */ + +/** + * The seasonal multiplier is a weighted average factor over the published + * calendar, applied to the base subtotal — `sum(weight x multiplier) / (sum + * weight x BP_ONE)`, carried as an exact rational. + * + * Deliberate: it is exact, order-independent, identical to per-month + * computation whenever the unit price is uniform, and — the reason it is + * written this way — it composes with MARGINAL bands without anyone having to + * invent a rule for where a given month sits in the cumulative volume. That + * rule would be arbitrary, and arbitrary is not defensible in a protest. + */ +function seasonalFactor( + m: Extract, + weights: readonly number[], +): Rational { + let n = 0n + for (const p of m.periods) { + for (const month of p.months) { + n += BigInt(weights[month - 1] ?? 0) * BigInt(p.multiplier) + } + } + const total = weights.reduce((a, b) => a + b, 0) + return { n, d: BigInt(total) * BigInt(BP_ONE) } +} + +/* ── line ────────────────────────────────────────────────────────────────── */ + +export function evaluateLine( + priceLineId: string, + rate: RateStructure, + scenario: Scenario, +): LineDerivation { + assertWellFormed(scenario) + + const quantity = scenario.quantities[priceLineId] + if (quantity === undefined) { + return { + priceLineId, + amount: null, + reason: 'input_missing', + missing: [`scenario.quantities.${priceLineId}`], + steps: [], + } + } + + if (rate.base.kind === 'volume_banded' && !bandsContiguous(rate.base.bands)) { + return { + priceLineId, + amount: null, + reason: 'shape_unsupported', + missing: ['base.bands (not a contiguous ascending ladder)'], + steps: [], + } + } + + for (const m of rate.modifiers) { + if (m.kind === 'seasonal_multiplier' && !coversTwelveMonthsExactly(m)) { + return { + priceLineId, + amount: null, + reason: 'shape_unsupported', + missing: ['modifiers.seasonal_multiplier (periods do not cover all 12 months exactly once)'], + steps: [], + } + } + } + + const base = evaluateBase(rate.base, quantity) + const missing = [...base.missing] + const steps: Step[] = [...base.steps] + let value = base.value + + for (const m of rate.modifiers) { + if (m.kind === 'seasonal_multiplier') { + const weights = scenario.monthlyWeights + if (weights === undefined) { + // Never assume flat. Anacostia's own bid says a comparison ignoring the + // calendar flatters it, and assuming flat IS that comparison. + missing.push(`scenario.${MONTHLY_WEIGHTS}`) + value = null + continue + } + const f = seasonalFactor(m, weights) + if (value !== null) { + value = { n: value.n * f.n, d: value.d * f.d } + } + steps.push({ + label: 'Seasonal factor', + amount: null, + detail: `${(Number(f.n) / Number(f.d)).toFixed(6)} x, weighted over the published calendar`, + }) + continue + } + + if (m.kind === 'fixed_fee') { + if (m.amount === null) { + missing.push('modifiers.fixed_fee.amount') + value = null + continue + } + if (value !== null) addMinor(value, m.amount) + steps.push({ label: 'Fixed fee', amount: m.amount }) + continue + } + + // per_event_charge + let events = 1 + let unresolved = false + for (const v of m.count.product) { + const n = scenario.scalars[v] + if (n === undefined) { + missing.push(`scenario.scalars.${v}`) + unresolved = true + continue + } + events *= n + } + + let charge: Minor | null + if (m.rate === null) { + charge = null + missing.push('modifiers.per_event_charge.rate') + } else if (typeof m.rate === 'number') { + charge = m.rate + } else { + const at = scenario.scalars[m.rate.steppedBy] + if (at === undefined) { + missing.push(`scenario.scalars.${m.rate.steppedBy}`) + charge = null + } else { + const step = m.rate.steps.find((s) => s.at === at) + if (step === undefined) { + // The vendor did not price this service level. Recoverable — ask. + missing.push( + `modifiers.per_event_charge.rate.steps (no step at ${m.rate.steppedBy}=${at})`, + ) + charge = null + } else if (step.charge === null) { + missing.push(`modifiers.per_event_charge.rate.steps[at=${at}].charge`) + charge = null + } else { + charge = step.charge + } + } + } + + if (charge === null || unresolved) { + value = null + continue + } + if (value !== null) addMinor(value, charge * events) + steps.push({ + label: 'Per-event charge', + amount: charge, + detail: `x ${events} events (${m.count.product.join(' x ')})`, + }) + } + + if (value === null) { + return { priceLineId, amount: null, reason: 'input_missing', missing, steps } + } + + if (rate.minimumCharge !== undefined && compareMinor(value, rate.minimumCharge) < 0) { + value = { n: BigInt(rate.minimumCharge), d: 1n } + steps.push({ label: 'Minimum charge applied', amount: rate.minimumCharge }) + } + + // The one rounding point. Everything above is exact. + return { priceLineId, amount: roundHalfUp(value), reason: null, missing: [], steps } +} + +/* ── bid ─────────────────────────────────────────────────────────────────── */ + +export interface QuotedLine { + readonly priceLineId: string + readonly rate: RateStructure + /** A line the RFP requires priced. An optional line abstaining does not void the total. */ + readonly required: boolean +} + +export function evaluateBid(lines: readonly QuotedLine[], scenario: Scenario): Derivation { + const derived = lines.map((l) => evaluateLine(l.priceLineId, l.rate, scenario)) + const linesPriced = derived.filter((d) => d.amount !== null).length + const requiredIncomplete = lines.some((l, i) => l.required && derived[i]!.amount === null) + + return { + evaluatorVersion: EVALUATOR_VERSION, + // A partial sum is never shown as a total (#37's roll-up bug, in money). + amount: requiredIncomplete ? null : derived.reduce((sum, d) => sum + (d.amount ?? 0), 0), + reason: requiredIncomplete ? 'line_incomplete' : null, + lines: derived, + linesPriced, + lineCount: lines.length, + } +} diff --git a/src/pricing/exception.ts b/src/pricing/exception.ts new file mode 100644 index 0000000..01d97bd --- /dev/null +++ b/src/pricing/exception.ts @@ -0,0 +1,90 @@ +import type { Derivation, UnpricedReason } from './evaluate.js' +import type { Minor } from './rate.js' + +/** + * Exceptions. Closed by #29. + * + * An exception is a modification to the TERMS that sometimes carries a price + * consequence — not a price field. The corpus is unambiguous about why that + * distinction has to be structural: Anacostia labels three exceptions, two + * carrying deltas, and the third says that if declined the vendor cannot bid + * produce at all. A nullable `priceDeltaIfDeclined` reads that third one as + * "no cost impact", which is the inverse of the truth, and it happens to be + * the most consequential of the three. + */ +export type ExceptionConsequence = + | { readonly kind: 'price_delta'; readonly amountIfDeclined: Minor } + /** Cannot perform this scope if declined. A conditional withdrawal. */ + | { readonly kind: 'withdrawal' } + /** Asserts a consequence, states no figure. Recoverable: ask. */ + | { readonly kind: 'unquantified' } + +export interface ResponseException { + readonly id: string + /** + * False = found in prose with no heading, no delta, no "exception" wording — + * Chesapeake's polite sentence inside the Pricing section. Detecting it is + * valuable; PRICING it would be a model deciding (#15), so an unlabelled + * exception never moves arithmetic. It routes to a human as a finding and + * renders indeterminate (#36), and the number does not change until a person + * says it does. + */ + readonly labelled: boolean + readonly targetRequirementId: string | null + /** + * Set when the exception points at a document section the extractor never + * enumerated as a requirement — Anacostia's EX-3 targets C.3, which the + * truth file does not carry. That makes exceptions a COMPLETENESS SIGNAL + * feeding #16's sweep, not merely a response field. Handed to #16. + */ + readonly targetSection: string | null + readonly consequence: ExceptionConsequence +} + +export interface ExceptionAdjusted { + /** + * What the vendor is actually offering, and the ONLY figure that ranks. + * Whether to accept an exception is the retailer's call; folding it into the + * ordering would be the system pre-deciding it — the same boundary #15 draws + * around scoring. + */ + readonly asBid: Minor | null + /** Shown beside `asBid`. Never ranks. */ + readonly asIfDeclined: Minor | null + readonly asIfDeclinedReason: UnpricedReason | null + /** Unlabelled exceptions, and exceptions pointing at unenumerated sections. */ + readonly findings: readonly ResponseException[] +} + +export function applyExceptions( + derivation: Derivation, + exceptions: readonly ResponseException[], +): ExceptionAdjusted { + const findings = exceptions.filter((e) => !e.labelled || e.targetSection !== null) + const priced = exceptions.filter((e) => e.labelled) + + let asIfDeclined: Minor | null = derivation.amount + let asIfDeclinedReason: UnpricedReason | null = derivation.reason + + for (const e of priced) { + if (e.consequence.kind === 'withdrawal') { + // Not zero, and emphatically not the as-bid figure carried over. + asIfDeclined = null + asIfDeclinedReason = 'withdrawal_conditioned' + break + } + if (e.consequence.kind === 'unquantified') { + asIfDeclined = null + asIfDeclinedReason = 'input_missing' + break + } + if (asIfDeclined !== null) asIfDeclined += e.consequence.amountIfDeclined + } + + return { + asBid: derivation.amount, + asIfDeclined, + asIfDeclinedReason, + findings, + } +} diff --git a/src/pricing/index.ts b/src/pricing/index.ts index ba76d53..a2f4923 100644 --- a/src/pricing/index.ts +++ b/src/pricing/index.ts @@ -1,5 +1,3 @@ -import { Seam } from '../seam.js' - /** * Rate function evaluation. Shape closed by #29. * @@ -9,18 +7,22 @@ import { Seam } from '../seam.js' * - piecewise bands varying by category, threshold, or contract year * * This is deterministic by #15 decision 2 — a model may never evaluate it and - * there is no fallback path. So the v1 rate structure types must be CLOSED and - * computable: a shape the code cannot evaluate has nowhere to go. + * there is no fallback path. #29 resolved the vocabulary as a COMPOSITION — + * one base schedule plus closed modifiers (rate.ts), evaluated in an order + * fixed in code (evaluate.ts) — with exceptions modelled separately, because + * one of the three in the corpus has no price at all (exception.ts). + * + * The greater-of shape above is the one deliberately deferred: it abstains + * with `shape_unsupported` rather than being half-built. + * + * The seam that stood here is gone. What replaced it is not `=> number`: + * evaluation produces a Derivation, whose amount is nullable with a typed + * reason, because the corpus contains a bid that cannot be priced at all and + * a system that returns a number for it is lying. + * + * npm run check:pricing # the corpus assertions */ -export interface RateStructure { - readonly kind: string -} - -export interface ScenarioQuantities { - [priceLineId: string]: number -} - -/** Produces derived_cost: a comparison figure against the declared scenario, never contract value. */ -export function evaluate(_rate: RateStructure, _q: ScenarioQuantities): number { - throw new Seam('#29', 'the v1 rate structure types') -} +export * from './rate.js' +export * from './scenario.js' +export * from './evaluate.js' +export * from './exception.js' diff --git a/src/pricing/rate.ts b/src/pricing/rate.ts new file mode 100644 index 0000000..a531158 --- /dev/null +++ b/src/pricing/rate.ts @@ -0,0 +1,170 @@ +/** + * The v1 rate structure vocabulary. Closed by #29. + * + * Price is a rate function, not a scalar (#22), and #15 decision 2 bars any + * model from evaluating one — so every shape here must be computable by code + * with no fallback path. A structure the evaluator cannot reduce to a number + * does not degrade to a guess; it abstains (see evaluate.ts). + * + * COMPOSITION, NOT ENUMERATION. #29 rejected a closed list of whole shapes: + * the corpus already produced three bids that are the same object wearing + * different decoration (a unit price chosen by band, a unit price scaled by + * month, a unit price plus a per-stop charge), and enumerating whole shapes + * costs a cross-product. So a structure is ONE base schedule that decides a + * unit price, plus zero or more modifiers, plus an optional floor. Banded + * pricing that also varies by season composes for free — nobody designed that + * combination, and it is obviously real. + * + * Extending v1 means adding one member to one union. That was the point. + */ + +/** + * Money is integer minor units (cents). No float ever holds a price. + * The evaluator accumulates in scaled bigint and rounds exactly once — see + * `roundHalfUp` in evaluate.ts, and #29's rounding rule. + */ +export type Minor = number + +/** Basis points. 10_000 = 1.0. Multipliers are integers so the arithmetic is exact. */ +export type Bp = number + +export const BP_ONE: Bp = 10_000 + +/** + * The scenario vocabulary, curated the way the category spine is (#26). + * + * A rate structure may only read variables named here, and a structure that + * reads a variable the RFP did not publish is rejected at submission rather + * than resolving to null months later. This is the fairness constraint from + * #10 made structural: the scenario is published WITH the RFP, so every bid in + * a field is priced against identical assumptions. Let vendors reference + * arbitrary retailer-authored keys and two bids in one field can read + * different variables, which is precisely what derived_cost exists to prevent. + * + * Extending this is a schema change on purpose. A new category needing a new + * variable is a decision, not a config edit. + */ +export const SCALAR_VARIABLES = ['siteCount', 'deliveriesPerWeek', 'instructionalWeeks'] as const +export type ScalarVariable = (typeof SCALAR_VARIABLES)[number] + +/** + * The one vector variable: how volume is spread across the twelve months, + * indexed 0 = January. Anacostia's bid is unpriceable without it, and — the + * vendor says so themselves — a comparison assuming flat distribution flatters + * that bid. Absence must abstain, never assume flat. + * + * WEIGHTS, NOT SHARES, and the corpus check is why. Expressed as basis-point + * shares, twelve rounded values quantize the seasonal factor by ~1e-4, which + * is real money on a six-figure line — and #22 is emphatic that rounding + * erases results. Weights are exact: a school calendar publishes instructional + * days per month, an integer nobody has to round, and the evaluator divides by + * their sum as the last step. Any consistent unit works (days, cases, weeks) — + * only the ratios are read. + */ +export const MONTHLY_WEIGHTS = 'monthlyWeights' as const + +export type ScenarioVariable = ScalarVariable | typeof MONTHLY_WEIGHTS + +/** + * MONEY LEAVES ARE NULLABLE, and that is the model rather than a weakness. + * + * #29 separated "we cannot represent this shape" from "the shape is supported + * and a field is missing," because the corpus contains both and only the + * second is recoverable. Chesapeake's structure is `flat_unit` plus a per-stop + * charge — fully supported — and its unit case price is simply absent, living + * in an Excel sheet the extractor never received (KM-1). Modelling that as an + * unrepresentable shape throws away the one actionable fact: somebody can go + * and ask for the number. + * + * So extraction produces a structure with holes, the evaluator names them, and + * `missing[]` is the clarification request. A parse that rejected the whole + * structure would lose which field to ask about. + */ +export interface Band { + readonly from: number + /** Inclusive; null is open-ended. */ + readonly to: number | null + readonly unitPrice: Minor | null +} + +export type BaseSchedule = + | { readonly kind: 'flat_unit'; readonly unitPrice: Minor | null } + | { + readonly kind: 'volume_banded' + /** + * EXPLICIT, NEVER INFERRED. Potomac's bands are whole-basket — a + * retroactive year-end rebate repricing every case at the band rate. + * Marginal tiers, where each tier prices only the volume inside it, are + * just as common elsewhere. One word of data, thousands of dollars of + * difference, and no default is right more than about half the time. An + * extractor that must state which it saw is better than one that guesses. + */ + readonly application: 'whole_basket' | 'marginal' + /** + * A single-member union on purpose: it names the axis so extending is + * additive and visible. SLC bands on a sales threshold rather than + * volume, which is the second member when that fog clears. + */ + readonly measuredBy: 'line_quantity' + readonly bands: readonly Band[] + } + +/** How many chargeable events the scenario implies: the product of named variables. */ +export interface EventCount { + readonly product: readonly ScalarVariable[] +} + +/** A per-event charge that steps on a scenario variable, as Chesapeake's per-stop does. */ +export interface SteppedCharge { + readonly steppedBy: ScalarVariable + /** Applied where the variable equals `at`. Exact match — these are discrete service levels. */ + readonly steps: readonly { readonly at: number; readonly charge: Minor | null }[] +} + +export type Modifier = + /** + * Scales the volume term per period rather than the total, so cost depends + * on WHEN volume falls. Requires `monthlyDistribution`. + */ + | { + readonly kind: 'seasonal_multiplier' + /** Months are 1-12. Every month must be covered exactly once. */ + readonly periods: readonly { readonly months: readonly number[]; readonly multiplier: Bp }[] + } + /** Additive. Chesapeake's per-stop delivery charge; also per-order, per-site mobilisation. */ + | { + readonly kind: 'per_event_charge' + readonly count: EventCount + readonly rate: Minor | null | SteppedCharge + } + /** Additive, flat for the term. */ + | { readonly kind: 'fixed_fee'; readonly amount: Minor | null } + +export interface RateStructure { + readonly base: BaseSchedule + readonly modifiers: readonly Modifier[] + /** Applied to the subtotal, last. Absent means no floor. */ + readonly minimumCharge?: Minor +} + +/** + * DEFERRED, deliberately: `greater_of` — SLC's MAX(1/12 x minimum annual + * guarantee, % of gross receipts). It is genuinely recursive (two complete + * structures under a MAX), it belongs to concessions rather than supply, and + * SLC extraction is still fog on the map. Until it clears, a bid shaped that + * way falls to `shape_unsupported` and abstains, which is the correct outcome + * for a shape we cannot evaluate — not a half-built one we can evaluate wrong. + */ + +/** Which scenario variables a structure reads. Drives submission-time validation. */ +export function requiredVariables(rate: RateStructure): ScenarioVariable[] { + const out = new Set() + for (const m of rate.modifiers) { + if (m.kind === 'seasonal_multiplier') out.add(MONTHLY_WEIGHTS) + if (m.kind === 'per_event_charge') { + for (const v of m.count.product) out.add(v) + if (m.rate !== null && typeof m.rate === 'object') out.add(m.rate.steppedBy) + } + } + return [...out] +} diff --git a/src/pricing/scenario.ts b/src/pricing/scenario.ts new file mode 100644 index 0000000..f17896c --- /dev/null +++ b/src/pricing/scenario.ts @@ -0,0 +1,57 @@ +import { + MONTHLY_WEIGHTS, + type RateStructure, + type ScalarVariable, + type ScenarioVariable, + requiredVariables, +} from './rate.js' + +/** + * The published scenario. #10 put it in the RFP so price is bindable up front, + * and #29 made its variable set closed (see rate.ts). + * + * Note what a scenario variable IS: an assumption declared for comparison, not + * a contract term. Chesapeake's delivery frequency is changeable mid-term on + * two weeks' notice, so the awarded price will not match the derived cost and + * nobody should be surprised by that. Naming it an assumption here is cheaper + * than explaining it during a protest. + */ +export interface Scenario { + /** Per price line. Fractional quantities are fine; the evaluator scales to integers. */ + readonly quantities: Readonly> + readonly scalars: Readonly>> + /** + * Relative volume per month, index 0 = January. Non-negative integers in any + * consistent unit — instructional days is the natural one for a school food + * contract. Only the ratios are read, so nothing here needs normalising and + * therefore nothing here gets rounded. + */ + readonly monthlyWeights?: readonly number[] +} + +/** + * Submission-time validation: a structure that reads a variable this RFP did + * not publish is rejected NOW, while the vendor can still fix it — not + * resolved to a null in the evaluator months later when nobody can act on it. + */ +export function missingVariables(rate: RateStructure, scenario: Scenario): ScenarioVariable[] { + return requiredVariables(rate).filter((v) => + v === MONTHLY_WEIGHTS + ? scenario.monthlyWeights === undefined + : scenario.scalars[v] === undefined, + ) +} + +/** + * A malformed published scenario is a bug, not a bid outcome — so this throws + * rather than abstaining. Abstention is reserved for facts about the response. + */ +export function assertWellFormed(scenario: Scenario): void { + const w = scenario.monthlyWeights + if (w === undefined) return + if (w.length !== 12) throw new Error(`monthlyWeights has ${w.length} entries, expected 12`) + if (w.some((n) => !Number.isInteger(n) || n < 0)) { + throw new Error('monthlyWeights must be non-negative integers') + } + if (w.reduce((a, b) => a + b, 0) <= 0) throw new Error('monthlyWeights sum to zero') +}