diff --git a/prisma/migrations/20261014160000_c2_plan_order/migration.sql b/prisma/migrations/20261014160000_c2_plan_order/migration.sql new file mode 100644 index 0000000..ae3b335 --- /dev/null +++ b/prisma/migrations/20261014160000_c2_plan_order/migration.sql @@ -0,0 +1,102 @@ +-- CreateTable +CREATE TABLE `svc_plan` ( + `id` VARCHAR(36) NOT NULL, + `tenant_code` VARCHAR(64) NOT NULL, + `elder_id` VARCHAR(36) NOT NULL, + `plan_period_start` DATE NOT NULL, + `plan_period_end` DATE NOT NULL, + `care_level` VARCHAR(20) NOT NULL, + `care_mode` VARCHAR(20) NOT NULL, + `item_count` INTEGER NOT NULL DEFAULT 0, + `item_count_rule` VARCHAR(100) NULL, + `extra_item_count` INTEGER NOT NULL DEFAULT 0, + `week_freq` INTEGER NULL, + `month_hours` INTEGER NULL, + `plan_status` VARCHAR(20) NOT NULL DEFAULT 'draft', + `confirm_elder` BOOLEAN NOT NULL DEFAULT false, + `confirm_guardian` BOOLEAN NOT NULL DEFAULT false, + `confirm_time` DATETIME(3) NULL, + `plan_basis` JSON NULL, + `change_from_plan_id` VARCHAR(36) NULL, + `biz_line` VARCHAR(20) NOT NULL DEFAULT 'ltci', + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `created_by` VARCHAR(36) NULL, + `updated_at` DATETIME(3) NOT NULL, + `deleted_at` DATETIME(3) NULL, + + INDEX `svc_plan_tenant_code_elder_id_idx`(`tenant_code`, `elder_id`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; + +-- CreateTable +CREATE TABLE `svc_plan_item` ( + `id` VARCHAR(36) NOT NULL, + `plan_id` VARCHAR(36) NOT NULL, + `tenant_code` VARCHAR(64) NOT NULL, + `svc_id` VARCHAR(36) NOT NULL, + `svc_name_snapshot` VARCHAR(100) NOT NULL, + `svc_code_snapshot` VARCHAR(20) NULL, + `freq_type` VARCHAR(20) NULL, + `freq_value` INTEGER NULL, + `duration_min` INTEGER NULL, + `photo_tier` VARCHAR(10) NOT NULL DEFAULT 'free', + `caution_note` TEXT NULL, + `is_medical` BOOLEAN NOT NULL DEFAULT false, + `need_cert` BOOLEAN NOT NULL DEFAULT false, + + INDEX `svc_plan_item_plan_id_idx`(`plan_id`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; + +-- CreateTable +CREATE TABLE `svc_order` ( + `id` VARCHAR(36) NOT NULL, + `tenant_code` VARCHAR(64) NOT NULL, + `elder_id` VARCHAR(36) NOT NULL, + `plan_id` VARCHAR(36) NOT NULL, + `service_date` DATE NOT NULL, + `time_slot_start` DATETIME(3) NOT NULL, + `time_slot_end` DATETIME(3) NOT NULL, + `assignee_id` VARCHAR(36) NULL, + `assign_time` DATETIME(3) NULL, + `assign_mode` VARCHAR(20) NULL, + `order_status` VARCHAR(20) NOT NULL DEFAULT 'to_assign', + `item_list` JSON NOT NULL, + `need_photo` BOOLEAN NOT NULL DEFAULT false, + `cancel_reason` VARCHAR(200) NULL, + `reschedule_log` JSON NULL, + `qualification_check` VARCHAR(20) NULL, + `billable` BOOLEAN NOT NULL DEFAULT true, + `price_snapshot` JSON NULL, + `settle_period` VARCHAR(20) NULL, + `not_met_reason` VARCHAR(50) NULL, + `not_met_at` DATETIME(3) NULL, + `biz_line` VARCHAR(20) NOT NULL DEFAULT 'ltci', + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `created_by` VARCHAR(36) NULL, + `updated_at` DATETIME(3) NOT NULL, + `deleted_at` DATETIME(3) NULL, + + INDEX `svc_order_tenant_code_assignee_id_service_date_idx`(`tenant_code`, `assignee_id`, `service_date`), + INDEX `svc_order_tenant_code_elder_id_idx`(`tenant_code`, `elder_id`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; + +-- CreateTable +CREATE TABLE `ltc_elder_svc` ( + `id` VARCHAR(36) NOT NULL, + `tenant_code` VARCHAR(64) NOT NULL, + `elder_id` VARCHAR(36) NOT NULL, + `svc_id` VARCHAR(36) NOT NULL, + `svc_name_snapshot` VARCHAR(100) NOT NULL, + `svc_code_snapshot` VARCHAR(20) NULL, + `care_mode` VARCHAR(20) NOT NULL, + `is_active` BOOLEAN NOT NULL DEFAULT true, + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `created_by` VARCHAR(36) NULL, + `updated_at` DATETIME(3) NOT NULL, + `deleted_at` DATETIME(3) NULL, + + INDEX `ltc_elder_svc_tenant_code_elder_id_idx`(`tenant_code`, `elder_id`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3137971..97bf63e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -488,3 +488,106 @@ model ElderStatusLog { @@index([elderId]) @@map("ltc_elder_status_log") } + +/// 服务计划头 +model Plan { + id String @id @default(uuid(7)) @db.VarChar(36) + tenantCode String @map("tenant_code") @db.VarChar(64) + elderId String @map("elder_id") @db.VarChar(36) + planPeriodStart DateTime @map("plan_period_start") @db.Date + planPeriodEnd DateTime @map("plan_period_end") @db.Date + careLevel String @map("care_level") @db.VarChar(20) + careMode String @map("care_mode") @db.VarChar(20) + itemCount Int @default(0) @map("item_count") + itemCountRule String? @map("item_count_rule") @db.VarChar(100) + extraItemCount Int @default(0) @map("extra_item_count") + weekFreq Int? @map("week_freq") + monthHours Int? @map("month_hours") + planStatus String @default("draft") @map("plan_status") @db.VarChar(20) + confirmElder Boolean @default(false) @map("confirm_elder") + confirmGuardian Boolean @default(false) @map("confirm_guardian") + confirmTime DateTime? @map("confirm_time") + planBasis Json? @map("plan_basis") + changeFromPlanId String? @map("change_from_plan_id") @db.VarChar(36) + bizLine String @default("ltci") @map("biz_line") @db.VarChar(20) + createdAt DateTime @default(now()) @map("created_at") + createdBy String? @map("created_by") @db.VarChar(36) + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@index([tenantCode, elderId]) + @@map("svc_plan") +} + +/// 服务计划项 +model PlanItem { + id String @id @default(uuid(7)) @db.VarChar(36) + planId String @map("plan_id") @db.VarChar(36) + tenantCode String @map("tenant_code") @db.VarChar(64) + svcId String @map("svc_id") @db.VarChar(36) + svcNameSnapshot String @map("svc_name_snapshot") @db.VarChar(100) + svcCodeSnapshot String? @map("svc_code_snapshot") @db.VarChar(20) + freqType String? @map("freq_type") @db.VarChar(20) + freqValue Int? @map("freq_value") + durationMin Int? @map("duration_min") + photoTier String @default("free") @map("photo_tier") @db.VarChar(10) + cautionNote String? @map("caution_note") @db.Text + isMedical Boolean @default(false) @map("is_medical") + needCert Boolean @default(false) @map("need_cert") + + @@index([planId]) + @@map("svc_plan_item") +} + +/// 工单 +model Order { + id String @id @default(uuid(7)) @db.VarChar(36) + tenantCode String @map("tenant_code") @db.VarChar(64) + elderId String @map("elder_id") @db.VarChar(36) + planId String @map("plan_id") @db.VarChar(36) + serviceDate DateTime @map("service_date") @db.Date + timeSlotStart DateTime @map("time_slot_start") + timeSlotEnd DateTime @map("time_slot_end") + assigneeId String? @map("assignee_id") @db.VarChar(36) + assignTime DateTime? @map("assign_time") + assignMode String? @map("assign_mode") @db.VarChar(20) + orderStatus String @default("to_assign") @map("order_status") @db.VarChar(20) + itemList Json @map("item_list") + needPhoto Boolean @default(false) @map("need_photo") + cancelReason String? @map("cancel_reason") @db.VarChar(200) + rescheduleLog Json? @map("reschedule_log") + qualificationCheck String? @map("qualification_check") @db.VarChar(20) + billable Boolean @default(true) @map("billable") + priceSnapshot Json? @map("price_snapshot") + settlePeriod String? @map("settle_period") @db.VarChar(20) + notMetReason String? @map("not_met_reason") @db.VarChar(50) + notMetAt DateTime? @map("not_met_at") + bizLine String @default("ltci") @map("biz_line") @db.VarChar(20) + createdAt DateTime @default(now()) @map("created_at") + createdBy String? @map("created_by") @db.VarChar(36) + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@index([tenantCode, assigneeId, serviceDate]) + @@index([tenantCode, elderId]) + @@map("svc_order") +} + +/// 老人个人项目库 +model ElderSvc { + id String @id @default(uuid(7)) @db.VarChar(36) + tenantCode String @map("tenant_code") @db.VarChar(64) + elderId String @map("elder_id") @db.VarChar(36) + svcId String @map("svc_id") @db.VarChar(36) + svcNameSnapshot String @map("svc_name_snapshot") @db.VarChar(100) + svcCodeSnapshot String? @map("svc_code_snapshot") @db.VarChar(20) + careMode String @map("care_mode") @db.VarChar(20) + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + createdBy String? @map("created_by") @db.VarChar(36) + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@index([tenantCode, elderId]) + @@map("ltc_elder_svc") +} diff --git a/src/prisma/prisma.service.ts b/src/prisma/prisma.service.ts index d10893a..136b263 100644 --- a/src/prisma/prisma.service.ts +++ b/src/prisma/prisma.service.ts @@ -5,7 +5,7 @@ import { getRequestContext } from '../common/context/request-context.js'; /** 不带 tenantCode 的模型(租户表自身)。 */ const TENANT_FREE = new Set(['Tenant', 'Agency', 'SvcNational', 'SvcLocal', 'SvcMapping', 'LocConfig']); /** 软删模型:读操作统一注入 deletedAt IS NULL。 */ -const SOFT_DELETE = new Set(['User', 'Role', 'Resource', 'Org', 'DictType', 'DictItem', 'Config', 'Notice', 'Staff', 'SvcOrg', 'Elder']); +const SOFT_DELETE = new Set(['User', 'Role', 'Resource', 'Org', 'DictType', 'DictItem', 'Config', 'Notice', 'Staff', 'SvcOrg', 'Elder', 'Plan', 'Order', 'ElderSvc']); const READ_OPS = new Set(['findMany', 'findFirst', 'findUnique', 'count', 'aggregate', 'groupBy']); /** 没有 where 子句的操作(create 的租户由 service 在 data 里显式写入)。 */ const NO_WHERE_OPS = new Set(['create', 'createMany']);