MeshiTrack/packages/api/src/modules/medicine-prices/medicine-prices.service.ts

94 lines
3.1 KiB
TypeScript
Raw Normal View History

import type { MedicinePricesRepository } from './medicine-prices.repository.js';
import type { MedicineProductsRepository } from '../medicine-products/medicine-products.repository.js';
import type { StoresRepository } from '../stores/stores.repository.js';
import type {
CreateMedicinePriceRecordInput,
MedicinePriceHistoryQueryInput,
MedicinePriceAnalyticsQueryInput,
} from '@meshitrack/shared';
import { NotFoundError } from '../../common/errors.js';
interface Deps {
medicinePricesRepository: MedicinePricesRepository;
medicineProductsRepository: MedicineProductsRepository;
storesRepository: StoresRepository;
}
export class MedicinePricesService {
private readonly medicinePricesRepository: MedicinePricesRepository;
private readonly medicineProductsRepository: MedicineProductsRepository;
private readonly storesRepository: StoresRepository;
public constructor({ medicinePricesRepository, medicineProductsRepository, storesRepository }: Deps) {
this.medicinePricesRepository = medicinePricesRepository;
this.medicineProductsRepository = medicineProductsRepository;
this.storesRepository = storesRepository;
}
public async recordPrice(
data: CreateMedicinePriceRecordInput,
householdId: string,
userId: string,
) {
const product = await this.medicineProductsRepository.findById(
data.medicineProductId,
householdId,
);
if (!product) throw new NotFoundError('Medicine product not found');
const store = await this.storesRepository.findById(data.storeId, householdId);
if (!store) throw new NotFoundError('Store not found');
const pricePerUnit = data.price / data.quantity;
const date = data.date ? new Date(data.date) : new Date();
return this.medicinePricesRepository.create({
householdId,
medicineProductId: data.medicineProductId,
medicineProductBrand: product.brand ?? product.medicineName,
medicineId: data.medicineId,
medicineName: product.medicineName,
storeId: data.storeId,
storeName: store.name,
price: data.price,
currency: data.currency,
quantity: data.quantity,
unit: data.unit,
pricePerUnit,
date,
isInsurancePrice: data.isInsurancePrice,
notes: data.notes,
createdBy: userId,
});
}
public async getPriceHistory(
householdId: string,
medicineId: string,
query: MedicinePriceHistoryQueryInput,
) {
return this.medicinePricesRepository.findByMedicine(householdId, medicineId, query);
}
public async compareStores(householdId: string, medicineId: string) {
return this.medicinePricesRepository.compareStores(householdId, medicineId);
}
public async estimatePrice(
householdId: string,
medicineId: string,
storeId?: string,
): Promise<number | null> {
const record = await this.medicinePricesRepository.getLatestForMedicine(
householdId,
medicineId,
storeId,
);
return record ? (record.pricePerUnit as number) : null;
}
public async getAnalytics(householdId: string, query: MedicinePriceAnalyticsQueryInput) {
return this.medicinePricesRepository.getAnalytics(householdId, query);
}
}