aboutsummaryrefslogtreecommitdiffstats

accounted-multicase-intgr

Example integration that sends vouchers (bilag) from a Multicase "buntfil" export to Accounted through its v1 REST API.

It reads the .xls export, groups the posting lines into vouchers, maps them to Accounted journal entries and creates them as drafts, optionally posting them.

Install

go install simenandre.no/accounted-multicase-intgr@latest

Usage

cp config.example.json config.json   # then adjust the mapping

# Parse and map every voucher, no network access
accounted-multicase-intgr check "MC Buntfil 01102026-12102026.xls"
accounted-multicase-intgr check -v "MC Buntfil 01102026-12102026.xls"   # print each entry

export ACCOUNTED_API_KEY=gnubok_sk_...      # scope bookkeeping:write
export ACCOUNTED_COMPANY_ID=<company uuid>
# export ACCOUNTED_URL=https://app.accounted.se

accounted-multicase-intgr push -dry-run export.xls   # server validates, nothing is saved
accounted-multicase-intgr push export.xls            # create drafts
accounted-multicase-intgr push -commit export.xls    # create and post, assigning voucher numbers

push validates everything before it writes anything: if any voucher has an unmapped account or VAT code, or a date outside an open fiscal period, nothing is sent.

How vouchers are mapped

  • Grouping. Lines are grouped by BilagsArt and Bilagsnummer. Inventory corrections (Lagerkorrigering) carry Bilagsnummer 0 and are grouped per batch (BuntHodeID) instead.
  • Amounts. Belop is used, in the Multicase company's base currency. Positive is debit, negative is credit. Amounts are rounded to two decimals; Multicase writes currency conversions with three, so a voucher can end up a few öre off. That difference, up to max_rounding_ore, is posted to rounding_account. Zero-amount lines are dropped.
  • Accounts. A line whose Konto equals the customer number (Faktura kundenr) or supplier number (LevNr.) is a subledger line and is posted to customer_ledger_account / supplier_ledger_account. Every other account must be listed in accounts.
  • VAT. Multicase posts revenue and cost lines gross with an MVA code and leaves the split to the receiving ledger. For codes with a rate, the net amount stays on the mapped account and the VAT goes to the code's account. Codes with rate 0 pass through untouched.
  • Dimensions. AvdNr. and Prosjekt are sent as the SIE dimensions named in dimensions (by default 1, kostnadsställe, and 6, projekt).

config.example.json maps the accounts found in one Print Supplies AS export to BAS 2026 accounts. It is a starting point only: have the mapping, and in particular the VAT codes, checked by whoever keeps the books.

Not booking twice

Each voucher is sent with source_id multicase:<BilagsArt>:<Bilagsnummer> and a deterministic Idempotency-Key, so retries after a timeout are replayed by the server rather than repeated. Accounted keeps idempotency keys for 24 hours, so push also records every draft and posted voucher in multicase-state.json. Re-running an overlapping export skips what was sent.

A voucher that changed in Multicase after it was sent is reported and skipped. Posted vouchers cannot be edited; correct them in Accounted (storno or rättelse).

Limitations

  • Accounted keeps its ledger in SEK. Amounts are sent as they appear in Multicase, so the export's base currency must match the Accounted company's.
  • Only the first worksheet of the export is read, and only Excel 97-2003 (.xls) files are supported. The bundled BIFF8 reader exists because the available Go libraries decode negative whole-number cells as large positive numbers.
  • Requests are throttled to stay under the default limit of 100 requests per minute per API key; 429 and 5xx responses are retried.