---
id: TST-ACC-TRX-081
title: Receive offline suite
kind: integration
product_area: accounting
module: transactions
revision: 1
status: draft
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
repository: services-accounting
files:
  - >-
    modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js
implements:
  - ATS-ACC-TRX-006-01
  - ATS-ACC-TRX-006-03
  - ATS-ACC-TRX-006-04
  - ATS-ACC-TRX-006-05
  - ATS-ACC-TRX-006-06
  - ATS-ACC-TRX-006-07
  - ATS-ACC-TRX-008-01
  - ATS-ACC-TRX-008-03
  - ATS-ACC-TRX-008-08
  - ATS-ACC-TRX-020-04
implements_parts:
  - scenario: ATS-ACC-TRX-006-01
    assertion: it refuses an amount in another currency (currency_mismatch)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses an amount in another currency (currency_mismatch)
  - scenario: ATS-ACC-TRX-006-03
    assertion: it refuses a bank account of another unit (cash_account_mismatch)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a bank account of another unit (cash_account_mismatch)
  - scenario: ATS-ACC-TRX-006-03
    assertion: it refuses a bank account in another currency (cash_account_mismatch)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a bank account in another currency (cash_account_mismatch)
  - scenario: ATS-ACC-TRX-006-03
    assertion: it refuses a check with no bank account (cash_account_mismatch)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a check with no bank account (cash_account_mismatch)
  - scenario: ATS-ACC-TRX-006-04
    assertion: >-
      it refuses a payment naming no batch in a unit with no batch assignment
      rule (batch_required), writing nothing
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a payment naming no batch in a unit with no batch assignment rule
      (batch_required), writing nothing
  - scenario: ATS-ACC-TRX-006-05
    assertion: it refuses a date in no open period (period_not_open)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a date in no open period (period_not_open)
  - scenario: ATS-ACC-TRX-006-06
    assertion: >-
      it numbers the tenant’s first payment 1,000,000, succeeded, in the bank
      account and the unit’s batch
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      numbers the tenant’s first payment 1,000,000, succeeded, in the bank
      account and the unit’s batch
  - scenario: ATS-ACC-TRX-006-06
    assertion: 'it numbers the next payment 1,000,001'
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      numbers the next payment 1,000,001
  - scenario: ATS-ACC-TRX-006-07
    assertion: it pays the rest of the invoice (1000) and leaves 1500 unapplied
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      pays the rest of the invoice (1000) and leaves 1500 unapplied
  - scenario: ATS-ACC-TRX-006-07
    assertion: >-
      it writes the payment item’s facts: minus the whole amount, then plus each
      allocation, summing to minus the unapplied money
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      writes the payment item’s facts: minus the whole amount, then plus each
      allocation, summing to minus the unapplied money
  - scenario: ATS-ACC-TRX-008-01
    assertion: it refuses a draft invoice’s line (invoice_not_draft)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a draft invoice’s line (invoice_not_draft)
  - scenario: ATS-ACC-TRX-008-01
    assertion: it refuses an invoice of another unit (business_unit_mismatch)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses an invoice of another unit (business_unit_mismatch)
  - scenario: ATS-ACC-TRX-008-03
    assertion: >-
      it allocates the line target exactly and the invoice target by pay
      priority, the second line taking the 3000
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      allocates the line target exactly and the invoice target by pay priority,
      the second line taking the 3000
  - scenario: ATS-ACC-TRX-008-08
    assertion: >-
      it converts an unconverted pro forma the first payment names, in the
      payment’s batch, and pays it (Commerce’s first payment makes it real)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      converts an unconverted pro forma the first payment names, in the
      payment’s batch, and pays it (Commerce’s first payment makes it real)
  - scenario: ATS-ACC-TRX-020-04
    assertion: >-
      it refuses another principal’s use of the key (idempotency_key_in_use,
      409, naming the key), never an unhandled error (DEF-ACT-0800)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses another principal’s use of the key (idempotency_key_in_use, 409,
      naming the key), never an unhandled error (DEF-ACT-0800)
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 3
isolation: >-
  Suite-marked records in the prepared local test database; fixture teardown
  removes owned records.
provenance: test
source: >-
  services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js
evidence:
  - provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js
    assertion_titles:
      - 'receivePayment, offline (integration)'
      - >-
        a check of 10000 allocated 6000 to the first line and the rest to the
        invoice
      - >-
        numbers the tenant’s first payment 1,000,000, succeeded, in the bank
        account and the unit’s batch
      - >-
        allocates the line target exactly and the invoice target by pay
        priority, the second line taking the 3000
      - >-
        raises the lines’ amount_paid and lowers their balances: the first line
        is paid, the second still owes 1000
      - answers the payment with its allocations and amounts in minor units
      - >-
        writes the payment item’s facts: minus the whole amount, then plus each
        allocation, summing to minus the unapplied money
      - >-
        writes each line’s allocation fact, so the invoice’s facts sum to its
        balance
      - records the record document event and the payment events
      - 'numbers the next payment 1,000,001'
      - 'replays the same key and body as the same payment, writing nothing'
      - refuses the same key with another body (idempotency_key_reused)
      - >-
        refuses another principal’s use of the key (idempotency_key_in_use, 409,
        naming the key), never an unhandled error (DEF-ACT-0800)
      - >-
        refuses a payment naming no batch in a unit with no batch assignment
        rule (batch_required), writing nothing
      - >-
        an invoice target with no amount takes as much as the invoice owes, up
        to the money
      - pays the rest of the invoice (1000) and leaves 1500 unapplied
      - refuses nothing_to_allocate when the invoice owes nothing more
      - a pro forma named by the first payment
      - >-
        converts an unconverted pro forma the first payment names, in the
        payment’s batch, and pays it (Commerce’s first payment makes it real)
      - 'its refusals, each leaving nothing'
      - refuses a bank account of another unit (cash_account_mismatch)
      - refuses a bank account in another currency (cash_account_mismatch)
      - refuses a check with no bank account (cash_account_mismatch)
      - refuses an amount in another currency (currency_mismatch)
      - refuses more on a line than it owes (over_application)
      - refuses more on an invoice than it can take (over_application)
      - refuses allocating more than the payment holds (over_application)
      - refuses a draft invoice’s line (invoice_not_draft)
      - refuses an invoice of another unit (business_unit_mismatch)
      - refuses a date in no open period (period_not_open)
    imports:
      - 'const { sql } = require(''drizzle-orm'');'
      - 'const { stage } = require(''@rhythmsoftware/macroservice-testing/stage'');'
      - >-
        const { createDraft } =
        require('../../../../services/invoices/invoice-drafts');
      - >-
        const { receivePayment } =
        require('../../../../services/payments/payment-receive');
      - '} = require(''../../payments-fixtures'');'
      - >-
        const { TEST_CLOCK } =
        require('@rhythmsoftware/macroservice-testing/execution-context');
      - "\t\t\tconst { invoice } = world.require();"
      - "\t\t\tconst { payment } = paid.require();"
      - "\t\t\tconst { invoice, payment } = paid.require();"
      - "\t\t\tconst { invoice } = paid.require();"
      - "\t\t\tconst { invoice, payment } = paid.require();"
      - "\t\t\tconst { payment } = paid.require();"
      - "\t\t\tconst { invoice } = paid.require();"
      - "\t\t\tconst { payment } = paid.require();"
      - "\t\t\tconst { invoice, payment } = paid.require();"
      - "\t\t\tconst { invoice } = world.require();"
      - "\t\t\tconst { invoice } = world.require();"
    test_double_declarations: []
---

# Receive offline suite

## Verification Boundary

The suite exercises transaction commands and database protections in the local prepared test environment. Registration records the existing executable file; it does not report a run or establish product approval.

## What This Suite Proves

Its cited assertions contribute evidence for invalid money cannot become a receipt; offline destination matches the receipt context; receipt batching follows explicit or assigned choice; uncovered accounting dates prevent receipt entry; receipt numbering advances in its own sequence; excess receipt value remains held; allocation rejects incompatible invoice context; target granularity controls distribution; first payment recognizes the quote; another actor cannot reuse a held key. The structured assertion bindings identify which parts of combined scenarios it executes.

## What It Does Not Prove

Local commands and route invocations do not establish deployed routing, live processor guarantees or the complete staff browser experience. An unbound feature chain remains proposed, and this registration carries no execution result.

## Real Dependencies and Test Doubles

The suite uses the imported commands, route handlers or persistence code against the local test database. Fixture helpers supply accounting context; any stepped clock, dummy processor or substituted external client is retained in the evidence declarations.

## Must Not Be Doubled

The command or persistence behavior under assertion and its relevant database protections must remain real. Substituting the final financial result removes evidence of transactional effects.
