import { ok, err } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { CurrencyNotFoundError, InactiveCurrencyError, InvalidExchangeRateError, SameCurrencyPairError, } from "../lib/errors.generated"; interface CreateExchangeRateInput { sourceCurrencyId: string; targetCurrencyId: string; rate: number; effectiveDate: Date; } /** * Function: createExchangeRate * * Establishes a new conversion ratio between a currency pair with a specific * effective date. The rate specifies how many units of the target currency * equal one unit of the source currency. */ export async function run>( db: Transaction, input: CreateExchangeRateInput & CF, ) { const { sourceCurrencyId, targetCurrencyId, rate, effectiveDate, ...customFields } = input; // 1. Check source currency exists const sourceCurrency = await db .selectFrom("Currency") .selectAll() .where("id", "=", sourceCurrencyId) .executeTakeFirst(); if (!sourceCurrency) { return err(new CurrencyNotFoundError(sourceCurrencyId)); } // 2. Check source currency is active if (sourceCurrency.status !== "ACTIVE") { return err(new InactiveCurrencyError(sourceCurrency.code)); } // 3. Check target currency exists const targetCurrency = await db .selectFrom("Currency") .selectAll() .where("id", "=", targetCurrencyId) .executeTakeFirst(); if (!targetCurrency) { return err(new CurrencyNotFoundError(targetCurrencyId)); } // 4. Check target currency is active if (targetCurrency.status !== "ACTIVE") { return err(new InactiveCurrencyError(targetCurrency.code)); } // 5. Check source and target are different if (sourceCurrencyId === targetCurrencyId) { return err(new SameCurrencyPairError(sourceCurrencyId)); } // 6. Validate rate is positive if (rate <= 0) { return err(new InvalidExchangeRateError(String(rate))); } // 7. Create exchange rate const exchangeRate = await db .insertInto("ExchangeRate") .values({ ...(customFields as Record), sourceCurrencyId, targetCurrencyId, rate, effectiveDate, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ exchangeRate }); }