CREATE TYPE "MaterialKind" AS ENUM ('WAX', 'FRAGRANCE', 'WICK', 'DYE', 'VESSEL', 'PACKAGING', 'LABEL', 'OTHER'); CREATE TYPE "MaterialUnit" AS ENUM ('GRAM', 'KILOGRAM', 'MILLILITRE', 'LITRE', 'PIECE', 'METRE'); CREATE TABLE "suppliers" ( "id" UUID NOT NULL, "organization_id" UUID NOT NULL, "name" VARCHAR(160) NOT NULL, "code" VARCHAR(32) NOT NULL, "contact_name" VARCHAR(160) NOT NULL, "email" VARCHAR(254) NOT NULL, "phone" VARCHAR(24) NOT NULL, "active" BOOLEAN NOT NULL DEFAULT true, "created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMPTZ(3) NOT NULL, CONSTRAINT "suppliers_pkey" PRIMARY KEY ("id") ); CREATE TABLE "materials" ( "id" UUID NOT NULL, "organization_id" UUID NOT NULL, "name" VARCHAR(160) NOT NULL, "code" VARCHAR(32) NOT NULL, "kind" "MaterialKind" NOT NULL, "unit" "MaterialUnit" NOT NULL, "active" BOOLEAN NOT NULL DEFAULT true, "created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMPTZ(3) NOT NULL, CONSTRAINT "materials_pkey" PRIMARY KEY ("id") ); CREATE TABLE "supplier_materials" ( "supplier_id" UUID NOT NULL, "material_id" UUID NOT NULL, "organization_id" UUID NOT NULL, "supplier_sku" VARCHAR(64) NOT NULL, "lead_time_days" INTEGER NOT NULL, "min_order_quantity" DECIMAL(12,3) NOT NULL, "unit_price" DECIMAL(12,2) NOT NULL, "currency" CHAR(3) NOT NULL, "active" BOOLEAN NOT NULL DEFAULT true, "updated_at" TIMESTAMPTZ(3) NOT NULL, CONSTRAINT "supplier_materials_pkey" PRIMARY KEY ("supplier_id", "material_id") ); CREATE UNIQUE INDEX "suppliers_organization_id_code_key" ON "suppliers"("organization_id", "code"); CREATE UNIQUE INDEX "suppliers_id_organization_id_key" ON "suppliers"("id", "organization_id"); CREATE INDEX "suppliers_organization_id_active_name_id_idx" ON "suppliers"("organization_id", "active", "name", "id"); CREATE UNIQUE INDEX "materials_organization_id_code_key" ON "materials"("organization_id", "code"); CREATE UNIQUE INDEX "materials_id_organization_id_key" ON "materials"("id", "organization_id"); CREATE INDEX "materials_organization_id_active_kind_name_id_idx" ON "materials"("organization_id", "active", "kind", "name", "id"); CREATE INDEX "supplier_materials_material_id_organization_id_active_idx" ON "supplier_materials"("material_id", "organization_id", "active"); ALTER TABLE "suppliers" ADD CONSTRAINT "suppliers_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "materials" ADD CONSTRAINT "materials_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "supplier_materials" ADD CONSTRAINT "supplier_materials_supplier_id_organization_id_fkey" FOREIGN KEY ("supplier_id", "organization_id") REFERENCES "suppliers"("id", "organization_id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "supplier_materials" ADD CONSTRAINT "supplier_materials_material_id_organization_id_fkey" FOREIGN KEY ("material_id", "organization_id") REFERENCES "materials"("id", "organization_id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "supplier_materials" ADD CONSTRAINT "supplier_materials_bounds" CHECK ("lead_time_days" BETWEEN 0 AND 365 AND "min_order_quantity" > 0 AND "unit_price" >= 0 AND "currency" IN ('INR', 'USD', 'EUR', 'GBP')); UPDATE "roles" SET "permissions" = ARRAY(SELECT DISTINCT permission FROM unnest("permissions" || ARRAY['procurement.read', 'procurement.manage']::text[]) AS permission ORDER BY permission) WHERE "is_system" = true;