nx_bills.nx source
↩ module page · 62 lines · 2631 B
1// nx_bills.nx -- R1 of THE NISHI SITUATION-MANAGEMENT arc: the recurring BILLS / OBLIGATIONS register
2// (insurance, mortgage, HOA, utilities, ...). The ledger tracks what HAPPENED; this tracks what is COMMITTED
3// and what is DUE. Exact no-float (nx_money): a bill carries an amount (cents), a cadence in months
4// (1=monthly, 3=quarterly, 6=semiannual, 12=annual), a due day-of-month, a category code, and a paid-this-
5// period flag. Computes the true MONTHLY obligation (cadence-normalized), per-category totals, what is DUE
6// SOON, and what is OVERDUE -- so a person sees their whole picture and never misses a bill. Data-driven,
7// no hardware writes. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_money.nx"
10
11// category codes (DATA convention): 0 housing, 1 insurance, 2 utility, 3 debt, 4 other.
12const BL_HOUSING: i64 = 0
13const BL_INSURANCE: i64 = 1
14const BL_UTILITY: i64 = 2
15const BL_DEBT: i64 = 3
16const BL_OTHER: i64 = 4
17
18// monthly-equivalent of one bill = amount / cadence_months, exact (banker's rounding).
19func bl_monthly(amount: i64, cadence_months: i64) -> i64 {
20 if cadence_months <= 0 { return amount }
21 return mny_div_round(amount, cadence_months, RND_HALF_EVEN)
22}
23
24// total monthly obligation across n bills.
25func bl_monthly_total(amounts: *i64, cadences: *i64, n: i64) -> i64 {
26 var t: i64 = 0
27 var i: i64 = 0
28 while i < n { t = mny_add(t, bl_monthly(amounts[i], cadences[i])); i = i + 1 }
29 return t
30}
31
32// monthly obligation for one category.
33func bl_category_monthly(amounts: *i64, cadences: *i64, cats: *i64, n: i64, target: i64) -> i64 {
34 var t: i64 = 0
35 var i: i64 = 0
36 while i < n { if cats[i] == target { t = mny_add(t, bl_monthly(amounts[i], cadences[i])) } i = i + 1 }
37 return t
38}
39
40// bills due within `window` days of `today` (both are day-of-month 1..31). writes their indices to
41// out_idx[]; returns the count. (In-month window; cross-month wrap is the refinement.)
42func bl_due_soon(due_days: *i64, today: i64, window: i64, n: i64, out_idx: *i64) -> i64 {
43 var c: i64 = 0
44 var i: i64 = 0
45 while i < n {
46 let d: i64 = due_days[i]
47 if d >= today { if (d - today) <= window { out_idx[c] = i; c = c + 1 } }
48 i = i + 1
49 }
50 return c
51}
52
53// overdue bills: due day already passed this period AND not paid (paid[i]==0). writes indices; returns count.
54func bl_overdue(due_days: *i64, paid: *i64, today: i64, n: i64, out_idx: *i64) -> i64 {
55 var c: i64 = 0
56 var i: i64 = 0
57 while i < n {
58 if due_days[i] < today { if paid[i] == 0 { out_idx[c] = i; c = c + 1 } }
59 i = i + 1
60 }
61 return c
62}