P3: the IIF in plain ASCII with every change listed, and the CPA package as of one day (defects 7, 21)
The CPA package's general-journal.iif now holds every posted entry through as_of (closing entries left out, D-36), written as plain ASCII with CR LF, DOCNUM the entry id, QuickBooks Desktop's field limits and subaccount types honoured, and every character written differently listed in the export's warnings and the README (grouped by substitution, TINs masked). The 1099 worksheet stops at as_of too. PDFs print CJK, Arabic, Hebrew, Thai and Devanagari (Noto fallbacks, OFL), and so does the viewer. has_full_tin reads Unicode separators. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
48 files changed
+5661
-317
No files matched your search
+59
-9
@@ -1131,7 +1131,8 @@ posting.
|
||||
## Tools — export
|
||||
|
||||
- `books.export { format, report, start?, end?, as_of?, cash_accounts?,
|
||||
financing_accounts?, investing_accounts? }` → `{ content, content_encoding? }`.
|
||||
financing_accounts?, investing_accounts? }` → `{ content,
|
||||
content_encoding?, warnings? }`.
|
||||
- Reports: `profit_and_loss`, `balance_sheet`, `cash_flow` (needs
|
||||
`cash_accounts`), `trial_balance`, `members_equity` (statement of
|
||||
changes in members' equity; members from `wanderbooks.toml`; earnings
|
||||
@@ -1142,11 +1143,40 @@ posting.
|
||||
balance and split, ending balance), `general_journal` (alias
|
||||
`journal`: every entry, line by line, in date order).
|
||||
- Formats: `pdf` and `xlsx` (base64) for the five statements; `xlsx`,
|
||||
`csv`, `json` for every report; `iif` for the journal (QuickBooks
|
||||
Desktop).
|
||||
`csv`, `json` for every report; `iif` for `general_journal` (alias
|
||||
`journal`), for QuickBooks Desktop.
|
||||
- Dates: period reports take `start` (default: first entry) and `end`
|
||||
(default: today, local time); `balance_sheet` and `trial_balance`
|
||||
take `as_of`.
|
||||
(default: today, local time); `balance_sheet`, `trial_balance`,
|
||||
`fixed_asset_register` and `iif` take `as_of` (default today).
|
||||
- IIF (`docs/spec/rules.md` B-34; plan D-36): plain ASCII text, every
|
||||
line ending CR LF, inline (no `content_encoding`): every posted entry
|
||||
from the first through `as_of`, period-closing entries left out
|
||||
(QuickBooks keeps none; imported, a close would zero its period's
|
||||
profit), each transaction's DOCNUM its entry id; its BANK accounts are
|
||||
`cash_accounts`, else the settings'. `start` or `end` is refused: the
|
||||
file is cumulative, so QuickBooks' balances match the books'. A
|
||||
character past ASCII is transliterated ("René" "Rene", "北京" "Bei
|
||||
Jing", "—" "--"), a double quote is a single one (QuickBooks reads it
|
||||
as a text delimiter), a tab or line break is a space, a control
|
||||
character '?'. Within QuickBooks Desktop's limits (Intuit): an account
|
||||
name level past 31 characters is cut there; accounts whose names would
|
||||
then match get " (code)" (QuickBooks would merge them); a subaccount
|
||||
whose QuickBooks type differs from its parent's is written at the top
|
||||
level (QuickBooks gives a subaccount its parent's type); each parent
|
||||
is declared before its subaccounts; an account number past 7
|
||||
characters, or written like another's, is left out of ACCNUM; a memo
|
||||
past 4,095 characters is cut. No line names a customer or vendor (no
|
||||
NAME column; see the package's README). `warnings` (absent when
|
||||
there are none) says what the file writes differently from the books,
|
||||
for the human: each account's name, number and place a line (`account 6010's
|
||||
name "Café meals" is written "Cafe meals"`, `account number
|
||||
"12345678" is left out: QuickBooks Desktop holds 7 characters at
|
||||
most`); the memos grouped, each thing written differently once with
|
||||
every entry it is in (`"—" is written "--" in the memos of entries 3,
|
||||
5, 9`; a run of changed characters is one thing), then the memos cut,
|
||||
so a hundred memos with an em dash make one line. No line holds a full
|
||||
TIN: a run of nine digits, or every numeral of a text holding one in
|
||||
another script, is masked `•`.
|
||||
- Presentation (PDF and XLSX alike, QuickBooks-style): centered company,
|
||||
title, and period; a column-header row; "$" on subtotals and totals;
|
||||
negatives in parentheses with decimal points aligned; a rule above every
|
||||
@@ -1414,8 +1444,25 @@ entries.
|
||||
|
||||
- `books.export_cpa_package { as_of?, cash_accounts?, financing_accounts?,
|
||||
investing_accounts?, include_receipts?, include_tins? }` → `{ file,
|
||||
tins_included, tin_gaps, note }`: the zip, `cpa-package-<as_of>.zip`,
|
||||
handed over as `file` (a `HandedFile`, "Tools — the TIN vault").
|
||||
tins_included, tin_gaps, warnings?, note }`: the zip,
|
||||
`cpa-package-<as_of>.zip`, handed over as `file` (a `HandedFile`,
|
||||
"Tools — the TIN vault").
|
||||
**As of one day** (`docs/spec/rules.md` B-33): nothing in it reflects
|
||||
anything dated after `as_of` (default today): no figure, entry,
|
||||
receipt or worksheet row; the chart and `documents/` are as they stand.
|
||||
One list of cash accounts and one of financing accounts serve the
|
||||
whole package: the request's, else the settings'.
|
||||
**QuickBooks file** (`general-journal.iif`, B-34): as `books.export`
|
||||
iif makes it, through `as_of`; `warnings` says what it writes
|
||||
differently from the books, in the same lines as `books.export` iif's
|
||||
(account names and numbers one each, the memos grouped; every other
|
||||
file keeps the books' text), the README lists the same lines (and
|
||||
names the entries with a line on accounts receivable or payable, to
|
||||
which QuickBooks Desktop may ask the CPA to add a customer or vendor),
|
||||
and `note` ends "N account name(s), number(s), place(s) or memo(s)
|
||||
are written differently in general-journal.iif to fit QuickBooks
|
||||
Desktop (warnings says how; so does the README): tell the human.", N
|
||||
counting each name, number, place and memo.
|
||||
**Receipts** (`include_receipts`, default true): `receipts/` holds every
|
||||
current file behind each posted entry of the fiscal year to date, filed
|
||||
on it or linked to it (`books.link_attachment`; a linked file counts as
|
||||
@@ -1453,8 +1500,11 @@ entries.
|
||||
party is the party with the member's name (not a display name) and the
|
||||
member role, as the viewer's capital statement finds it; with none, the
|
||||
member's TIN is a gap.
|
||||
**1099 worksheet** with TINs adds `party_id, tin_last4, tin, tin_type,
|
||||
tin_note`. A zip with the full set, each
|
||||
**1099 worksheet** (`1099-worksheet-<year>.csv`, `as_of`'s calendar
|
||||
year): the payments from January 1 through `as_of` (the year to date;
|
||||
the whole year for a December 31 package; DECISION D-36), and the
|
||||
README says which. With TINs it adds `party_id, tin_last4, tin,
|
||||
tin_type, tin_note`. A zip with the full set, each
|
||||
statement as PDF and XLSX: `profit-and-loss`, `balance-sheet`,
|
||||
`cash-flow` (reconciled to `cash_accounts`), `members-equity`
|
||||
(multi-member LLCs), `trial-balance`; plus `general-ledger.xlsx` and
|
||||
|
||||
+175
-2
@@ -490,7 +490,8 @@ years after 2026, indexed to inflation and rounded to the nearest $100
|
||||
Attorneys' gross proceeds stay at $600 (not modeled).
|
||||
|
||||
What counts as paid: payments made in the calendar year (§6041(a)), so a
|
||||
prepayment counts when made. The engine counts credits minus debits to the
|
||||
prepayment counts when made. A worksheet as of a day (the CPA package's,
|
||||
B-33) counts the year's payments from January 1 through that day. The engine counts credits minus debits to the
|
||||
payment sources on a vendor's tagged entries: `[books] cash_accounts` and
|
||||
`financing_accounts` (a member or lender paying on the company's behalf;
|
||||
the company is still the payer). A card charge leaves neither (1099-K); a
|
||||
@@ -680,7 +681,12 @@ with `include_tins` (DECISION, the owner, 2026-10-15: for the CPA, when
|
||||
asked): a refusal that quotes its input masks any TIN in it
|
||||
(`parties::redact_full_tins`, checked by `refusals_never_echo_a_tin`),
|
||||
and a party text field refuses nine digits however they are separated
|
||||
(space, hyphen, dot, slash, underscore; `has_full_tin`). Files holding one (`books.get_w9`, `books.vendor_1099`'s
|
||||
(`has_full_tin`: up to three spaces, hyphens, dots, slashes or
|
||||
underscores between neighbors, in any script's digits; past ASCII every
|
||||
Unicode space and dash and the fullwidth and small forms count, and
|
||||
invisible characters such as a zero-width space or a right-to-left mark
|
||||
don't count toward the three: `sources/unicode-tin-text.md`, Unicode
|
||||
17.0). Files holding one (`books.get_w9`, `books.vendor_1099`'s
|
||||
`csv` with `include_tins`, and the CPA package, whose K-1 and 1099
|
||||
worksheets carry every member's and payee's TIN by default) are never
|
||||
written to a path: no tool takes one (D-29, P2 slice 6). Each is handed
|
||||
@@ -1015,3 +1021,170 @@ checked to change no figure or entry; `approval_rules_off_by_default`,
|
||||
(`exports_round_trip`) and codec unit tests; `ledger-mcp`
|
||||
`tests/spec_kept.rs`; Lean `Step.record_changes_no_figure`,
|
||||
`Reachable.records`; fuzz `fuzz_settings_replay`.
|
||||
|
||||
## B-33 A package as of a day shows the books through that day
|
||||
|
||||
**Status:** CONVENTION (a report as of a day reports the books on that
|
||||
day: balances through it, a period's activity from the period's start
|
||||
through it; nearest authorities the accounting period, IRS Pub. 538,
|
||||
`sources/irs-periods-and-methods.md`, and the information returns'
|
||||
calendar year, `sources/irs-1099-thresholds.md`); DECISION (owner,
|
||||
2026-10-20, plan D-36: the 1099 worksheet stops at as_of too)
|
||||
|
||||
Nothing in the CPA package made as of a day (`books.export_cpa_package`,
|
||||
the viewer's Export for CPA) reflects anything dated after it: no figure,
|
||||
entry, receipt or worksheet row. The statements and the ledgers cover
|
||||
the fiscal year containing as_of, through it; the balance sheet, the
|
||||
trial balance and the fixed asset register are as of it (the register
|
||||
only when an asset was bought by then); receipts/ holds the evidence of
|
||||
the year's entries through it; the members' equity statement and the
|
||||
K-1 worksheet, the year to date; general-journal.iif, every posted entry
|
||||
from the first through it (B-34). The 1099 worksheet counts the payments
|
||||
of as_of's calendar year from January 1 through as_of: information
|
||||
returns add up what is paid "in any calendar year" (26 U.S.C. §6041(a);
|
||||
"during such calendar year", §6041A(a)(2)), so a worksheet as of June 30
|
||||
is the year to date, and a vendor not yet at the threshold is not yet
|
||||
reportable; a December 31 package counts the whole year, as before. The
|
||||
chart of accounts and documents/ are as they stand when the package is
|
||||
made. One list of cash accounts and one of financing accounts serve the
|
||||
whole package (the request's, else the settings'): the cash flow, the
|
||||
K-1 worksheet, the IIF's bank accounts and the 1099 payments read the
|
||||
same.
|
||||
|
||||
**Enforced:** `ledger_package::build_package` (INVARIANTS 1, 6, 7),
|
||||
`ledger_package::export_iif`, `ledger_package::vendor_1099_report` and
|
||||
`ledger_core::vendor_1099_report_with_members` (`through`).
|
||||
**Checked:** `ledger-package` `tests/package.rs`
|
||||
(`every_file_in_an_as_of_package_stops_at_as_of`: books the same through
|
||||
as_of, with and without activity after it (a 1099 payment with its
|
||||
receipt, an asset bought, a reversal of an entry dated as_of, the
|
||||
members' contributions, an earlier asset sold), make the same package
|
||||
byte for byte, every file and which files there are, with and without a
|
||||
fixed asset register, mid-year and at year end; `as_of_package_iif_stops_at_as_of`,
|
||||
`the_iif_through_as_of_at_its_edges`,
|
||||
`the_1099_worksheet_stops_at_as_of`,
|
||||
`one_list_of_cash_accounts_per_package`; the property
|
||||
`iif_ties_to_the_trial_balance_as_of`, 2,000 cases); `ledger-mcp`
|
||||
`oracle_mcp.rs` (`cpa_package_holds_the_year_and_its_evidence`); the
|
||||
bookspec examples `bookspec/examples/as-of-package-stops-at-as-of.toml`
|
||||
and `bookspec/examples/1099-worksheet-through-as-of.toml`.
|
||||
|
||||
## B-34 The QuickBooks Desktop file (IIF): plain ASCII, every entry through as_of, closes left out
|
||||
|
||||
**Status:** AUTHORITY (Intuit, `sources/intuit-iif.md`: IIF files are
|
||||
ASCII text, tab-separated, with no escape; an account is known by its
|
||||
NAME, a subaccount's NAME its path joined by colons; lists come before
|
||||
what uses them; DOCNUM is "the transaction's number"; the kit's 2007+
|
||||
example file ends every line CR LF; QuickBooks Desktop holds an account
|
||||
name of 31 characters, an account number of 7 and a memo of 4,095; "The
|
||||
parent and subaccount must be the same account type"; a journal entry
|
||||
to accounts receivable or payable needs a customer or vendor, and takes
|
||||
one such account a transaction); CONVENTION (a QuickBooks integrator and
|
||||
an IIF importer, same file: a longer name is cut on a chart import but not
|
||||
in a journal's lines; a double quote is a text delimiter); DECISION (owner, 2026-10-20, plan D-36: plain ASCII, what isn't
|
||||
ASCII transliterated and listed; CR LF; DOCNUM the entry's id; closing
|
||||
entries left out; every entry since the company began until the CPA
|
||||
says otherwise); Unicode Standard Annex #14 (the mandatory line breaks)
|
||||
|
||||
1. **One transaction per posted entry dated on or before as_of**, from
|
||||
the first, in the order posted, **except period-closing entries**:
|
||||
QuickBooks keeps no closing entries (it works out retained earnings
|
||||
itself; its "closing date" only locks a period), so an imported close
|
||||
would zero its period's profit. The file's balances are the trial
|
||||
balance as of as_of without the closes, and its income and expenses
|
||||
each period's profit and loss; the members' shares are in the
|
||||
package's members' equity statement and K-1 worksheet.
|
||||
`books.export` iif takes as_of (default today), never a range.
|
||||
Whether the file should hold only the fiscal year instead goes to the
|
||||
CPA before the 2027 package (D-36); for the first year the two are
|
||||
the same.
|
||||
2. **DOCNUM is the entry's id** in the books, on the TRNS and every SPL,
|
||||
so the CPA can trace a QuickBooks transaction to its entry and its
|
||||
receipts.
|
||||
3. **The file is ASCII and every line ends CR LF.** In a field (a NAME,
|
||||
an ACCNUM, a MEMO) a tab or a mandatory line break (LF, VT, FF, CR,
|
||||
NEL, U+2028, U+2029) is a space; any other control character is '?';
|
||||
printable ASCII is itself, but a double quote, which is a single one
|
||||
(QuickBooks reads a double quote as a text delimiter); any other
|
||||
character is its transliteration by deunicode 1.6.0, pinned exactly
|
||||
("René" "Rene", "北京" "Bei Jing", "—" "--", "“" "'", "😀" "grinning";
|
||||
a transliterated word's trailing space dropped at the end or before a
|
||||
space), or '?' when it has none. Every other file in the package keeps
|
||||
the books' text (the PDFs carry Inter and Noto fallbacks for Chinese,
|
||||
Japanese, Korean, Arabic, Hebrew, Thai and Devanagari, Arabic and
|
||||
Hebrew set right to left; no emoji font, so an emoji prints as an
|
||||
empty box).
|
||||
4. **An account's own name**, so written, has each ':' replaced by '-'
|
||||
(a fullwidth colon too), is trimmed ('?' if nothing is left) and cut
|
||||
to 31 characters (QuickBooks Desktop's limit; cut by QuickBooks, the
|
||||
ACCNT line and the transactions' would no longer match); its NAME is
|
||||
its parents' NAMEs and its own, joined by ':'. A subaccount whose
|
||||
QuickBooks type differs from its parent's (a bank account under a
|
||||
header that is no bank, an asset's cost under a "Fixed assets" header)
|
||||
is written at the top level, its own subaccounts with it: QuickBooks
|
||||
gives a subaccount its parent's type, and the type decides where its
|
||||
balance shows. Each parent is declared before its subaccounts, the
|
||||
accounts otherwise in the order of their codes. Accounts whose NAMEs
|
||||
would match ignoring case, which QuickBooks would merge, get
|
||||
" (code)" after their own names (the name cut to make room, the code
|
||||
written like a name, "no number" for a blank one), level by level from
|
||||
the top and again until no two match; a match left after that (two
|
||||
codes written alike, ignoring case, or alike in their first 30
|
||||
characters) is refused.
|
||||
5. **ACCNUM is the account's code**, written as a field and trimmed, or
|
||||
left blank (ACCNUM is optional; the NAME identifies the account) when
|
||||
it is longer than 7 characters (QuickBooks Desktop's limit) or another
|
||||
account's would be written the same, ignoring case. **A MEMO** is cut
|
||||
to 4,095 characters (QuickBooks Desktop's limit).
|
||||
6. **Nothing changes silently.** Each account name, number or place and
|
||||
each memo the file writes differently from the books (`Iif::changes`)
|
||||
is said, both texts quoted and escaped, one line each, in the
|
||||
`warnings` of `books.export` and `books.export_cpa_package` and in the
|
||||
package README (the viewer's note counts them): each account's name,
|
||||
number and place a line; the memos grouped by what is written
|
||||
differently, each run of changed characters once with every entry it
|
||||
is in (`"—" is written "--" in the memos of entries 3, 5, 9`), then
|
||||
the memos cut. No line holds a full TIN (B-26): a run of nine digits,
|
||||
in any script's digits and separators, is masked, and so is every
|
||||
numeral of a text that holds one once written as a field (digits a
|
||||
tab apart, letters deunicode writes as digits); a memo line whose
|
||||
digits are masked says so.
|
||||
7. **No customer or vendor NAME.** Intuit's IIF help makes NAME
|
||||
optional and states no need of it in a journal; QuickBooks Desktop
|
||||
asks for a customer or vendor on a journal entry to accounts
|
||||
receivable or payable, and takes one A/R or A/P account a transaction
|
||||
(Intuit staff and help, `sources/intuit-iif.md`). Writing names would
|
||||
need the customer and vendor lists declared as well, with names unique
|
||||
across them. So the file names none, and the package README names the
|
||||
entries with a line on an A/R or A/P account (`Iif::receivable_payable`),
|
||||
so the CPA can add the name if QuickBooks asks.
|
||||
|
||||
**Enforced:** `ledger_import::iif` (`field`, `iif_accounts`,
|
||||
`journal_to_iif`, `Iif::warnings`), `ledger_package::export_iif` and
|
||||
`build_package`, `ledger-mcp` `books.export` and
|
||||
`books.export_cpa_package`.
|
||||
**Checked:** `ledger-import` `iif.rs` unit tests (every one of the
|
||||
1,112,064 Unicode scalar values written as printable ASCII, alone and
|
||||
beside a letter, and kept by a second pass; the transliteration table
|
||||
pinned); `tests/spec_import.rs` (`iif_docnum_is_the_entry_id`,
|
||||
`iif_writes_plain_ascii_and_lists_every_change`,
|
||||
`iif_every_line_ends_cr_lf`, `iif_distinct_accounts_never_share_a_name`,
|
||||
`iif_a_subaccount_of_another_type_stands_at_the_top_level`,
|
||||
`iif_declares_each_parent_before_its_subaccounts`,
|
||||
`iif_fits_quickbooks_desktop_limits`,
|
||||
`iif_warnings_group_the_memos_by_what_is_written_differently`,
|
||||
`iif_warnings_never_hold_a_tin`,
|
||||
`iif_change_warnings_are_one_line_each`,
|
||||
`iif_keeps_a_tin_readable_to_the_package_scan`, the properties
|
||||
`iif_round_trips_random_books` and
|
||||
`iif_names_never_clash_and_every_change_is_listed`); `ledger-package`
|
||||
`tests/package.rs` (`iif_leaves_out_period_closes`,
|
||||
`the_readme_lists_what_the_iif_writes_differently`,
|
||||
`the_readme_names_the_entries_on_receivables_and_payables`,
|
||||
`the_bookspec_iif_example_matches_the_engine`, and B-33's); the bookspec
|
||||
example `bookspec/examples/iif-quickbooks-journal-file.toml` (formats
|
||||
appendix: the file line by line and its changes, derived by hand);
|
||||
`ledger-mcp` `oracle_mcp.rs`
|
||||
(`iif_declares_accounts_by_role_and_balances_every_transaction`,
|
||||
`iif_without_as_of_is_as_of_today_and_ties_to_the_trial_balance`),
|
||||
`mcp_stdio.rs` (`mcp_import_export_over_stdio`).
|
||||
@@ -107,12 +107,84 @@ SHA-256 of the retrieved file (`journal.zip`): `4f578d227810f5bfadde142cdab9f941
|
||||
|
||||
Cited (not quoted): its read-me says list declarations (accounts, classes, customers, vendors, other names) come first so names land on the correct lists, and that header columns must be present even when left blank. Its `!ACCNT` rows show a subaccount written `Construction:Labor`. Its address fields that contain a comma are wrapped in double quotes (`"Anywhere, AZ 85740"`), as a spreadsheet writes tab-delimited text; the kit does not say whether QuickBooks strips those quotes.
|
||||
|
||||
## Character limitations for fields in QuickBooks (US, updated 8/3/2026)
|
||||
Source: <https://quickbooks.intuit.com/learn-support/en-us/help-article/printing-preferences/character-limitations-fields-quickbooks/L7eIy5gE3_US_en_US>
|
||||
Retrieved: 2026-10-20
|
||||
SHA-256: not available (read through a fetch tool; a direct download was refused by the server)
|
||||
|
||||
Tagged for QuickBooks Desktop (Mac Plus, Premier Plus, Pro Plus). Its one sentence of text:
|
||||
|
||||
> Each field in your company data file has a maximum number of characters that can be entered.
|
||||
|
||||
Cited (not quoted), from its table: Account Name 31; Account Numbers 7; Memo 4,095 (of which printed checks show about 30 to 60 and the Transaction Detail report 96); invoice number 11; customer, vendor and other names 41. It has no row for a journal entry's number, and says nothing of what QuickBooks does with longer text, on import or otherwise.
|
||||
|
||||
The same article for the UK (`.../en-uk/help-article/printing-preferences/character-limitations-fields-quickbooks/L7eIy5gE3_GB_en_GB`, retrieved 2026-10-20) gives Account Name 31 but Account Numbers 25: a different product. The books are a US company's, so the US figures hold.
|
||||
|
||||
## Intuit's .NET SDK reference: `Account.Name`
|
||||
Source: <https://static.developer.intuit.com/sdkdocs/qbv3doc/ippdotnetdevkitv3/html/cd41295e-8e12-8b96-1ff3-728a807fa9cd.htm>
|
||||
Retrieved: 2026-10-20
|
||||
|
||||
Cited (not quoted): "User recognizable name for the Account", with ValidRange "QBW: Max=31" (QuickBooks Desktop; QuickBooks Online: 100). Its `Account.AcctNum` page (`.../95a0835b-80bd-4fe1-2d7f-96ea2c372442.htm`) states no length.
|
||||
|
||||
So the limits are Intuit's own: an account name (one level of a subaccount's NAME, as the account's own name is entered) at most 31 characters, an account number at most 7, a memo at most 4,095. The books write each within them: a longer level is cut to 31 (then no two NAMEs may match), a longer number is left out of ACCNUM (it is optional; the NAME identifies the account), a longer memo is cut to 4,095, and every one is listed (rules.md B-34).
|
||||
|
||||
## Add, edit, or delete accounts in QuickBooks Desktop (US, updated 8/4/2026)
|
||||
Source: <https://quickbooks.intuit.com/learn-support/en-us/help-article/chart-accounts/add-edit-delete-accounts-quickbooks-desktop-mac/L95VT34uN_US_en_US>
|
||||
Retrieved: 2026-10-20
|
||||
SHA-256: not available (read through a fetch tool)
|
||||
|
||||
Tagged for QuickBooks Desktop (Mac Plus, Premier Plus, Pro Plus, Accountant, Enterprise). Under "Add a subaccount", a note:
|
||||
|
||||
> The parent and subaccount must be the same account type.
|
||||
|
||||
So the books write a subaccount whose QuickBooks type differs from its parent's (a bank account under a header that is no bank, an asset's cost account under a "Fixed assets" header) at the top level, its own subaccounts with it, and list it (rules.md B-34). Intuit's own journal sample (`journal.zip`, above) declares `Construction:Labor` without ever declaring `Construction`, so QuickBooks makes a missing parent itself; the books declare each parent before its subaccounts all the same, so a parent keeps its own type and number rather than taking ones QuickBooks guesses.
|
||||
|
||||
## Customer and vendor names on accounts receivable and payable
|
||||
|
||||
Searched 2026-10-20. What Intuit says:
|
||||
|
||||
- The IIF Import Kit's header help (`!TRNS.htm`, `!SPL.htm`, above) marks TRNSTYPE, ACCNT and AMOUNT required; NAME is "the name of the customer, vendor, payee, or employee", not marked required, with no word on accounts receivable or payable. The kit's General Journal example and the journal sample have no NAME column at all.
|
||||
- The journal sample's read-me (`journal.zip`, `General Journal IIF file read me.txt`, SHA-256 `2e45b0f7a15d78f487d510547084d401d99bda02630d10747e37e00ca56f2c52`): "A customer name attached to the spl line of a General Journal transaction will import to the vendor list and the vendor name attached to the trns line of a General Journal transaction will import to the other names list unless the names are already on the correct lists." So a NAME written without declaring the customer and vendor lists first lands on the wrong list.
|
||||
- Intuit's QuickBooks Team, answering "Can I post a journal entry to Accounts Receivable without specifying a customer name?" (Maybelle_S, QuickBooks Team badge, 12 January 2024), <https://quickbooks.intuit.com/community/reports-and-accounting-5/can-i-post-a-journal-entry-to-accounts-receivable-without-specifying-a-customer-name-64395> (retrieved 2026-10-20), about QuickBooks Desktop:
|
||||
|
||||
> Accounts Receivable (AR) or Accounts Payable (AP) requires a customer or vendor name assignment.
|
||||
|
||||
- "Troubleshoot ... Warning: You Cannot Use More Than One" (US, updated 8/5/2026; QuickBooks Desktop Mac Plus, Premier Plus, Pro Plus), <https://quickbooks.intuit.com/learn-support/en-us/help-article/accounts-receivable/warning-cannot-use-one-ar-ap-account-transaction/L7xqDWcmE_US_en_US> (retrieved 2026-10-20): QuickBooks will not record a transaction with two A/R accounts, two A/P accounts, or one of each; its message:
|
||||
|
||||
> Warning: You cannot use more than one A/R or A/P account in the same transaction.
|
||||
|
||||
Not Intuit, for the record: a third-party IIF vendor answering on Intuit's community (BigRedConsulting, 14 April 2020, <https://quickbooks.intuit.com/learn-support/en-us/other-questions/iif-import-error-3040/00/535675>) wrote that "a NAME is required for any AR row", about a bill, not a journal; QuickBooks Desktop sync tools quote the refusal "Transaction split lines to accounts receivable must include a customer on that split line" (Acctivate, <https://hub.acctivate.com/articles/troubleshoot/synchronization/transaction-split-lines-to-accounts-receivable-must-include-a-customer-on-that-split-line>).
|
||||
|
||||
No Intuit source says what an IIF journal import does with an A/R or A/P line that has no NAME (refuses it, imports it, or asks). So the books write no NAME (writing names would need the customer and vendor lists declared too, with a name unique across them) and the package README names the entries with an A/R or A/P line, so the CPA can add the name in QuickBooks if it asks (rules.md B-34 rule 7).
|
||||
|
||||
## What QuickBooks does with an over-long name (not Intuit)
|
||||
Source: Thomson Reuters, Accounting CS help, "Export payroll journal entries", <https://thomsonreuters.com/en-us/help/accounting-cs/integrate-data-with-other-applications/export-payroll-journal-entries>
|
||||
Retrieved: 2026-10-20
|
||||
|
||||
Cited (not quoted), a QuickBooks integrator's documentation, not Intuit's: QuickBooks limits an account's name to 31 characters; importing a chart of accounts IIF file cuts a longer name to 31, but importing a journal IIF file does not, so the journal's accounts no longer match and QuickBooks creates a new (duplicate) bank account for each it doesn't recognize. It advises names of 31 characters or fewer. This is why the books cut each level themselves: the ACCNT line and every TRNS and SPL line then carry the same name.
|
||||
|
||||
## Double quotes in an IIF field (not Intuit)
|
||||
Intuit's own journal sample (above) wraps fields holding a comma in double quotes, as a spreadsheet writes tab-delimited text, so QuickBooks' reader treats a double quote as more than a character. Two non-Intuit sources say so outright:
|
||||
|
||||
- Reckon, "Importing the IIF file in Reckon Accounts Business, changes the Inch “ symbol to Feet ‘ symbol", <https://help.reckon.com/article/1ap8nwl0v2-kba-5589-importing-the-iif-file-in-reckon-accounts-business-changes-the-inch-symbol-to-feet-symbol> (retrieved 2026-10-20, no date given). Cited (not quoted): Reckon Accounts Business, which imports IIF files, changes each double quote to a single one by design, because many file formats treat the double quote as a special character.
|
||||
- Jonathan Clark, interchange-users mailing list, 28 July 2003, <https://www.interchangecommerce.org/pipermail/interchange-users/2003-July/034578.html>:
|
||||
|
||||
> From what we can tell, QB uses double quotation marks (") as text delimiters when there are certain characters in the field.
|
||||
|
||||
> For imports, you will break the import if you have double quotes within your text
|
||||
|
||||
So the books write a double quote as a single one, listed like any other change (rules.md B-34).
|
||||
|
||||
## Not found in any Intuit source
|
||||
|
||||
Searched 2026-10-13 (the help articles above and every document in the IIF Import Kit and journal sample); none states:
|
||||
Searched 2026-10-13 and 2026-10-20 (the help articles above and every document in the IIF Import Kit and journal sample); none states:
|
||||
|
||||
- an escaping mechanism for tabs, line breaks, or double quotes inside a field (no escape syntax is documented; the only safe reading is that fields must not contain tabs or line breaks);
|
||||
- an escaping mechanism for tabs, line breaks, or double quotes inside a field (no escape syntax is documented; the only safe reading is that fields must not contain tabs or line breaks, and, from the reports above, double quotes);
|
||||
- an explicit sentence that a transaction's TRNS and SPL amounts must sum to zero (every example does; the sign rule implies it);
|
||||
- the allowed number of decimal places, or whether thousands separators or currency symbols are accepted in AMOUNT;
|
||||
- the character encoding beyond "ASCII text";
|
||||
- whether a four-digit year is accepted everywhere despite the "MM/DD/YY" wording (Intuit's 2007+ example uses one).
|
||||
- the character encoding beyond "ASCII text" (so the books write plain ASCII, transliterating anything else and listing what changed: rules.md B-34, DECISION D-36);
|
||||
- whether a four-digit year is accepted everywhere despite the "MM/DD/YY" wording (Intuit's 2007+ example uses one);
|
||||
- what QuickBooks Desktop does on import with an account name, account number or memo longer than its limits (only the non-Intuit note above, for names), how many levels of subaccounts it allows, or a limit on a whole NAME with its parents;
|
||||
- how long a journal entry's number (DOCNUM) may be (the limits article has no row for it; the books' entry ids are a few digits);
|
||||
- whether QuickBooks matches account names or numbers ignoring case (the books keep no two alike even ignoring case);
|
||||
- what an IIF journal import does with a line on accounts receivable or payable that names no customer or vendor (above).
|
||||
@@ -0,0 +1,65 @@
|
||||
# Unicode character properties: how a TIN can be written
|
||||
|
||||
Governs `ledger_core::parties::has_full_tin` (rules.md B-26): which
|
||||
characters separate a TIN's digits, and which are invisible between them.
|
||||
The Unicode Character Database is © Unicode, Inc., under the Unicode
|
||||
License v3, which permits copying the data files; the code point lists
|
||||
below are transcribed from them (facts, not prose).
|
||||
|
||||
## PropList.txt, Unicode 17.0.0 (2025-06-30)
|
||||
Source: <https://www.unicode.org/Public/17.0.0/ucd/PropList.txt>
|
||||
Retrieved: 2026-10-20
|
||||
SHA-256 of the retrieved file: `130dcddcaadaf071008bdfce1e7743e04fdfbc910886f017d9f9ac931d8c64dd`
|
||||
|
||||
**Dash** (every dash and hyphen): U+002D, U+058A ARMENIAN HYPHEN, U+05BE
|
||||
HEBREW PUNCTUATION MAQAF, U+1400, U+1806, U+2010..U+2015 (HYPHEN,
|
||||
NON-BREAKING HYPHEN, FIGURE DASH, EN DASH, EM DASH, HORIZONTAL BAR),
|
||||
U+2053 SWUNG DASH, U+207B SUPERSCRIPT MINUS, U+208B SUBSCRIPT MINUS,
|
||||
U+2212 MINUS SIGN, U+2E17, U+2E1A, U+2E3A..U+2E3B, U+2E40, U+2E5D,
|
||||
U+301C WAVE DASH, U+3030 WAVY DASH, U+30A0, U+FE31..U+FE32, U+FE58 SMALL
|
||||
EM DASH, U+FE63 SMALL HYPHEN-MINUS, U+FF0D FULLWIDTH HYPHEN-MINUS,
|
||||
U+10D6E, U+10EAD.
|
||||
|
||||
**White_Space**: U+0009..U+000D, U+0020, U+0085, U+00A0, U+1680,
|
||||
U+2000..U+200A, U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR,
|
||||
U+202F, U+205F, U+3000 IDEOGRAPHIC SPACE. Less the controls and the two
|
||||
line and paragraph separators, these are the space separators (general
|
||||
category Zs). Rust's `char::is_whitespace` is this property.
|
||||
|
||||
## DerivedCoreProperties.txt, Unicode 17.0.0
|
||||
Source: <https://www.unicode.org/Public/17.0.0/ucd/DerivedCoreProperties.txt>
|
||||
Retrieved: 2026-10-20
|
||||
SHA-256 of the retrieved file: `24c7fed1195c482faaefd5c1e7eb821c5ee1fb6de07ecdbaa64b56a99da22c08`
|
||||
|
||||
**Default_Ignorable_Code_Point** (drawn as nothing when not supported):
|
||||
U+00AD SOFT HYPHEN, U+034F, U+061C ARABIC LETTER MARK, U+115F..U+1160,
|
||||
U+17B4..U+17B5, U+180B..U+180F, U+200B..U+200F (ZERO WIDTH SPACE, the
|
||||
joiners, LEFT-TO-RIGHT and RIGHT-TO-LEFT MARK), U+202A..U+202E,
|
||||
U+2060..U+206F (WORD JOINER, the invisible operators, the directional
|
||||
isolates), U+3164, U+FE00..U+FE0F (variation selectors), U+FEFF ZERO
|
||||
WIDTH NO-BREAK SPACE, U+FFA0, U+FFF0..U+FFF8, U+1BCA0..U+1BCA3,
|
||||
U+1D173..U+1D17A, U+E0000..U+E0FFF (tags, variation selectors
|
||||
supplement).
|
||||
|
||||
## Compatibility decompositions (UnicodeData.txt)
|
||||
Derived 2026-10-20 with Python's `unicodedata` (Unicode 16.0.0; these
|
||||
mappings are unchanged in 17.0): the characters past ASCII whose NFKC
|
||||
form is one of the ASCII separators.
|
||||
|
||||
- `' '`: U+00A0, U+2000..U+200A, U+202F, U+205F, U+3000 (all Zs).
|
||||
- `'-'`: U+FE63, U+FF0D (both Dash).
|
||||
- `'.'`: U+2024 ONE DOT LEADER, U+FE52 SMALL FULL STOP, U+FF0E FULLWIDTH
|
||||
FULL STOP.
|
||||
- `'/'`: U+FF0F FULLWIDTH SOLIDUS.
|
||||
- `'_'`: U+FE33, U+FE34, U+FE4D..U+FE4F, U+FF3F FULLWIDTH LOW LINE.
|
||||
|
||||
## How the books read them (rules.md B-26)
|
||||
|
||||
A TIN is nine numerals (any script's: `char::is_numeric`) with at most
|
||||
three separators between neighbors. In ASCII the separators are exactly
|
||||
the space, hyphen, dot, slash and underscore (a tab or line break is
|
||||
not one). Past ASCII they are every Zs space, every Dash character, and
|
||||
the compatibility forms of the dot, slash and underscore above; the line
|
||||
and paragraph separators and NEL are line breaks, as in ASCII, and end a
|
||||
run. Default-ignorable characters are invisible, so any number of them
|
||||
may sit between two digits without counting toward the three.
|
||||
+195
@@ -700,6 +700,201 @@ fields; `Currency::allocation_places`. P3's accept counts `ledger-core` and
|
||||
`ledger-import` (R-6); the store and MCP mutants above are for the whole
|
||||
pass.
|
||||
|
||||
## P3: the IIF and as-of (2026-10-20)
|
||||
|
||||
Defects 7 and 21 (plan P3; the owner's decisions D-36). Rules
|
||||
`docs/spec/rules.md` B-33 (a package as of a day) and B-34 (the IIF). No
|
||||
mutation run (D-33): what P12 must cover is at the end.
|
||||
|
||||
**Named regression tests**, each from its reproduction, on anonymized
|
||||
fixtures:
|
||||
- Defect 7, DOCNUM: `ledger-import` `tests/spec_import.rs`
|
||||
`iif_docnum_is_the_entry_id` (a draft never posted, three entries
|
||||
posted out of id and date order: DOCNUM 3, 2, 4 on the TRNS and every
|
||||
SPL; the file had written 1, 2, 3).
|
||||
- Defect 7, the characters (D-36, plain ASCII):
|
||||
`iif_writes_plain_ascii_and_lists_every_change` (accented letters,
|
||||
Chinese, emoji, a fullwidth colon and fullwidth digits, a tab in a
|
||||
name, controls, a decomposed accent, private use: each written form
|
||||
exact, every change listed exactly), `iif_every_line_ends_cr_lf`,
|
||||
`iif_change_warnings_are_one_line_each`,
|
||||
`iif_keeps_a_tin_readable_to_the_package_scan` (an en-dash or
|
||||
no-break-space TIN in a memo stays a TIN to the package's TIN scan),
|
||||
`iif_distinct_accounts_never_share_a_name` (review R2: duplicate names,
|
||||
by case, siblings, a fullwidth colon against a hyphen, two private-use
|
||||
names; a name that is another's tagged form tagged in turn; the clash
|
||||
left when two codes are written alike refused),
|
||||
`iif_fits_quickbooks_desktop_limits` (Intuit's limits, found in the P3
|
||||
review: a level past 31 characters cut, two alike once cut tagged, a
|
||||
subaccount under its cut parent; an account number past 7 characters
|
||||
and two written alike left out of ACCNUM; a memo past 4,095 cut; every
|
||||
line of the warnings exact; a hand-built level past 31 refused),
|
||||
`iif_warnings_group_the_memos_by_what_is_written_differently` (the
|
||||
lead's call: 100 depreciation memos with an em dash make one line),
|
||||
`iif_warnings_never_hold_a_tin` (a TIN in a memo or an account name,
|
||||
in ASCII or fullwidth digits, never in a warning),
|
||||
`iif_field_transliteration_exact` and `iif_paths_and_transliteration`
|
||||
(the old expectations, "Caf? meals" among them, rewritten to the rule).
|
||||
- Defect 21, the package's IIF: `ledger-package` `tests/package.rs`
|
||||
`as_of_package_iif_stops_at_as_of` (next year's rent was in the file;
|
||||
now the four entries of the year, by id, tied to the trial balance),
|
||||
`the_iif_through_as_of_at_its_edges` (an entry on as_of in, the day
|
||||
after out, a reversal after as_of leaving its original, as of a day
|
||||
before the first entry: the accounts and no transaction).
|
||||
- Defect 21, every file: `every_file_in_an_as_of_package_stops_at_as_of`
|
||||
(review R4: books the same through as_of, one set with a 1099 payment,
|
||||
its receipt and an asset bought the day after, a reversal of the entry
|
||||
dated as_of, the members' contributions and an earlier desk sold, build
|
||||
the same package byte for byte, every file and which files there are,
|
||||
PDFs included, with and without TINs and receipts, with and without a
|
||||
fixed asset register, mid-year and at year end; a package days later
|
||||
sees the activity). Undoing any one of the as-of
|
||||
bounds (the IIF's entries, its FIXASSET typing, the 1099 worksheet's
|
||||
`through`, the fixed asset register's presence) fails it; checked by
|
||||
hand.
|
||||
- D-36, the 1099 worksheet: `the_1099_worksheet_stops_at_as_of` (a
|
||||
payment on as_of counts, the day after doesn't; a vendor under the
|
||||
threshold so far is not yet reportable; a year-end package and the
|
||||
tools' worksheet unchanged).
|
||||
- D-36, closes: `iif_leaves_out_period_closes` (two months closed: no
|
||||
close written, income and expenses equal the year's profit and loss,
|
||||
balances the trial balance without the closes).
|
||||
- Plan P3's accept, a bookspec example per regression test: the as-of
|
||||
ones (`bookspec/examples/as-of-package-stops-at-as-of.toml`,
|
||||
`1099-worksheet-through-as-of.toml`) and the IIF's
|
||||
(`iif-quickbooks-journal-file.toml`, formats appendix), each expected
|
||||
value derived by hand; `the_bookspec_iif_example_matches_the_engine`
|
||||
reads the IIF example and checks the engine gives exactly its file and
|
||||
changes.
|
||||
- Review R18 and the README: `one_list_of_cash_accounts_per_package`,
|
||||
`the_readme_lists_what_the_iif_writes_differently` (the memos grouped:
|
||||
six depreciation memos and a lunch with an em dash, one line).
|
||||
|
||||
**Exhaustive and property tests.** `iif.rs`'s unit tests write every
|
||||
one of the 1,112,064 Unicode scalar values (alone, after a letter, before
|
||||
one) and check the field is printable ASCII without a double quote and a
|
||||
fixed point, its changed runs empty exactly when it is unchanged, and a
|
||||
level never empty, colon-free, trimmed and at most 31 characters (a
|
||||
complete check over the finite alphabet; review R15); `with_tag`'s and
|
||||
`changed_runs`' edges by hand; `the_transliteration_table_is_pinned`
|
||||
samples deunicode 1.6.0, pinned exactly in `Cargo.toml` (R14).
|
||||
Properties: `iif_round_trips_random_books` (memos mixing ASCII, Latin-1,
|
||||
dashes and quotes, every kind of line break, controls, CJK, emoji,
|
||||
combining marks, private use; DOCNUM, CR LF, the changes list exact),
|
||||
`iif_names_never_clash_and_every_change_is_listed` (random charts from a
|
||||
pool of clashing names, long names alike once cut, codes with colons,
|
||||
past 7 characters, and one alike another once trimmed; every warning
|
||||
line checked against the books and the file), `iif_ties_to_the_trial_balance_as_of` (2,000
|
||||
cases: random books with reversals and closed months, random as_of; the
|
||||
file's entries and balances against the trial balance without the
|
||||
closes).
|
||||
|
||||
**End to end.** `ledger-mcp` `oracle_mcp.rs`:
|
||||
`iif_declares_accounts_by_role_and_balances_every_transaction` (as_of,
|
||||
DOCNUM the ids, the warnings exact: the fixture's line-broken memo and
|
||||
the engine's own "Depreciation — Laptop — 2025-03" memos, the alias, a
|
||||
range refused), `iif_without_as_of_is_as_of_today_and_ties_to_the_trial_balance`
|
||||
(review R5), `cpa_package_holds_the_year_and_its_evidence` (the IIF from
|
||||
the prior year's sale through as_of; a payment after as_of to the
|
||||
contractor left out of the 1099 worksheet; the note's count);
|
||||
`mcp_stdio.rs` (a Chinese account name over stdio: ASCII text, CR LF,
|
||||
`warnings`); `spec_mcp.rs` (iif with as_of); `ledger-gui`
|
||||
`tests/exports.rs` (the README's IIF line names the as_of).
|
||||
|
||||
**Names in every script, in the PDFs and the viewer.** Inter has no
|
||||
Chinese, Japanese, Korean, Arabic, Hebrew, Thai or Devanagari glyphs:
|
||||
every such character printed as Inter's empty box (glyph 0), and the
|
||||
viewer drew boxes too. `ledger-import` `src/fonts.rs` now bundles the
|
||||
fallbacks, each once: a subset of Noto Sans CJK SC
|
||||
(`fonts/NotoSansCJK-LICENSE.txt` says how it was made) and Noto Sans
|
||||
Arabic UI, Hebrew, Thai and Devanagari, unmodified
|
||||
(`fonts/NotoSans-LICENSE.txt`: versions, upstream commits, SHA-256; 412,968
|
||||
bytes for the four). Arabic is the UI form because Noto Sans Arabic 2.013
|
||||
draws a letter's dots as marks of their own, which Typst writes as text
|
||||
runs of their own: its PDFs' text read "شلام" for "سلام", with letters
|
||||
doubled. No emoji font (about 10 MB): an emoji prints as an empty box in
|
||||
the PDFs. Tests: `fonts.rs`
|
||||
`every_template_names_every_fallback_in_order`; `pdf.rs`
|
||||
`chinese_japanese_and_korean_print_as_written` and
|
||||
`arabic_hebrew_thai_and_devanagari_print_as_written` (every glyph from
|
||||
its script's font, none glyph 0); `spec_import.rs`
|
||||
`pdf_keeps_chinese_japanese_and_korean_names` (the ToUnicode map) and
|
||||
`pdf_prints_every_bundled_script_as_written` (the PDF read back with
|
||||
hayro, the viewer's own reader: Arabic and Hebrew read right to left give
|
||||
the words, the lam-alef ligature included; Thai, Devanagari and Chinese
|
||||
left to right; every font embedded; failed with Noto Sans Arabic 2.013).
|
||||
The viewer registers the same `FALLBACKS` after its own fonts in every
|
||||
family (`ledger-gui` `theme.rs` `every_family_falls_back_to_the_noto_fonts`:
|
||||
the very bytes, by pointer, and a real glyph for each script's letters in
|
||||
every family) and `tests/scripts.rs`
|
||||
`account_names_in_other_scripts_show_as_written` (the Accounts page paints
|
||||
each name; with `SHOT_DIR` set, it saves `scripts.png`: looked at,
|
||||
2026-10-20). egui shapes and joins each word, right to left for Arabic
|
||||
and Hebrew, but doesn't reorder the words of a right-to-left phrase:
|
||||
"مكتب الرياض" shows its two words left to right.
|
||||
|
||||
**TINs in any script (B-26).** `ledger_core::parties::has_full_tin`
|
||||
missed "123-45-6789": the fullwidth hyphen-minus, the ideographic
|
||||
and thin spaces, the Hebrew maqaf and the other Unicode dashes weren't
|
||||
separators, and a zero-width space or a right-to-left mark between digits
|
||||
ended a run. Past ASCII every Zs space, every Dash character and the
|
||||
compatibility forms of the dot, slash and underscore now separate, and
|
||||
default-ignorable characters don't count (`docs/spec/sources/unicode-tin-text.md`,
|
||||
Unicode 17.0); ASCII reads as before. `spec_parties.rs`
|
||||
`has_full_tin_reads_every_script_and_separator` and the property
|
||||
`has_full_tin_keeps_its_ascii_reading` (2,000 cases: on ASCII the same
|
||||
answer as the old reading, kept in the test; elsewhere it finds at least
|
||||
what the old one did).
|
||||
|
||||
**Second review (2026-10-20).** QuickBooks gives a subaccount its
|
||||
parent's type (Intuit): `iif_a_subaccount_of_another_type_stands_at_the_top_level`
|
||||
(a bank account under a header that is no bank, an asset's cost under
|
||||
"Fixed assets": each written at the top level, keeping its type, listed,
|
||||
its own subaccount with it, a name it then shares told apart by code);
|
||||
`check_iif` now checks every subaccount's type is its parent's and every
|
||||
parent is declared before it; `iif_declares_each_parent_before_its_subaccounts`.
|
||||
The file names no customer or vendor (Intuit states no need for an IIF
|
||||
journal; QuickBooks Desktop asks for one on A/R or A/P):
|
||||
`the_readme_names_the_entries_on_receivables_and_payables`. A memo line
|
||||
whose digits are masked says so (`iif_warnings_never_hold_a_tin`, which
|
||||
now also holds a name and a memo that are a TIN only once written, digits
|
||||
a tab apart: with `has_full_tin` reading every script, nothing else
|
||||
tested the masks' second pass). `iif_fits_quickbooks_desktop_limits` now
|
||||
holds a number of exactly 7 characters (kept) and two alike but for case
|
||||
(left out): undoing either bound of the 7 had failed no test. Each was
|
||||
checked by undoing it and seeing its test fail.
|
||||
|
||||
The GnuCash differential (`oracle/`) compares the engine's figures and
|
||||
has no IIF and no package, so it has nothing to re-adjudicate here.
|
||||
|
||||
Each of the review's fixes was checked by undoing it by hand and seeing
|
||||
its test fail (2026-10-20): the 31-character cut, the clash loop's
|
||||
second round, the double quote, the TIN mask, the memo cut, each reason
|
||||
a number is left out, the memo grouping, the tag's colon; and, for the
|
||||
builder's, the as_of `<=`, the register's presence, the 1099 `through`,
|
||||
the closes filter, the FIXASSET date filter and the package's cash list.
|
||||
|
||||
**For P12:** mutation over `ledger-import` `iif.rs` (each `breaks` arm,
|
||||
the control, quote and `None` arms of `each_piece`, the deunicode
|
||||
post-mapping, `segment`'s colon, trim, cut and "?" fallback, `tag`,
|
||||
`with_tag`'s room, the clash loop's depth bound, rounds and tag,
|
||||
`journal_to_iif`'s clash and length refusals, the number rules, the memo
|
||||
cut, each `changes` comparison and its order, `warnings`' grouping,
|
||||
order and masks, `shown`, DOCNUM, `EOL`), `pdf.rs` (the fallback font),
|
||||
`ledger-package` `iif.rs` (`<=` in the as_of filter, the closes filter,
|
||||
the FIXASSET date filter) and `package.rs` (the cash and financing
|
||||
resolution, the register's presence, the 1099 `through`, the README's
|
||||
IIF line, closes sentence, warnings block and 1099 wording), and
|
||||
`ledger-core` `form1099.rs` (the `through` bound), `ledger-mcp`
|
||||
`server.rs` (the iif report, range and as_of checks, `warnings`, the
|
||||
package note), `ledger-gui` `menu.rs` (the note). From the second
|
||||
review: `iif.rs` `iif_accounts`' type filter on parents and
|
||||
`apart_from`, `parents_first`, the `AtTopLevel` change, the TIN note's
|
||||
condition and `receivable_payable`; `fonts.rs` and `theme.rs`
|
||||
`font_definitions`; the README's A/R and A/P sentence; `ledger-core`
|
||||
`parties.rs` `tin_separator`'s arms and `tin_invisible`, and the gap that
|
||||
doesn't count them.
|
||||
|
||||
## Benchmarks (baseline 2026-10-13)
|
||||
|
||||
No budget, by decision (the owner, 2026-10-13: the books do little work
|
||||
|
||||
Reference in new issue
Block a user