From ccba9df9e58c4375a7f39a7450a0569bc859dce8 Mon Sep 17 00:00:00 2001 From: devinleighsmith Date: Fri, 17 Apr 2026 14:36:34 -0700 Subject: [PATCH 1/2] remove the notice of claim if the noc comment/date are not specified. --- .../src/features/mapSideBar/acquisition/add/models.ts | 8 ++++++-- .../fileDetails/update/UpdateAcquisitionFileYupSchema.ts | 5 ++++- .../acquisition/tabs/fileDetails/update/models.ts | 9 +++++++-- .../mapSideBar/management/models/ManagementFormModel.ts | 9 +++++++-- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/source/frontend/src/features/mapSideBar/acquisition/add/models.ts b/source/frontend/src/features/mapSideBar/acquisition/add/models.ts index 79de49e13d..e6dceae2ee 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/add/models.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/add/models.ts @@ -14,7 +14,7 @@ import { stringToNumberOrNull, toTypeCodeNullable, } from '@/utils/formUtils'; -import { exists, isValidId, isValidIsoDateTime } from '@/utils/utils'; +import { exists, isValidId, isValidIsoDateTime, isValidString } from '@/utils/utils'; import { PropertyForm } from '../../shared/models'; import { ChecklistItemFormModel } from '../../shared/tabs/checklist/update/models'; @@ -136,7 +136,11 @@ export class AcquisitionForm implements WithAcquisitionTeam, WithAcquisitionOwne legacyStakeholders: null, product: null, project: null, - noticeOfClaim: exists(this.noticeOfClaim) ? [this.noticeOfClaim] : [], + noticeOfClaim: + isValidString(this.noticeOfClaim?.receivedDate) || + isValidString(this.noticeOfClaim?.comment) + ? [this.noticeOfClaim] + : [], ...getEmptyBaseAudit(this.rowVersion), }; } diff --git a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/UpdateAcquisitionFileYupSchema.ts b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/UpdateAcquisitionFileYupSchema.ts index 7ef81468ef..344a2aff86 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/UpdateAcquisitionFileYupSchema.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/UpdateAcquisitionFileYupSchema.ts @@ -42,7 +42,10 @@ export const UpdateAcquisitionFileYupSchema = yup .nullable() .max(2000, 'Physical file details must be at most ${max} characters'), noticeOfClaim: yup.object().shape({ - comment: yup.string().max(4000, 'Notice of claim comment must be at most ${max} characters'), + comment: yup + .string() + .nullable() + .max(4000, 'Notice of claim comment must be at most ${max} characters'), }), }) .concat(UpdateAcquisitionTeamYupSchema) diff --git a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts index a5039bd80c..ea28d9b6bd 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts @@ -9,7 +9,7 @@ import { ApiGen_Concepts_InterestHolder } from '@/models/api/generated/ApiGen_Co import { ApiGen_Concepts_NoticeOfClaim } from '@/models/api/generated/ApiGen_Concepts_NoticeOfClaim'; import { getEmptyBaseAudit } from '@/models/defaultInitializers'; import { fromTypeCode, fromTypeCodeNullable, toTypeCodeNullable } from '@/utils/formUtils'; -import { exists, isValidId, isValidIsoDateTime } from '@/utils/utils'; +import { exists, isValidId, isValidIsoDateTime, isValidString } from '@/utils/utils'; import { AcquisitionOwnerFormModel, @@ -79,6 +79,7 @@ export class UpdateAcquisitionSummaryFormModel noticeOfClaim: ApiGen_Concepts_NoticeOfClaim; toApi(): ApiGen_Concepts_AcquisitionFile { + console.log(this.noticeOfClaim); return { id: this.id || 0, parentAcquisitionFileId: isValidId(this.parentAcquisitionFileId) @@ -143,7 +144,11 @@ export class UpdateAcquisitionSummaryFormModel product: null, project: null, totalAllowableCompensation: null, - noticeOfClaim: exists(this.noticeOfClaim) ? [this.noticeOfClaim] : [], + noticeOfClaim: + isValidString(this.noticeOfClaim?.receivedDate) || + isValidString(this.noticeOfClaim?.comment) + ? [this.noticeOfClaim] + : [], ...getEmptyBaseAudit(this.rowVersion), }; } diff --git a/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts index 2bfc9e0c79..6f6ab80d6d 100644 --- a/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts +++ b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts @@ -12,7 +12,7 @@ import { ApiGen_Concepts_NoticeOfClaim } from '@/models/api/generated/ApiGen_Con import { getEmptyBaseAudit } from '@/models/defaultInitializers'; import { applyDisplayOrder } from '@/utils'; import { fromTypeCode, toNullableId, toTypeCodeNullable } from '@/utils/formUtils'; -import { exists, isValidId } from '@/utils/utils'; +import { exists, isValidId, isValidString } from '@/utils/utils'; import { PropertyForm } from '../../shared/models'; import { ManagementTeamSubFormModel, WithManagementTeam } from './ManagementTeamSubFormModel'; @@ -81,7 +81,12 @@ export class ManagementFormModel implements WithManagementTeam { .filter(exists), fileProperties: sortedProperties ?? [], ...getEmptyBaseAudit(this.rowVersion), - noticeOfClaim: exists(this.noticeOfClaim) ? [this.noticeOfClaim] : [], + noticeOfClaim: + isValidString(this.noticeOfClaim?.receivedDate) || + isValidString(this.noticeOfClaim?.comment) + ? [this.noticeOfClaim] + : [], + ...getEmptyBaseAudit(this.rowVersion), }; } From a97077ce6728e1a07d324a8b13b824f8d266b95f Mon Sep 17 00:00:00 2001 From: devinleighsmith Date: Fri, 17 Apr 2026 16:43:53 -0700 Subject: [PATCH 2/2] add unit tests. --- .../mapSideBar/acquisition/add/models.test.ts | 38 +++++++++++ .../mapSideBar/acquisition/add/models.ts | 19 ++++-- .../tabs/fileDetails/update/models.test.ts | 43 ++++++++++++ .../tabs/fileDetails/update/models.ts | 21 ++++-- .../models/ManagementFormModel.test.ts | 65 +++++++++++++++++++ .../management/models/ManagementFormModel.ts | 19 ++++-- 6 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.test.ts create mode 100644 source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.test.ts diff --git a/source/frontend/src/features/mapSideBar/acquisition/add/models.test.ts b/source/frontend/src/features/mapSideBar/acquisition/add/models.test.ts index 4782e47c17..33f2d6ab10 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/add/models.test.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/add/models.test.ts @@ -201,5 +201,43 @@ describe('Create acquisition model tests', () => { } as ApiGen_Concepts_AcquisitionFileTeam), ); }); + + it('omits notice of claim when date and comment are empty strings', () => { + const model = new AcquisitionForm(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: '', + receivedDate: '', + rowVersion: null, + }; + + const apiAcquisitionFile = model.toApi(); + + expect(apiAcquisitionFile.noticeOfClaim).toEqual([]); + }); + + it('normalizes notice of claim values before sending to api', () => { + const model = new AcquisitionForm(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: ' Test comment ', + receivedDate: '', + rowVersion: null, + }; + + const apiAcquisitionFile = model.toApi(); + + expect(apiAcquisitionFile.noticeOfClaim).toHaveLength(1); + expect(apiAcquisitionFile.noticeOfClaim?.[0]).toEqual( + expect.objectContaining({ + comment: 'Test comment', + receivedDate: null, + }), + ); + }); }); }); diff --git a/source/frontend/src/features/mapSideBar/acquisition/add/models.ts b/source/frontend/src/features/mapSideBar/acquisition/add/models.ts index e6dceae2ee..578c87734b 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/add/models.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/add/models.ts @@ -81,6 +81,19 @@ export class AcquisitionForm implements WithAcquisitionTeam, WithAcquisitionOwne toApi(): ApiGen_Concepts_AcquisitionFile { const fileProperties = this.properties.map(x => this.toPropertyApi(x)); const sortedProperties = applyDisplayOrder(fileProperties); + const noticeOfClaim: ApiGen_Concepts_NoticeOfClaim | null = this.noticeOfClaim + ? { + ...this.noticeOfClaim, + receivedDate: isValidString(this.noticeOfClaim?.receivedDate) + ? this.noticeOfClaim.receivedDate + : null, + comment: isValidString(this.noticeOfClaim?.comment?.trim()) + ? this.noticeOfClaim.comment.trim() + : null, + } + : null; + const hasNoticeOfClaim = + isValidString(noticeOfClaim?.receivedDate) || isValidString(noticeOfClaim?.comment); return { id: this.id ?? 0, @@ -136,11 +149,7 @@ export class AcquisitionForm implements WithAcquisitionTeam, WithAcquisitionOwne legacyStakeholders: null, product: null, project: null, - noticeOfClaim: - isValidString(this.noticeOfClaim?.receivedDate) || - isValidString(this.noticeOfClaim?.comment) - ? [this.noticeOfClaim] - : [], + noticeOfClaim: hasNoticeOfClaim && noticeOfClaim ? [noticeOfClaim] : [], ...getEmptyBaseAudit(this.rowVersion), }; } diff --git a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.test.ts b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.test.ts new file mode 100644 index 0000000000..7ccaa99da7 --- /dev/null +++ b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.test.ts @@ -0,0 +1,43 @@ +import { UpdateAcquisitionSummaryFormModel } from './models'; + +describe('UpdateAcquisitionSummaryFormModel', () => { + describe('toApi noticeOfClaim handling', () => { + it('omits noticeOfClaim when date and comment are empty', () => { + const model = new UpdateAcquisitionSummaryFormModel(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: '', + receivedDate: '', + rowVersion: null, + }; + + const apiModel = model.toApi(); + + expect(apiModel.noticeOfClaim).toEqual([]); + }); + + it('normalizes empty date to null and trims comment', () => { + const model = new UpdateAcquisitionSummaryFormModel(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: ' file update comment ', + receivedDate: '', + rowVersion: null, + }; + + const apiModel = model.toApi(); + + expect(apiModel.noticeOfClaim).toHaveLength(1); + expect(apiModel.noticeOfClaim?.[0]).toEqual( + expect.objectContaining({ + comment: 'file update comment', + receivedDate: null, + }), + ); + }); + }); +}); diff --git a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts index ea28d9b6bd..e80f43b15b 100644 --- a/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts +++ b/source/frontend/src/features/mapSideBar/acquisition/tabs/fileDetails/update/models.ts @@ -79,7 +79,20 @@ export class UpdateAcquisitionSummaryFormModel noticeOfClaim: ApiGen_Concepts_NoticeOfClaim; toApi(): ApiGen_Concepts_AcquisitionFile { - console.log(this.noticeOfClaim); + const noticeOfClaim: ApiGen_Concepts_NoticeOfClaim | null = this.noticeOfClaim + ? { + ...this.noticeOfClaim, + receivedDate: isValidString(this.noticeOfClaim?.receivedDate) + ? this.noticeOfClaim.receivedDate + : null, + comment: isValidString(this.noticeOfClaim?.comment?.trim()) + ? this.noticeOfClaim.comment.trim() + : null, + } + : null; + const hasNoticeOfClaim = + isValidString(noticeOfClaim?.receivedDate) || isValidString(noticeOfClaim?.comment); + return { id: this.id || 0, parentAcquisitionFileId: isValidId(this.parentAcquisitionFileId) @@ -144,11 +157,7 @@ export class UpdateAcquisitionSummaryFormModel product: null, project: null, totalAllowableCompensation: null, - noticeOfClaim: - isValidString(this.noticeOfClaim?.receivedDate) || - isValidString(this.noticeOfClaim?.comment) - ? [this.noticeOfClaim] - : [], + noticeOfClaim: hasNoticeOfClaim && noticeOfClaim ? [noticeOfClaim] : [], ...getEmptyBaseAudit(this.rowVersion), }; } diff --git a/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.test.ts b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.test.ts new file mode 100644 index 0000000000..9428048fc8 --- /dev/null +++ b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.test.ts @@ -0,0 +1,65 @@ +import { ManagementFormModel } from './ManagementFormModel'; + +describe('ManagementFormModel', () => { + describe('toApi noticeOfClaim handling', () => { + it('omits noticeOfClaim when date and comment are empty', () => { + const model = new ManagementFormModel(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: '', + receivedDate: '', + rowVersion: null, + }; + + const apiModel = model.toApi(); + + expect(apiModel.noticeOfClaim).toEqual([]); + }); + + it('normalizes empty date to null and trims comment', () => { + const model = new ManagementFormModel(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: ' comment from formik ', + receivedDate: '', + rowVersion: null, + }; + + const apiModel = model.toApi(); + + expect(apiModel.noticeOfClaim).toHaveLength(1); + expect(apiModel.noticeOfClaim?.[0]).toEqual( + expect.objectContaining({ + comment: 'comment from formik', + receivedDate: null, + }), + ); + }); + + it('keeps receivedDate when provided and normalizes empty comment', () => { + const model = new ManagementFormModel(); + model.noticeOfClaim = { + id: null, + acquisitionFileId: null, + managementFileId: null, + comment: ' ', + receivedDate: '2026-04-17', + rowVersion: null, + }; + + const apiModel = model.toApi(); + + expect(apiModel.noticeOfClaim).toHaveLength(1); + expect(apiModel.noticeOfClaim?.[0]).toEqual( + expect.objectContaining({ + comment: null, + receivedDate: '2026-04-17', + }), + ); + }); + }); +}); diff --git a/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts index 6f6ab80d6d..6bbe11348d 100644 --- a/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts +++ b/source/frontend/src/features/mapSideBar/management/models/ManagementFormModel.ts @@ -50,6 +50,19 @@ export class ManagementFormModel implements WithManagementTeam { const sortedProperties = applyDisplayOrder(fileProperties); const personId = this.responsiblePayer?.personId ?? null; const organizationId = !personId ? this.responsiblePayer?.organizationId ?? null : null; + const noticeOfClaim: ApiGen_Concepts_NoticeOfClaim | null = this.noticeOfClaim + ? { + ...this.noticeOfClaim, + receivedDate: isValidString(this.noticeOfClaim?.receivedDate) + ? this.noticeOfClaim.receivedDate + : null, + comment: isValidString(this.noticeOfClaim?.comment?.trim()) + ? this.noticeOfClaim.comment.trim() + : null, + } + : null; + const hasNoticeOfClaim = + isValidString(noticeOfClaim?.receivedDate) || isValidString(noticeOfClaim?.comment); return { id: this.id ?? 0, @@ -81,11 +94,7 @@ export class ManagementFormModel implements WithManagementTeam { .filter(exists), fileProperties: sortedProperties ?? [], ...getEmptyBaseAudit(this.rowVersion), - noticeOfClaim: - isValidString(this.noticeOfClaim?.receivedDate) || - isValidString(this.noticeOfClaim?.comment) - ? [this.noticeOfClaim] - : [], + noticeOfClaim: hasNoticeOfClaim && noticeOfClaim ? [noticeOfClaim] : [], ...getEmptyBaseAudit(this.rowVersion), }; }