diff --git a/drizzle/0025_portal-registration-requests.sql b/drizzle/0025_portal-registration-requests.sql new file mode 100644 index 0000000..1649e36 --- /dev/null +++ b/drizzle/0025_portal-registration-requests.sql @@ -0,0 +1,14 @@ +ALTER TABLE "registration_submissions" ADD COLUMN "source" text DEFAULT 'public' NOT NULL;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD COLUMN "animal_id" uuid;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD COLUMN "ownership_id" uuid;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD COLUMN "auth_identity_id" uuid;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD COLUMN "requested_year" integer;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD COLUMN "owner_note" text;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_animal_id_animals_id_fk" FOREIGN KEY ("animal_id") REFERENCES "public"."animals"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_ownership_id_ownerships_id_fk" FOREIGN KEY ("ownership_id") REFERENCES "public"."ownerships"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_auth_identity_id_auth_identities_id_fk" FOREIGN KEY ("auth_identity_id") REFERENCES "public"."auth_identities"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +CREATE UNIQUE INDEX "registration_submissions_pending_animal_year_key" ON "registration_submissions" USING btree ("animal_id","requested_year") WHERE "registration_submissions"."status" = 'pending' AND "registration_submissions"."animal_id" IS NOT NULL;--> statement-breakpoint +CREATE INDEX "registration_submissions_animal_year_idx" ON "registration_submissions" USING btree ("animal_id","requested_year");--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_source_check" CHECK ("registration_submissions"."source" IN ('public','portal'));--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_requested_year_check" CHECK ("registration_submissions"."requested_year" IS NULL OR "registration_submissions"."requested_year" BETWEEN 2000 AND 2200);--> statement-breakpoint +ALTER TABLE "registration_submissions" ADD CONSTRAINT "registration_submissions_portal_linkage_check" CHECK ("registration_submissions"."source" <> 'portal' OR ("registration_submissions"."animal_id" IS NOT NULL AND "registration_submissions"."requested_year" IS NOT NULL)); \ No newline at end of file diff --git a/drizzle/meta/0025_snapshot.json b/drizzle/meta/0025_snapshot.json new file mode 100644 index 0000000..ff56fcd --- /dev/null +++ b/drizzle/meta/0025_snapshot.json @@ -0,0 +1,6519 @@ +{ + "id": "bdb8dcde-1241-4fac-af50-dee5fe0fe01f", + "prevId": "092821dd-9655-4f6b-9943-35bcfc4c9222", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.admin_users": { + "name": "admin_users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "auth_identity_id": { + "name": "auth_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "admin_users_email_key": { + "name": "admin_users_email_key", + "columns": [ + { + "expression": "lower(\"email\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "admin_users_auth_identity_id_auth_identities_id_fk": { + "name": "admin_users_auth_identity_id_auth_identities_id_fk", + "tableFrom": "admin_users", + "tableTo": "auth_identities", + "columnsFrom": [ + "auth_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "admin_users_person_id_persons_id_fk": { + "name": "admin_users_person_id_persons_id_fk", + "tableFrom": "admin_users", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "admin_users_role_check": { + "name": "admin_users_role_check", + "value": "\"admin_users\".\"role\" IN ('admin','editor')" + } + }, + "isRLSEnabled": false + }, + "public.animal_lifecycle_events": { + "name": "animal_lifecycle_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "from_status": { + "name": "from_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "to_status": { + "name": "to_status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "effective_on": { + "name": "effective_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_ref": { + "name": "source_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_identity_id": { + "name": "actor_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "animal_lifecycle_events_animal_idx": { + "name": "animal_lifecycle_events_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "effective_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "animal_lifecycle_events_animal_id_animals_id_fk": { + "name": "animal_lifecycle_events_animal_id_animals_id_fk", + "tableFrom": "animal_lifecycle_events", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "animal_lifecycle_events_actor_identity_id_auth_identities_id_fk": { + "name": "animal_lifecycle_events_actor_identity_id_auth_identities_id_fk", + "tableFrom": "animal_lifecycle_events", + "tableTo": "auth_identities", + "columnsFrom": [ + "actor_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "animal_lifecycle_events_from_status_check": { + "name": "animal_lifecycle_events_from_status_check", + "value": "\"animal_lifecycle_events\".\"from_status\" IS NULL OR \"animal_lifecycle_events\".\"from_status\" IN ('active','deceased','moved-off-saba','unknown','merged')" + }, + "animal_lifecycle_events_to_status_check": { + "name": "animal_lifecycle_events_to_status_check", + "value": "\"animal_lifecycle_events\".\"to_status\" IN ('active','deceased','moved-off-saba','unknown','merged')" + }, + "animal_lifecycle_events_source_check": { + "name": "animal_lifecycle_events_source_check", + "value": "\"animal_lifecycle_events\".\"source\" IN ('staff','owner-request','import','merge')" + } + }, + "isRLSEnabled": false + }, + "public.animal_merges": { + "name": "animal_merges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retired_animal_id": { + "name": "retired_animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "survivor_animal_id": { + "name": "survivor_animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "retired_registry_ref": { + "name": "retired_registry_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "retired_legacy_id": { + "name": "retired_legacy_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "field_choices": { + "name": "field_choices", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "moved_counts": { + "name": "moved_counts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_label": { + "name": "merged_by_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_identity_id": { + "name": "merged_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "animal_merges_retired_key": { + "name": "animal_merges_retired_key", + "columns": [ + { + "expression": "retired_animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "animal_merges_survivor_idx": { + "name": "animal_merges_survivor_idx", + "columns": [ + { + "expression": "survivor_animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "animal_merges_retired_animal_id_animals_id_fk": { + "name": "animal_merges_retired_animal_id_animals_id_fk", + "tableFrom": "animal_merges", + "tableTo": "animals", + "columnsFrom": [ + "retired_animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "animal_merges_survivor_animal_id_animals_id_fk": { + "name": "animal_merges_survivor_animal_id_animals_id_fk", + "tableFrom": "animal_merges", + "tableTo": "animals", + "columnsFrom": [ + "survivor_animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "animal_merges_merged_by_identity_id_auth_identities_id_fk": { + "name": "animal_merges_merged_by_identity_id_auth_identities_id_fk", + "tableFrom": "animal_merges", + "tableTo": "auth_identities", + "columnsFrom": [ + "merged_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "animal_merges_not_self_check": { + "name": "animal_merges_not_self_check", + "value": "\"animal_merges\".\"retired_animal_id\" <> \"animal_merges\".\"survivor_animal_id\"" + } + }, + "isRLSEnabled": false + }, + "public.animals": { + "name": "animals", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "legacy_id": { + "name": "legacy_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "registry_ref": { + "name": "registry_ref", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'SFPCA-' || lpad(nextval('animal_registry_ref_seq'::regclass)::text, 6, '0')" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "species": { + "name": "species", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sex": { + "name": "sex", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "birth_date": { + "name": "birth_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "birth_date_estimated": { + "name": "birth_date_estimated", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "identifying_notes": { + "name": "identifying_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lifecycle_status": { + "name": "lifecycle_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "lifecycle_effective_on": { + "name": "lifecycle_effective_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "adoption_status": { + "name": "adoption_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'not-listed'" + }, + "sterilization_status": { + "name": "sterilization_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "sterilized_on": { + "name": "sterilized_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "sterilized_by": { + "name": "sterilized_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "photo_urls": { + "name": "photo_urls", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "animals_legacy_id_key": { + "name": "animals_legacy_id_key", + "columns": [ + { + "expression": "legacy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "animals_registry_ref_key": { + "name": "animals_registry_ref_key", + "columns": [ + { + "expression": "registry_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "animals_lifecycle_status_idx": { + "name": "animals_lifecycle_status_idx", + "columns": [ + { + "expression": "lifecycle_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "animals_adoption_status_idx": { + "name": "animals_adoption_status_idx", + "columns": [ + { + "expression": "adoption_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "animals_species_check": { + "name": "animals_species_check", + "value": "\"animals\".\"species\" IN ('dog','cat','other')" + }, + "animals_sex_check": { + "name": "animals_sex_check", + "value": "\"animals\".\"sex\" IN ('male','female','unknown')" + }, + "animals_lifecycle_status_check": { + "name": "animals_lifecycle_status_check", + "value": "\"animals\".\"lifecycle_status\" IN ('active','deceased','moved-off-saba','unknown','merged')" + }, + "animals_adoption_status_check": { + "name": "animals_adoption_status_check", + "value": "\"animals\".\"adoption_status\" IN ('not-listed','available','pending','adopted')" + }, + "animals_sterilization_status_check": { + "name": "animals_sterilization_status_check", + "value": "\"animals\".\"sterilization_status\" IN ('unknown','sterilized','intact')" + }, + "animals_birth_estimate_consistency_check": { + "name": "animals_birth_estimate_consistency_check", + "value": "\"animals\".\"birth_date_estimated\" = false OR \"animals\".\"birth_date\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.app_state": { + "name": "app_state", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "default": 1 + }, + "lifecycle": { + "name": "lifecycle", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'prelaunch-demo'" + }, + "live_at": { + "name": "live_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "demo_seeded_at": { + "name": "demo_seeded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "demo_seed_version": { + "name": "demo_seed_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "app_state_single_row_check": { + "name": "app_state_single_row_check", + "value": "\"app_state\".\"id\" = 1" + }, + "app_state_lifecycle_check": { + "name": "app_state_lifecycle_check", + "value": "\"app_state\".\"lifecycle\" IN ('prelaunch-demo','live')" + } + }, + "isRLSEnabled": false + }, + "public.audit_events": { + "name": "audit_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "actor_identity_id": { + "name": "actor_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "before": { + "name": "before", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "after": { + "name": "after", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "audit_events_entity_idx": { + "name": "audit_events_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_events_created_idx": { + "name": "audit_events_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "audit_events_actor_identity_id_auth_identities_id_fk": { + "name": "audit_events_actor_identity_id_auth_identities_id_fk", + "tableFrom": "audit_events", + "tableTo": "auth_identities", + "columnsFrom": [ + "actor_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_identities": { + "name": "auth_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_uid": { + "name": "provider_uid", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "auth_identities_provider_uid_key": { + "name": "auth_identities_provider_uid_key", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_uid", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "auth_identities_person_id_persons_id_fk": { + "name": "auth_identities_person_id_persons_id_fk", + "tableFrom": "auth_identities", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.clinic_expectations": { + "name": "clinic_expectations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "expected_on": { + "name": "expected_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "session_label": { + "name": "session_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'expected'" + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "clinic_expectations_animal_idx": { + "name": "clinic_expectations_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "clinic_expectations_expected_idx": { + "name": "clinic_expectations_expected_idx", + "columns": [ + { + "expression": "expected_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"clinic_expectations\".\"status\" = 'expected'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "clinic_expectations_animal_id_animals_id_fk": { + "name": "clinic_expectations_animal_id_animals_id_fk", + "tableFrom": "clinic_expectations", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "clinic_expectations_person_id_persons_id_fk": { + "name": "clinic_expectations_person_id_persons_id_fk", + "tableFrom": "clinic_expectations", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "clinic_expectations_encounter_id_vet_encounters_id_fk": { + "name": "clinic_expectations_encounter_id_vet_encounters_id_fk", + "tableFrom": "clinic_expectations", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "clinic_expectations_status_check": { + "name": "clinic_expectations_status_check", + "value": "\"clinic_expectations\".\"status\" IN ('expected','seen','no_show','cancelled')" + }, + "clinic_expectations_resolved_consistency_check": { + "name": "clinic_expectations_resolved_consistency_check", + "value": "(\"clinic_expectations\".\"status\" = 'expected') = (\"clinic_expectations\".\"resolved_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.communication_preferences": { + "name": "communication_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "opted_out": { + "name": "opted_out", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "communication_preferences_person_kind_key": { + "name": "communication_preferences_person_kind_key", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "channel", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "communication_preferences_person_id_persons_id_fk": { + "name": "communication_preferences_person_id_persons_id_fk", + "tableFrom": "communication_preferences", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "communication_preferences_channel_check": { + "name": "communication_preferences_channel_check", + "value": "\"communication_preferences\".\"channel\" IN ('email','sms','whatsapp','phone')" + }, + "communication_preferences_kind_check": { + "name": "communication_preferences_kind_check", + "value": "\"communication_preferences\".\"kind\" IN ('vaccination-reminder')" + } + }, + "isRLSEnabled": false + }, + "public.communications": { + "name": "communications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'queued'" + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "related_type": { + "name": "related_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "related_id": { + "name": "related_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cycle_key": { + "name": "cycle_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "touch": { + "name": "touch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "recipient": { + "name": "recipient", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body_text": { + "name": "body_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body_html": { + "name": "body_html", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_message_id": { + "name": "provider_message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "detail": { + "name": "detail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sent_at": { + "name": "sent_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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "communications_idempotency_key": { + "name": "communications_idempotency_key", + "columns": [ + { + "expression": "idempotency_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_person_idx": { + "name": "communications_person_idx", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_animal_idx": { + "name": "communications_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_related_idx": { + "name": "communications_related_idx", + "columns": [ + { + "expression": "related_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "related_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_queued_idx": { + "name": "communications_queued_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"communications\".\"status\" = 'queued'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_sending_idx": { + "name": "communications_sending_idx", + "columns": [ + { + "expression": "last_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"communications\".\"status\" = 'sending'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "communications_exceptions_idx": { + "name": "communications_exceptions_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"communications\".\"status\" IN ('failed','skipped')", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "communications_person_id_persons_id_fk": { + "name": "communications_person_id_persons_id_fk", + "tableFrom": "communications", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "communications_animal_id_animals_id_fk": { + "name": "communications_animal_id_animals_id_fk", + "tableFrom": "communications", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "communications_channel_check": { + "name": "communications_channel_check", + "value": "\"communications\".\"channel\" IN ('email','sms','whatsapp','phone')" + }, + "communications_status_check": { + "name": "communications_status_check", + "value": "\"communications\".\"status\" IN ('queued','sending','sent','delivered','failed','skipped')" + }, + "communications_sent_consistency_check": { + "name": "communications_sent_consistency_check", + "value": "\"communications\".\"sent_at\" IS NOT NULL OR \"communications\".\"status\" NOT IN ('sent','delivered')" + }, + "communications_delivered_consistency_check": { + "name": "communications_delivered_consistency_check", + "value": "\"communications\".\"delivered_at\" IS NULL OR \"communications\".\"status\" IN ('delivered','failed')" + }, + "communications_attempts_check": { + "name": "communications_attempts_check", + "value": "\"communications\".\"attempts\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.data_quality_reviews": { + "name": "data_quality_reviews", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "detector": { + "name": "detector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_a": { + "name": "entity_a", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_b": { + "name": "entity_b", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "fingerprint": { + "name": "fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "decision": { + "name": "decision", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "decided_by_label": { + "name": "decided_by_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "decided_by_identity_id": { + "name": "decided_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "data_quality_reviews_finding_key": { + "name": "data_quality_reviews_finding_key", + "columns": [ + { + "expression": "detector", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_a", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"entity_b\", '00000000-0000-0000-0000-000000000000'::uuid)", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "data_quality_reviews_decided_by_identity_id_auth_identities_id_fk": { + "name": "data_quality_reviews_decided_by_identity_id_auth_identities_id_fk", + "tableFrom": "data_quality_reviews", + "tableTo": "auth_identities", + "columnsFrom": [ + "decided_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "data_quality_reviews_decision_check": { + "name": "data_quality_reviews_decision_check", + "value": "\"data_quality_reviews\".\"decision\" IN ('confirmed','dismissed')" + }, + "data_quality_reviews_pair_order_check": { + "name": "data_quality_reviews_pair_order_check", + "value": "\"data_quality_reviews\".\"entity_b\" IS NULL OR \"data_quality_reviews\".\"entity_a\" < \"data_quality_reviews\".\"entity_b\"" + } + }, + "isRLSEnabled": false + }, + "public.demo_seed_entities": { + "name": "demo_seed_entities", + "schema": "", + "columns": { + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_store": { + "name": "entity_store", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_table": { + "name": "entity_table", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "demo_seed_entities_run_idx": { + "name": "demo_seed_entities_run_idx", + "columns": [ + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "demo_seed_entities_run_id_demo_seed_runs_id_fk": { + "name": "demo_seed_entities_run_id_demo_seed_runs_id_fk", + "tableFrom": "demo_seed_entities", + "tableTo": "demo_seed_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "demo_seed_entities_entity_store_entity_table_entity_id_pk": { + "name": "demo_seed_entities_entity_store_entity_table_entity_id_pk", + "columns": [ + "entity_store", + "entity_table", + "entity_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "demo_seed_entities_store_check": { + "name": "demo_seed_entities_store_check", + "value": "\"demo_seed_entities\".\"entity_store\" IN ('postgres','firestore','storage','auth')" + } + }, + "isRLSEnabled": false + }, + "public.demo_seed_runs": { + "name": "demo_seed_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "seed_version": { + "name": "seed_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "seeded_at": { + "name": "seeded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "reset_at": { + "name": "reset_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seeded_counts": { + "name": "seeded_counts", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "empty_firestore_collections": { + "name": "empty_firestore_collections", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "empty_storage_prefixes": { + "name": "empty_storage_prefixes", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "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.follow_ups": { + "name": "follow_ups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "registration_id": { + "name": "registration_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "due_on": { + "name": "due_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'open'" + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "follow_ups_due_idx": { + "name": "follow_ups_due_idx", + "columns": [ + { + "expression": "due_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "follow_ups_animal_idx": { + "name": "follow_ups_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "follow_ups_open_due_idx": { + "name": "follow_ups_open_due_idx", + "columns": [ + { + "expression": "due_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"follow_ups\".\"status\" = 'open'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "follow_ups_animal_id_animals_id_fk": { + "name": "follow_ups_animal_id_animals_id_fk", + "tableFrom": "follow_ups", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "follow_ups_person_id_persons_id_fk": { + "name": "follow_ups_person_id_persons_id_fk", + "tableFrom": "follow_ups", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "follow_ups_registration_id_registrations_id_fk": { + "name": "follow_ups_registration_id_registrations_id_fk", + "tableFrom": "follow_ups", + "tableTo": "registrations", + "columnsFrom": [ + "registration_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "follow_ups_encounter_id_vet_encounters_id_fk": { + "name": "follow_ups_encounter_id_vet_encounters_id_fk", + "tableFrom": "follow_ups", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "follow_ups_status_check": { + "name": "follow_ups_status_check", + "value": "\"follow_ups\".\"status\" IN ('open','completed','cancelled')" + }, + "follow_ups_resolved_consistency_check": { + "name": "follow_ups_resolved_consistency_check", + "value": "(\"follow_ups\".\"status\" = 'open') = (\"follow_ups\".\"resolved_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.household_members": { + "name": "household_members", + "schema": "", + "columns": { + "household_id": { + "name": "household_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "household_members_household_id_households_id_fk": { + "name": "household_members_household_id_households_id_fk", + "tableFrom": "household_members", + "tableTo": "households", + "columnsFrom": [ + "household_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "household_members_person_id_persons_id_fk": { + "name": "household_members_person_id_persons_id_fk", + "tableFrom": "household_members", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "household_members_household_id_person_id_pk": { + "name": "household_members_household_id_person_id_pk", + "columns": [ + "household_id", + "person_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "household_members_role_check": { + "name": "household_members_role_check", + "value": "\"household_members\".\"role\" IN ('member','primary')" + } + }, + "isRLSEnabled": false + }, + "public.household_merges": { + "name": "household_merges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retired_household_id": { + "name": "retired_household_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "survivor_household_id": { + "name": "survivor_household_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "retired_name": { + "name": "retired_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "retired_address": { + "name": "retired_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "field_choices": { + "name": "field_choices", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "moved_counts": { + "name": "moved_counts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_label": { + "name": "merged_by_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_identity_id": { + "name": "merged_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "household_merges_retired_key": { + "name": "household_merges_retired_key", + "columns": [ + { + "expression": "retired_household_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "household_merges_survivor_idx": { + "name": "household_merges_survivor_idx", + "columns": [ + { + "expression": "survivor_household_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "household_merges_retired_household_id_households_id_fk": { + "name": "household_merges_retired_household_id_households_id_fk", + "tableFrom": "household_merges", + "tableTo": "households", + "columnsFrom": [ + "retired_household_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "household_merges_survivor_household_id_households_id_fk": { + "name": "household_merges_survivor_household_id_households_id_fk", + "tableFrom": "household_merges", + "tableTo": "households", + "columnsFrom": [ + "survivor_household_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "household_merges_merged_by_identity_id_auth_identities_id_fk": { + "name": "household_merges_merged_by_identity_id_auth_identities_id_fk", + "tableFrom": "household_merges", + "tableTo": "auth_identities", + "columnsFrom": [ + "merged_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "household_merges_not_self_check": { + "name": "household_merges_not_self_check", + "value": "\"household_merges\".\"retired_household_id\" <> \"household_merges\".\"survivor_household_id\"" + } + }, + "isRLSEnabled": false + }, + "public.households": { + "name": "households", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.lost_found_cases": { + "name": "lost_found_cases", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "case_type": { + "name": "case_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'open'" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "reported_at": { + "name": "reported_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "reported_via": { + "name": "reported_via", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'staff'" + }, + "reporter_name": { + "name": "reporter_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reporter_contact": { + "name": "reporter_contact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_seen_on": { + "name": "last_seen_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "last_seen_location": { + "name": "last_seen_location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "found_on": { + "name": "found_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "found_location": { + "name": "found_location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "photo_urls": { + "name": "photo_urls", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "chip_number": { + "name": "chip_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chip_display": { + "name": "chip_display", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "microchip_record_id": { + "name": "microchip_record_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "linked_at": { + "name": "linked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "linked_by": { + "name": "linked_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "published_by": { + "name": "published_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_note": { + "name": "public_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "outcome": { + "name": "outcome", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolution_note": { + "name": "resolution_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_identity_id": { + "name": "actor_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "lost_found_cases_animal_idx": { + "name": "lost_found_cases_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_chip_idx": { + "name": "lost_found_cases_chip_idx", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_open_idx": { + "name": "lost_found_cases_open_idx", + "columns": [ + { + "expression": "case_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "reported_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"lost_found_cases\".\"status\" = 'open'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_public_idx": { + "name": "lost_found_cases_public_idx", + "columns": [ + { + "expression": "reported_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"lost_found_cases\".\"status\" = 'open' AND \"lost_found_cases\".\"published_at\" IS NOT NULL AND \"lost_found_cases\".\"case_type\" = 'missing'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_open_missing_key": { + "name": "lost_found_cases_open_missing_key", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"lost_found_cases\".\"status\" = 'open' AND \"lost_found_cases\".\"case_type\" = 'missing'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_open_found_key": { + "name": "lost_found_cases_open_found_key", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"lost_found_cases\".\"status\" = 'open' AND \"lost_found_cases\".\"case_type\" = 'found' AND \"lost_found_cases\".\"animal_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "lost_found_cases_open_chip_key": { + "name": "lost_found_cases_open_chip_key", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"lost_found_cases\".\"status\" = 'open' AND \"lost_found_cases\".\"animal_id\" IS NULL AND \"lost_found_cases\".\"chip_number\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "lost_found_cases_animal_id_animals_id_fk": { + "name": "lost_found_cases_animal_id_animals_id_fk", + "tableFrom": "lost_found_cases", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "lost_found_cases_microchip_record_id_microchip_records_id_fk": { + "name": "lost_found_cases_microchip_record_id_microchip_records_id_fk", + "tableFrom": "lost_found_cases", + "tableTo": "microchip_records", + "columnsFrom": [ + "microchip_record_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "lost_found_cases_actor_identity_id_auth_identities_id_fk": { + "name": "lost_found_cases_actor_identity_id_auth_identities_id_fk", + "tableFrom": "lost_found_cases", + "tableTo": "auth_identities", + "columnsFrom": [ + "actor_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "lost_found_cases_type_check": { + "name": "lost_found_cases_type_check", + "value": "\"lost_found_cases\".\"case_type\" IN ('missing','found')" + }, + "lost_found_cases_status_check": { + "name": "lost_found_cases_status_check", + "value": "\"lost_found_cases\".\"status\" IN ('open','resolved','cancelled')" + }, + "lost_found_cases_outcome_check": { + "name": "lost_found_cases_outcome_check", + "value": "\"lost_found_cases\".\"outcome\" IS NULL OR \"lost_found_cases\".\"outcome\" IN ('reunited','owner-located','in-care','deceased','other')" + }, + "lost_found_cases_reported_via_check": { + "name": "lost_found_cases_reported_via_check", + "value": "\"lost_found_cases\".\"reported_via\" IN ('staff','owner-portal')" + }, + "lost_found_cases_missing_animal_check": { + "name": "lost_found_cases_missing_animal_check", + "value": "\"lost_found_cases\".\"case_type\" = 'found' OR \"lost_found_cases\".\"animal_id\" IS NOT NULL" + }, + "lost_found_cases_resolved_consistency_check": { + "name": "lost_found_cases_resolved_consistency_check", + "value": "(\"lost_found_cases\".\"status\" = 'open') = (\"lost_found_cases\".\"resolved_at\" IS NULL)" + }, + "lost_found_cases_outcome_consistency_check": { + "name": "lost_found_cases_outcome_consistency_check", + "value": "(\"lost_found_cases\".\"status\" = 'resolved') = (\"lost_found_cases\".\"outcome\" IS NOT NULL)" + }, + "lost_found_cases_publish_check": { + "name": "lost_found_cases_publish_check", + "value": "\"lost_found_cases\".\"published_at\" IS NULL OR (\"lost_found_cases\".\"case_type\" = 'missing' AND \"lost_found_cases\".\"animal_id\" IS NOT NULL)" + }, + "lost_found_cases_linked_check": { + "name": "lost_found_cases_linked_check", + "value": "\"lost_found_cases\".\"linked_at\" IS NULL OR (\"lost_found_cases\".\"linked_by\" IS NOT NULL AND \"lost_found_cases\".\"animal_id\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.lost_found_updates": { + "name": "lost_found_updates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "case_id": { + "name": "case_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "occurred_at": { + "name": "occurred_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reporter_name": { + "name": "reporter_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reporter_contact": { + "name": "reporter_contact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'staff'" + }, + "actor_identity_id": { + "name": "actor_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "lost_found_updates_case_idx": { + "name": "lost_found_updates_case_idx", + "columns": [ + { + "expression": "case_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "lost_found_updates_case_id_lost_found_cases_id_fk": { + "name": "lost_found_updates_case_id_lost_found_cases_id_fk", + "tableFrom": "lost_found_updates", + "tableTo": "lost_found_cases", + "columnsFrom": [ + "case_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "lost_found_updates_actor_identity_id_auth_identities_id_fk": { + "name": "lost_found_updates_actor_identity_id_auth_identities_id_fk", + "tableFrom": "lost_found_updates", + "tableTo": "auth_identities", + "columnsFrom": [ + "actor_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "lost_found_updates_kind_check": { + "name": "lost_found_updates_kind_check", + "value": "\"lost_found_updates\".\"kind\" IN ('sighting','scan','update')" + }, + "lost_found_updates_source_check": { + "name": "lost_found_updates_source_check", + "value": "\"lost_found_updates\".\"source\" IN ('staff','owner-portal','public')" + } + }, + "isRLSEnabled": false + }, + "public.medical_alerts": { + "name": "medical_alerts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "severity": { + "name": "severity", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'important'" + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "recorded_on": { + "name": "recorded_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "resolved_on": { + "name": "resolved_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "medical_alerts_animal_idx": { + "name": "medical_alerts_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "medical_alerts_active_idx": { + "name": "medical_alerts_active_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"medical_alerts\".\"status\" = 'active'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "medical_alerts_animal_id_animals_id_fk": { + "name": "medical_alerts_animal_id_animals_id_fk", + "tableFrom": "medical_alerts", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "medical_alerts_encounter_id_vet_encounters_id_fk": { + "name": "medical_alerts_encounter_id_vet_encounters_id_fk", + "tableFrom": "medical_alerts", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "medical_alerts_kind_check": { + "name": "medical_alerts_kind_check", + "value": "\"medical_alerts\".\"kind\" IN ('allergy','contraindication','condition','other')" + }, + "medical_alerts_severity_check": { + "name": "medical_alerts_severity_check", + "value": "\"medical_alerts\".\"severity\" IN ('info','important','critical')" + }, + "medical_alerts_status_check": { + "name": "medical_alerts_status_check", + "value": "\"medical_alerts\".\"status\" IN ('active','resolved')" + }, + "medical_alerts_resolved_consistency_check": { + "name": "medical_alerts_resolved_consistency_check", + "value": "(\"medical_alerts\".\"status\" = 'resolved') = (\"medical_alerts\".\"resolved_on\" IS NOT NULL)" + }, + "medical_alerts_resolved_range_check": { + "name": "medical_alerts_resolved_range_check", + "value": "\"medical_alerts\".\"resolved_on\" IS NULL OR \"medical_alerts\".\"resolved_on\" >= \"medical_alerts\".\"recorded_on\"" + } + }, + "isRLSEnabled": false + }, + "public.microchip_conflicts": { + "name": "microchip_conflicts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chip_number": { + "name": "chip_number", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "claimed_animal_id": { + "name": "claimed_animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "existing_record_id": { + "name": "existing_record_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "existing_animal_id": { + "name": "existing_animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "detail": { + "name": "detail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'open'" + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolution_note": { + "name": "resolution_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "microchip_conflicts_chip_idx": { + "name": "microchip_conflicts_chip_idx", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "microchip_conflicts_animal_idx": { + "name": "microchip_conflicts_animal_idx", + "columns": [ + { + "expression": "claimed_animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "microchip_conflicts_open_dedup": { + "name": "microchip_conflicts_open_dedup", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "claimed_animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"microchip_conflicts\".\"status\" = 'open'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "microchip_conflicts_claimed_animal_id_animals_id_fk": { + "name": "microchip_conflicts_claimed_animal_id_animals_id_fk", + "tableFrom": "microchip_conflicts", + "tableTo": "animals", + "columnsFrom": [ + "claimed_animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "microchip_conflicts_existing_record_id_microchip_records_id_fk": { + "name": "microchip_conflicts_existing_record_id_microchip_records_id_fk", + "tableFrom": "microchip_conflicts", + "tableTo": "microchip_records", + "columnsFrom": [ + "existing_record_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "microchip_conflicts_existing_animal_id_animals_id_fk": { + "name": "microchip_conflicts_existing_animal_id_animals_id_fk", + "tableFrom": "microchip_conflicts", + "tableTo": "animals", + "columnsFrom": [ + "existing_animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "microchip_conflicts_source_check": { + "name": "microchip_conflicts_source_check", + "value": "\"microchip_conflicts\".\"source\" IN ('staff','import')" + }, + "microchip_conflicts_status_check": { + "name": "microchip_conflicts_status_check", + "value": "\"microchip_conflicts\".\"status\" IN ('open','resolved')" + }, + "microchip_conflicts_resolved_consistency_check": { + "name": "microchip_conflicts_resolved_consistency_check", + "value": "(\"microchip_conflicts\".\"status\" = 'open') = (\"microchip_conflicts\".\"resolved_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.microchip_records": { + "name": "microchip_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chip_number": { + "name": "chip_number", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chip_display": { + "name": "chip_display", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "manufacturer": { + "name": "manufacturer", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "implanted_on": { + "name": "implanted_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "implanted_by": { + "name": "implanted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "assigned_from": { + "name": "assigned_from", + "type": "date", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_to": { + "name": "assigned_to", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "closed_reason": { + "name": "closed_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "replaced_by_id": { + "name": "replaced_by_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "microchip_active_chip_key": { + "name": "microchip_active_chip_key", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"microchip_records\".\"assigned_to\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "microchip_active_animal_key": { + "name": "microchip_active_animal_key", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"microchip_records\".\"assigned_to\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "microchip_chip_number_idx": { + "name": "microchip_chip_number_idx", + "columns": [ + { + "expression": "chip_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "microchip_animal_idx": { + "name": "microchip_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "microchip_records_animal_id_animals_id_fk": { + "name": "microchip_records_animal_id_animals_id_fk", + "tableFrom": "microchip_records", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "microchip_records_replaced_by_id_microchip_records_id_fk": { + "name": "microchip_records_replaced_by_id_microchip_records_id_fk", + "tableFrom": "microchip_records", + "tableTo": "microchip_records", + "columnsFrom": [ + "replaced_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "microchip_assignment_range_check": { + "name": "microchip_assignment_range_check", + "value": "\"microchip_records\".\"assigned_to\" IS NULL OR \"microchip_records\".\"assigned_to\" >= \"microchip_records\".\"assigned_from\"" + }, + "microchip_closed_reason_check": { + "name": "microchip_closed_reason_check", + "value": "\"microchip_records\".\"closed_reason\" IS NULL OR \"microchip_records\".\"closed_reason\" IN ('replaced','removed','corrected')" + }, + "microchip_closure_consistency_check": { + "name": "microchip_closure_consistency_check", + "value": "(\"microchip_records\".\"assigned_to\" IS NULL) = (\"microchip_records\".\"closed_reason\" IS NULL)" + }, + "microchip_replaced_by_check": { + "name": "microchip_replaced_by_check", + "value": "\"microchip_records\".\"replaced_by_id\" IS NULL OR (\"microchip_records\".\"replaced_by_id\" <> \"microchip_records\".\"id\" AND \"microchip_records\".\"assigned_to\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.owner_requests": { + "name": "owner_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "auth_identity_id": { + "name": "auth_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "ownership_id": { + "name": "ownership_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "detail": { + "name": "detail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "resolution_note": { + "name": "resolution_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "owner_requests_pending_idx": { + "name": "owner_requests_pending_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"owner_requests\".\"status\" = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "owner_requests_person_idx": { + "name": "owner_requests_person_idx", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "owner_requests_animal_idx": { + "name": "owner_requests_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "owner_requests_identity_idx": { + "name": "owner_requests_identity_idx", + "columns": [ + { + "expression": "auth_identity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "owner_requests_pending_dedup": { + "name": "owner_requests_pending_dedup", + "columns": [ + { + "expression": "auth_identity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"animal_id\", '00000000-0000-0000-0000-000000000000'::uuid)", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"owner_requests\".\"status\" = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "owner_requests_auth_identity_id_auth_identities_id_fk": { + "name": "owner_requests_auth_identity_id_auth_identities_id_fk", + "tableFrom": "owner_requests", + "tableTo": "auth_identities", + "columnsFrom": [ + "auth_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "owner_requests_person_id_persons_id_fk": { + "name": "owner_requests_person_id_persons_id_fk", + "tableFrom": "owner_requests", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "owner_requests_animal_id_animals_id_fk": { + "name": "owner_requests_animal_id_animals_id_fk", + "tableFrom": "owner_requests", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "owner_requests_ownership_id_ownerships_id_fk": { + "name": "owner_requests_ownership_id_ownerships_id_fk", + "tableFrom": "owner_requests", + "tableTo": "ownerships", + "columnsFrom": [ + "ownership_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "owner_requests_kind_check": { + "name": "owner_requests_kind_check", + "value": "\"owner_requests\".\"kind\" IN ('account-claim','no-longer-mine','transfer','lifecycle-deceased','lifecycle-moved-off-saba')" + }, + "owner_requests_status_check": { + "name": "owner_requests_status_check", + "value": "\"owner_requests\".\"status\" IN ('pending','approved','rejected','cancelled')" + }, + "owner_requests_resolved_consistency_check": { + "name": "owner_requests_resolved_consistency_check", + "value": "(\"owner_requests\".\"status\" = 'pending') = (\"owner_requests\".\"resolved_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.ownership_confirmations": { + "name": "ownership_confirmations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "ownership_id": { + "name": "ownership_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "confirmed_by_identity_id": { + "name": "confirmed_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "confirmed_on": { + "name": "confirmed_on", + "type": "date", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ownership_confirmations_ownership_idx": { + "name": "ownership_confirmations_ownership_idx", + "columns": [ + { + "expression": "ownership_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ownership_confirmations_animal_idx": { + "name": "ownership_confirmations_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ownership_confirmations_confirmed_idx": { + "name": "ownership_confirmations_confirmed_idx", + "columns": [ + { + "expression": "confirmed_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ownership_confirmations_ownership_id_ownerships_id_fk": { + "name": "ownership_confirmations_ownership_id_ownerships_id_fk", + "tableFrom": "ownership_confirmations", + "tableTo": "ownerships", + "columnsFrom": [ + "ownership_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ownership_confirmations_animal_id_animals_id_fk": { + "name": "ownership_confirmations_animal_id_animals_id_fk", + "tableFrom": "ownership_confirmations", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ownership_confirmations_person_id_persons_id_fk": { + "name": "ownership_confirmations_person_id_persons_id_fk", + "tableFrom": "ownership_confirmations", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ownership_confirmations_confirmed_by_identity_id_auth_identities_id_fk": { + "name": "ownership_confirmations_confirmed_by_identity_id_auth_identities_id_fk", + "tableFrom": "ownership_confirmations", + "tableTo": "auth_identities", + "columnsFrom": [ + "confirmed_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ownership_confirmations_method_check": { + "name": "ownership_confirmations_method_check", + "value": "\"ownership_confirmations\".\"method\" IN ('owner-portal','staff')" + } + }, + "isRLSEnabled": false + }, + "public.ownerships": { + "name": "ownerships", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "household_id": { + "name": "household_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "valid_from": { + "name": "valid_from", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "valid_to": { + "name": "valid_to", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ownerships_animal_idx": { + "name": "ownerships_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ownerships_person_idx": { + "name": "ownerships_person_idx", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ownerships_household_idx": { + "name": "ownerships_household_idx", + "columns": [ + { + "expression": "household_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ownerships_animal_id_animals_id_fk": { + "name": "ownerships_animal_id_animals_id_fk", + "tableFrom": "ownerships", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ownerships_person_id_persons_id_fk": { + "name": "ownerships_person_id_persons_id_fk", + "tableFrom": "ownerships", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ownerships_household_id_households_id_fk": { + "name": "ownerships_household_id_households_id_fk", + "tableFrom": "ownerships", + "tableTo": "households", + "columnsFrom": [ + "household_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ownerships_one_owner_side_check": { + "name": "ownerships_one_owner_side_check", + "value": "num_nonnulls(\"ownerships\".\"person_id\", \"ownerships\".\"household_id\") = 1" + }, + "ownerships_valid_range_check": { + "name": "ownerships_valid_range_check", + "value": "\"ownerships\".\"valid_to\" IS NULL OR \"ownerships\".\"valid_to\" > \"ownerships\".\"valid_from\"" + } + }, + "isRLSEnabled": false + }, + "public.payment_events": { + "name": "payment_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "payment_id": { + "name": "payment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event": { + "name": "event", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "actor_label": { + "name": "actor_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'staff'" + }, + "detail": { + "name": "detail", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payment_events_payment_idx": { + "name": "payment_events_payment_idx", + "columns": [ + { + "expression": "payment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payment_events_created_idx": { + "name": "payment_events_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payment_events_payment_id_payments_id_fk": { + "name": "payment_events_payment_id_payments_id_fk", + "tableFrom": "payment_events", + "tableTo": "payments", + "columnsFrom": [ + "payment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "payment_events_event_check": { + "name": "payment_events_event_check", + "value": "\"payment_events\".\"event\" IN ('recorded','confirmed','failed','voided','refunded','adjusted')" + }, + "payment_events_source_check": { + "name": "payment_events_source_check", + "value": "\"payment_events\".\"source\" IN ('staff','provider')" + } + }, + "isRLSEnabled": false + }, + "public.payments": { + "name": "payments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "registration_id": { + "name": "registration_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "submission_id": { + "name": "submission_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "currency": { + "name": "currency", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'USD'" + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'payment'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'other'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'staff'" + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_ref": { + "name": "provider_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference": { + "name": "reference", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "related_payment_id": { + "name": "related_payment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "recorded_by": { + "name": "recorded_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "occurred_at": { + "name": "occurred_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payments_registration_idx": { + "name": "payments_registration_idx", + "columns": [ + { + "expression": "registration_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payments_person_idx": { + "name": "payments_person_idx", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payments_related_idx": { + "name": "payments_related_idx", + "columns": [ + { + "expression": "related_payment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payments_provider_ref_key": { + "name": "payments_provider_ref_key", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"payments\".\"provider_ref\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "payments_idempotency_key": { + "name": "payments_idempotency_key", + "columns": [ + { + "expression": "idempotency_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"payments\".\"idempotency_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payments_registration_id_registrations_id_fk": { + "name": "payments_registration_id_registrations_id_fk", + "tableFrom": "payments", + "tableTo": "registrations", + "columnsFrom": [ + "registration_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "payments_submission_id_registration_submissions_id_fk": { + "name": "payments_submission_id_registration_submissions_id_fk", + "tableFrom": "payments", + "tableTo": "registration_submissions", + "columnsFrom": [ + "submission_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "payments_person_id_persons_id_fk": { + "name": "payments_person_id_persons_id_fk", + "tableFrom": "payments", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "payments_related_payment_id_payments_id_fk": { + "name": "payments_related_payment_id_payments_id_fk", + "tableFrom": "payments", + "tableTo": "payments", + "columnsFrom": [ + "related_payment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "payments_kind_check": { + "name": "payments_kind_check", + "value": "\"payments\".\"kind\" IN ('payment','refund','adjustment')" + }, + "payments_status_check": { + "name": "payments_status_check", + "value": "\"payments\".\"status\" IN ('pending','confirmed','failed','void')" + }, + "payments_method_check": { + "name": "payments_method_check", + "value": "\"payments\".\"method\" IN ('cash','bank-transfer','other','online')" + }, + "payments_source_check": { + "name": "payments_source_check", + "value": "\"payments\".\"source\" IN ('staff','provider')" + }, + "payments_amount_check": { + "name": "payments_amount_check", + "value": "(\"payments\".\"kind\" IN ('payment','refund') AND \"payments\".\"amount_cents\" > 0) OR (\"payments\".\"kind\" = 'adjustment' AND \"payments\".\"amount_cents\" <> 0)" + }, + "payments_provider_consistency_check": { + "name": "payments_provider_consistency_check", + "value": "(\"payments\".\"method\" = 'online') = (\"payments\".\"provider\" IS NOT NULL) AND (\"payments\".\"provider_ref\" IS NULL OR \"payments\".\"provider\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.person_merges": { + "name": "person_merges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "retired_person_id": { + "name": "retired_person_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "survivor_person_id": { + "name": "survivor_person_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "retired_full_name": { + "name": "retired_full_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "retired_email": { + "name": "retired_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "field_choices": { + "name": "field_choices", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "moved_counts": { + "name": "moved_counts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_label": { + "name": "merged_by_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "merged_by_identity_id": { + "name": "merged_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "person_merges_retired_key": { + "name": "person_merges_retired_key", + "columns": [ + { + "expression": "retired_person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "person_merges_survivor_idx": { + "name": "person_merges_survivor_idx", + "columns": [ + { + "expression": "survivor_person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "person_merges_retired_person_id_persons_id_fk": { + "name": "person_merges_retired_person_id_persons_id_fk", + "tableFrom": "person_merges", + "tableTo": "persons", + "columnsFrom": [ + "retired_person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "person_merges_survivor_person_id_persons_id_fk": { + "name": "person_merges_survivor_person_id_persons_id_fk", + "tableFrom": "person_merges", + "tableTo": "persons", + "columnsFrom": [ + "survivor_person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "person_merges_merged_by_identity_id_auth_identities_id_fk": { + "name": "person_merges_merged_by_identity_id_auth_identities_id_fk", + "tableFrom": "person_merges", + "tableTo": "auth_identities", + "columnsFrom": [ + "merged_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "person_merges_not_self_check": { + "name": "person_merges_not_self_check", + "value": "\"person_merges\".\"retired_person_id\" <> \"person_merges\".\"survivor_person_id\"" + } + }, + "isRLSEnabled": false + }, + "public.persons": { + "name": "persons", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "full_name": { + "name": "full_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "preferred_channel": { + "name": "preferred_channel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "persons_email_idx": { + "name": "persons_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "persons_preferred_channel_check": { + "name": "persons_preferred_channel_check", + "value": "\"persons\".\"preferred_channel\" IS NULL OR \"persons\".\"preferred_channel\" IN ('email','phone','whatsapp','sms')" + } + }, + "isRLSEnabled": false + }, + "public.rate_limit_windows": { + "name": "rate_limit_windows", + "schema": "", + "columns": { + "bucket": { + "name": "bucket", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "window_start": { + "name": "window_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "rate_limit_windows_expiry_idx": { + "name": "rate_limit_windows_expiry_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "rate_limit_windows_bucket_subject_window_start_pk": { + "name": "rate_limit_windows_bucket_subject_window_start_pk", + "columns": [ + "bucket", + "subject", + "window_start" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.registration_submissions": { + "name": "registration_submissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "legacy_id": { + "name": "legacy_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_name": { + "name": "owner_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_address": { + "name": "owner_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_phone": { + "name": "owner_phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_email": { + "name": "owner_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "animals": { + "name": "animals", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "ownership_id": { + "name": "ownership_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "auth_identity_id": { + "name": "auth_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "requested_year": { + "name": "requested_year", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "owner_note": { + "name": "owner_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "payment_receipt_path": { + "name": "payment_receipt_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "receipt_requested": { + "name": "receipt_requested", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "receipt_verified_at": { + "name": "receipt_verified_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "receipt_purged_at": { + "name": "receipt_purged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "total_fee_cents": { + "name": "total_fee_cents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "currency": { + "name": "currency", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'USD'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "submitted_at": { + "name": "submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "decided_at": { + "name": "decided_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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "registration_submissions_legacy_id_key": { + "name": "registration_submissions_legacy_id_key", + "columns": [ + { + "expression": "legacy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "registration_submissions_pending_animal_year_key": { + "name": "registration_submissions_pending_animal_year_key", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "requested_year", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"registration_submissions\".\"status\" = 'pending' AND \"registration_submissions\".\"animal_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "registration_submissions_animal_year_idx": { + "name": "registration_submissions_animal_year_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "requested_year", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "registration_submissions_person_id_persons_id_fk": { + "name": "registration_submissions_person_id_persons_id_fk", + "tableFrom": "registration_submissions", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "registration_submissions_animal_id_animals_id_fk": { + "name": "registration_submissions_animal_id_animals_id_fk", + "tableFrom": "registration_submissions", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "registration_submissions_ownership_id_ownerships_id_fk": { + "name": "registration_submissions_ownership_id_ownerships_id_fk", + "tableFrom": "registration_submissions", + "tableTo": "ownerships", + "columnsFrom": [ + "ownership_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "registration_submissions_auth_identity_id_auth_identities_id_fk": { + "name": "registration_submissions_auth_identity_id_auth_identities_id_fk", + "tableFrom": "registration_submissions", + "tableTo": "auth_identities", + "columnsFrom": [ + "auth_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "registration_submissions_status_check": { + "name": "registration_submissions_status_check", + "value": "\"registration_submissions\".\"status\" IN ('pending','approved','rejected')" + }, + "registration_submissions_fee_check": { + "name": "registration_submissions_fee_check", + "value": "\"registration_submissions\".\"total_fee_cents\" >= 0" + }, + "registration_submissions_source_check": { + "name": "registration_submissions_source_check", + "value": "\"registration_submissions\".\"source\" IN ('public','portal')" + }, + "registration_submissions_requested_year_check": { + "name": "registration_submissions_requested_year_check", + "value": "\"registration_submissions\".\"requested_year\" IS NULL OR \"registration_submissions\".\"requested_year\" BETWEEN 2000 AND 2200" + }, + "registration_submissions_portal_linkage_check": { + "name": "registration_submissions_portal_linkage_check", + "value": "\"registration_submissions\".\"source\" <> 'portal' OR (\"registration_submissions\".\"animal_id\" IS NOT NULL AND \"registration_submissions\".\"requested_year\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.registrations": { + "name": "registrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "submission_id": { + "name": "submission_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "year": { + "name": "year", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "ownership_id": { + "name": "ownership_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "household_id": { + "name": "household_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "owner_label": { + "name": "owner_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "submitted_at": { + "name": "submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "registered_at": { + "name": "registered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "amount_due_cents": { + "name": "amount_due_cents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "currency": { + "name": "currency", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'USD'" + }, + "resolution": { + "name": "resolution", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolution_note": { + "name": "resolution_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancelled_at": { + "name": "cancelled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancellation_reason": { + "name": "cancellation_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancellation_note": { + "name": "cancellation_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "registrations_animal_year_key": { + "name": "registrations_animal_year_key", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "year", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "registrations_submission_idx": { + "name": "registrations_submission_idx", + "columns": [ + { + "expression": "submission_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "registrations_year_status_idx": { + "name": "registrations_year_status_idx", + "columns": [ + { + "expression": "year", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "registrations_person_idx": { + "name": "registrations_person_idx", + "columns": [ + { + "expression": "person_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "registrations_household_idx": { + "name": "registrations_household_idx", + "columns": [ + { + "expression": "household_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "registrations_animal_id_animals_id_fk": { + "name": "registrations_animal_id_animals_id_fk", + "tableFrom": "registrations", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "registrations_submission_id_registration_submissions_id_fk": { + "name": "registrations_submission_id_registration_submissions_id_fk", + "tableFrom": "registrations", + "tableTo": "registration_submissions", + "columnsFrom": [ + "submission_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "registrations_ownership_id_ownerships_id_fk": { + "name": "registrations_ownership_id_ownerships_id_fk", + "tableFrom": "registrations", + "tableTo": "ownerships", + "columnsFrom": [ + "ownership_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "registrations_person_id_persons_id_fk": { + "name": "registrations_person_id_persons_id_fk", + "tableFrom": "registrations", + "tableTo": "persons", + "columnsFrom": [ + "person_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "registrations_household_id_households_id_fk": { + "name": "registrations_household_id_households_id_fk", + "tableFrom": "registrations", + "tableTo": "households", + "columnsFrom": [ + "household_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "registrations_year_check": { + "name": "registrations_year_check", + "value": "\"registrations\".\"year\" BETWEEN 2000 AND 2200" + }, + "registrations_status_check": { + "name": "registrations_status_check", + "value": "\"registrations\".\"status\" IN ('active','cancelled')" + }, + "registrations_amount_check": { + "name": "registrations_amount_check", + "value": "\"registrations\".\"amount_due_cents\" >= 0" + }, + "registrations_owner_side_check": { + "name": "registrations_owner_side_check", + "value": "NOT (\"registrations\".\"person_id\" IS NOT NULL AND \"registrations\".\"household_id\" IS NOT NULL)" + }, + "registrations_cancellation_consistency_check": { + "name": "registrations_cancellation_consistency_check", + "value": "(\"registrations\".\"status\" = 'cancelled') = (\"registrations\".\"cancelled_at\" IS NOT NULL) AND (\"registrations\".\"cancelled_at\" IS NULL) = (\"registrations\".\"cancellation_reason\" IS NULL)" + }, + "registrations_cancellation_reason_check": { + "name": "registrations_cancellation_reason_check", + "value": "\"registrations\".\"cancellation_reason\" IS NULL OR \"registrations\".\"cancellation_reason\" IN ('correction','withdrawn')" + }, + "registrations_resolution_check": { + "name": "registrations_resolution_check", + "value": "\"registrations\".\"resolution\" IS NULL OR \"registrations\".\"resolution\" IN ('waived','complimentary')" + }, + "registrations_resolution_consistency_check": { + "name": "registrations_resolution_consistency_check", + "value": "(\"registrations\".\"resolution\" IS NULL) = (\"registrations\".\"resolved_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.retention_holds": { + "name": "retention_holds", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by_label": { + "name": "created_by_label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by_identity_id": { + "name": "created_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "removed_by_label": { + "name": "removed_by_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "removed_by_identity_id": { + "name": "removed_by_identity_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "retention_holds_active_key": { + "name": "retention_holds_active_key", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"retention_holds\".\"removed_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "retention_holds_entity_idx": { + "name": "retention_holds_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "retention_holds_created_by_identity_id_auth_identities_id_fk": { + "name": "retention_holds_created_by_identity_id_auth_identities_id_fk", + "tableFrom": "retention_holds", + "tableTo": "auth_identities", + "columnsFrom": [ + "created_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "retention_holds_removed_by_identity_id_auth_identities_id_fk": { + "name": "retention_holds_removed_by_identity_id_auth_identities_id_fk", + "tableFrom": "retention_holds", + "tableTo": "auth_identities", + "columnsFrom": [ + "removed_by_identity_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "retention_holds_entity_type_check": { + "name": "retention_holds_entity_type_check", + "value": "\"retention_holds\".\"entity_type\" IN ('registration_submission','registration')" + }, + "retention_holds_reason_check": { + "name": "retention_holds_reason_check", + "value": "length(btrim(\"retention_holds\".\"reason\")) > 0" + }, + "retention_holds_removed_consistency_check": { + "name": "retention_holds_removed_consistency_check", + "value": "(\"retention_holds\".\"removed_at\" IS NULL) = (\"retention_holds\".\"removed_by_label\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.vaccinations": { + "name": "vaccinations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "vaccine_name": { + "name": "vaccine_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "series_key": { + "name": "series_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "generated": { + "as": "lower(regexp_replace(\"vaccine_name\", '[^a-zA-Z0-9]+', '', 'g'))", + "type": "stored" + } + }, + "administered_on": { + "name": "administered_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "due_on": { + "name": "due_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "valid_until": { + "name": "valid_until", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "product_name": { + "name": "product_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "manufacturer": { + "name": "manufacturer", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lot_number": { + "name": "lot_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "administered_by": { + "name": "administered_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "document_path": { + "name": "document_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "vaccinations_animal_idx": { + "name": "vaccinations_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vaccinations_due_idx": { + "name": "vaccinations_due_idx", + "columns": [ + { + "expression": "due_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vaccinations_series_idx": { + "name": "vaccinations_series_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "series_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vaccinations_animal_id_animals_id_fk": { + "name": "vaccinations_animal_id_animals_id_fk", + "tableFrom": "vaccinations", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vaccinations_encounter_id_vet_encounters_id_fk": { + "name": "vaccinations_encounter_id_vet_encounters_id_fk", + "tableFrom": "vaccinations", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "vaccinations_due_range_check": { + "name": "vaccinations_due_range_check", + "value": "\"vaccinations\".\"due_on\" IS NULL OR \"vaccinations\".\"due_on\" >= \"vaccinations\".\"administered_on\"" + }, + "vaccinations_valid_range_check": { + "name": "vaccinations_valid_range_check", + "value": "\"vaccinations\".\"valid_until\" IS NULL OR \"vaccinations\".\"valid_until\" >= \"vaccinations\".\"administered_on\"" + } + }, + "isRLSEnabled": false + }, + "public.vet_documents": { + "name": "vet_documents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "vaccination_id": { + "name": "vaccination_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "storage_path": { + "name": "storage_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "vet_documents_animal_idx": { + "name": "vet_documents_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vet_documents_encounter_idx": { + "name": "vet_documents_encounter_idx", + "columns": [ + { + "expression": "encounter_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vet_documents_storage_path_key": { + "name": "vet_documents_storage_path_key", + "columns": [ + { + "expression": "storage_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vet_documents_animal_id_animals_id_fk": { + "name": "vet_documents_animal_id_animals_id_fk", + "tableFrom": "vet_documents", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vet_documents_encounter_id_vet_encounters_id_fk": { + "name": "vet_documents_encounter_id_vet_encounters_id_fk", + "tableFrom": "vet_documents", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vet_documents_vaccination_id_vaccinations_id_fk": { + "name": "vet_documents_vaccination_id_vaccinations_id_fk", + "tableFrom": "vet_documents", + "tableTo": "vaccinations", + "columnsFrom": [ + "vaccination_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "vet_documents_path_check": { + "name": "vet_documents_path_check", + "value": "\"vet_documents\".\"storage_path\" ~ '^vet-docs/'" + } + }, + "isRLSEnabled": false + }, + "public.vet_encounters": { + "name": "vet_encounters", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'visit'" + }, + "occurred_on": { + "name": "occurred_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "complaint": { + "name": "complaint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "findings": { + "name": "findings", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "assessment": { + "name": "assessment", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "vet_encounters_animal_idx": { + "name": "vet_encounters_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vet_encounters_animal_id_animals_id_fk": { + "name": "vet_encounters_animal_id_animals_id_fk", + "tableFrom": "vet_encounters", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "vet_encounters_kind_check": { + "name": "vet_encounters_kind_check", + "value": "\"vet_encounters\".\"kind\" IN ('visit','history','note')" + } + }, + "isRLSEnabled": false + }, + "public.vet_medications": { + "name": "vet_medications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "medication": { + "name": "medication", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dose": { + "name": "dose", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "route": { + "name": "route", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "frequency": { + "name": "frequency", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start_on": { + "name": "start_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "end_on": { + "name": "end_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "instructions": { + "name": "instructions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prescribed_by": { + "name": "prescribed_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "vet_medications_animal_idx": { + "name": "vet_medications_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "start_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vet_medications_encounter_idx": { + "name": "vet_medications_encounter_idx", + "columns": [ + { + "expression": "encounter_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vet_medications_animal_id_animals_id_fk": { + "name": "vet_medications_animal_id_animals_id_fk", + "tableFrom": "vet_medications", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vet_medications_encounter_id_vet_encounters_id_fk": { + "name": "vet_medications_encounter_id_vet_encounters_id_fk", + "tableFrom": "vet_medications", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "vet_medications_range_check": { + "name": "vet_medications_range_check", + "value": "\"vet_medications\".\"end_on\" IS NULL OR \"vet_medications\".\"end_on\" >= \"vet_medications\".\"start_on\"" + } + }, + "isRLSEnabled": false + }, + "public.vet_procedures": { + "name": "vet_procedures", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "performed_on": { + "name": "performed_on", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "vet_procedures_animal_idx": { + "name": "vet_procedures_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "performed_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vet_procedures_encounter_idx": { + "name": "vet_procedures_encounter_idx", + "columns": [ + { + "expression": "encounter_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vet_procedures_animal_id_animals_id_fk": { + "name": "vet_procedures_animal_id_animals_id_fk", + "tableFrom": "vet_procedures", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vet_procedures_encounter_id_vet_encounters_id_fk": { + "name": "vet_procedures_encounter_id_vet_encounters_id_fk", + "tableFrom": "vet_procedures", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "vet_procedures_kind_check": { + "name": "vet_procedures_kind_check", + "value": "\"vet_procedures\".\"kind\" IN ('spay','neuter','surgery','dental','wound','other')" + } + }, + "isRLSEnabled": false + }, + "public.weight_records": { + "name": "weight_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "animal_id": { + "name": "animal_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "encounter_id": { + "name": "encounter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "measured_on": { + "name": "measured_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "weight_grams": { + "name": "weight_grams", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "weight_records_animal_idx": { + "name": "weight_records_animal_idx", + "columns": [ + { + "expression": "animal_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "measured_on", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "weight_records_encounter_idx": { + "name": "weight_records_encounter_idx", + "columns": [ + { + "expression": "encounter_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weight_records_animal_id_animals_id_fk": { + "name": "weight_records_animal_id_animals_id_fk", + "tableFrom": "weight_records", + "tableTo": "animals", + "columnsFrom": [ + "animal_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "weight_records_encounter_id_vet_encounters_id_fk": { + "name": "weight_records_encounter_id_vet_encounters_id_fk", + "tableFrom": "weight_records", + "tableTo": "vet_encounters", + "columnsFrom": [ + "encounter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "weight_records_grams_check": { + "name": "weight_records_grams_check", + "value": "\"weight_records\".\"weight_grams\" > 0 AND \"weight_records\".\"weight_grams\" <= 200000" + } + }, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index fdef98a..1ef47da 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -176,6 +176,13 @@ "when": 1791074381378, "tag": "0024_prelaunch-legacy-remediation", "breakpoints": true + }, + { + "idx": 25, + "version": "7", + "when": 1791156700901, + "tag": "0025_portal-registration-requests", + "breakpoints": true } ] } diff --git a/src/app/admin/registrations/actions.ts b/src/app/admin/registrations/actions.ts index e9a5953..752ca82 100644 --- a/src/app/admin/registrations/actions.ts +++ b/src/app/admin/registrations/actions.ts @@ -10,6 +10,7 @@ import { adminReceiptBucket } from "@/lib/firebase-admin-storage"; import { createRegistration, getRegistrationQueues, + getSubmissionLinkTarget, listRegistrationSubmissions, updateSubmissionStatus, type AdminRegistrationSubmission, @@ -58,6 +59,14 @@ function toRegistration( paymentReceipt: dto.paymentReceiptPath, receiptVerifiedAt: dto.receiptVerifiedAt, receiptPurgedAt: dto.receiptPurgedAt, + source: (dto.source === "portal" ? "portal" : "public") as + | "public" + | "portal", + linkedAnimalId: dto.animalId, + linkedAnimalName: dto.linkedAnimalName, + linkedAnimalRegistryRef: dto.linkedAnimalRegistryRef, + requestedYear: dto.requestedYear, + ownerNote: dto.ownerNote, totalFee: dto.totalFeeCents / 100, status: dto.status as AnimalRegistration["status"], createdAt: dto.submittedAt, @@ -213,19 +222,42 @@ export async function getRegistrationQueuesAction(): Promise return getRegistrationQueues(); } -// Link a reviewed submission's animal claim to a registry animal and -// create the authoritative registration. Matching is ALWAYS the -// staff member's choice via the animal picker — intake data never -// auto-matches (#178 owns generic duplicate detection). +// Link a reviewed submission to a registry animal and create the +// authoritative registration. For PUBLIC submissions matching is +// ALWAYS the staff member's choice via the animal picker — intake data +// never auto-matches (#178 owns generic duplicate detection). For +// PORTAL-originated requests the canonical animal and year are already +// stored on the row (server-resolved at submit time); passing +// animalId=null makes the server use them rather than trusting the +// client's pick. export async function createRegistrationFromSubmissionAction( - animalId: string, + animalId: string | null, submissionId: string, ): Promise { const { authorized, user } = await requireAdmin(); if (!authorized) throw new Error("Unauthorized"); try { + const target = await getSubmissionLinkTarget(submissionId); + if (!target) return { ok: false, reason: "not-found" }; + // A rejected submission records a staff decision — registering it + // anyway would contradict that decision. Reconsideration goes + // through the review transition back to pending first. + if (target.status === "rejected") { + return { ok: false, reason: "invalid" }; + } + const resolvedAnimalId = + target.source === "portal" && target.animalId + ? target.animalId + : animalId; + if (!resolvedAnimalId) return { ok: false, reason: "invalid" }; const result = await createRegistration( - { animalId, submissionId }, + { + animalId: resolvedAnimalId, + submissionId, + ...(target.source === "portal" && target.requestedYear !== null + ? { year: target.requestedYear } + : {}), + }, user?.email ?? "unknown", ); return result.ok ? { ok: true } : { ok: false, reason: result.reason }; diff --git a/src/app/admin/registrations/page.tsx b/src/app/admin/registrations/page.tsx index 48115b5..5019f2d 100644 --- a/src/app/admin/registrations/page.tsx +++ b/src/app/admin/registrations/page.tsx @@ -299,6 +299,40 @@ export default function RegistrationsPage() { } }; + // Portal-originated requests (#297): the canonical animal/year are + // already on the row — a single deliberate click creates the + // registration through the same service, no re-matching needed. + const registerPortalRequest = (registration: AnimalRegistration) => { + mutation.run(async () => { + try { + const result = await createRegistrationFromSubmissionAction( + null, + registration.id, + ); + if (!result.ok) { + toast({ + title: "Couldn't register", + description: + result.reason === "conflict" + ? "That animal already has a registration for this period." + : "Failed to create the registration. Try again.", + variant: "destructive", + }); + return; + } + toast({ title: "Registration created and linked" }); + await loadAll(); + } catch (error) { + logError("registration", "registration-link", error); + toast({ + title: "Error", + description: "Failed to create the registration. Try again.", + variant: "destructive", + }); + } + }, `register-portal-${registration.id}`); + }; + const linkSubmission = (animalId: string) => { if (!linking) return; mutation.run(async () => { @@ -715,12 +749,32 @@ export default function RegistrationsPage() { ))} + {/* Portal requests carry the canonical animal — + staff verify rather than re-match (#297). */} + {registration.linkedAnimalId && ( +
+ + {registration.linkedAnimalName ?? "Linked animal"} + + {registration.linkedAnimalRegistryRef && ( + + {registration.linkedAnimalRegistryRef} + + )} +
+ )} ${registration.totalFee ?? "—"}
+ {registration.source === "portal" && ( + Owner portal + )} {registration.retentionHold && ( - + {/* Portal requests are pre-linked server-side — + one deliberate click registers them; public + submissions still need the animal picker. + A rejected row records a decision — no + register affordance on it. */} + {registration.source === "portal" ? ( + registration.status !== "rejected" && ( + + ) + ) : ( + + )} {registration.paymentReceipt && (
+ {selected.source === "portal" && ( +
+

Portal request

+

+ {selected.requestedYear ?? "—"} registration · linked to{" "} + {selected.linkedAnimalId ? ( + + {selected.linkedAnimalName ?? "animal"} + + ) : ( + "—" + )} + {selected.linkedAnimalRegistryRef && + ` (${selected.linkedAnimalRegistryRef})`} +

+ {selected.ownerNote && ( +

+ Owner note:{" "} + {selected.ownerNote} +

+ )} +
+ )}

Owner

{selected.ownerInfo?.name ?? "—"}

diff --git a/src/app/portal/actions.ts b/src/app/portal/actions.ts index 063e3cf..206e16c 100644 --- a/src/app/portal/actions.ts +++ b/src/app/portal/actions.ts @@ -20,6 +20,12 @@ import { type OwnerRequestKind, } from "@/lib/registry/owner-request-kinds"; import { reportMissingByOwner } from "@/lib/registry/lost-found"; +import { + createPortalRegistrationRequest, + PORTAL_REQUEST_NOTE_MAX, +} from "@/lib/registry/registrations"; +import { checkRateLimit, warnThrottled } from "@/lib/rate-limit"; +import { subjectForPrincipal } from "@/lib/request-identity"; import { logError } from "@/lib/logger"; export interface PortalActionResult { @@ -232,6 +238,84 @@ export async function cancelOwnerRequestAction( } } +export interface RequestRegistrationInput { + ownershipId: string; + // Client-generated uuid — the receipt object name and the idempotent + // retry handle, same contract as the public intake. + submissionId: string; + // Optional "something changed" note for staff — a claim reviewed by + // humans, never an auto-applied edit to canonical records. + note?: string; + wantsReceipt?: boolean; +} + +export type RequestRegistrationResult = + | { ok: true; submissionId: string } + | { ok: false; error: string }; + +// "Please register my animal for this year" (#297). Creates a +// staff-reviewed submission in the SAME intake queue as the public +// form — never an authoritative registration. The service re-verifies +// the ownership relationship, animal eligibility, and (animal, year) +// slot server-side; the client supplies no ids beyond the ownership. +export async function requestRegistrationAction( + input: RequestRegistrationInput, +): Promise { + const ctx = await requireLinkedOwner(); + if (!ctx.ok) return { ok: false, error: ctx.error }; + + if (input.note && input.note.length > PORTAL_REQUEST_NOTE_MAX) { + return { ok: false, error: "Note is too long." }; + } + + // Authenticated abuse is bounded by the unique pending-request index + // and staff pacing, but a user-scoped limiter is still cheap + // defense-in-depth — keyed by identity, never by shared-IP heuristics. + const gate = await checkRateLimit( + "registration.submit", + subjectForPrincipal("owner", ctx.identity.id), + ); + if (!gate.allowed) { + warnThrottled("registration", "registration.submit", gate); + return { + ok: false, + error: "Too many requests. Please wait a moment and try again.", + }; + } + + try { + const result = await createPortalRegistrationRequest( + { + ownershipId: input.ownershipId, + personId: ctx.person.id, + authIdentityId: ctx.identity.id, + submissionId: input.submissionId, + ownerNote: input.note, + receiptRequested: input.wantsReceipt === true, + }, + ctx.identity.email ?? ctx.person.fullName, + ); + if (!result.ok) { + return { + ok: false, + error: + result.reason === "not-owner" + ? "That animal is not associated with you." + : result.reason === "conflict" + ? `This animal already has a registration or a pending request for this year.` + : result.reason === "not-eligible" + ? "This animal isn't eligible for registration right now." + : "Invalid request. Please try again.", + }; + } + revalidatePath("/portal"); + return { ok: true, submissionId: result.submissionId }; + } catch (error) { + logError("portal", "request-registration", error); + return { ok: false, error: "Something went wrong. Please try again." }; + } +} + // Owner self-service contact details. `notes` is staff-only scratch // space — never writable through this path. export async function updateOwnerProfileAction( diff --git a/src/app/portal/portal-client.tsx b/src/app/portal/portal-client.tsx index bd8020f..3b8fe5e 100644 --- a/src/app/portal/portal-client.tsx +++ b/src/app/portal/portal-client.tsx @@ -13,6 +13,13 @@ import { motion } from "framer-motion"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader } from "@/components/ui/card"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; @@ -29,9 +36,12 @@ import { cancelOwnerRequestAction, confirmAnimalAction, reportMissingAction, + requestRegistrationAction, submitOwnerReportAction, updateOwnerProfileAction, } from "./actions"; +import { isReceiptFile, RECEIPT_MAX_BYTES } from "@/lib/animal-registration"; +import { logError } from "@/lib/logger"; import { OWNER_REQUEST_KIND_LABELS, OWNER_SUBMITTABLE_KINDS, @@ -75,13 +85,28 @@ function formatMoney(cents: number, currency: string): string { // Exported for component tests — the status presentation carries the // confirmation-vs-registration distinction owners must understand. -export function AnimalCard({ animal }: { animal: PortalAnimal }) { +export function AnimalCard({ + animal, + owner, +}: { + animal: PortalAnimal; + // The signed-in owner's own contact snapshot — shown read-only in the + // registration request dialog. Optional so card tests can omit it. + owner?: Pick< + PersonRecord, + "fullName" | "email" | "phone" | "address" + > | null; +}) { const { toast } = useToast(); const [pending, startTransition] = useTransition(); const statusTransition = useMotionTransition({ duration: 0.25, ease: "easeOut", }); + const [requestOpen, setRequestOpen] = useState(false); + const [requestNote, setRequestNote] = useState(""); + const [receiptFile, setReceiptFile] = useState(null); + const [receiptError, setReceiptError] = useState(null); const [reportKind, setReportKind] = useState(""); const [detail, setDetail] = useState(""); const [targetName, setTargetName] = useState(""); @@ -99,6 +124,70 @@ export function AnimalCard({ animal }: { animal: PortalAnimal }) { (y) => y !== animal.registration?.year, ); + // The receipt is a second write AFTER the request row lands — the + // same bounded upload route as the public form (claim + byte + // validation + create-only storage). A failed upload must not undo + // the request, only warn about the file. + const submitRequest = () => { + if (receiptFile && !isReceiptFile(receiptFile)) { + setReceiptError( + `Receipt must be a PDF or image up to ${Math.round(RECEIPT_MAX_BYTES / (1024 * 1024))} MB.`, + ); + return; + } + startTransition(async () => { + const submissionId = crypto.randomUUID(); + const result = await requestRegistrationAction({ + ownershipId: animal.ownershipId, + submissionId, + note: requestNote || undefined, + wantsReceipt: receiptFile !== null, + }); + if (!result.ok) { + toast({ + title: "Couldn't submit the request", + description: result.error, + variant: "destructive", + }); + return; + } + let receiptDelivered = true; + if (receiptFile) { + try { + const upload = await fetch(`/api/receipts/${submissionId}`, { + method: "POST", + headers: { "Content-Type": receiptFile.type }, + body: receiptFile, + }); + if (!upload.ok) { + if (upload.status !== 429) { + logError( + "registration", + "receipt-upload", + new Error(`upload ${upload.status}`), + ); + } + receiptDelivered = false; + } + } catch (uploadError) { + receiptDelivered = false; + logError("registration", "receipt-upload", uploadError); + } + } + toast({ + title: "Request submitted", + description: + receiptFile && !receiptDelivered + ? `Your ${animal.registrationYear} request went through, but the receipt could not be uploaded — staff can still review the request.` + : `SFPCA staff will review your ${animal.registrationYear} request for ${animal.name}.`, + }); + setRequestOpen(false); + setRequestNote(""); + setReceiptFile(null); + setReceiptError(null); + }); + }; + const confirm = () => { startTransition(async () => { const result = await confirmAnimalAction(animal.ownershipId); @@ -256,22 +345,66 @@ export function AnimalCard({ animal }: { animal: PortalAnimal }) { {registrationPeriodLabel(animal.registrationYear)}

{animal.registration === null ? ( - <> -

-

-

- Required for every animal each year. -

- {/* The existing intake path: the public form lands in - staff review, which produces the registration row. */} - - + animal.registrationRequest ? ( + /* In-flight portal request (#297) — the honest in-between + state: not yet registered, no second request allowed. */ + <> +

+ {animal.registrationRequest.status === "rejected" + ? "Request declined" + : animal.registrationRequest.status === "approved" + ? "Approved" + : "Request submitted"} +

+

+ {animal.registrationRequest.status === "rejected" ? ( + <> + Staff declined the request —{" "} + + contact us + {" "} + if you have questions. + + ) : animal.registrationRequest.status === "approved" ? ( + "SFPCA is finalizing the registration." + ) : ( + `Awaiting SFPCA review · sent ${formatIsoDate(animal.registrationRequest.submittedAt)}` + )} +

+ + ) : animal.registrationCancelled ? ( + /* A cancelled row still holds the (animal, year) slot — + staff resolve it; an owner request can never fulfil it. */ + <> +

Not registered

+

+ + Contact us + {" "} + about {animal.name}'s {animal.registrationYear}{" "} + registration. +

+ + ) : ( + <> +

+

+

+ Required for every animal each year. +

+ {/* Portal-native request (#297): prefilled from canonical + data, lands in the same staff review queue as the + public intake — never a direct registration. */} + + + ) ) : OUTSTANDING_PAYMENT_STATES.includes( animal.registration.paymentState, ) ? ( @@ -476,6 +609,108 @@ export function AnimalCard({ animal }: { animal: PortalAnimal }) {

)} + + {/* Registration request dialog (#297) — prefilled from the + canonical records the portal already knows; nothing typed + here mutates them. */} + + + + + Register {animal.name} for {animal.registrationYear} + + + We'll use the information already on file. SFPCA staff + will review the request before the registration is + finalized. + + +
+
+

Animal on file

+

+ {animal.name} · {animal.species} · {animal.sex} + {animal.chipNumber ? ` · Microchip ${animal.chipNumber}` : ""} +

+
+ {owner && ( +
+

Your details on file

+

+ {owner.fullName} + {owner.address ? ` · ${owner.address}` : ""} +

+

+ {[owner.phone, owner.email].filter(Boolean).join(" · ") || + "No contact details on file"} +

+

+ Out of date? Update your profile below before + submitting. +

+
+ )} +
+ +