Add repairs domain with tickets, line items, batches, and service templates
Full-stack implementation of instrument repair tracking: DB schema with repair_ticket, repair_line_item, repair_batch, and repair_service_template tables. Backend services and routes with pagination/search/sort. 20 API tests covering CRUD, status workflow, line items, and batch operations. Admin frontend with ticket list, detail with status progression, line item management, batch list/detail with approval workflow, and new ticket form with searchable account picker and intake photo uploads.
This commit is contained in:
78
packages/backend/src/db/migrations/0015_repairs.sql
Normal file
78
packages/backend/src/db/migrations/0015_repairs.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
-- Repair domain enums
|
||||
CREATE TYPE "repair_ticket_status" AS ENUM ('intake', 'diagnosing', 'pending_approval', 'approved', 'in_progress', 'pending_parts', 'ready', 'picked_up', 'delivered', 'cancelled');
|
||||
CREATE TYPE "repair_line_item_type" AS ENUM ('labor', 'part', 'flat_rate', 'misc');
|
||||
CREATE TYPE "repair_condition_in" AS ENUM ('excellent', 'good', 'fair', 'poor');
|
||||
CREATE TYPE "repair_batch_status" AS ENUM ('intake', 'in_progress', 'pending_approval', 'approved', 'completed', 'delivered', 'cancelled');
|
||||
CREATE TYPE "repair_batch_approval" AS ENUM ('pending', 'approved', 'rejected');
|
||||
|
||||
-- Repair batches (defined first — tickets FK to it)
|
||||
CREATE TABLE "repair_batch" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"company_id" uuid NOT NULL REFERENCES "company"("id"),
|
||||
"location_id" uuid REFERENCES "location"("id"),
|
||||
"batch_number" varchar(50),
|
||||
"account_id" uuid NOT NULL REFERENCES "account"("id"),
|
||||
"contact_name" varchar(255),
|
||||
"contact_phone" varchar(50),
|
||||
"contact_email" varchar(255),
|
||||
"status" "repair_batch_status" NOT NULL DEFAULT 'intake',
|
||||
"approval_status" "repair_batch_approval" NOT NULL DEFAULT 'pending',
|
||||
"approved_by" uuid REFERENCES "user"("id"),
|
||||
"approved_at" timestamp with time zone,
|
||||
"pickup_date" timestamp with time zone,
|
||||
"due_date" timestamp with time zone,
|
||||
"completed_date" timestamp with time zone,
|
||||
"delivered_date" timestamp with time zone,
|
||||
"instrument_count" integer NOT NULL DEFAULT 0,
|
||||
"received_count" integer NOT NULL DEFAULT 0,
|
||||
"estimated_total" numeric(10, 2),
|
||||
"actual_total" numeric(10, 2),
|
||||
"notes" text,
|
||||
"legacy_id" varchar(255),
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
"updated_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Repair tickets
|
||||
CREATE TABLE "repair_ticket" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"company_id" uuid NOT NULL REFERENCES "company"("id"),
|
||||
"location_id" uuid REFERENCES "location"("id"),
|
||||
"repair_batch_id" uuid REFERENCES "repair_batch"("id"),
|
||||
"ticket_number" varchar(50),
|
||||
"account_id" uuid REFERENCES "account"("id"),
|
||||
"customer_name" varchar(255) NOT NULL,
|
||||
"customer_phone" varchar(50),
|
||||
"inventory_unit_id" uuid REFERENCES "inventory_unit"("id"),
|
||||
"instrument_description" text,
|
||||
"serial_number" varchar(255),
|
||||
"condition_in" "repair_condition_in",
|
||||
"condition_in_notes" text,
|
||||
"problem_description" text NOT NULL,
|
||||
"technician_notes" text,
|
||||
"status" "repair_ticket_status" NOT NULL DEFAULT 'intake',
|
||||
"assigned_technician_id" uuid REFERENCES "user"("id"),
|
||||
"estimated_cost" numeric(10, 2),
|
||||
"actual_cost" numeric(10, 2),
|
||||
"intake_date" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
"promised_date" timestamp with time zone,
|
||||
"completed_date" timestamp with time zone,
|
||||
"legacy_id" varchar(255),
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
"updated_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Repair line items
|
||||
CREATE TABLE "repair_line_item" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"repair_ticket_id" uuid NOT NULL REFERENCES "repair_ticket"("id"),
|
||||
"item_type" "repair_line_item_type" NOT NULL,
|
||||
"description" varchar(255) NOT NULL,
|
||||
"product_id" uuid REFERENCES "product"("id"),
|
||||
"qty" numeric(10, 3) NOT NULL DEFAULT 1,
|
||||
"unit_price" numeric(10, 2) NOT NULL DEFAULT 0,
|
||||
"total_price" numeric(10, 2) NOT NULL DEFAULT 0,
|
||||
"cost" numeric(10, 2),
|
||||
"technician_id" uuid REFERENCES "user"("id"),
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE "repair_service_template" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"company_id" uuid NOT NULL REFERENCES "company"("id"),
|
||||
"name" varchar(255) NOT NULL,
|
||||
"instrument_type" varchar(100),
|
||||
"size" varchar(50),
|
||||
"description" text,
|
||||
"item_type" "repair_line_item_type" NOT NULL DEFAULT 'flat_rate',
|
||||
"default_price" numeric(10, 2) NOT NULL DEFAULT 0,
|
||||
"default_cost" numeric(10, 2),
|
||||
"sort_order" integer NOT NULL DEFAULT 0,
|
||||
"is_active" boolean NOT NULL DEFAULT true,
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
"updated_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
@@ -106,6 +106,20 @@
|
||||
"when": 1774740000000,
|
||||
"tag": "0014_user_is_active",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"version": "7",
|
||||
"when": 1774750000000,
|
||||
"tag": "0015_repairs",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"version": "7",
|
||||
"when": 1774760000000,
|
||||
"tag": "0016_repair_service_templates",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user