Implement regimens
This commit is contained in:
parent
1f66fab30f
commit
9f416903ef
66 changed files with 9130 additions and 189 deletions
|
|
@ -29,6 +29,8 @@ const {
|
|||
mockFindExpiringSoon,
|
||||
mockSoftDelete,
|
||||
mockCountByMedicineId,
|
||||
mockDiscard,
|
||||
mockFindActiveByMedicineForFEFO,
|
||||
} = vi.hoisted(() => ({
|
||||
mockFindByHousehold: vi.fn(),
|
||||
mockFindById: vi.fn(),
|
||||
|
|
@ -39,6 +41,8 @@ const {
|
|||
mockFindExpiringSoon: vi.fn(),
|
||||
mockSoftDelete: vi.fn(),
|
||||
mockCountByMedicineId: vi.fn(),
|
||||
mockDiscard: vi.fn(),
|
||||
mockFindActiveByMedicineForFEFO: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('./cabinet.repository.js', () => ({
|
||||
|
|
@ -52,6 +56,8 @@ vi.mock('./cabinet.repository.js', () => ({
|
|||
findExpiringSoon = mockFindExpiringSoon;
|
||||
softDelete = mockSoftDelete;
|
||||
countByMedicineId = mockCountByMedicineId;
|
||||
discard = mockDiscard;
|
||||
findActiveByMedicineForFEFO = mockFindActiveByMedicineForFEFO;
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
@ -105,6 +111,28 @@ vi.mock('../medicines/medicines.service.js', () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
vi.mock('../cabinet-events/cabinet-events.repository.js', () => ({
|
||||
CabinetEventsRepository: class {
|
||||
create = vi.fn();
|
||||
createMany = vi.fn();
|
||||
findByHousehold = vi.fn();
|
||||
findByCabinetItem = vi.fn();
|
||||
getSpendingSummary = vi.fn();
|
||||
getAvgUnitPriceByMedicine = vi.fn();
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../cabinet-events/cabinet-events.service.js', () => ({
|
||||
CabinetEventsService: class {
|
||||
logEvent = vi.fn();
|
||||
logEvents = vi.fn();
|
||||
listEvents = vi.fn();
|
||||
getEventsByItem = vi.fn();
|
||||
getSpendingSummary = vi.fn();
|
||||
getAvgUnitPrices = vi.fn();
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../users/users.repository.js', () => ({
|
||||
UsersRepository: class {
|
||||
findByKeycloakId = vi.fn().mockResolvedValue({ householdIds: ['hh1'] });
|
||||
|
|
@ -117,6 +145,7 @@ import householdPlugin from '../../plugins/household.plugin.js';
|
|||
import usersRoutes from '../users/users.routes.js';
|
||||
import medicinesRoutes from '../medicines/medicines.routes.js';
|
||||
import medicineProductsRoutes from '../medicine-products/medicine-products.routes.js';
|
||||
import cabinetEventsRoutes from '../cabinet-events/cabinet-events.routes.js';
|
||||
import cabinetRoutes from './cabinet.routes.js';
|
||||
|
||||
function makeFakeCabinetItem(overrides = {}) {
|
||||
|
|
@ -155,6 +184,7 @@ describe('cabinet.routes', () => {
|
|||
await instance.register(usersRoutes);
|
||||
await instance.register(medicinesRoutes);
|
||||
await instance.register(medicineProductsRoutes);
|
||||
await instance.register(cabinetEventsRoutes);
|
||||
await instance.register(cabinetRoutes);
|
||||
await instance.ready();
|
||||
return instance;
|
||||
|
|
@ -242,6 +272,40 @@ describe('cabinet.routes', () => {
|
|||
expect(body.data[0].expirationDate).toBe('2026-12-31T00:00:00.000Z');
|
||||
expect(body.data[0].createdAt).toBe('2024-01-01T00:00:00.000Z');
|
||||
});
|
||||
|
||||
it('includes optional purchase and store fields when present', async () => {
|
||||
const item = makeFakeCabinetItem({
|
||||
concentration: 5.0,
|
||||
concentrationUnit: 'mg/mL',
|
||||
purchaseDate: new Date('2024-03-01T00:00:00.000Z'),
|
||||
unitPrice: 1.5,
|
||||
totalPrice: 45.0,
|
||||
currency: 'USD',
|
||||
storeId: 'store-1',
|
||||
storeName: 'Pharmacy Plus',
|
||||
});
|
||||
mockFindByHousehold.mockResolvedValue({
|
||||
data: [item],
|
||||
pagination: { cursor: null, hasMore: false },
|
||||
});
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/api/v1/households/hh1/cabinet',
|
||||
headers: authHeaders,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
const body = res.json();
|
||||
expect(body.data[0].concentration).toBe(5.0);
|
||||
expect(body.data[0].concentrationUnit).toBe('mg/mL');
|
||||
expect(body.data[0].purchaseDate).toBe('2024-03-01T00:00:00.000Z');
|
||||
expect(body.data[0].unitPrice).toBe(1.5);
|
||||
expect(body.data[0].totalPrice).toBe(45.0);
|
||||
expect(body.data[0].currency).toBe('USD');
|
||||
expect(body.data[0].storeId).toBe('store-1');
|
||||
expect(body.data[0].storeName).toBe('Pharmacy Plus');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/v1/households/:householdId/cabinet/summary', () => {
|
||||
|
|
@ -379,4 +443,32 @@ describe('cabinet.routes', () => {
|
|||
expect(res.statusCode).toBe(204);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /api/v1/households/:householdId/cabinet/:id/discard', () => {
|
||||
it('discards a cabinet item', async () => {
|
||||
mockFindById.mockResolvedValue(makeFakeCabinetItem({ quantity: 20 }));
|
||||
mockDiscard.mockResolvedValue(makeFakeCabinetItem({ quantity: 0, isDeleted: true }));
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/v1/households/hh1/cabinet/ci-1/discard',
|
||||
headers: authHeaders,
|
||||
payload: { reason: 'expired' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.json().quantity).toBe(0);
|
||||
});
|
||||
|
||||
it('returns 400 for missing reason', async () => {
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/v1/households/hh1/cabinet/ci-1/discard',
|
||||
headers: authHeaders,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue