MPH WMS
IntegrationsAccounting

Accounting

How MPH WMS sends invoices to your accounting system and what happens when something cannot be booked

MPH WMS is the source for your sales accounting. It sends invoices to your accounting system, one per order, and then reconciles the money that actually arrives, payout by payout. Your ledger receives two things from MPH: an invoice when you sell, and a voucher when the money lands on the bank.

Fortnox is the supported accounting system today.

Connecting

  1. Go to Settings → Integrations → Add integration and choose Fortnox.
  2. Approve the access in Fortnox.
  3. You are returned to MPH WMS with the connection active. It now appears as a set of books under Settings → Accounting, where the account mapping, payment methods and general policy live.

Fortnox access tokens are refreshed automatically every night. If Fortnox is unreachable during a refresh, the next refresh picks it up; if the connection has genuinely expired, the app asks you to reconnect.

What a sale becomes

Every order that comes in, or changes, is turned into an accounting document in the background. Building it takes four steps, and anything the system cannot decide with certainty stops the document instead of guessing:

  1. Classify the tax. Domestic VAT, OSS (EU distance selling), or export, from the destination and the customer.
  2. Map the accounts. Each combination of tax regime, destination country, VAT rate and line type is looked up under Settings → Accounting → Account mapping. A missing combination holds the document.
  3. Reconcile. The lines are checked against the order total. A difference up to the rounding tolerance becomes a visible rounding line; anything bigger holds the document.
  4. Decide the payment handling from the order's payment method. See Payment methods below.

The grace period

A document waits (30 minutes by default, under Settings → Accounting → General) before it is sent. It is rebuilt from the current order data immediately before sending, so a cancellation or an address change in the first minutes never reaches the ledger. Once sent, a document is immutable; a later change to the order produces an adjustment or a credit note instead.

What is created in Fortnox

  • A customer per e-mail address, created or updated on first use.
  • An article per SKU. Fortnox articles are not stock-keeping; MPH remains the stock master.
  • The invoice, in the order's own currency. A currency Fortnox does not know blocks the push until it is added to the currency register there.

If MPH loses contact with Fortnox after the invoice was created but before the reference was saved, the retry finds the existing invoice and adopts it rather than creating a second one.

Payment methods

Settings → Accounting → Payment methods holds one row per payment method the sales channel sends (for example shopify_payments, klarna, manual). Each row decides what happens to the document:

SettingEffect
Hold for reviewThe document stays in the review queue until someone approves it. Use for invoice or prepayment orders, which are often business purchases.
Post automaticallyBook the invoice in Fortnox rather than leaving it as an unposted draft.
Mark as paidRegister the payment on the invoice straight away, against the payment account, instead of leaving it open.

Post automatically and mark as paid are separate on purpose: an invoice can be posted automatically while still sitting open in the ledger. An unmapped payment method defaults to review, never to a guess.

For a payment provider that pays you in batches, such as Shopify Payments, there are two ways to get the invoice marked as paid: here, at invoice time, or when the payout arrives. Payouts explains the difference and why you should pick one.

The review queue

Finance → Review queue lists every document that was held back before reaching the ledger, grouped by what is blocking it. The button offered depends on the cause, and only appears where it can succeed:

  • Approve & send lifts a hold that a payment method's Hold for review raised. Someone has looked at the order and says it is fine to book.
  • Retry covers the rest. A document that failed on the way to Fortnox, for example during an outage, is simply sent again. A data hold (a missing account mapping, an amount that did not reconcile, a missing exchange rate) is built again from the order, so fix the cause first: add the mapping, add the rate, correct the order. Retrying without fixing the cause puts the document straight back in the queue.

Retry all at the top of the queue does the same for every document at once, for the common case where one fix, such as a new account mapping, unblocks many documents.

Several sets of books

An organization can hold more than one connected set of books, for separate legal entities. Each has its own chart of accounts, its own voucher series and its own OSS report. An order is booked into the ledger that its sales channel points to; channels with no explicit ledger use the default.

Reports

  • Finance → OSS report summarises EU distance sales per destination country and VAT rate for the period, from the documents that reached the ledger.
  • Finance → Payouts lists every payout and its status. See Payouts.

Permissions

PermissionAllows
accounting:readView accounting documents, payouts and VAT reports
accounting:manageEdit account mappings, payment methods and payout settings, and post to the ledger

What a ledger plugin declares

Every accounting system is a plugin under plugins/accounting-*, built on @mph-wms/plugin-sdk/accounting. The app never names a ledger: the settings pages, the connect flow and the checks on the account mapping read what the plugin's manifest says about itself, and the sentences around those facts stay in MPH's own translations.

Manifest fieldWhat it drives
authHow a company connects. oauth2 names the config keys for the app's client id and secret, and the Connect button goes straight to the provider. api_key lists the fields the merchant pastes (stored encrypted under apiKey, apiSecret or accessToken), and the app renders a generic connect form from them.
vatRatesThe VAT rates a fresh company in that ledger knows. The account mapping flags a row whose rate is not in the list. Leave it out if the ledger accepts any rate.
linksHelp pages in the ledger's own documentation for vatRates, chartOfAccounts and vatAccounts. They appear under the matching warnings in the account mapping.
iconA generic word for the card on the add-integration page, such as ledger.
connectPathWhere the connect flow starts, when it is not the default for the auth type.
docsUrlThe provider's setup guide, linked from the connect form.

Adding a ledger

  1. Write the manifest with auth, and vatRates, links, icon and connectPath where they apply.
  2. Implement the connector. An api_key ledger must implement verifyCredentials, so a mistyped key fails on the form rather than at the first push.
  3. Implement fetchCompany if the ledger can report the company's base currency. Without it, the operator sets the base currency on the connection's settings tab.
  4. Add a config group in core/config/src/schema.ts for every key the manifest names (clientIdKey and clientSecretKey for OAuth, appKeys for an API-key ledger with an app identity of its own). Then run pnpm --filter @mph-wms/config gen so .env.example follows.
  5. Add a catalogue line to INTEGRATION_PROVIDERS in core/shared, with category: "accounting", so the ledger is offered on the add-integration page.
  6. Import the plugin in core/plugin-host/src/register.ts.
  7. Run pnpm --filter @mph-wms/plugin-host test. It fails when a shipped plugin has no catalogue line, or declares a capability its connector does not implement.

The web app and the worker may not import a ledger plugin package directly. Lint fails the build if they do, because everything they need comes through the manifest.

On this page