This document describes everything MyFinAI books, process by process: what triggers it, what journal entry it writes, what it controls and what evidence it leaves. It's the reference for your accountant or CPA when they ask "and how exactly does this get recorded?".
How to read it. Each process appears as *trigger → journal entry → control*. The account codes shown are the ones from the generic business chart (1000 Bank, 1100 AR, 2000 AP…); the system does not work off fixed codes: it resolves each account by name in that workspace's chart, so a Colombian PUC chart (Decreto 2650 de 1993) uses 1105/1305/2205/2408 and the entry is the same. Where a mandatory account is missing (withholding, sales tax, exchange difference), the system creates it with its name and its legal basis rather than losing the record.
the ledger: ΣDebits = ΣCredits, computed in decimal (never floating point). An entry that doesn't balance is rejected; there is no "we'll balance it later".
not assembled on the side: they derive from the ledger. If a number shows on a dashboard, you can open it down to the entry behind it.
ledger, isolated in the database row by row (RLS). The business ledger and the household ledger never mix, even when the same person signs in.
dollars in Puerto Rico and the United States, pesos in Colombia. A document in another currency converts at the official rate of the document's date and keeps the original amount, the rate and the date.
prepare. No money-moving tool is ever exposed to an agent: payment, collection, tax remittance and close are confirmed by a human with sufficient role.
Nothing posts itself. The automatic sweep that runs every six hours only reads (it raises alerts, links identities and understands movements); it never writes an entry. When you press ↻ Post to the ledger, the system runs the processes in dependency order inside a single transaction: transactions → invoices → deferred recognition → inventory receipts → bills → collections → payments → equity → properties → cost of goods sold → payroll. If anything fails to balance, nothing lands.
Idempotency. Each entry is stamped with the type and id of the document that produced it (bill, invoice, bill_payment, pay_run, depreciation…), so reprocessing a document can never book it twice. Single-shot entries — loan, lease, tax remittance, manual journal, period accrual — are recorded every time you confirm them: to correct one you reverse it from the ledger (it stays, flagged as reversed, never deleted).
| Step | What it does |
|---|---|
| Template | When the workspace is created the chart is provisioned: business (generic), household, or PUC for a Colombian business (Decreto 2650 de 1993). The choice comes from the workspace's jurisdiction, not from a hand-typed string. |
| Resolution by name | The engine looks up "accounts payable", "sales tax", "withholding at source", "exchange difference"… by name, with each country's variants. That's why the same code works on a PR chart and on a PUC. |
| Cited auto-creation | If a mandatory account is missing it is created with its name and its law: withholdings payable (2340 in PR, Sec. 1062.03), withholding at source / VAT withholding / local trade withholding (2365/2367/2368 in Colombia), VAT payable (2408), exchange difference (421020 / 530525 in PUC). |
| Opening balances | Opening balances enter as one balanced entry against Opening balance equity (3900). It is the only entry allowed to "invent" equity, and it is flagged as the opening. |
Trigger: you issue the invoice (manually, from a subscription, from billed hours, or from the timesheet reader).
| Account | Amount | |
|---|---|---|
| DR | 1100 Accounts receivable | total (base + tax) |
| CR | 4000/4050/4100 Revenue (each line's account) | base |
| CR | 2300 Sales tax payable (IVU/VAT) | tax on the lines |
Controls: a draft invoice recognizes no revenue; per-line tax is split out of revenue and if the chart has no sales-tax account one is created (tax is never "dissolved" into revenue); the header total is reconciled against its lines.
An annual invoice recognizes deferred revenue and releases it per period on its recognition schedule: DR deferred revenue / CR revenue for the month. That's the ASC 606 treatment for what you billed up front.
Trigger: you record the collection (or reconciliation brings it from the bank, or the receipts mailbox reads it).
| Account | Amount | |
|---|---|---|
| DR | 1000 Bank / deposit account | net received |
| DR | 1355 Tax credits and withholdings suffered (asset) | withholding your client applied |
| DR | Processing-fee expense | gateway fee |
| CR | 1100 Accounts receivable | invoice gross |
Controls: withholding suffered is never lost: it stays as a tax asset in your favor (1355 in the PUC); the gross settles the receivable even though less money hits the bank; the matching bank movement is created (idempotent) so Transactions and the ledger tell the same story; the collection voucher PDF is generated with the workspace's legal name.
The collections agent prioritizes what's overdue by aging, proposes the reminders and records every attempt. Bad debt is written off as such (the invoice is not deleted).
Trigger: you upload the vendor bill, it arrives at the invoicing@ mailbox, you import it from the DIAN document report, or you capture it by hand. The reader handles PDF, image, Word, Excel, CSV or the email body, identifies the vendor or consultant as a single entity and proposes the expense account.
| Account | Amount | |
|---|---|---|
| DR | Expense account (lines, or the document's account) | base |
| DR | 2408 Deductible VAT (Colombia) | VAT on the purchase |
| CR | 2000 Accounts payable | total |
If the bill is tied to a purchase order whose goods were already received, the entry relieves Goods received not invoiced (GRNI 2150) instead of recognizing the expense again.
Controls: a bill with no expense account is not posted (the system doesn't guess); the original document is stored and viewable; duplicates are caught by party + number or amount + date + party; a draft recognizes nothing; in a currency other than the book currency it converts at the exact rate of its date.
The order records what was ordered; receiving records what arrived (and capitalizes inventory); the bill cannot exceed what was received — the 3-way match blocks, it doesn't merely warn.
Trigger: a human records the payment (method, account, date and receipt) or fires it through PayPal Payouts.
| Account | Amount | |
|---|---|---|
| DR | 2000 Accounts payable | gross |
| CR | 2340 Withholdings payable (PR) · 2365/2367/2368 (Colombia) | withholding applied |
| DR | Processing-fee expense | payment-method fee |
| CR | 1000 Bank | net + fee |
| DR/CR | Exchange difference (gain or loss) | if the bill was in another currency |
Controls: withholding computes itself (the vendor's percentage, or amounts typed on the payment) and each type goes to its own liability; in Colombia the vendor's single percentage is withholding at source on the base (2365), never Puerto Rico's withholding; dual control: a payment above the workspace threshold is held for approval before posting; the payment generates the payment voucher PDF (with the receipt attached when it arrived at paymentReceipt@) and the remittance advice to the vendor; the idempotent bank movement is created; the gross settles the payable.
Flow: draft → submitted → approved → paid. Lines are editable only in draft, and submitting requires every line to be classified. On approval the report becomes a payable in the person's name: the reimbursement then goes out through the same door as any other payment (with its voucher, its withholding where it applies and its bank movement) instead of a side entrance. The reimbursement itself is its own entry: DR the liability with the person / CR bank.
Anything capitalizable becomes an asset instead of an expense, with the threshold expressed in the workspace's currency. Nobody approves their own expense: the submitter doesn't approve, unless the owner explicitly enables self-approval for principals; an employee never can. Reopening an approved report voids its payable (or books a reversing entry on reports that predate the payable link), and it is refused once the report is paid.
Petty cash keeps its own control register with opening, replenishments, expenses, adjustments and counts (book balance vs. counted); it is a control subledger and does not post to the ledger on its own. Cards track charges, payments and statement dates: a charge enters as a movement with source "card" and credits the card liability, and paying it from the bank is a liability transfer, not an expense (a classic error the system avoids by design).
| Process | Entry |
|---|---|
| Recategorize an already-posted movement | the previous entry is marked reversed (kept for audit) and a new one is posted |
| Bad debt | DR bad-debt expense / CR accounts receivable |
| Asset disposal | DR bank (proceeds) + DR accumulated depreciation / CR asset cost, with the gain or loss on sale |
| Period-end accrual | DR expense for what was ordered and received / CR accrued liability, with its automatic reversal the next day |
| Tax accrual (Colombia) | DR the tax expense / CR its own liability — only for the taxes accrued by hand (local trade tax and stamp duty); VAT and withholdings arise from invoices and payments |
| Step | What it does |
|---|---|
| Upload | The multi-file reader handles real timesheets and remembers the person → consultant mapping. |
| Double-count guard | Before you confirm, it detects period totals loaded as a single day, re-uploads of the same file, and hours already loaded; the decision is human and is recorded. |
| One rate rule | Bill rate and cost come from a single hierarchy (entry → assignment → consultant → project); only approved hours can be billed. |
| Accrual | On approval: DR 1250 Work in progress (WIP) / CR 4050 Hourly revenue, with each entry's share stamped on the journal. |
| Billing | When those hours are invoiced the accrual is relieved (DR 4050 / CR 1250) and the invoice posts its own entry — revenue is never counted twice. |
| Consultant cost | The consultant's bill enters as a payable and settles the hours it covers. |
| Margin split | Per-project compensation splits the margin (sale − costs) among participants and settles as a payable to each of them. |
The regime comes from the workspace's jurisdiction, not from a loose flag.
Puerto Rico / United States. FICA 7.65% exact on the employee side (6.2% Social Security + 1.45% Medicare), federal and state withholding as a reviewable percentage.
| Account | |
|---|---|
| DR | Payroll expense (gross) |
| CR | Payroll withholdings payable (federal, state, FICA) |
| CR | Payroll payable (net) |
Colombia (Ley 100 de 1993 and the Labor Code). Employee: health 4% + pension 4% + withholding at source. Employer: health 8.5%, pension 12%, occupational-risk insurance (Decreto 1607 de 2002) and payroll levies; statutory benefits: severance 8.33%, severance interest ≈1%, service bonus 8.33% and vacation 4.17%. Transport allowance where it applies.
| Account | |
|---|---|
| DR | 5105 Personnel expense |
| CR | 2370 Social security payable |
| CR | 2365 Withholding at source payable |
| CR | 2610 Statutory benefits payable |
| CR | 2505 Payroll payable (net) |
Paying the net is its own entry (DR payroll payable / CR bank) and a human fires it. The employee portal shows their stub with their own country's concepts (federal/state/FICA and W-2 / 499R in PR; health, pension and withholding with the income and withholding certificate, DIAN form 220, in Colombia).
| Process | Entry |
|---|---|
| Goods receipt | DR Inventory / CR 2150 GRNI (goods received not invoiced) |
| Cost of goods sold | DR 5000 Cost of goods sold / CR Inventory |
On-hand is derived from the inventory movements (not from a parallel counter) and valuation is weighted average, maintained by the database itself on every movement. A sale generates its inventory movement from the invoice line (idempotent per line), and the operations module adds multi-location, demand (velocity, ABC, days of cover), suggested replenishment, sales orders, lots with expiry and inter-location transfers.
| Process | Entry / treatment |
|---|---|
| Capitalization | An expense above the threshold (expressed in the workspace's currency) enters as an asset, not an expense. |
| Depreciation | Straight line with a catch-up model: each run posts exactly what's missing for accumulated depreciation to be correct as of the date (DR depreciation expense / CR accumulated depreciation), idempotent per asset. |
| Properties | The property subledger (rent, expenses, mortgage) is carried to the ledger, so net worth and the P&L tie to the books. |
| Loans | Disbursement: DR bank / CR loan payable. Payment: DR loan (principal) + DR interest expense + DR fees / CR bank. |
| Leases | Recognition of the right-of-use asset and its liability, and each payment split into principal and interest. |
| Shareholder capital | Contributions and distributions to the ledger (DR bank / CR equity; DR distributions / CR bank), only after the opening entry so history isn't double-counted. |
| Step | What it does |
|---|---|
| Intake | You import the statement (CSV or PDF, read by AI) or connect the bank through Plaid — MyFinAI never touches your credentials. |
| Idempotency | Every movement carries a fingerprint; re-importing the same statement duplicates nothing. |
| Understanding | A deterministic reader separates merchant, channel, location, cardholder and reference out of the bank descriptor, and ties it to the registered counterparty (vendor, customer, consultant, employee, household member) with its history. |
| Categorization | A workspace rule or an AI proposal; the human confirms. |
| Entry | DR/CR by the movement's direction and account, with dimensions (class, location, department) when defined. |
| Transfers | Movements between your own accounts are paired and posted as a transfer, not as income or expense. |
| Bank reconciliation | You tick what appears on the statement, record the statement balance and date, and reconcile; each account shows "reconciled through" and what's pending since. |
| Subledger reconciliation | A report compares receivables against open invoices, payables against open bills, inventory against its valuation and each bank against its balance, and flags any difference above one cent. |
date — the official TRM for the Colombian peso (Banco de la República / Superintendencia Financiera public series) and ECB reference rates for the rest; between two non-dollar currencies the cross goes through the dollar. It never approximates: if the rate is missing, the document is flagged for review instead of being booked wrong.
days earlier (otherwise the exact one is fetched — a July receipt would otherwise take June's rate), and each currency has a sanity band: an out-of-band reading is rejected rather than allowed to corrupt balances.
rate and the payment-day rate goes to exchange gain or loss (in a PUC chart, 421020 / 530525 — Decreto 2650 de 1993).
currency is proposed in dry-run mode and posted when a human approves it.
articles 21-1 and 288 of the Tax Statute for the tax effect; ASC 830-20-30-1 in Puerto Rico and the United States.
MyFinAI only shows — and only allows — what applies to the workspace. The rule is single: Colombia is country CO or currency COP; empty is treated as Puerto Rico.
Puerto Rico. Sales & use tax (IVU) per invoice line to the sales-tax liability; services withholding (Sec. 1062.03) on payment → 2340; municipal license and income-tax estimates from the posted ledger; 480.6 and IVU exports; drafts of 941, 499R-1B and W-2PR from the pay runs; the State Insurance Fund (CFSE) policy and payroll declaration (Ley 45 de 1935) with its August 15 deadline.
Colombia. VAT (19%/5%/exempt) with deductible VAT on purchases; withholding at source, VAT withholding and local trade withholding each to its own account; a catalog of 16 taxes with code, legal basis and PUC account; the DIAN calendar and document-report import. Electronic invoicing with CUFE is modeled but does not transmit without the client's credentials and numbering resolution.
Tax remittance. Paying the tax or withholding to the authority is its own entry (DR the tax liability / CR bank) and it only accepts a tax liability — you cannot "remit" a vendor as if it were a tax. Every tax has its account and its law cited in the regulatory framework kept next to the code (docs/regulatory-framework.md).
| Step | What it does |
|---|---|
| Close status | The pre-close checklist: transactions, invoices and bills still unposted as of the cutoff, the trial-balance delta, the period's result, and whether the period is already closed. |
| Close | Posts what's pending and locks the period. It refuses to close an unbalanced ledger, and warns — letting you override with judgment — when more than 5% of the period's movements are unreconciled. An entry dated on or before the lock is rejected; so is reversing an entry from a closed period. |
| Period lock | The lock date lives in the workspace settings and must be in the past (a future date would freeze current operations). |
| Year-end close | Rolls the year's result into retained earnings, with a dry run before posting, and moves the lock to December 31 — never backwards. |
constraint that fires at commit and rejects any unbalanced entry, even one that arrived outside the engine (a bad migration, a direct insert, a new bug).
(hash = sha256(previous_hash ‖ payload)): altering a record breaks the chain and is detected. Verification reports the linkage (authoritative) separately from content re-hashing (indicative, because the database's JSON form isn't byte-reproducible). The log has UPDATE and DELETE revoked at the database level.
is a new event pointing at the previous one.
posting, and what holds them is the database itself (a trigger marks the payment as pending on insert), not just the application.
active workspace; platform-wide aggregators are sealed when the active workspace is a demo.
double entry per entry and globally, subledgers against the ledger, every payment with its bank movement and its withholding, identity uniqueness, hours with their key to the consultant, and the document currency with its rate. A failure blocks the deploy; "0 cases" is reported as empty, never as passed.
are validated (tenants ≥ 1, ΣDR − ΣCR = 0.00) before it counts as good.
| Output | Where |
|---|---|
| General ledger and each entry's detail | Accounting → Ledger (clicking an entry opens its lines) |
| Trial balance (full chart, posted only, zero-balance accounts kept) | Accounting → Ledger (✓ balanced seal) |
| Income statement with period, prior comparable, 12-month trend and margins | Financials |
| Balance sheet and cash flow, the latter both direct and indirect (the indirect one starts from net income, adds back depreciation and the changes in receivables / inventory / payables) | Financials |
| IFRS-format statements (Colombia): statement of financial position (current / non-current), statement of comprehensive income, statement of changes in equity, and notes | Financials (Colombian workspaces) |
| P&L by dimension (class, location, department, project, fund) and by date range | Reports |
| Consolidated report across group companies | Consolidation |
| Aging: what's overdue by bucket and the next collection step | Collections and Payables |
| Tax: returns, fiscal liabilities per account (with the detail per withholding subject) and estimates | Tax |
| Subledger reconciliation against the ledger and FX exposure | Reconciliations and Tax |
| Documents: invoice PDF, payment voucher, collection voucher, hours certification | In each module, with the workspace's legal name and logo |
| Exports: statements as PDF and Excel, 480.6 / IVU (PR), bank payment batch, CO tax catalog, CSV of any table | Financials, Tax and Payables |
Every table in the app carries search, filters, sorting and totals of the filtered set; every tile and KPI drills down to the data behind it.
Cónclave (orchestrates), Lente (reads documents), Libro (bookkeeping), Espejo (reconciliation), Cobro (collections), Mecenas (payments), Salario (payroll), Fisco (tax), Caudal (cash flow), Guardián (anomalies), Norte (plan) and Mayor (close and audit).
What they do: read, extract, classify, match, compute, alert and prepare the action. What they never do: move money, approve their own proposal, file with an authority, or alter a closed entry. Every intervention is recorded in the action ledger with its value and the time saved.
What MyFinAI does not do today, stated plainly:
declaration, DIAN calendar); filing is done by a person on the authority's portal.
transmission needs the client's credentials and numbering resolution.
your accountant or CPA validates and signs.
confirmation always comes from a person in the app.
and payroll levies; the exemption for workers under 10 minimum wages needs the taxpayer type and the year's minimum wage declared — it's on the backlog.
reconciliation) still use fixed codes from the generic chart instead of resolving the account by name; on a PUC chart, check the account before confirming. It is identified and queued for generalization.
| Process | Code module |
|---|---|
Journal engine, all post_*, revaluation, year-end close | app/posting.py |
| Depreciation | app/depreciation.py |
| Book currency and rates | app/fx.py |
| Jurisdiction, calendar and tax liabilities | app/compliance.py |
| Colombian tax catalog | app/co_taxes.py |
| Document reading (bills, receipts, payment receipts, timesheets) | app/felipe.py, app/ap_intake.py, app/expense_intake.py |
| Hours, rates and duplicates | app/hours_rates.py, app/hours_dupes.py |
| Bank-movement counterparty | app/txn_parse.py, app/txn_enrich.py |
| Single identity for people and companies | app/identity.py |
| PDF vouchers and advices | app/payments.py |
| Assurance checks | infra/assurance.py |
For the detail of every rule cited — article, effective date and official link — see the regulatory framework kept with the code (docs/regulatory-framework.md). For the step by step of your role, open your manual in the Documentation center.