Phase 5 cleanup
This commit is contained in:
parent
5536acd67d
commit
76a516a417
136 changed files with 6322 additions and 1985 deletions
|
|
@ -235,9 +235,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
];
|
||||
const byPeriod = [{ _id: '2024-01', totalSpent: 100 }];
|
||||
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce(byMedicine)
|
||||
.mockResolvedValueOnce(byPeriod);
|
||||
mockAggregate.mockResolvedValueOnce(byMedicine).mockResolvedValueOnce(byPeriod);
|
||||
|
||||
const result = await repo.getSpendingSummary('hh1', { period: 'month' });
|
||||
|
||||
|
|
@ -256,9 +254,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('returns null currency when no medicine data', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
const result = await repo.getSpendingSummary('hh1', { period: 'month' });
|
||||
|
||||
|
|
@ -269,9 +265,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('filters by medicineId', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', { period: 'month', medicineId: 'med-1' });
|
||||
|
||||
|
|
@ -279,9 +273,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('filters by startDate only', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', {
|
||||
period: 'month',
|
||||
|
|
@ -292,9 +284,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('filters by endDate only', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', {
|
||||
period: 'month',
|
||||
|
|
@ -305,9 +295,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('filters by both startDate and endDate', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', {
|
||||
period: 'month',
|
||||
|
|
@ -319,9 +307,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('uses quarter date format', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', { period: 'quarter' });
|
||||
|
||||
|
|
@ -329,9 +315,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
});
|
||||
|
||||
it('uses year date format', async () => {
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
||||
|
||||
await repo.getSpendingSummary('hh1', { period: 'year' });
|
||||
|
||||
|
|
@ -350,9 +334,7 @@ describe(CabinetEventsRepository.name, () => {
|
|||
currency: null,
|
||||
},
|
||||
];
|
||||
mockAggregate
|
||||
.mockResolvedValueOnce(byMedicine)
|
||||
.mockResolvedValueOnce([]);
|
||||
mockAggregate.mockResolvedValueOnce(byMedicine).mockResolvedValueOnce([]);
|
||||
|
||||
const result = await repo.getSpendingSummary('hh1', { period: 'month' });
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,11 @@ export class CabinetEventsRepository {
|
|||
{
|
||||
$addFields: {
|
||||
avgUnitPrice: {
|
||||
$cond: [{ $gt: ['$totalQuantity', 0] }, { $divide: ['$totalSpent', '$totalQuantity'] }, 0],
|
||||
$cond: [
|
||||
{ $gt: ['$totalQuantity', 0] },
|
||||
{ $divide: ['$totalSpent', '$totalQuantity'] },
|
||||
0,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -153,7 +157,7 @@ export class CabinetEventsRepository {
|
|||
0,
|
||||
);
|
||||
const currency =
|
||||
byMedicine.length > 0 ? (byMedicine[0].currency as string | null) ?? null : null;
|
||||
byMedicine.length > 0 ? ((byMedicine[0].currency as string | null) ?? null) : null;
|
||||
|
||||
return {
|
||||
totalSpent,
|
||||
|
|
@ -174,7 +178,8 @@ export class CabinetEventsRepository {
|
|||
}
|
||||
|
||||
public async getAvgUnitPriceByMedicine(householdId: string, medicineIds: string[]) {
|
||||
if (medicineIds.length === 0) return new Map<string, { avgUnitPrice: number; currency: string | null }>();
|
||||
if (medicineIds.length === 0)
|
||||
return new Map<string, { avgUnitPrice: number; currency: string | null }>();
|
||||
|
||||
const results = await CabinetEventModel.aggregate([
|
||||
{
|
||||
|
|
@ -196,7 +201,11 @@ export class CabinetEventsRepository {
|
|||
{
|
||||
$addFields: {
|
||||
avgUnitPrice: {
|
||||
$cond: [{ $gt: ['$totalQuantity', 0] }, { $divide: ['$totalSpent', '$totalQuantity'] }, 0],
|
||||
$cond: [
|
||||
{ $gt: ['$totalQuantity', 0] },
|
||||
{ $divide: ['$totalSpent', '$totalQuantity'] },
|
||||
0,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -234,11 +234,14 @@ describe('cabinet-events.routes', () => {
|
|||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(mockListEvents).toHaveBeenCalledWith('hh1', expect.objectContaining({
|
||||
medicineId: 'med-1',
|
||||
eventType: 'purchased',
|
||||
limit: 10,
|
||||
}));
|
||||
expect(mockListEvents).toHaveBeenCalledWith(
|
||||
'hh1',
|
||||
expect.objectContaining({
|
||||
medicineId: 'med-1',
|
||||
eventType: 'purchased',
|
||||
limit: 10,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -276,10 +279,14 @@ describe('cabinet-events.routes', () => {
|
|||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(mockGetEventsByItem).toHaveBeenCalledWith('hh1', 'ci-1', expect.objectContaining({
|
||||
limit: 5,
|
||||
cursor: 'abc',
|
||||
}));
|
||||
expect(mockGetEventsByItem).toHaveBeenCalledWith(
|
||||
'hh1',
|
||||
'ci-1',
|
||||
expect.objectContaining({
|
||||
limit: 5,
|
||||
cursor: 'abc',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('handles ObjectId and Date objects in by-item response', async () => {
|
||||
|
|
@ -356,10 +363,13 @@ describe('cabinet-events.routes', () => {
|
|||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(mockGetSpendingSummary).toHaveBeenCalledWith('hh1', expect.objectContaining({
|
||||
period: 'quarter',
|
||||
medicineId: 'med-1',
|
||||
}));
|
||||
expect(mockGetSpendingSummary).toHaveBeenCalledWith(
|
||||
'hh1',
|
||||
expect.objectContaining({
|
||||
period: 'quarter',
|
||||
medicineId: 'med-1',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns empty summary with null currency', async () => {
|
||||
|
|
|
|||
|
|
@ -142,10 +142,7 @@ export default fp(
|
|||
},
|
||||
handler: async (request, reply) => {
|
||||
const service = fastify.diContainer.resolve('cabinetEventsService');
|
||||
const summary = await service.getSpendingSummary(
|
||||
request.params.householdId,
|
||||
request.query,
|
||||
);
|
||||
const summary = await service.getSpendingSummary(request.params.householdId, request.query);
|
||||
return reply.send(summary);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -136,7 +136,9 @@ describe(CabinetEventsService.name, () => {
|
|||
const result = await service.getAvgUnitPrices('hh1', ['med-1']);
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
expect(mockCabinetEventsRepo.getAvgUnitPriceByMedicine).toHaveBeenCalledWith('hh1', ['med-1']);
|
||||
expect(mockCabinetEventsRepo.getAvgUnitPriceByMedicine).toHaveBeenCalledWith('hh1', [
|
||||
'med-1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import type { CabinetEventsRepository, CreateCabinetEventData } from './cabinet-events.repository.js';
|
||||
import type {
|
||||
CabinetEventsRepository,
|
||||
CreateCabinetEventData,
|
||||
} from './cabinet-events.repository.js';
|
||||
import type { CabinetEventQueryInput, SpendingSummaryQueryInput } from '@meshitrack/shared';
|
||||
|
||||
interface Deps {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue