From 322331001ed55692f10bfe021ce896315f1468ae Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Thu, 2 Nov 2023 18:14:48 -0700 Subject: [PATCH 1/4] Update service to return property lease information --- .../Concepts/Property/PropertyManagementModel.cs | 14 +++++--------- source/backend/api/Services/PropertyService.cs | 8 ++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/source/backend/api/Models/Concepts/Property/PropertyManagementModel.cs b/source/backend/api/Models/Concepts/Property/PropertyManagementModel.cs index f5f61c160a..d03c3d8e19 100644 --- a/source/backend/api/Models/Concepts/Property/PropertyManagementModel.cs +++ b/source/backend/api/Models/Concepts/Property/PropertyManagementModel.cs @@ -24,7 +24,7 @@ public class PropertyManagementModel : BaseAppModel public string AdditionalDetails { get; set; } /// - /// get/set - Whether utilities are payable for this property.. + /// get/set - Whether utilities are payable for this property. /// public bool? IsUtilitiesPayable { get; set; } @@ -34,17 +34,13 @@ public class PropertyManagementModel : BaseAppModel public bool? IsTaxesPayable { get; set; } /// - /// get/set - Whether this property has an "active lease". + /// get/set - The number of leases for this property. Returns 0 when there are no leases. /// - public bool IsLeaseActive { get; set; } + public long RelatedLeases { get; set; } /// - /// get/set - Whether this property has an "active lease" that is expired. - /// - public bool IsLeaseExpired { get; set; } - - /// - /// get/set - The expiry date on the active lease for this property (if any). + /// get/set - The expiry date of the lease when there is only ONE lease for this property (regardless of status). + /// This field is null when the lease does not expire. /// public DateTime? LeaseExpiryDate { get; set; } } diff --git a/source/backend/api/Services/PropertyService.cs b/source/backend/api/Services/PropertyService.cs index 885d06250f..67a1ee52e6 100644 --- a/source/backend/api/Services/PropertyService.cs +++ b/source/backend/api/Services/PropertyService.cs @@ -179,12 +179,12 @@ public PropertyManagementModel GetPropertyManagement(long propertyId) var property = GetById(propertyId); var propertyLeases = _propertyLeaseRepository.GetAllByPropertyId(propertyId); - var activeLease = propertyLeases.FirstOrDefault(pl => pl.Lease.LeaseStatusTypeCode == "ACTIVE")?.Lease; - var leaseExpiryDate = activeLease?.GetExpiryDate()?.FilterSqlMinDate() ?? null; + var leaseCount = propertyLeases.Count(); + var firstLease = leaseCount == 1 ? propertyLeases.First().Lease : null; + var leaseExpiryDate = firstLease is not null ? firstLease.GetExpiryDate()?.FilterSqlMinDate() : null; var propertyManagement = _mapper.Map(property); - propertyManagement.IsLeaseActive = activeLease is not null; - propertyManagement.IsLeaseExpired = leaseExpiryDate is not null && (leaseExpiryDate < DateTime.UtcNow); + propertyManagement.RelatedLeases = leaseCount; propertyManagement.LeaseExpiryDate = leaseExpiryDate; return propertyManagement; From 9174a6dc1a46353dd7f4aa2186090faa0e85f3f4 Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Thu, 2 Nov 2023 18:16:15 -0700 Subject: [PATCH 2/4] Align frontend api models --- .../src/mocks/propertyManagement.mock.ts | 3 +-- source/frontend/src/models/api/Property.ts | 3 +-- source/frontend/src/utils/propertyUtils.ts | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/frontend/src/mocks/propertyManagement.mock.ts b/source/frontend/src/mocks/propertyManagement.mock.ts index 7ca3cfcf0f..fc5a9da53a 100644 --- a/source/frontend/src/mocks/propertyManagement.mock.ts +++ b/source/frontend/src/mocks/propertyManagement.mock.ts @@ -7,8 +7,7 @@ export const getMockApiPropertyManagement = (id = 123459): Api_PropertyManagemen additionalDetails: 'test', isTaxesPayable: null, isUtilitiesPayable: null, - isLeaseActive: false, - isLeaseExpired: false, + relatedLeases: 0, leaseExpiryDate: null, }); diff --git a/source/frontend/src/models/api/Property.ts b/source/frontend/src/models/api/Property.ts index dfe1b95733..dd62cedaa1 100644 --- a/source/frontend/src/models/api/Property.ts +++ b/source/frontend/src/models/api/Property.ts @@ -145,8 +145,7 @@ export interface Api_PropertyManagement extends Api_ConcurrentVersion_Null, Api_ additionalDetails: string | null; isUtilitiesPayable: boolean | null; isTaxesPayable: boolean | null; - isLeaseActive: boolean; - isLeaseExpired: boolean; + relatedLeases: number; leaseExpiryDate: string | null; } diff --git a/source/frontend/src/utils/propertyUtils.ts b/source/frontend/src/utils/propertyUtils.ts index 0af9aff9b7..6166b6b512 100644 --- a/source/frontend/src/utils/propertyUtils.ts +++ b/source/frontend/src/utils/propertyUtils.ts @@ -97,14 +97,16 @@ export const formatBcaAddress = (address?: IBcAssessmentSummary['ADDRESSES'][0]) .join(' '); export function formatApiPropertyManagementLease(base?: Api_PropertyManagement | null): string { - if (!base) { - return ''; - } + const count = base?.relatedLeases || 0; + switch (count) { + case 0: + return 'No active Lease/License'; + + case 1: + const expiryDate = base?.leaseExpiryDate ? `(${prettyFormatDate(base.leaseExpiryDate)})` : ''; + return `Yes ${expiryDate}`.trim(); - if (base.isLeaseActive) { - const expiryDate = base.leaseExpiryDate ? `(${prettyFormatDate(base.leaseExpiryDate)})` : ''; - return base.isLeaseExpired ? `Expired ${expiryDate}`.trim() : `Yes ${expiryDate}`.trim(); - } else { - return 'No active Lease/License'; + default: + return 'Multiple'; } } From accd5d84e1d88cfe889054dea0bcd1e5caca2ecf Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Thu, 2 Nov 2023 18:18:42 -0700 Subject: [PATCH 3/4] Update lease information on property management update form --- .../update/summary/PropertyManagementUpdateContainer.tsx | 3 +-- .../update/summary/PropertyManagementUpdateForm.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateContainer.tsx b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateContainer.tsx index c44518ba62..ec6c12e152 100644 --- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateContainer.tsx +++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateContainer.tsx @@ -27,8 +27,7 @@ export const PropertyManagementUpdateContainer = React.forwardRef< additionalDetails: null, isUtilitiesPayable: null, isTaxesPayable: null, - isLeaseActive: false, - isLeaseExpired: false, + relatedLeases: 0, leaseExpiryDate: null, }); diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateForm.tsx b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateForm.tsx index 9c98cfe099..3fe46607c7 100644 --- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateForm.tsx +++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/PropertyManagementUpdateForm.tsx @@ -58,7 +58,7 @@ export const PropertyManagementUpdateForm = React.forwardRef< /> - {formikProps.values.formatLeaseInformation()} + {formikProps.values.formattedLeaseInformation ?? ''} From 4236a6848509d67b9a99ec889d7d5a2c14fa7699 Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Thu, 2 Nov 2023 18:19:02 -0700 Subject: [PATCH 4/4] Test corrections --- .../FilterContentContainer.test.tsx | 17 +----- .../update/summary/models.test.ts | 60 ++++++------------- .../update/summary/models.ts | 24 ++------ 3 files changed, 26 insertions(+), 75 deletions(-) diff --git a/source/frontend/src/components/maps/leaflet/Control/AdvancedFilter/FilterContentContainer.test.tsx b/source/frontend/src/components/maps/leaflet/Control/AdvancedFilter/FilterContentContainer.test.tsx index 65d7e51e11..fc5af18908 100644 --- a/source/frontend/src/components/maps/leaflet/Control/AdvancedFilter/FilterContentContainer.test.tsx +++ b/source/frontend/src/components/maps/leaflet/Control/AdvancedFilter/FilterContentContainer.test.tsx @@ -5,7 +5,6 @@ import { forwardRef } from 'react'; import { useMapStateMachine } from '@/components/common/mapFSM/MapStateMachineContext'; import { mockLookups } from '@/mocks/lookups.mock'; import { mapMachineBaseMock } from '@/mocks/mapFSM.mock'; -import { getMockApiPropertyManagement } from '@/mocks/propertyManagement.mock'; import { lookupCodesSlice } from '@/store/slices/lookupCodes'; import { render, RenderOptions, waitFor } from '@/utils/test-utils'; @@ -66,22 +65,10 @@ describe('FilterContentContainer component', () => { }); it('fetches filter data from the api', async () => { - mockGetApi.execute.mockResolvedValue(getMockApiPropertyManagement(1)); + mockGetApi.execute.mockResolvedValue([1, 2]); setup({}); viewProps.onChange(new PropertyFilterFormModel()); expect(mockGetApi.execute).toBeCalledWith(new PropertyFilterFormModel().toApi()); - await waitFor(() => - expect(mapMachineBaseMock.setVisiblePimsProperties).toBeCalledWith({ - additionalDetails: 'test', - id: 1, - isLeaseActive: false, - isLeaseExpired: false, - isTaxesPayable: null, - isUtilitiesPayable: null, - leaseExpiryDate: null, - managementPurposes: [], - rowVersion: 1, - }), - ); + await waitFor(() => expect(mapMachineBaseMock.setVisiblePimsProperties).toBeCalledWith([1, 2])); }); }); diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.test.ts b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.test.ts index 4cc5df2fc3..ce2fdbfd20 100644 --- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.test.ts +++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.test.ts @@ -18,8 +18,7 @@ describe('Property management model tests', () => { expect(model.additionalDetails).toBe(''); expect(model.isTaxesPayable).toBe(null); expect(model.isUtilitiesPayable).toBe(null); - expect(model.isLeaseActive).toBe(false); - expect(model.leaseExpiryDate).toBe(''); + expect(model.formattedLeaseInformation).toBe('No active Lease/License'); }); it('fromApi sets values as expected from api response', () => { @@ -36,46 +35,26 @@ describe('Property management model tests', () => { expect(model.additionalDetails).toBe('test'); expect(model.isTaxesPayable).toBe(null); expect(model.isUtilitiesPayable).toBe(null); - expect(model.isLeaseActive).toBe(false); - expect(model.leaseExpiryDate).toBe(''); + expect(model.formattedLeaseInformation).toBe('No active Lease/License'); }); - it('returns default text when no lease information is available', () => { - const model = PropertyManagementFormModel.fromApi(getMockApiPropertyManagement()); - expect(model.formatLeaseInformation()).toBe('No active Lease/License'); - }); - - it('returns active lease information and expiry date', () => { - let apiManagement: Api_PropertyManagement = { - ...getMockApiPropertyManagement(), - isLeaseActive: true, - leaseExpiryDate: '2020-03-15', - }; - const model = PropertyManagementFormModel.fromApi(apiManagement); - expect(model.formatLeaseInformation()).toBe('Yes (Mar 15, 2020)'); - }); - - it('returns expired lease information and expiry date', () => { - let apiManagement: Api_PropertyManagement = { - ...getMockApiPropertyManagement(), - isLeaseActive: true, - isLeaseExpired: true, - leaseExpiryDate: '2020-03-15', - }; - const model = PropertyManagementFormModel.fromApi(apiManagement); - expect(model.formatLeaseInformation()).toBe('Expired (Mar 15, 2020)'); - }); - - it('returns available lease information without an expiry date', () => { - let apiManagement: Api_PropertyManagement = { - ...getMockApiPropertyManagement(), - isLeaseActive: true, - isLeaseExpired: false, - leaseExpiryDate: null, - }; - const model = PropertyManagementFormModel.fromApi(apiManagement); - expect(model.formatLeaseInformation()).toBe('Yes'); - }); + it.each([ + ['NO lease found', 0, null, 'No active Lease/License'], + ['ONE lease with expiry date', 1, '2020-03-15', 'Yes (Mar 15, 2020)'], + ['ONE lease with no expiry date', 1, null, 'Yes'], + ['MULTIPLE leases', 5, null, 'Multiple'], + ])( + 'returns lease information as expected - %s', + (_: string, leaseCount: number, expiryDate: string | null, expectedResult: string) => { + let apiManagement: Api_PropertyManagement = { + ...getMockApiPropertyManagement(), + relatedLeases: leaseCount, + leaseExpiryDate: expiryDate, + }; + const model = PropertyManagementFormModel.fromApi(apiManagement); + expect(model.formattedLeaseInformation).toBe(expectedResult); + }, + ); it('toApi converts form values to the api format', () => { const purpose = new ManagementPurposeModel(); @@ -96,7 +75,6 @@ describe('Property management model tests', () => { expect(apiManagement.additionalDetails).toBe('test'); expect(apiManagement.isUtilitiesPayable).toBe(true); expect(apiManagement.isTaxesPayable).toBe(null); - expect(apiManagement.leaseExpiryDate).toBe(null); expect(apiManagement.managementPurposes).toHaveLength(1); expect(apiManagement.managementPurposes[0]).toEqual( expect.objectContaining({ diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.ts b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.ts index 770ef7a5ac..4dbd8fb4c6 100644 --- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.ts +++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/update/summary/models.ts @@ -1,6 +1,6 @@ import { Api_PropertyManagement, Api_PropertyManagementPurpose } from '@/models/api/Property'; import { ILookupCode } from '@/store/slices/lookupCodes'; -import { prettyFormatDate } from '@/utils'; +import { formatApiPropertyManagementLease } from '@/utils'; import { stringToNull } from '@/utils/formUtils'; export class PropertyManagementFormModel { @@ -10,9 +10,7 @@ export class PropertyManagementFormModel { additionalDetails: string = ''; isUtilitiesPayable: boolean | null = null; isTaxesPayable: boolean | null = null; - isLeaseActive: boolean = false; - isLeaseExpired: boolean = false; - leaseExpiryDate: string | null = null; + formattedLeaseInformation: string | null = null; static fromApi(base: Api_PropertyManagement | null): PropertyManagementFormModel { const newFormModel = new PropertyManagementFormModel(); @@ -23,9 +21,7 @@ export class PropertyManagementFormModel { newFormModel.additionalDetails = base?.additionalDetails || ''; newFormModel.isUtilitiesPayable = base?.isUtilitiesPayable ?? null; newFormModel.isTaxesPayable = base?.isTaxesPayable ?? null; - newFormModel.isLeaseActive = base?.isLeaseActive || false; - newFormModel.isLeaseExpired = base?.isLeaseExpired || false; - newFormModel.leaseExpiryDate = base?.leaseExpiryDate || ''; + newFormModel.formattedLeaseInformation = formatApiPropertyManagementLease(base); return newFormModel; } @@ -41,20 +37,10 @@ export class PropertyManagementFormModel { additionalDetails: stringToNull(this.additionalDetails), isUtilitiesPayable: this.isUtilitiesPayable, isTaxesPayable: this.isTaxesPayable, - isLeaseActive: this.isLeaseActive, - isLeaseExpired: this.isLeaseExpired, - leaseExpiryDate: stringToNull(this.leaseExpiryDate), + relatedLeases: 0, + leaseExpiryDate: null, }; } - - formatLeaseInformation(): string { - if (this.isLeaseActive) { - const expiryDate = this.leaseExpiryDate ? `(${prettyFormatDate(this.leaseExpiryDate)})` : ''; - return this.isLeaseExpired ? `Expired ${expiryDate}`.trim() : `Yes ${expiryDate}`.trim(); - } else { - return 'No active Lease/License'; - } - } } export class ManagementPurposeModel {