Skip to content

Commit fe2da41

Browse files
committed
added other category RRs to car filtering
1 parent c4ac82f commit fe2da41

3 files changed

Lines changed: 142 additions & 34 deletions

File tree

src/backend/src/services/reimbursement-requests.services.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import {
3535
validateRefund,
3636
validateUserIsPartOfFinanceTeamOrHead,
3737
isUserFinanceTeamOrHead,
38-
updateMaterialStatusesOnPayment
38+
updateMaterialStatusesOnPayment,
39+
getCarNumberFilter
3940
} from '../utils/reimbursement-requests.utils.js';
4041
import {
4142
AccessDeniedAdminOnlyException,
@@ -95,12 +96,7 @@ export default class ReimbursementRequestService {
9596
dateDeleted: null,
9697
recipientId: recipient.userId,
9798
organizationId: organization.organizationId,
98-
...(carNumber !== undefined &&
99-
carNumber !== null && {
100-
reimbursementProducts: {
101-
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
102-
}
103-
})
99+
...getCarNumberFilter(carNumber)
104100
},
105101
...getReimbursementRequestQueryArgs(organization.organizationId)
106102
});
@@ -123,12 +119,7 @@ export default class ReimbursementRequestService {
123119
dateDeleted: null,
124120
assigneeId: assignee.userId,
125121
organizationId: organization.organizationId,
126-
...(carNumber !== undefined &&
127-
carNumber !== null && {
128-
reimbursementProducts: {
129-
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
130-
}
131-
})
122+
...getCarNumberFilter(carNumber)
132123
},
133124
...getReimbursementRequestQueryArgs(organization.organizationId)
134125
});
@@ -187,12 +178,7 @@ export default class ReimbursementRequestService {
187178
dateDeleted: null,
188179
recipientId: { in: Array.from(teamUserIds) },
189180
organizationId: organization.organizationId,
190-
...(carNumber !== undefined &&
191-
carNumber !== null && {
192-
reimbursementProducts: {
193-
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
194-
}
195-
})
181+
...getCarNumberFilter(carNumber)
196182
},
197183
...getReimbursementRequestQueryArgs(organization.organizationId)
198184
});
@@ -630,12 +616,7 @@ export default class ReimbursementRequestService {
630616
}
631617
},
632618
accountCode: { organizationId: organization.organizationId },
633-
...(carNumber !== undefined &&
634-
carNumber !== null && {
635-
reimbursementProducts: {
636-
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
637-
}
638-
})
619+
...getCarNumberFilter(carNumber)
639620
},
640621
...getReimbursementRequestQueryArgs(organization.organizationId)
641622
});
@@ -1041,12 +1022,7 @@ export default class ReimbursementRequestService {
10411022
where: {
10421023
dateDeleted: null,
10431024
accountCode: { organizationId: organization.organizationId },
1044-
...(carNumber !== undefined &&
1045-
carNumber !== null && {
1046-
reimbursementProducts: {
1047-
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
1048-
}
1049-
})
1025+
...getCarNumberFilter(carNumber)
10501026
},
10511027
...getReimbursementRequestQueryArgs(organization.organizationId)
10521028
});

src/backend/src/utils/reimbursement-requests.utils.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,3 +635,21 @@ export const updateMaterialStatusesOnPayment = async (reimbursementRequestId: st
635635
});
636636
}
637637
};
638+
639+
export const getCarNumberFilter = (carNumber?: number) => {
640+
if (carNumber === undefined || carNumber === null) return {};
641+
return {
642+
OR: [
643+
{
644+
reimbursementProducts: {
645+
some: { reimbursementProductReason: { wbsElement: { carNumber } } }
646+
}
647+
},
648+
{
649+
reimbursementProducts: {
650+
none: { reimbursementProductReason: { wbsElementId: { not: null } } }
651+
}
652+
}
653+
]
654+
};
655+
};

src/backend/tests/unit/reimbursement-requests.test.ts

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,55 @@ describe('Reimbursement Requests', () => {
758758
test('carNumber 0 filters to only car-0 requests and does not return all requests (Fergus regression)', async () => {
759759
const fergusResults = await ReimbursementRequestService.getUserReimbursementRequests(createdUser, org, 0);
760760
expect(fergusResults).toHaveLength(1);
761-
expect(fergusResults[0].reimbursementRequestId).toBe(reimbursementRequest.reimbursementRequestId);
761+
expect(fergusResults.map((r) => r.reimbursementRequestId)).toContain(reimbursementRequest.reimbursementRequestId);
762+
expect(fergusResults.map((r) => r.reimbursementRequestId)).not.toContain(car1RR.reimbursementRequestId);
763+
});
764+
test('category-only RR does not cause WBS-linked car-1 RR to bleed into car-0 results', async () => {
765+
const categoryOnlyRR = await ReimbursementRequestService.createReimbursementRequest(
766+
createdUser,
767+
createdVendor.vendorId,
768+
createdIndexCode.indexCodeId,
769+
[
770+
{
771+
name: 'CONSUMABLES',
772+
reason: createdOtherProductReason,
773+
cost: 250,
774+
refundSources: [{ indexCode: createdIndexCode, amount: 250 }]
775+
}
776+
],
777+
[],
778+
createdAccountCode.accountCodeId,
779+
250,
780+
org
781+
);
782+
783+
const results = await ReimbursementRequestService.getUserReimbursementRequests(createdUser, org, 0);
784+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
785+
expect(results.map((r) => r.reimbursementRequestId)).not.toContain(car1RR.reimbursementRequestId);
786+
});
787+
788+
test('category-only RR does not cause WBS-linked car-0 RR to bleed into car-1 results', async () => {
789+
const categoryOnlyRR = await ReimbursementRequestService.createReimbursementRequest(
790+
createdUser,
791+
createdVendor.vendorId,
792+
createdIndexCode.indexCodeId,
793+
[
794+
{
795+
name: 'CONSUMABLES',
796+
reason: createdOtherProductReason,
797+
cost: 250,
798+
refundSources: [{ indexCode: createdIndexCode, amount: 250 }]
799+
}
800+
],
801+
[],
802+
createdAccountCode.accountCodeId,
803+
250,
804+
org
805+
);
806+
807+
const results = await ReimbursementRequestService.getUserReimbursementRequests(createdUser, org, 1);
808+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
809+
expect(results.map((r) => r.reimbursementRequestId)).not.toContain(reimbursementRequest.reimbursementRequestId);
762810
});
763811
});
764812

@@ -786,7 +834,8 @@ describe('Reimbursement Requests', () => {
786834
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
787835
const fergusResults = await ReimbursementRequestService.getAllReimbursementRequests(financeHead, org, 0);
788836
expect(fergusResults).toHaveLength(1);
789-
expect(fergusResults[0].reimbursementRequestId).toBe(reimbursementRequest.reimbursementRequestId);
837+
expect(fergusResults.map((r) => r.reimbursementRequestId)).toContain(reimbursementRequest.reimbursementRequestId);
838+
expect(fergusResults.map((r) => r.reimbursementRequestId)).not.toContain(car1RR.reimbursementRequestId);
790839
});
791840
});
792841

@@ -855,7 +904,8 @@ describe('Reimbursement Requests', () => {
855904
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
856905
const fergusResults = await ReimbursementRequestService.getUsersTeamsReimbursementRequests(financeHead, org, 0);
857906
expect(fergusResults).toHaveLength(1);
858-
expect(fergusResults[0].reimbursementRequestId).toBe(reimbursementRequest.reimbursementRequestId);
907+
expect(fergusResults.map((r) => r.reimbursementRequestId)).toContain(reimbursementRequest.reimbursementRequestId);
908+
expect(fergusResults.map((r) => r.reimbursementRequestId)).not.toContain(car1RR.reimbursementRequestId);
859909
});
860910
});
861911
});
@@ -955,4 +1005,68 @@ describe('Reimbursement Requests', () => {
9551005
expect(result.saboId).toEqual('SABO-001');
9561006
});
9571007
});
1008+
1009+
describe('category-only requests appear under every car', () => {
1010+
let categoryOnlyRR: ReimbursementRequest;
1011+
1012+
beforeEach(async () => {
1013+
categoryOnlyRR = await ReimbursementRequestService.createReimbursementRequest(
1014+
createdUser,
1015+
createdVendor.vendorId,
1016+
createdIndexCode.indexCodeId,
1017+
[
1018+
{
1019+
name: 'CONSUMABLES',
1020+
reason: createdOtherProductReason,
1021+
cost: 250,
1022+
refundSources: [{ indexCode: createdIndexCode, amount: 250 }]
1023+
}
1024+
],
1025+
[],
1026+
createdAccountCode.accountCodeId,
1027+
250,
1028+
org
1029+
);
1030+
});
1031+
1032+
test('category-only RR appears under car 0 for getUserReimbursementRequests', async () => {
1033+
const results = await ReimbursementRequestService.getUserReimbursementRequests(createdUser, org, 0);
1034+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1035+
});
1036+
1037+
test('category-only RR appears under car 1 for getUserReimbursementRequests', async () => {
1038+
const results = await ReimbursementRequestService.getUserReimbursementRequests(createdUser, org, 1);
1039+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1040+
});
1041+
1042+
test('category-only RR appears under car 0 for getAllReimbursementRequests', async () => {
1043+
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
1044+
const results = await ReimbursementRequestService.getAllReimbursementRequests(financeHead, org, 0);
1045+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1046+
});
1047+
1048+
test('category-only RR appears under car 1 for getAllReimbursementRequests', async () => {
1049+
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
1050+
const results = await ReimbursementRequestService.getAllReimbursementRequests(financeHead, org, 1);
1051+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1052+
});
1053+
1054+
test('category-only RR appears under car 0 for getUsersTeamsReimbursementRequests', async () => {
1055+
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
1056+
const results = await ReimbursementRequestService.getUsersTeamsReimbursementRequests(financeHead, org, 0);
1057+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1058+
});
1059+
1060+
test('category-only RR appears under car 1 for getUsersTeamsReimbursementRequests', async () => {
1061+
const financeHead = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeHead' } });
1062+
const results = await ReimbursementRequestService.getUsersTeamsReimbursementRequests(financeHead, org, 1);
1063+
expect(results.map((r) => r.reimbursementRequestId)).toContain(categoryOnlyRR.reimbursementRequestId);
1064+
});
1065+
1066+
test('category-only RR does not appear under getUserAssignedReimbursementRequests when unassigned', async () => {
1067+
const financeMember = await prisma.user.findUniqueOrThrow({ where: { googleAuthId: 'financeMember' } });
1068+
const results = await ReimbursementRequestService.getUserAssignedReimbursementRequests(financeMember, org, 0);
1069+
expect(results.map((r) => r.reimbursementRequestId)).not.toContain(categoryOnlyRR.reimbursementRequestId);
1070+
});
1071+
});
9581072
});

0 commit comments

Comments
 (0)