The Account Mapping page tells BuyerKiosk which QuickBooks Online account to use for each field on your daily POS close report. Without complete mappings the system can't post journal entries, so this is the first thing to set up after connecting to QBO.

> **Permissions:** Admin-only. You need the `quickbooks_config` permission for the store.

***

## Where to find it

From the sidebar: **QuickBooks** > **Account Mapping**. Direct URL: `/admin/{typeNum}/quickbooks/mapping`.

The Dashboard shows your mapping completeness as a percentage ("X of Y fields mapped"). 100% means you can post.

***

## How mapping works

Your nightly close report has ~36 financial fields (cashTendered, totalSales, taxCollected, newReturns, buyPaidCash, etc.). Each field needs to map to:

1. A **QBO account** — where the value goes (e.g. `Cash`, `Sales Income`, `Sales Tax Payable`).
2. An **entry type** — `debit` or `credit`. This is the *base* direction for a positive value.
3. Optionally an **offset account** — when the field's accounting effect needs a balancing entry (e.g. cash + a corresponding revenue line).

When the nightly job runs, the system reads each field, looks up its mapping, and emits a journal line. The lines are summed to verify debits = credits.

***

## Required (critical) fields

Some mappings are required for any sync to succeed. If any of these are blank, the Approval Queue blocks approval with a "Mapping incomplete" error:

- `cashTendered`
- `totalSales`
- `taxCollected`
- `newReturns`
- `usedReturns`
- `cashOverShort`
- `buyPaidCash`

Optional fields (gift cards, store credits issued, etc.) can be left unmapped if your store doesn't use them — the system simply skips fields with no mapping.

***

## Setting a mapping

For each row in the table:

1. Click the QBO account dropdown. The list is fetched live from your connected QBO company file.
2. Type to filter. Select the correct account.
3. Optionally set an offset account if the row needs one.
4. Click `Save`.

Mappings save individually per row, so you can finish setup over time.

> **Tip:** A mapping change is logged to the Audit Log as a `mapping_updated` event. If a future variance turns out to be a mis-mapping, you can prove exactly when the mapping was changed and by whom.

***

## Sign semantics (read this if you map Returns or Refunds)

POS data uses **negative numbers as a labeling convention** for things like returns: `newReturns: -3.99` means "a return of $3.99," not "negative $3.99 owed somewhere."

Each mapping row has a **`signSemantics`** column that controls how the system interprets the source value's sign:

| Setting | Meaning | When to use |
| ------- | ------- | ----------- |
| `directional` *(default)* | The sign of the source value carries meaning. Negative source values flip the entryType (DR ↔ CR). | Fields where positive vs negative is real (e.g. `cashOverShort`: positive = drawer over, negative = drawer short — both legs need opposite-side posting). |
| `absolute` | The sign of the source value is just a labeling convention and the entryType is the truth. The amount is always abs(value). | Fields where negative is just how the POS labels something (returns, refunds, void counts). |

For most fields you'll never need to think about this — the system seeds sensible defaults. The `ABS` badge next to a row's DR/CR badge indicates an `absolute` mapping; everything else is `directional`.

| Field | `entryType` | `signSemantics` | Source `-3.99` | Posted as |
| ----- | ----------- | --------------- | -------------- | --------- |
| `newReturns` | `debit` | `absolute` | ignored | DEBIT $3.99 to contra-revenue ✓ |
| `usedReturns` | `debit` | `absolute` | ignored | DEBIT $3.99 to contra-revenue ✓ |
| `totalSales` | `credit` | `directional` | (always positive) | CREDIT to Sales Revenue |
| `cashOverShort` | `credit` | `directional` | matters: -$5 → DR (short = expense) | DEBIT $5 to Cash Over/Short |

> **Note for accountants/bookkeepers:** if a row's DR/CR badge looks "backwards" for what the field is, check whether it has an **ABS** badge. If yes, the entryType is the actual posting direction — the source value's sign is decoration only. Without ABS, expect negative source values to flip the posting direction.

> **Historical context:** older versions of BuyerKiosk used an implicit sign-flip without the `signSemantics` column — the same end result, but mapping rows read "backwards" (e.g. newReturns mapped as `credit` but actually posting as DEBIT). Migration `048_010` introduced the explicit column and atomically migrated those rows so the mapping reads correctly. If you've used BuyerKiosk pre-Phase-2 you'll see those rows have flipped from `credit` to `debit` + gained the `ABS` badge — math output is identical to before.

***

## Offset accounts

Most POS fields imply a paired entry. Cash paid for a buy debits the **Cash** asset account and credits the **Inventory** asset account; cash tendered for a sale debits **Cash** and credits **Sales Revenue**. The mapping page now has a per-row **Offset** dropdown to express this directly.

When you set an offset account on a field, the daily sync emits **two** journal lines per non-zero source value: the primary line at the field's main account, and a mirror-direction offset line at the offset account. So a `$10.00 cashTendered` field with primary `Cash` (DR) and offset `Sales Revenue` (CR) posts:

```
DR  $10.00  Cash
CR  $10.00  Sales Revenue
```

That single field then balances internally — debits = credits for that pair — regardless of what's happening with other fields on the same close report.

**When to leave the offset blank ("single-sided"):**

Some fields don't have a natural double-entry partner inside the same close report. The dropdown's first option is `-- (single-sided, no offset) --` for these. Examples:

- `cashOverShort` — the partner is the cash account, but cashOverShort itself stands alone in QBO as either an expense or expense reduction.
- Fields where another field on the same report is implicitly the partner (e.g. `cashTendered` and `totalSales` may already balance each other out without explicit offsets).

If you're not sure whether to set an offset, check whether your daily JE balances when you leave it single-sided. If you see consistent variance, the field probably needs an offset. The Approval Queue's balance banner (see [Daily approval workflow](/support/articles/quickbooks-daily-approval-workflow)) flags imbalances explicitly so you can iterate.

> **Tip:** Setting offsets on every field that has a logical partner makes your daily JE balance to the penny on day one, instead of leaning on Cash Over/Short to absorb the gap. Time well spent during initial setup.

***

## Mid-period changes

You *can* change a mapping at any time, but think about timing:

- A mapping change applies to the **next** sync. Already-posted journal entries are not retroactively re-posted.
- If you change a mapping mid-month and have already posted entries that used the old mapping, your books will have a mix. Either accept this and document the change date, or void the affected entries and re-post.

The Audit Log's `mapping_updated` event preserves the old → new account ids, so you can always reconstruct what was active when.

***

## Reconnecting QBO and your mappings

If you disconnect and reconnect to a *different* QBO company file, your mapped account ids will no longer be valid (each QBO company has its own account id space). The system shows a banner if any mapped account no longer exists in the connected file. You'll need to re-map fields one by one.

***

## What's next

- [Connect & configure](/support/articles/quickbooks-connect-and-configure) — required first step before mapping.
- [Daily approval workflow](/support/articles/quickbooks-daily-approval-workflow) — what to do once mappings are complete.
- [Reconciliation & audit](/support/articles/quickbooks-reconciliation-and-audit) — verifying mappings produce correct totals.
