55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import { CURRENCY_CATALOG } from '@mento/shared';
|
|
import { Prisma } from '@prisma/client';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
|
|
export type RateMap = {
|
|
baseCurrency: string;
|
|
/** currency code → how many base units for 1 unit of that currency */
|
|
rates: Map<string, number>;
|
|
};
|
|
|
|
export function isKnownCurrency(code: string): boolean {
|
|
return CURRENCY_CATALOG.some((c) => c.code === code);
|
|
}
|
|
|
|
export async function loadOrgRates(
|
|
prisma: PrismaService,
|
|
organizationId: string,
|
|
): Promise<RateMap> {
|
|
const org = await prisma.organization.findUnique({
|
|
where: { id: organizationId },
|
|
select: {
|
|
baseCurrency: true,
|
|
exchangeRates: { select: { currency: true, rateToBase: true } },
|
|
},
|
|
});
|
|
const baseCurrency = org?.baseCurrency || 'IRR';
|
|
const rates = new Map<string, number>();
|
|
rates.set(baseCurrency, 1);
|
|
for (const row of org?.exchangeRates ?? []) {
|
|
rates.set(row.currency, Number(row.rateToBase));
|
|
}
|
|
return { baseCurrency, rates };
|
|
}
|
|
|
|
export function toBaseAmount(
|
|
amount: number | null | undefined,
|
|
currency: string | null | undefined,
|
|
map: RateMap,
|
|
): number {
|
|
if (amount == null || Number.isNaN(amount)) return 0;
|
|
const code = (currency || map.baseCurrency).trim() || map.baseCurrency;
|
|
if (code === map.baseCurrency) return amount;
|
|
const rate = map.rates.get(code);
|
|
if (rate == null || rate <= 0) return amount;
|
|
return amount * rate;
|
|
}
|
|
|
|
export function decimalToBase(
|
|
amount: Prisma.Decimal | null | undefined,
|
|
currency: string | null | undefined,
|
|
map: RateMap,
|
|
): number {
|
|
return toBaseAmount(amount == null ? 0 : Number(amount), currency, map);
|
|
}
|