refactor(mcp): the party_id, document_id and cash_account aliases are removed (P5)
Agent reason: one name for one thing. S4 and S6 kept the old spellings "until P5" so an agent that learned them did not break; P5 removes them, so the schema an agent reads has one parameter for each fact and a call cannot name the same thing twice with different answers. books.create_invoice takes customer and books.create_bill vendor (a record's id, its party's id or its name; required), no party_id. books.receive_payment and books.pay_bill take invoice or bill and deposit_to or paid_from, no document_id or cash_account; a payment names its document and its account or is refused saying which to pass. A number that is one record's id and another's name is still refused, never guessed (INVARIANT 6). The over-the-wire tests that used the old spellings now use the new (document_id becomes invoice or bill, cash_account becomes deposit_to or paid_from, party_id becomes customer or vendor given as the id's text); the one test that named the alias, party_id_alias_still_works, is now a_customer_by_id_and_by_name_is_one_record and checks the same two spellings of a customer, by id and by name, name one record. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
70a3f795f4
commit
a319a64c3a
13 files changed
+81
-135
No files matched your search
@@ -496,18 +496,18 @@ fn terms_fall_back_in_order() {
|
||||
assert_eq!(bill["terms"], "Net 10", "{bill}");
|
||||
}
|
||||
|
||||
/// `party_id` is the old spelling of `customer`/`vendor` and still names
|
||||
/// the same record (until P5); a number that is one record's id and
|
||||
/// A customer given by id and by name is the same record (the old
|
||||
/// `party_id` spelling is gone, P5); a number that is one record's id and
|
||||
/// another's name is refused, never guessed.
|
||||
#[test]
|
||||
fn party_id_alias_still_works() {
|
||||
fn a_customer_by_id_and_by_name_is_one_record() {
|
||||
let books = Books::new("documents-alias");
|
||||
let mut m = Mcp::spawn(&books);
|
||||
let harbor = m.customer("Harbor Coffee");
|
||||
let line = json!([{"description": "Work", "amount": "10.00"}]);
|
||||
let by_alias = m.call(
|
||||
let by_id = m.call(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": harbor, "date": "2026-02-01", "terms": "Net 30",
|
||||
json!({"customer": (harbor).to_string(), "date": "2026-02-01", "terms": "Net 30",
|
||||
"lines": line, "confirmed": true}),
|
||||
);
|
||||
let by_name = m.call(
|
||||
@@ -520,8 +520,8 @@ fn party_id_alias_still_works() {
|
||||
.iter()
|
||||
.map(|e| e["payload"]["customer_id"].as_u64().unwrap())
|
||||
.collect();
|
||||
assert_eq!(parties, [harbor, harbor], "one customer, two spellings");
|
||||
assert_eq!(by_alias["total"], by_name["total"]);
|
||||
assert_eq!(parties, [harbor, harbor], "one customer, an id and a name");
|
||||
assert_eq!(by_id["total"], by_name["total"]);
|
||||
|
||||
// A customer named "2" that is not customer 2: the number is
|
||||
// ambiguous, and is refused rather than guessed.
|
||||
@@ -730,7 +730,7 @@ fn mark_sent_records_who_and_how() {
|
||||
.unwrap();
|
||||
let invoice = common::answer_of(&wire.call(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
"lines": [{"description": "Design", "amount": "1200.00"}], "confirmed": true}),
|
||||
))
|
||||
.unwrap()["id"]
|
||||
@@ -876,7 +876,7 @@ mod paying_on_terms {
|
||||
ok(
|
||||
&mut self.wire,
|
||||
"books.create_invoice",
|
||||
json!({"party_id": self.customer, "date": date, "due_date": due,
|
||||
json!({"customer": (self.customer).to_string(), "date": date, "due_date": due,
|
||||
"lines": [{"description": "Consulting", "amount": amount}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -897,7 +897,7 @@ mod paying_on_terms {
|
||||
ok(
|
||||
&mut self.wire,
|
||||
"books.create_bill",
|
||||
json!({"party_id": self.vendor, "date": date, "due_date": due,
|
||||
json!({"vendor": (self.vendor).to_string(), "date": date, "due_date": due,
|
||||
"vendor_ref": format!("TH-{}", self.bills),
|
||||
"lines": [{"description": "Paper", "amount": amount, "account": "6999"}],
|
||||
"upload_id": file, "confirmed": true}),
|
||||
@@ -1258,7 +1258,7 @@ mod bad_debts {
|
||||
wire,
|
||||
"books.create_invoice",
|
||||
json!({
|
||||
"party_id": customer,
|
||||
"customer": (customer).to_string(),
|
||||
"date": "2026-01-05",
|
||||
"due_date": "2026-02-04",
|
||||
"lines": [{ "description": "Design", "amount": "100.00" }],
|
||||
@@ -1286,10 +1286,10 @@ mod bad_debts {
|
||||
&mut wire,
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true,
|
||||
"document_id": inv,
|
||||
"invoice": inv,
|
||||
"date": "2026-01-20",
|
||||
"amount": "40.00",
|
||||
"cash_account": "1000",
|
||||
"deposit_to": "1000",
|
||||
}),
|
||||
);
|
||||
// The write-off's evidence, uploaded as an agent uploads it (D-46).
|
||||
@@ -1361,10 +1361,10 @@ mod bad_debts {
|
||||
&mut wire,
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true,
|
||||
"document_id": inv,
|
||||
"invoice": inv,
|
||||
"date": "2026-03-02",
|
||||
"amount": "60.00",
|
||||
"cash_account": "1000",
|
||||
"deposit_to": "1000",
|
||||
}),
|
||||
);
|
||||
let doc = ok(
|
||||
|
||||
@@ -767,7 +767,7 @@ fn books_p2_served_cut_over_whole() {
|
||||
let invoice = a
|
||||
.call(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": 1, "date": "2026-01-05", "due_date": "2026-02-04",
|
||||
json!({"customer": (1).to_string(), "date": "2026-01-05", "due_date": "2026-02-04",
|
||||
"lines": [{"description": "Design", "amount": "400.00"}], "confirmed": true}),
|
||||
)
|
||||
.unwrap()["id"]
|
||||
@@ -789,7 +789,7 @@ fn books_p2_served_cut_over_whole() {
|
||||
let unpaid = a
|
||||
.call(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-01-10", "due_date": "2026-02-09",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-01-10", "due_date": "2026-02-09",
|
||||
"lines": [{"description": "Survey", "amount": "300.00"}], "confirmed": true}),
|
||||
)
|
||||
.unwrap()["id"]
|
||||
|
||||
@@ -1017,13 +1017,13 @@ fn inputs_that_once_panicked_are_refused_or_answered() {
|
||||
),
|
||||
(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": client, "date": "2026-05-01", "due_date": "2026-06-01",
|
||||
json!({"customer": (client).to_string(), "date": "2026-05-01", "due_date": "2026-06-01",
|
||||
"lines": [{"description": "a", "amount": MAX},
|
||||
{"description": "b", "amount": "1"}], "confirmed": true}),
|
||||
),
|
||||
(
|
||||
"books.create_bill",
|
||||
json!({"party_id": acme, "date": "2026-05-01", "due_date": "2026-06-01",
|
||||
json!({"vendor": (acme).to_string(), "date": "2026-05-01", "due_date": "2026-06-01",
|
||||
"vendor_ref": "H-1",
|
||||
"lines": [{"description": "a", "amount": MAX, "account": "6000"},
|
||||
{"description": "b", "amount": "1", "account": "6000"}],
|
||||
@@ -1031,7 +1031,7 @@ fn inputs_that_once_panicked_are_refused_or_answered() {
|
||||
),
|
||||
(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": client, "date": "2026-05-01", "due_date": "+262142-12-31",
|
||||
json!({"customer": (client).to_string(), "date": "2026-05-01", "due_date": "+262142-12-31",
|
||||
"lines": [{"description": "a", "amount": "1"}], "confirmed": true}),
|
||||
),
|
||||
(
|
||||
|
||||
@@ -274,7 +274,7 @@ fn invoiced_and_billed_project_figures_are_the_same_in_the_viewer_and_from_the_s
|
||||
let bill = server.tool("books.create_bill", bill_args);
|
||||
server.tool(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": inv["id"], "date": "2026-02-20", "amount": "1830.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "invoice": inv["id"], "date": "2026-02-20", "amount": "1830.00", "deposit_to": "1000"}),
|
||||
);
|
||||
let b = data::load_once(&Source {
|
||||
data_dir: data.clone(),
|
||||
|
||||
@@ -424,7 +424,7 @@ fn a_file_links_to_every_kind_of_subject() {
|
||||
let rent_invoice = m.upload(b"rent invoice", "rent.pdf", "application/pdf", "receipt");
|
||||
let bill = m.ok(
|
||||
"books.create_bill",
|
||||
json!({"party_id": vendor, "date": "2026-02-01", "due_date": "2026-02-28",
|
||||
json!({"vendor": (vendor).to_string(), "date": "2026-02-01", "due_date": "2026-02-28",
|
||||
"vendor_ref": "RENT-2",
|
||||
"lines": [{"description": "Rent", "amount": "300.00", "account": "6000"}],
|
||||
"upload_id": rent_invoice, "confirmed": true}),
|
||||
@@ -432,7 +432,7 @@ fn a_file_links_to_every_kind_of_subject() {
|
||||
.clone();
|
||||
let invoice = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
"lines": [{"description": "Work", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
|
||||
@@ -911,7 +911,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
// A/R and A/P.
|
||||
let inv = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
"lines": [{"description": "Consulting", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -919,7 +919,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
.unwrap();
|
||||
m.ok(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": inv, "date": "2026-02-10", "amount": "200.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "invoice": inv, "date": "2026-02-10", "amount": "200.00", "deposit_to": "1000"}),
|
||||
);
|
||||
let vendor_invoice = m.upload(
|
||||
b"vendor invoice",
|
||||
@@ -929,7 +929,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
);
|
||||
let bill = m.ok(
|
||||
"books.create_bill",
|
||||
json!({"party_id": vendor, "date": "2026-02-01", "due_date": "2026-02-28",
|
||||
json!({"vendor": (vendor).to_string(), "date": "2026-02-01", "due_date": "2026-02-28",
|
||||
"vendor_ref": "V-1001",
|
||||
"lines": [{"description": "Office rent", "amount": "300.00", "account": "6000"}],
|
||||
"upload_id": vendor_invoice, "confirmed": true}),
|
||||
@@ -938,7 +938,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
.unwrap();
|
||||
m.ok(
|
||||
"books.pay_bill",
|
||||
json!({"confirmed": true, "document_id": bill, "date": "2026-02-05", "amount": "300.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "bill": bill, "date": "2026-02-05", "amount": "300.00", "paid_from": "1000"}),
|
||||
);
|
||||
m.ok("books.ar_aging", json!({"as_of": "2026-06-30"}));
|
||||
m.ok("books.ap_aging", json!({"as_of": "2026-06-30"}));
|
||||
@@ -946,7 +946,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
// P4b S1: a document voided, and the control accounts' tie-out.
|
||||
let dup = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
"lines": [{"description": "Consulting, entered twice", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -972,7 +972,7 @@ fn happy_path(name: &str) -> Mcp {
|
||||
// P4b S7: a bad debt, its evidence uploaded and filed with it.
|
||||
let bad = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-03", "due_date": "2026-03-03",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-03", "due_date": "2026-03-03",
|
||||
"lines": [{"description": "Consulting, never paid", "amount": "400.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -1685,15 +1685,15 @@ fn run_op(m: &mut Mcp, k: &mut Known, op: &Op) {
|
||||
vendor_ref,
|
||||
} => (
|
||||
"books.create_bill",
|
||||
json!({"party_id": party.resolve(&k.vendors), "date": "2026-03-01",
|
||||
json!({"vendor": (party.resolve(&k.vendors)).to_string(), "date": "2026-03-01",
|
||||
"due_date": "2026-03-31", "vendor_ref": vendor_ref,
|
||||
"lines": [{"description": "thing", "amount": amount, "account": "6000"}],
|
||||
"existing_attachment_id": k.vendor_invoice, "confirmed": true}),
|
||||
),
|
||||
Op::PayBill { doc, amount } => (
|
||||
"books.pay_bill",
|
||||
json!({"confirmed": true, "document_id": doc.resolve(&k.bills), "date": "2026-03-15", "amount": amount,
|
||||
"cash_account": "1000"}),
|
||||
json!({"confirmed": true, "bill": doc.resolve(&k.bills), "date": "2026-03-15", "amount": amount,
|
||||
"paid_from": "1000"}),
|
||||
),
|
||||
Op::Payout { deposit } => (
|
||||
"books.record_payout",
|
||||
@@ -1834,7 +1834,7 @@ fn inv3_other_tools_refuse_ungrammatical_amounts() {
|
||||
);
|
||||
m.refuse(
|
||||
"books.create_bill",
|
||||
json!({"party_id": vendor, "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
json!({"vendor": (vendor).to_string(), "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
"lines": [{"description": "x", "amount": bad}]}),
|
||||
);
|
||||
m.refuse(
|
||||
@@ -2591,7 +2591,7 @@ fn assigned_roles_steer_invoices() {
|
||||
.unwrap();
|
||||
m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
"lines": [{"description": "Consulting", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
);
|
||||
@@ -2654,7 +2654,7 @@ fn documents_void_and_tie_out_over_the_wire() {
|
||||
);
|
||||
let inv = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
"lines": [{"description": "Consulting", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -2662,8 +2662,8 @@ fn documents_void_and_tie_out_over_the_wire() {
|
||||
.unwrap();
|
||||
let paid = m.ok(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": inv, "date": "2026-02-10", "amount": "200.00",
|
||||
"cash_account": "1000", "instrument": "Harbor checking", "reference": "tr_8812"}),
|
||||
json!({"confirmed": true, "invoice": inv, "date": "2026-02-10", "amount": "200.00",
|
||||
"deposit_to": "1000", "instrument": "Harbor checking", "reference": "tr_8812"}),
|
||||
);
|
||||
assert_eq!(paid["remaining"], "300.00", "{paid}");
|
||||
assert_eq!(paid["status"], "partial", "{paid}");
|
||||
@@ -2685,7 +2685,7 @@ fn documents_void_and_tie_out_over_the_wire() {
|
||||
|
||||
let dup = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
json!({"customer": (customer).to_string(), "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
"lines": [{"description": "Consulting, entered twice", "amount": "500.00"}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -2753,7 +2753,7 @@ fn documents_list_and_timeline_over_the_wire() {
|
||||
let invoice = |m: &mut Mcp, date: &str, due: &str, amount: &str| {
|
||||
m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": customer, "date": date, "due_date": due,
|
||||
json!({"customer": (customer).to_string(), "date": date, "due_date": due,
|
||||
"lines": [{"description": "Consulting", "amount": amount}],
|
||||
"confirmed": true}),
|
||||
)["id"]
|
||||
@@ -2764,7 +2764,7 @@ fn documents_list_and_timeline_over_the_wire() {
|
||||
let later = invoice(&mut m, "2026-02-05", "2026-04-30", "80.00");
|
||||
let pay = m.ok(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": late, "date": "2026-02-10", "amount": "200.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "invoice": late, "date": "2026-02-10", "amount": "200.00", "deposit_to": "1000"}),
|
||||
)["entry_id"]
|
||||
.as_u64()
|
||||
.unwrap();
|
||||
|
||||
@@ -835,15 +835,15 @@ fn party_totals_match_a_hand_computed_year() {
|
||||
);
|
||||
let bill = m.ok(
|
||||
"books.create_bill",
|
||||
json!({"party_id": v, "date": "2026-07-01", "due_date": "2026-07-31",
|
||||
json!({"vendor": (v).to_string(), "date": "2026-07-01", "due_date": "2026-07-31",
|
||||
"vendor_ref": "D-1041",
|
||||
"lines": [{"description": "Logo", "amount": "800.00", "account": "6000"}],
|
||||
"upload_id": logo_invoice, "confirmed": true}),
|
||||
);
|
||||
let pay = m.ok(
|
||||
"books.pay_bill",
|
||||
json!({"confirmed": true, "document_id": bill["id"], "date": "2026-07-15", "amount": "300.00",
|
||||
"cash_account": "1000"}),
|
||||
json!({"confirmed": true, "bill": bill["id"], "date": "2026-07-15", "amount": "300.00",
|
||||
"paid_from": "1000"}),
|
||||
)["entry_id"]
|
||||
.as_u64()
|
||||
.unwrap();
|
||||
@@ -917,14 +917,14 @@ fn party_totals_for_a_customer_a_member_and_a_prepaid() {
|
||||
.unwrap();
|
||||
let inv = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": c, "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
json!({"customer": (c).to_string(), "date": "2026-03-01", "due_date": "2026-03-31",
|
||||
"lines": [{"description": "Work", "amount": "1000.00"}],
|
||||
"confirmed": true}),
|
||||
);
|
||||
let pay = m.ok(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": inv["id"], "date": "2026-03-20", "amount": "600.00",
|
||||
"cash_account": "1000"}),
|
||||
json!({"confirmed": true, "invoice": inv["id"], "date": "2026-03-20", "amount": "600.00",
|
||||
"deposit_to": "1000"}),
|
||||
)["entry_id"]
|
||||
.as_u64()
|
||||
.unwrap();
|
||||
|
||||
@@ -1231,7 +1231,7 @@ fn invoice_and_bill_lines_count_toward_their_projects() {
|
||||
);
|
||||
let inv = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": cedar, "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
json!({"customer": (cedar).to_string(), "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
{"description": "Design", "amount": "3000.00", "class": "Zeta site"},
|
||||
{"description": "Hosting", "amount": "200.00", "class": harbor.to_string()},
|
||||
{"description": "Rush fee", "amount": "100.00"},
|
||||
@@ -1264,7 +1264,7 @@ fn invoice_and_bill_lines_count_toward_their_projects() {
|
||||
);
|
||||
let bill = m.ok(
|
||||
"books.create_bill",
|
||||
json!({"party_id": dana_vendor, "date": "2026-03-09", "due_date": "2026-04-08",
|
||||
json!({"vendor": (dana_vendor).to_string(), "date": "2026-03-09", "due_date": "2026-04-08",
|
||||
"vendor_ref": "DANA-77",
|
||||
"lines": [
|
||||
{"description": "Illustration", "amount": "1200.00", "account": "6000", "class": "Zeta site"},
|
||||
@@ -1284,11 +1284,11 @@ fn invoice_and_bill_lines_count_toward_their_projects() {
|
||||
// Payments are balance-sheet only: no project.
|
||||
let got = m.ok(
|
||||
"books.receive_payment",
|
||||
json!({"confirmed": true, "document_id": inv["id"], "date": "2026-03-20", "amount": "3800.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "invoice": inv["id"], "date": "2026-03-20", "amount": "3800.00", "deposit_to": "1000"}),
|
||||
);
|
||||
let paid = m.ok(
|
||||
"books.pay_bill",
|
||||
json!({"confirmed": true, "document_id": bill["id"], "date": "2026-03-30", "amount": "1250.00", "cash_account": "1000"}),
|
||||
json!({"confirmed": true, "bill": bill["id"], "date": "2026-03-30", "amount": "1250.00", "paid_from": "1000"}),
|
||||
);
|
||||
for e in [&got["entry_id"], &paid["entry_id"]] {
|
||||
let e = e.as_u64().unwrap();
|
||||
@@ -1356,7 +1356,7 @@ fn a_document_naming_an_unknown_project_is_refused_whole() {
|
||||
for (tool, party) in [("books.create_invoice", &cedar), ("books.create_bill", &v)] {
|
||||
let why = m.refuse(
|
||||
tool,
|
||||
json!({"party_id": party, "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
json!({"customer": (party).to_string(), "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
{"description": "a", "amount": "10.00", "class": "Zeta site"},
|
||||
{"description": "b", "amount": "10.00", "class": "Nowhere"},
|
||||
]}),
|
||||
@@ -1379,7 +1379,7 @@ fn a_document_for_a_finished_project_says_so() {
|
||||
let cedar = m.ok("books.add_customer", json!({"name": "Cedar"}))["id"].clone();
|
||||
let out = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": cedar, "date": "2026-10-05", "due_date": "2026-11-04", "lines": [
|
||||
json!({"customer": (cedar).to_string(), "date": "2026-10-05", "due_date": "2026-11-04", "lines": [
|
||||
{"description": "Final", "amount": "10.00", "class": "Harbor"},
|
||||
{"description": "Again", "amount": "10.00", "class": "harbor"},
|
||||
{"description": "Old", "amount": "10.00", "class": "Dock"},
|
||||
@@ -1424,7 +1424,7 @@ fn an_invoice_for_an_on_spec_project_asks_about_an_agreement() {
|
||||
let v = m.ok("books.add_vendor", json!({"name": "Dana"}))["id"].clone();
|
||||
let out = m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": cedar, "date": "2026-10-05", "due_date": "2026-11-04", "lines": [
|
||||
json!({"customer": (cedar).to_string(), "date": "2026-10-05", "due_date": "2026-11-04", "lines": [
|
||||
{"description": "Build", "amount": "10.00", "class": "Kestrel"},
|
||||
{"description": "More", "amount": "5.00", "class": "kestrel"},
|
||||
{"description": "Site", "amount": "7.00", "class": "Zeta"},
|
||||
@@ -1450,7 +1450,7 @@ fn an_invoice_for_an_on_spec_project_asks_about_an_agreement() {
|
||||
);
|
||||
let bill = m.ok(
|
||||
"books.create_bill",
|
||||
json!({"party_id": v, "date": "2026-10-05", "due_date": "2026-11-04",
|
||||
json!({"vendor": (v).to_string(), "date": "2026-10-05", "due_date": "2026-11-04",
|
||||
"vendor_ref": "V-512",
|
||||
"lines": [
|
||||
{"description": "Icons", "amount": "10.00", "account": "6000", "class": "Kestrel"},
|
||||
@@ -1475,7 +1475,7 @@ fn books_without_the_feature_refuse_a_tagged_document() {
|
||||
for (tool, party) in [("books.create_invoice", &cedar), ("books.create_bill", &v)] {
|
||||
let why = m.refuse(
|
||||
tool,
|
||||
json!({"party_id": party, "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
json!({"customer": (party).to_string(), "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
{"description": "a", "amount": "10.00", "class": "Zeta site"},
|
||||
]}),
|
||||
);
|
||||
@@ -1487,7 +1487,7 @@ fn books_without_the_feature_refuse_a_tagged_document() {
|
||||
assert_eq!(m.journal(), head, "nothing journaled");
|
||||
m.ok(
|
||||
"books.create_invoice",
|
||||
json!({"party_id": cedar, "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
json!({"customer": (cedar).to_string(), "date": "2026-03-02", "due_date": "2026-04-01", "lines": [
|
||||
{"description": "a", "amount": "10.00"},
|
||||
], "confirmed": true}),
|
||||
);
|
||||
|
||||
@@ -278,7 +278,7 @@ fn require_tax_category_refuses_defect_8() {
|
||||
);
|
||||
let bill = m.call(
|
||||
"books.create_bill",
|
||||
json!({"party_id": vendor["id"], "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
json!({"vendor": (vendor["id"]).to_string(), "date": "2026-02-01", "due_date": "2026-03-01",
|
||||
"vendor_ref": "CH-1",
|
||||
"lines": [{"description": "hosting", "amount": "42.00", "account": "6150"}],
|
||||
"upload_id": first_invoice, "confirmed": true}),
|
||||
@@ -303,7 +303,7 @@ fn require_tax_category_refuses_defect_8() {
|
||||
);
|
||||
let again = m.call(
|
||||
"books.create_bill",
|
||||
json!({"party_id": vendor["id"], "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
json!({"vendor": (vendor["id"]).to_string(), "date": "2026-02-02", "due_date": "2026-03-02",
|
||||
"vendor_ref": "CH-2",
|
||||
"lines": [{"description": "hosting", "amount": "1.00", "account": "6150"}],
|
||||
"upload_id": second_invoice, "confirmed": true}),
|
||||
|
||||
Reference in new issue
Block a user