viewer: drop parties' bill arms (the ledger tags bill entries with their vendor, which wins); burn tests for one covered month and breaking even
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
1 parent
7a6cc154ae
commit
ca3a279219
2 files changed
+50
-13
No files matched your search
@@ -489,18 +489,15 @@ impl Books {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Customer or vendor names for entries created by invoices and bills and
|
/// Customer names for entries created by invoices and their payments,
|
||||||
/// their payments, from the journal.
|
/// from the journal. (Bills and bill payments need nothing here: the
|
||||||
|
/// ledger tags their entries with the vendor, which takes precedence.)
|
||||||
fn parties(ledger: &Ledger, journal: &[JournalLine]) -> HashMap<EntryId, String> {
|
fn parties(ledger: &Ledger, journal: &[JournalLine]) -> HashMap<EntryId, String> {
|
||||||
let mut out = HashMap::new();
|
let mut out = HashMap::new();
|
||||||
let customer = |id: Option<u64>| {
|
let customer = |id: Option<u64>| {
|
||||||
id.and_then(|c| ledger.get_customer(c))
|
id.and_then(|c| ledger.get_customer(c))
|
||||||
.map(|c| c.name.clone())
|
.map(|c| c.name.clone())
|
||||||
};
|
};
|
||||||
let vendor = |id: Option<u64>| {
|
|
||||||
id.and_then(|v| ledger.get_vendor(v))
|
|
||||||
.map(|v| v.name.clone())
|
|
||||||
};
|
|
||||||
let u = |p: &Value, k: &str| p.get(k).and_then(|v| v.as_u64());
|
let u = |p: &Value, k: &str| p.get(k).and_then(|v| v.as_u64());
|
||||||
for line in journal {
|
for line in journal {
|
||||||
let p = &line.payload;
|
let p = &line.payload;
|
||||||
@@ -514,12 +511,6 @@ fn parties(ledger: &Ledger, journal: &[JournalLine]) -> HashMap<EntryId, String>
|
|||||||
.and_then(|i| ledger.get_invoice(i))
|
.and_then(|i| ledger.get_invoice(i))
|
||||||
.map(|i| i.customer_id),
|
.map(|i| i.customer_id),
|
||||||
),
|
),
|
||||||
"bill.created" => vendor(u(p, "vendor_id")),
|
|
||||||
"bill.paid" => vendor(
|
|
||||||
u(p, "bill_id")
|
|
||||||
.and_then(|b| ledger.get_bill(b))
|
|
||||||
.map(|b| b.vendor_id),
|
|
||||||
),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(n) = name {
|
if let Some(n) = name {
|
||||||
|
|||||||
@@ -430,7 +430,53 @@ fn comparisons_and_burn_on_fixed_dates() {
|
|||||||
let b3 = data::load_once(&source(&d3, "", today)).unwrap();
|
let b3 = data::load_once(&source(&d3, "", today)).unwrap();
|
||||||
// 10.00 / 3 = 3.333... -> 3.33
|
// 10.00 / 3 = 3.333... -> 3.33
|
||||||
assert_eq!(b3.kpis.monthly_burn, Some(Decimal::new(333, 2)));
|
assert_eq!(b3.kpis.monthly_burn, Some(Decimal::new(333, 2)));
|
||||||
for x in [d, d2, d3] {
|
// Books covering only last month: one month, not two.
|
||||||
|
let (d4, mut s4) = store_at("burn-one");
|
||||||
|
let c4 = s4
|
||||||
|
.add_account("1000", "Checking", AccountType::Asset, None, false)
|
||||||
|
.unwrap();
|
||||||
|
let e4 = s4
|
||||||
|
.add_account("6000", "Rent", AccountType::Expense, None, false)
|
||||||
|
.unwrap();
|
||||||
|
post(
|
||||||
|
&mut s4,
|
||||||
|
NaiveDate::from_ymd_opt(2026, 4, 20).unwrap(),
|
||||||
|
e4,
|
||||||
|
c4,
|
||||||
|
9_000,
|
||||||
|
);
|
||||||
|
drop(s4);
|
||||||
|
let b4 = data::load_once(&source(&d4, "", today)).unwrap();
|
||||||
|
assert_eq!(b4.kpis.monthly_burn, Some(Decimal::new(9_000, 2)));
|
||||||
|
// Breaking even burns nothing.
|
||||||
|
let (d5, mut s5) = store_at("burn-even");
|
||||||
|
let c5 = s5
|
||||||
|
.add_account("1000", "Checking", AccountType::Asset, None, false)
|
||||||
|
.unwrap();
|
||||||
|
let r5 = s5
|
||||||
|
.add_account("4000", "Sales", AccountType::Revenue, None, false)
|
||||||
|
.unwrap();
|
||||||
|
let e5 = s5
|
||||||
|
.add_account("6000", "Rent", AccountType::Expense, None, false)
|
||||||
|
.unwrap();
|
||||||
|
post(
|
||||||
|
&mut s5,
|
||||||
|
NaiveDate::from_ymd_opt(2026, 3, 5).unwrap(),
|
||||||
|
e5,
|
||||||
|
c5,
|
||||||
|
4_000,
|
||||||
|
);
|
||||||
|
post(
|
||||||
|
&mut s5,
|
||||||
|
NaiveDate::from_ymd_opt(2026, 3, 6).unwrap(),
|
||||||
|
c5,
|
||||||
|
r5,
|
||||||
|
4_000,
|
||||||
|
);
|
||||||
|
drop(s5);
|
||||||
|
let b5 = data::load_once(&source(&d5, "", today)).unwrap();
|
||||||
|
assert_eq!(b5.kpis.monthly_burn, None);
|
||||||
|
for x in [d, d2, d3, d4, d5] {
|
||||||
let _ = std::fs::remove_dir_all(x);
|
let _ = std::fs::remove_dir_all(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user