diff --git a/src/plan/plan.service.spec.ts b/src/plan/plan.service.spec.ts index 8bf31d4..2f633b9 100644 --- a/src/plan/plan.service.spec.ts +++ b/src/plan/plan.service.spec.ts @@ -136,7 +136,7 @@ describe('PlanService', () => { elderId: 'e1', itemCount: 18, itemCountRule: 'inst_medical/care_1 ≥18 项', - planStatus: 'draft', + planStatus: 'active', tenantCode: 'T001', createdBy: 'u1', }), @@ -208,12 +208,12 @@ describe('PlanService', () => { ); expect(planCreate).toHaveBeenCalledWith({ - data: expect.objectContaining({ careMode: 'home_org', itemCount: 0, planStatus: 'draft' }), + data: expect.objectContaining({ careMode: 'home_org', itemCount: 0, planStatus: 'active' }), }); }); it('变更留旧版:旧计划转 changed + 新计划 change_from_plan_id', async () => { - const planFindUnique = vi.fn().mockResolvedValue({ id: 'p-old', planStatus: 'active' }); + const planFindUnique = vi.fn().mockResolvedValue({ id: 'p-old', elderId: 'e1', planStatus: 'active' }); const planCreate = vi.fn().mockResolvedValue({ id: 'p-new' }); const planUpdate = vi.fn().mockResolvedValue({ id: 'p-old' }); const { service } = makeService({ planFindUnique, planCreate, planUpdate }); @@ -233,8 +233,8 @@ describe('PlanService', () => { }); }); - it('确认置 confirm_time + elder/guardian 布尔 + 转 active', async () => { - const planFindUnique = vi.fn().mockResolvedValue({ id: 'p1', planStatus: 'draft' }); + it('确认置 confirm_time + elder/guardian 布尔,不改变 plan_status', async () => { + const planFindUnique = vi.fn().mockResolvedValue({ id: 'p1', planStatus: 'active' }); const planUpdate = vi.fn().mockResolvedValue({ id: 'p1' }); const { service } = makeService({ planFindUnique, planUpdate }); @@ -242,15 +242,30 @@ describe('PlanService', () => { expect(planUpdate).toHaveBeenCalledWith({ where: { id: 'p1' }, - data: expect.objectContaining({ + data: { confirmElder: true, confirmGuardian: false, confirmTime: expect.any(Date), - planStatus: 'active', - }), + }, }); }); + it('变更计划 elder 不匹配 → 拒绝,不写新计划', async () => { + const planFindUnique = vi.fn().mockResolvedValue({ id: 'p-old', elderId: 'e-other', planStatus: 'active' }); + const planCreate = vi.fn(); + const planUpdate = vi.fn(); + const { service } = makeService({ planFindUnique, planCreate, planUpdate }); + + await expect( + runWithRequestContext(ctx, () => + service.change({ ...baseDto, careMode: 'home_org', items: [], changeFromPlanId: 'p-old' }), + ), + ).rejects.toMatchObject({ response: { code: ErrorCodes.PLAN_NOT_FOUND } }); + + expect(planCreate).not.toHaveBeenCalled(); + expect(planUpdate).not.toHaveBeenCalled(); + }); + it('detail 返回计划头 + 计划项', async () => { const planFindUnique = vi.fn().mockResolvedValue({ id: 'p1', elderId: 'e1', planStatus: 'active' }); const planItemFindMany = vi.fn().mockResolvedValue([{ id: 'pi1', planId: 'p1' }]); diff --git a/src/plan/plan.service.ts b/src/plan/plan.service.ts index d813b10..375f48a 100644 --- a/src/plan/plan.service.ts +++ b/src/plan/plan.service.ts @@ -17,7 +17,7 @@ interface ResolvedPlanItem extends PlanItemInputDto { * 服务计划(svc_plan/svc_plan_item)业务服务。 * * - 制定计划:校验老人存在 + 每个 svc_id 落本机构 L4 + 属地项数(昆明校验/州市提示); - * 快照 item_count/item_count_rule,plan_status 默认 draft;写 plan_item(svc_name/code 快照)。 + * 快照 item_count/item_count_rule,plan_status=active;写 plan_item(svc_name/code 快照)。 * - 变更计划:新建 Plan + change_from_plan_id 指向旧计划,旧计划转 changed,不原地改。 * - 确认:置 confirm_time + elder/guardian 布尔,计划转 active。 */ @@ -25,20 +25,23 @@ interface ResolvedPlanItem extends PlanItemInputDto { export class PlanService { constructor(private readonly prisma: PrismaService) {} - /** 制定服务计划(draft)。 */ + /** 制定服务计划(active)。 */ create(dto: CreatePlanDto) { - return this.buildPlan(dto, { planStatus: 'draft' }); + return this.buildPlan(dto, { planStatus: 'active' }); } /** 变更服务计划:新建 active 计划并指向旧计划,旧计划转 changed。 */ async change(dto: ChangePlanDto) { - await this.requireExists(dto.changeFromPlanId); + const oldPlan = await this.requireExists(dto.changeFromPlanId); + if (oldPlan.elderId !== dto.elderId) { + throw new BusinessException(ErrorCodes.PLAN_NOT_FOUND, '被变更计划不属于该老人', HttpStatus.BAD_REQUEST); + } const newPlan = await this.buildPlan(dto, { planStatus: 'active', changeFromPlanId: dto.changeFromPlanId }); await this.prisma.client.plan.update({ where: { id: dto.changeFromPlanId }, data: { planStatus: 'changed' } }); return newPlan; } - /** 确认计划:置确认时间与老人/家属布尔,计划转 active。 */ + /** 确认计划:仅写确认时间与老人/家属布尔(不改变 plan_status)。 */ async confirm(id: string, dto: ConfirmPlanDto) { await this.requireExists(id); return this.prisma.client.plan.update({ @@ -47,7 +50,6 @@ export class PlanService { confirmElder: dto.confirmElder, confirmGuardian: dto.confirmGuardian ?? false, confirmTime: new Date(), - planStatus: 'active', }, }); }