From c00c4ee00730f310553c3774ca73207cd574c7e9 Mon Sep 17 00:00:00 2001 From: liuyun Date: Thu, 15 Oct 2026 01:00:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(c3):=20record=20=E5=9D=90=E6=A0=87=20Decima?= =?UTF-8?q?l=20=E8=BF=94=E5=9B=9E=E5=89=8D=E8=BD=AC=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=EF=BC=8C=E9=98=B2=E6=B3=84=E6=BC=8F=20{s,e,d}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- src/record/record.service.spec.ts | 21 +++++++++++++++++++++ src/record/record.service.ts | 21 ++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/record/record.service.spec.ts b/src/record/record.service.spec.ts index 207015d..39a08d3 100644 --- a/src/record/record.service.spec.ts +++ b/src/record/record.service.spec.ts @@ -647,6 +647,27 @@ describe('RecordService.detail / list / prepaidList', () => { expect(res).toMatchObject({ id: 'r1', items: [{ id: 'ri1' }], photos: [{ id: 'rp1' }], abnormals: [{ id: 'ra1' }] }); }); + it('detail/list 将 Decimal 坐标序列化为字符串(null 保持 null)', async () => { + const recordFindUnique = vi.fn().mockResolvedValue({ + id: 'r1', + recordStatus: 'submitted', + checkinLat: { toString: () => '25.010000' }, + checkinLng: null, + }); + const recordFindMany = vi.fn().mockResolvedValue([ + { id: 'r2', checkinLat: { toString: () => '26.500000' }, checkinLng: { toString: () => '103.100000' } }, + ]); + const { service } = makeService({ recordFindUnique, recordFindMany }); + + const detail = await runWithRequestContext(ctx, () => service.detail('r1')); + expect(detail.checkinLat).toBe('25.010000'); + expect(detail.checkinLng).toBeNull(); + + const list = await runWithRequestContext(ctx, () => service.list({})); + expect(list[0].checkinLat).toBe('26.500000'); + expect(list[0].checkinLng).toBe('103.100000'); + }); + it('list 按 elder/assignee/状态筛选', async () => { const recordFindMany = vi.fn().mockResolvedValue([{ id: 'r1' }]); const { service } = makeService({ recordFindMany }); diff --git a/src/record/record.service.ts b/src/record/record.service.ts index 42bfa98..892c3f7 100644 --- a/src/record/record.service.ts +++ b/src/record/record.service.ts @@ -267,11 +267,11 @@ export class RecordService { this.prisma.client.recordPhoto.findMany({ where: { recordId: id } }), this.prisma.client.recordAbnormal.findMany({ where: { recordId: id } }), ]); - return { ...record, items, photos, abnormals }; + return this.serializeRecord({ ...record, items, photos, abnormals }); } /** 列表:按老人/护理员/日期/状态筛选。 */ - list(q: ListRecordQuery) { + async list(q: ListRecordQuery) { const where: Record = {}; if (q.elderId) where.elderId = q.elderId; if (q.assigneeId) where.assigneeId = q.assigneeId; @@ -282,12 +282,14 @@ export class RecordService { lte: new Date(`${q.serviceDate}T23:59:59.999+08:00`), }; } - return this.prisma.client.record.findMany({ where, orderBy: { checkinTime: 'desc' } }); + const rows = await this.prisma.client.record.findMany({ where, orderBy: { checkinTime: 'desc' } }); + return rows.map((r) => this.serializeRecord(r)); } /** 垫付台账:按老人返回 is_prepaid=1 的记录。 */ - prepaidList(q: PrepaidListQuery) { - return this.prisma.client.record.findMany({ where: { elderId: q.elderId, isPrepaid: true } }); + async prepaidList(q: PrepaidListQuery) { + const rows = await this.prisma.client.record.findMany({ where: { elderId: q.elderId, isPrepaid: true } }); + return rows.map((r) => this.serializeRecord(r)); } /** 结转:复制垫付 record → 正式 record(is_prepaid=0 + source_prepaid_of),原记录不改。 */ @@ -387,6 +389,15 @@ export class RecordService { return record; } + /** Prisma Decimal 经 TransformInterceptor 不会转,泄漏为 {s,e,d};返回前把坐标转字符串(null 保持 null)。 */ + private serializeRecord(record: Record): Record { + return { + ...record, + checkinLat: record.checkinLat != null ? record.checkinLat.toString() : null, + checkinLng: record.checkinLng != null ? record.checkinLng.toString() : null, + }; + } + /** 校验 exec_result 枚举 + svc_id 落本机构 L4,并解析快照;photo_required 从 order.item_list 推导。 */ private async resolveItems(items: RecordItemDto[], order?: Record | null) { return Promise.all(