Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1x 1x 1x | import { BillsService, BudgetLimitStore, BudgetsService } from "@billos/firefly-iii-sdk"
import pino from "pino"
import { client } from "../../client"
import { env } from "../../config"
import { getDateNow } from "../../utils/date"
import { addJobToQueue } from "../utils"
import { SimpleJob } from "./BaseJob"
const logger = pino()
async function getTotalAmountOfBills(start: string, end: string): Promise<number> {
const allBills = await BillsService.listBill({ client, query: { page: 1, limit: 50, start, end } })
// Filtering inactive bills
const bills = allBills.data.data.filter(({ attributes }) => attributes.active)
const paidBills = bills.filter(({ attributes: { paid_dates } }) => paid_dates.length > 0)
const unpaidBills = bills
.filter(({ attributes: { paid_dates } }) => paid_dates.length === 0)
.filter(({ attributes: { next_expected_match } }) => !!next_expected_match)
const maximumUnpaidBill = unpaidBills.reduce((acc, bill) => acc + parseFloat(bill.attributes.amount_max), 0)
let paidBillsValue = 0
for (const bill of paidBills) {
const {
data: { data: transactions },
} = await BillsService.listTransactionByBill({
client,
path: { id: bill.id },
query: { page: 1, limit: 50, start, end },
})
for (const { attributes } of transactions) {
for (const { amount } of attributes.transactions) {
paidBillsValue += parseFloat(amount)
}
}
}
const total = paidBillsValue + maximumUnpaidBill
logger.info("You have paid %d in bills", paidBillsValue)
logger.info("You have at most %d in unpaid bills", maximumUnpaidBill)
logger.info("Total bills value is at most %d", total)
return total
}
export class UpdateBillsBudgetLimitJob extends SimpleJob {
readonly id = "update-bills-budget-limit"
override readonly startDelay = 15
async run(): Promise<void> {
if (!env.billsBudgetId) {
logger.warn("Bills budget name is not set in environment variables, skipping updateBillsBudgetLimit job")
return
}
// Get all budgets
const start = getDateNow().startOf("month").toISODate()
const end = getDateNow().endOf("month").toISODate()
const total = await getTotalAmountOfBills(start, end)
const { data: existingLimits } = await BudgetsService.listBudgetLimitByBudget({
client,
path: { id: env.billsBudgetId },
query: { start, end },
})
if (existingLimits.data.length > 1) {
throw new Error("There are more than one limit for the bills budget")
}
const body: BudgetLimitStore = {
amount: total.toString(),
budget_id: env.billsBudgetId,
start,
end,
fire_webhooks: false,
}
if (existingLimits.data.length === 0) {
logger.info("There are no limits for the bills budget, creating budget limit")
await BudgetsService.storeBudgetLimit({ client, path: { id: env.billsBudgetId }, body })
return
}
if (existingLimits.data[0].attributes.amount === body.amount) {
logger.info("The bills budget limit is already up to date, no changes needed")
return
}
const [limit] = existingLimits.data
try {
await BudgetsService.updateBudgetLimit({ client, path: { id: env.billsBudgetId, limitId: limit.id }, body })
} catch (err) {
logger.error({ err }, "Error updating bills budget limit:")
}
logger.info("Bills budget limit updated")
}
override async init(): Promise<void> {
logger.info("Initializing UpdateBillsBudgetLimit job")
await addJobToQueue(this)
logger.info("UpdateBillsBudgetLimit job initialized")
}
}
|