feat(miniapp): improve mobile billing and utility controls

This commit is contained in:
2026-03-10 18:50:19 +04:00
parent 3168356431
commit b7658164a8
15 changed files with 878 additions and 52 deletions

View File

@@ -296,6 +296,54 @@ export function createDbFinanceRepository(
})
},
async updateUtilityBill(input) {
const rows = await db
.update(schema.utilityBills)
.set({
billName: input.billName,
amountMinor: input.amountMinor,
currency: input.currency
})
.where(
and(
eq(schema.utilityBills.householdId, householdId),
eq(schema.utilityBills.id, input.billId)
)
)
.returning({
id: schema.utilityBills.id,
billName: schema.utilityBills.billName,
amountMinor: schema.utilityBills.amountMinor,
currency: schema.utilityBills.currency,
createdByMemberId: schema.utilityBills.createdByMemberId,
createdAt: schema.utilityBills.createdAt
})
const row = rows[0]
if (!row) {
return null
}
return {
...row,
currency: toCurrencyCode(row.currency),
createdAt: instantFromDatabaseValue(row.createdAt)!
}
},
async deleteUtilityBill(billId) {
const rows = await db
.delete(schema.utilityBills)
.where(
and(eq(schema.utilityBills.householdId, householdId), eq(schema.utilityBills.id, billId))
)
.returning({
id: schema.utilityBills.id
})
return rows.length > 0
},
async getRentRuleForPeriod(period) {
const rows = await db
.select({

View File

@@ -121,6 +121,14 @@ class FinanceRepositoryStub implements FinanceRepository {
this.lastUtilityBill = input
}
async updateUtilityBill() {
return null
}
async deleteUtilityBill() {
return false
}
async getRentRuleForPeriod(): Promise<FinanceRentRuleRecord | null> {
return this.rentRule
}

View File

@@ -466,6 +466,17 @@ export interface FinanceCommandService {
currency: CurrencyCode
period: string
} | null>
updateUtilityBill(
billId: string,
billName: string,
amountArg: string,
currencyArg?: string
): Promise<{
billId: string
amount: Money
currency: CurrencyCode
} | null>
deleteUtilityBill(billId: string): Promise<boolean>
generateDashboard(periodArg?: string): Promise<FinanceDashboard | null>
generateStatement(periodArg?: string): Promise<string | null>
}
@@ -596,6 +607,34 @@ export function createFinanceCommandService(
}
},
async updateUtilityBill(billId, billName, amountArg, currencyArg) {
const settings = await householdConfigurationRepository.getHouseholdBillingSettings(
dependencies.householdId
)
const currency = parseCurrency(currencyArg, settings.settlementCurrency)
const amount = Money.fromMajor(amountArg, currency)
const updated = await repository.updateUtilityBill({
billId,
billName,
amountMinor: amount.amountMinor,
currency
})
if (!updated) {
return null
}
return {
billId: updated.id,
amount,
currency
}
},
deleteUtilityBill(billId) {
return repository.deleteUtilityBill(billId)
},
async generateStatement(periodArg) {
const dashboard = await buildFinanceDashboard(dependencies, periodArg)
if (!dashboard) {

View File

@@ -165,6 +165,13 @@ export interface FinanceRepository {
currency: CurrencyCode
createdByMemberId: string
}): Promise<void>
updateUtilityBill(input: {
billId: string
billName: string
amountMinor: bigint
currency: CurrencyCode
}): Promise<FinanceUtilityBillRecord | null>
deleteUtilityBill(billId: string): Promise<boolean>
getRentRuleForPeriod(period: string): Promise<FinanceRentRuleRecord | null>
getUtilityTotalForCycle(cycleId: string): Promise<bigint>
listUtilityBillsForCycle(cycleId: string): Promise<readonly FinanceUtilityBillRecord[]>