@jwilleke/accounting-receivables-addon
v0.4.0
Published
Receivables for the ngdpbase accounting add-on: invoices for assessments, rent or dues; payments, credits and late charges
Readme
Accounting receivables
Receivables for the accounting add-on of ngdpbase: one invoice per billing address each month, payments as receipts, money paid ahead kept as credit, and late charges proposed for the treasurer to confirm. The Fairways (a condominium) is the reference site.
- Slug:
accounting-receivables, equal to thenameexported fromindex.ts. - Type:
additive. Depends onaccounting; the forms add-on carries the screens. - Requires: ngdpbase 5.31.0 or later.
- Accounts: read from managers named in configuration, and never copied. A condominium uses the
accommodation add-on (ngdpbase-addons):
AccommodationManager(accounts-manager) forlist(),get(id),assessment(id)(amount, monthly or annual, due day, from the accommodation's category) andlateCharges(); andResidencyManager(billing-manager) forbilling(ctx, id, { on }), where the unit's invoices go and its owners on the charge's due date, andownUnits(ctx), the units the viewer owns today. - Data: invoices are in this add-on's own database, declared as
ngdpbase.addons.accounting-receivables.database, outside the ledger, which holds only money that moved. A payment is a receipt made through the accounting add-on'sReceiptManager, whose line carriesreceivabledetails ({ account, invoiceId }) registered withLedgerManager.registerLineDetails. The accounting database is never touched. - Permissions: its own
invoice-issue(issue, void and email invoices), which the add-on's policy grants the treasurer role; recording a payment is accounting'sledger-record.
Why: D-035.
Turn it on
A condominium, with the accommodation add-on enabled and 4100 renamed in the chart:
{
"ngdpbase.addons.accounting.enabled": true,
"ngdpbase.addons.accounting.categories": {
"4100": { "name": "Assessments", "type": "income", "detailType": "Service/Fee Income" }
},
"ngdpbase.addons.accounting-receivables.enabled": true,
"ngdpbase.addons.accounting-receivables.label": { "singular": "Assessment", "plural": "Assessments" },
"ngdpbase.addons.accounting-receivables.organization": {
"name": "The Fairways Condominium Association",
"address": "…",
"pay-to": "Fairways Condominium Association, c/o …"
}
}How billing works
One balance per unit (D-047). Its owners owe it jointly; who they are, and each one's share, is the unit's owner list on the due date, from the accommodation add-on, by identity
@id. A payment names only the unit and settles its oldest invoice first, or the one it names first. What is left is the unit's credit. Refunds lower a payment; a bounced check does not count.One invoice per billing address. The unit's billing entries say only where invoices go: an address typed by the treasurer or an owner, and a share; usually one entry at 100%. Each entry's invoice carries its share of the month's charge and of the balance brought forward; late charges go on the first. An invoice keeps the address as typed and the owners'
@ids and shares, never names.A unit with no billing address is never billed to a guessed one. It shows as not billable on Prepare This Month's Invoices, with the reason, and the scheduled run names it in its result and in the notice to the people who issue invoices.
Each month is evaluated on its own. Prepare This Month's Invoices shows each entry's charge, the late charges due on the unit's earlier invoices, the balance brought forward and the amount owed. The treasurer then issues: I-0001 onwards, each stored exactly as issued with its SHA-256. A mistake is voided, with a reason, and the month issued again.
Late charges come from the account source's rules. A rule applies once an invoice is more than its days past due and still unpaid: once per invoice, or each month. Interest is simple, on what is still owed, at the annual rate ÷ 12. They are added only when the treasurer ticks the box.
Email: with email ticked, an invoice with money owed goes to each of the unit's owners with an email, looked up as the sender through ngdpbase's identity records (
identity-read); one paid in full by credit is kept and not sent.Sending to owners is off until a site sets
ngdpbase.addons.accounting-receivables.send-to-ownerstotrue. While it is off nothing is sent to owners, even with the email box ticked: a development or copied site never mails real owners.Your own bills: a unit's current owners, decided when they look, see its whole account on their profile: every billing entry's invoices, what is paid and left to pay, and the balance. A past owner keeps seeing the invoices issued while they owned it, without the balance; someone never billed sees no card (D-047, D-045). It needs
ledger-self, which every account holds.The board sees every unit's account under
account-read, which no role holds by default: a site grants it to its board in its own policy.PDF: an emailed invoice carries a PDF of itself, made by ngdpbase's export, when the site has a PDF provider (
ngdpbase.export.pdf.provider), and the PDF's SHA-256 is kept with the invoice. Without one, the email carries the page alone.Scheduled run: the job
accounting-receivables.issue-invoicesissues each month's invoices on the 1st at 06:00 in the site's time zone, with the late charges due, and emails them (D-035). It ships paused: turning it on (Admin → Scheduled Jobs → Resume) is the site's standing confirmation of the late charges and the email. Move the day with BackgroundJobManager's own keys. Run again for the same month, it issues nothing twice. A scheduled run acts as the job, which this add-on's policy grants onlyinvoice-issue,ledger-readand the accommodation add-on'saccommodation-billing-read; Run now acts as the admin who clicked. Whilesend-to-ownersis off, nothing goes to owners and the holders ofinvoice-issueget a notice of what was issued.
Not yet: sending by each user's communication preference (ngdpbase #1969).
Develop
npm install
npm test # builds, then runs vitest