feat(finance): add settlement currency and cycle fx rates

This commit is contained in:
2026-03-10 16:46:59 +04:00
parent 4c0508f618
commit fb85219409
38 changed files with 3546 additions and 114 deletions

View File

@@ -201,6 +201,89 @@ export function createDbFinanceRepository(
})
},
async getCycleExchangeRate(cycleId, sourceCurrency, targetCurrency) {
const rows = await db
.select({
cycleId: schema.billingCycleExchangeRates.cycleId,
sourceCurrency: schema.billingCycleExchangeRates.sourceCurrency,
targetCurrency: schema.billingCycleExchangeRates.targetCurrency,
rateMicros: schema.billingCycleExchangeRates.rateMicros,
effectiveDate: schema.billingCycleExchangeRates.effectiveDate,
source: schema.billingCycleExchangeRates.source
})
.from(schema.billingCycleExchangeRates)
.where(
and(
eq(schema.billingCycleExchangeRates.cycleId, cycleId),
eq(schema.billingCycleExchangeRates.sourceCurrency, sourceCurrency),
eq(schema.billingCycleExchangeRates.targetCurrency, targetCurrency)
)
)
.limit(1)
const row = rows[0]
if (!row) {
return null
}
return {
cycleId: row.cycleId,
sourceCurrency: toCurrencyCode(row.sourceCurrency),
targetCurrency: toCurrencyCode(row.targetCurrency),
rateMicros: row.rateMicros,
effectiveDate: row.effectiveDate,
source: 'nbg'
}
},
async saveCycleExchangeRate(input) {
const rows = await db
.insert(schema.billingCycleExchangeRates)
.values({
cycleId: input.cycleId,
sourceCurrency: input.sourceCurrency,
targetCurrency: input.targetCurrency,
rateMicros: input.rateMicros,
effectiveDate: input.effectiveDate,
source: input.source
})
.onConflictDoUpdate({
target: [
schema.billingCycleExchangeRates.cycleId,
schema.billingCycleExchangeRates.sourceCurrency,
schema.billingCycleExchangeRates.targetCurrency
],
set: {
rateMicros: input.rateMicros,
effectiveDate: input.effectiveDate,
source: input.source,
updatedAt: instantToDate(nowInstant())
}
})
.returning({
cycleId: schema.billingCycleExchangeRates.cycleId,
sourceCurrency: schema.billingCycleExchangeRates.sourceCurrency,
targetCurrency: schema.billingCycleExchangeRates.targetCurrency,
rateMicros: schema.billingCycleExchangeRates.rateMicros,
effectiveDate: schema.billingCycleExchangeRates.effectiveDate,
source: schema.billingCycleExchangeRates.source
})
const row = rows[0]
if (!row) {
throw new Error('Failed to save billing cycle exchange rate')
}
return {
cycleId: row.cycleId,
sourceCurrency: toCurrencyCode(row.sourceCurrency),
targetCurrency: toCurrencyCode(row.targetCurrency),
rateMicros: row.rateMicros,
effectiveDate: row.effectiveDate,
source: 'nbg'
}
},
async addUtilityBill(input) {
await db.insert(schema.utilityBills).values({
householdId,

View File

@@ -178,6 +178,7 @@ function toCurrencyCode(raw: string): CurrencyCode {
function toHouseholdBillingSettingsRecord(row: {
householdId: string
settlementCurrency: string
rentAmountMinor: bigint | null
rentCurrency: string
rentDueDay: number
@@ -188,6 +189,7 @@ function toHouseholdBillingSettingsRecord(row: {
}): HouseholdBillingSettingsRecord {
return {
householdId: row.householdId,
settlementCurrency: toCurrencyCode(row.settlementCurrency),
rentAmountMinor: row.rentAmountMinor,
rentCurrency: toCurrencyCode(row.rentCurrency),
rentDueDay: row.rentDueDay,
@@ -862,6 +864,7 @@ export function createDbHouseholdConfigurationRepository(databaseUrl: string): {
const rows = await db
.select({
householdId: schema.householdBillingSettings.householdId,
settlementCurrency: schema.householdBillingSettings.settlementCurrency,
rentAmountMinor: schema.householdBillingSettings.rentAmountMinor,
rentCurrency: schema.householdBillingSettings.rentCurrency,
rentDueDay: schema.householdBillingSettings.rentDueDay,
@@ -888,6 +891,11 @@ export function createDbHouseholdConfigurationRepository(databaseUrl: string): {
const rows = await db
.update(schema.householdBillingSettings)
.set({
...(input.settlementCurrency
? {
settlementCurrency: input.settlementCurrency
}
: {}),
...(input.rentAmountMinor !== undefined
? {
rentAmountMinor: input.rentAmountMinor
@@ -928,6 +936,7 @@ export function createDbHouseholdConfigurationRepository(databaseUrl: string): {
.where(eq(schema.householdBillingSettings.householdId, input.householdId))
.returning({
householdId: schema.householdBillingSettings.householdId,
settlementCurrency: schema.householdBillingSettings.settlementCurrency,
rentAmountMinor: schema.householdBillingSettings.rentAmountMinor,
rentCurrency: schema.householdBillingSettings.rentCurrency,
rentDueDay: schema.householdBillingSettings.rentDueDay,