diff --git a/src/elder/elder.service.spec.ts b/src/elder/elder.service.spec.ts index b33cac7..2dcff78 100644 --- a/src/elder/elder.service.spec.ts +++ b/src/elder/elder.service.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from 'vitest'; -import { ElderService, maskIdCard } from './elder.service.js'; +import { ElderService, maskIdCard, toDateOnly } from './elder.service.js'; import type { PrismaService } from '../prisma/prisma.service.js'; import type { StorageService } from '../storage/storage.service.js'; import type { AuditLogsService } from '../audit-logs/audit-logs.service.js'; @@ -109,6 +109,18 @@ describe('maskIdCard', () => { }); }); +describe('toDateOnly', () => { + it('date-only 字符串 → UTC 零点 Date(不提前一天)', () => { + expect(toDateOnly('1990-01-01')?.toISOString()).toBe('1990-01-01T00:00:00.000Z'); + expect(toDateOnly('2025-01-01')?.toISOString()).toBe('2025-01-01T00:00:00.000Z'); + }); + + it('空值返回 undefined', () => { + expect(toDateOnly(undefined)).toBeUndefined(); + expect(toDateOnly('')).toBeUndefined(); + }); +}); + describe('ElderService', () => { it('create 有等级无评估结论副本 → 抛 ELDER_LEVEL_REQUIRES_EVIDENCE', async () => { const { service, elderCreate } = makeService(); @@ -144,7 +156,7 @@ describe('ElderService', () => { }); }); - it('合法建档(含日期字段)成功创建,日期字段转为 Date', async () => { + it('合法建档(含日期字段)成功创建,日期字段转为 UTC 零点 Date 且值正确', async () => { const { service, elderCreate } = makeService(); await runWithRequestContext(ctx, () => @@ -159,17 +171,15 @@ describe('ElderService', () => { }), ); - expect(elderCreate).toHaveBeenCalledWith({ - data: expect.objectContaining({ - birthDate: expect.any(Date), - benefitStart: expect.any(Date), - benefitEnd: expect.any(Date), - assessDate: expect.any(Date), - insurVerifyDate: expect.any(Date), - hospStart: expect.any(Date), - hospEnd: expect.any(Date), - }), - }); + const data = elderCreate.mock.calls[0][0].data as Record; + expect(data.birthDate).toBeInstanceOf(Date); + expect((data.birthDate as Date).toISOString()).toBe('1990-01-01T00:00:00.000Z'); + expect((data.benefitStart as Date).toISOString()).toBe('2025-01-01T00:00:00.000Z'); + expect((data.benefitEnd as Date).toISOString()).toBe('2025-12-31T00:00:00.000Z'); + expect((data.assessDate as Date).toISOString()).toBe('2025-01-15T00:00:00.000Z'); + expect((data.insurVerifyDate as Date).toISOString()).toBe('2025-01-10T00:00:00.000Z'); + expect((data.hospStart as Date).toISOString()).toBe('2025-02-01T00:00:00.000Z'); + expect((data.hospEnd as Date).toISOString()).toBe('2025-02-05T00:00:00.000Z'); }); it('同机构重复 id_card_no → 抛 ELDER_ID_CARD_EXISTS', async () => { diff --git a/src/elder/elder.service.ts b/src/elder/elder.service.ts index 39804ea..c21a258 100644 --- a/src/elder/elder.service.ts +++ b/src/elder/elder.service.ts @@ -52,10 +52,10 @@ function resolveInitialStatus(benefitStart?: string, benefitEnd?: string): strin return 'waiting_period'; } -/** YYYY-MM-DD → 本地零点 Date(供 Prisma DateTime @db.Date 列写入);空值返回 undefined。 */ -function toDateOnly(v?: string): Date | undefined { +/** YYYY-MM-DD → UTC 零点 Date(Prisma @db.Date 按 UTC instant 取日期,须用 UTC 零点避免时区回退一天);空值返回 undefined。 */ +export function toDateOnly(v?: string): Date | undefined { if (!v) return undefined; - return new Date(`${v}T00:00:00`); + return new Date(`${v}T00:00:00Z`); } /**