From 1ae10432421e4556542692af7d595bb7be21f4aa Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Mon, 20 Jul 2026 14:45:04 -0400 Subject: [PATCH] fix(api): keep an uploaded file instrument record pending `upload` writes `pending: false` for every record regardless of instrument kind, while `create` writes `pending: instrument.kind === 'FILE'`. A file instrument record exists before its file does -- `FilesService` sets `pending: false` only once the upload lands, and refuses to attach a file to a record that is not pending -- so a bulk-uploaded file record is born settled and its files can never be attached. `upload` does not reject file instruments the way it rejects series instruments; verified live, a file instrument upload returns 201. Mirror `create` so the two paths agree. Scope note: this branch originally also introduced writing `pending` at all, since `upload` omitted the field entirely and only the find-side compatibility clause kept those records visible. main has since written the field independently in 573f307c9, hardcoded to false. What remains here is only the FILE case. Co-Authored-By: Claude Opus 4.8 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014ZEJLwa7jwD8sKzcE4PfSc --- .../instrument-records.service.spec.ts | 20 +++++++++++++++++-- .../instrument-records.service.ts | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/api/src/instrument-records/__tests__/instrument-records.service.spec.ts b/apps/api/src/instrument-records/__tests__/instrument-records.service.spec.ts index 6974ccade..fbf409bd9 100644 --- a/apps/api/src/instrument-records/__tests__/instrument-records.service.spec.ts +++ b/apps/api/src/instrument-records/__tests__/instrument-records.service.spec.ts @@ -240,8 +240,6 @@ describe('InstrumentRecordsService', () => { expect(sessionsService.create).toHaveBeenCalledWith(expect.objectContaining({ username: undefined })); }); - // `pending` is intentionally not written on create; the find-side OR filter treats missing and - // false `pending` alike (see the 'find' describe block), so records stay query-visible without it. it('should create records via createMany with the processed record data', async () => { await instrumentRecordsService.upload({ ...baseUploadData }); @@ -249,6 +247,24 @@ describe('InstrumentRecordsService', () => { data: [expect.objectContaining({ instrumentId: 'instrument-1', subjectId: 'subject-1' })] }); }); + + it('should settle a form instrument record, since an upload carries its data in full', async () => { + await instrumentRecordsService.upload({ ...baseUploadData }); + + expect(instrumentRecordModel.createMany).toHaveBeenCalledWith({ + data: [expect.objectContaining({ pending: false })] + }); + }); + + it('should leave a file instrument record pending, so its files can still be attached', async () => { + instrumentsService.findById.mockResolvedValue({ ...mockInstrument, kind: 'FILE' } as any); + + await instrumentRecordsService.upload({ ...baseUploadData }); + + expect(instrumentRecordModel.createMany).toHaveBeenCalledWith({ + data: [expect.objectContaining({ pending: true })] + }); + }); }); describe('find', () => { diff --git a/apps/api/src/instrument-records/instrument-records.service.ts b/apps/api/src/instrument-records/instrument-records.service.ts index e3fc2b682..188a9def6 100644 --- a/apps/api/src/instrument-records/instrument-records.service.ts +++ b/apps/api/src/instrument-records/instrument-records.service.ts @@ -445,7 +445,7 @@ export class InstrumentRecordsService { date, groupId, instrumentId, - pending: false, + pending: instrument.kind === 'FILE', sessionId: session.id, subjectId };