---
id: TST-ACC-TRX-122
title: Card fees 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/settlements/card-fees.integration.spec.js
implements:
  - ATS-ACC-TRX-009-08
  - ATS-ACC-TRX-009-09
  - ATS-ACC-TRX-009-10
  - ATS-ACC-TRX-012-10
  - ATS-ACC-TRX-013-06
  - ATS-ACC-TRX-014-07
implements_parts:
  - scenario: ATS-ACC-TRX-009-08
    assertion: >-
      it charges 10280 in one tender: the invoice and the fee of 280 (2.5% + 30)
      both paid, the step card_fee done, the fee invoice answered
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      charges 10280 in one tender: the invoice and the fee of 280 (2.5% + 30)
      both paid, the step card_fee done, the fee invoice answered
  - scenario: ATS-ACC-TRX-009-08
    assertion: >-
      it shares one fee over two required invoices in proportion, the fixed
      amount charged once: 20000 at 2.5% + 30 is 530
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      shares one fee over two required invoices in proportion, the fixed amount
      charged once: 20000 at 2.5% + 30 is 530
  - scenario: ATS-ACC-TRX-009-08
    assertion: >-
      it charges the fee on the required invoice’s share alone: 20280 for a
      required and a none invoice of 10000 each
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      charges the fee on the required invoice’s share alone: 20280 for a
      required and a none invoice of 10000 each
  - scenario: ATS-ACC-TRX-009-08
    assertion: it is charged when the payer accepts it
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      is charged when the payer accepts it
  - scenario: ATS-ACC-TRX-009-08
    assertion: >-
      it computes the fee on the 4000 tendered (130), charges 4130, and leaves
      the invoice owing 6000
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      computes the fee on the 4000 tendered (130), charges 4130, and leaves the
      invoice owing 6000
  - scenario: ATS-ACC-TRX-009-09
    assertion: >-
      it refuses the settlement with card_fee_required naming the invoice, and
      writes nothing
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      refuses the settlement with card_fee_required naming the invoice, and
      writes nothing
  - scenario: ATS-ACC-TRX-009-09
    assertion: >-
      it refuses a card paying a required invoice: card_fee_rule_missing names
      the unit and the invoice, nothing written
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      refuses a card paying a required invoice: card_fee_rule_missing names the
      unit and the invoice, nothing written
  - scenario: ATS-ACC-TRX-009-09
    assertion: it charges no fee on a check paying a required invoice
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      charges no fee on a check paying a required invoice
  - scenario: ATS-ACC-TRX-009-09
    assertion: >-
      it charges no fee on an electronic check unless the unit’s rule charges
      them, then the same fee as a card
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      charges no fee on an electronic check unless the unit’s rule charges them,
      then the same fee as a card
  - scenario: ATS-ACC-TRX-009-10
    assertion: >-
      it fails the settlement and voids the fee invoice it had issued, the
      invoice left owing
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      fails the settlement and voids the fee invoice it had issued, the invoice
      left owing
  - scenario: ATS-ACC-TRX-012-10
    assertion: >-
      it takes the fee’s share back with the line: 2000 of 4000 refunded is
      2065, the fee invoice credited 65
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      takes the fee’s share back with the line: 2000 of 4000 refunded is 2065,
      the fee invoice credited 65
  - scenario: ATS-ACC-TRX-012-10
    assertion: >-
      it credits the fee’s share even when the line is reopened: 1000 more is
      1032, the fee invoice credited 97 in all, the line owing 1000
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      credits the fee’s share even when the line is reopened: 1000 more is 1032,
      the fee invoice credited 97 in all, the line owing 1000
  - scenario: ATS-ACC-TRX-013-06
    assertion: >-
      it credits the fee invoice whole once the void reopens it: no money, no
      fee; the invoice owes again
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      credits the fee invoice whole once the void reopens it: no money, no fee;
      the invoice owes again
  - scenario: ATS-ACC-TRX-014-07
    assertion: >-
      it credits the fee’s share of the reversed money off the fee invoice and
      frees it with the rest: 4000 of 10000 reversed frees 4112
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js#it
      credits the fee’s share of the reversed money off the fee invoice and
      frees it with the rest: 4000 of 10000 reversed frees 4112
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/settlements/card-fees.integration.spec.js
evidence:
  - provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/settlements/card-fees.integration.spec.js
    assertion_titles:
      - the card processing fee at tender (integration)
      - before the unit has a rule
      - >-
        refuses a card paying a required invoice: card_fee_rule_missing names
        the unit and the invoice, nothing written
      - >-
        charges nothing on an optional invoice: there is no fee to offer, the
        card pays the invoice alone
      - the rule on the unit
      - >-
        answers the rule as written: the percent as a decimal string, the
        amounts as integers, the default policy still none
      - the policy on the invoice
      - >-
        stamps the request’s policy, else the unit’s default (none), on the
        draft and keeps it through the issue
      - >-
        takes the unit’s default when it is optional, and a fee invoice is never
        itself fee-bearing
      - >-
        freezes the policy with the issued invoice: the database refuses a
        change (RHA04)
      - a card paying a required invoice whole
      - >-
        charges 10280 in one tender: the invoice and the fee of 280 (2.5% + 30)
        both paid, the step card_fee done, the fee invoice answered
      - >-
        issued the fee invoice as one line of the fee product, to the same
        customer, in the settlement’s batch, dated with it, naming the invoice
      - >-
        replays the same key as the same settlement, with one fee invoice, not
        two
      - an optional fee
      - is charged when the payer accepts it
      - 'is not charged when the payer declines it, or was not asked'
      - a required fee declined
      - >-
        refuses the settlement with card_fee_required naming the invoice, and
        writes nothing
      - mixed policies in one tender
      - >-
        charges the fee on the required invoice’s share alone: 20280 for a
        required and a none invoice of 10000 each
      - >-
        shares one fee over two required invoices in proportion, the fixed
        amount charged once: 20000 at 2.5% + 30 is 530
      - a partial card payment
      - >-
        computes the fee on the 4000 tendered (130), charges 4130, and leaves
        the invoice owing 6000
      - offline tenders and electronic checks
      - charges no fee on a check paying a required invoice
      - >-
        charges no fee on an electronic check unless the unit’s rule charges
        them, then the same fee as a card
      - a card the processor declines
      - >-
        fails the settlement and voids the fee invoice it had issued, the
        invoice left owing
      - a direct card payment
      - >-
        raises the charge by the fee: a payment of 10280 allocated to the
        invoice and to the fee invoice its intent issued
      - >-
        refuses a required fee declined (card_fee_required) before any charge,
        and voids the fee invoice of a declined card
      - a card payment voided
      - >-
        credits the fee invoice whole once the void reopens it: no money, no
        fee; the invoice owes again
      - the reversal operation on a card-paid invoice
      - >-
        credits the fee’s share of the reversed money off the fee invoice and
        frees it with the rest: 4000 of 10000 reversed frees 4112
      - a refund by line of a card payment
      - >-
        takes the fee’s share back with the line: 2000 of 4000 refunded is 2065,
        the fee invoice credited 65
      - >-
        credits the fee’s share even when the line is reopened: 1000 more is
        1032, the fee invoice credited 97 in all, the line owing 1000
    imports:
      - 'const { sql } = require(''drizzle-orm'');'
      - 'const { stage } = require(''@rhythmsoftware/macroservice-testing/stage'');'
      - >-
        const { getBusinessUnit, updateBusinessUnit } =
        require('../../../../../books/services/persistence/business-units');
      - >-
        const { createProduct } =
        require('../../../../../products/services/persistence/products');
      - >-
        const { createDraft } =
        require('../../../../services/invoices/invoice-drafts');
      - >-
        const { issueInvoice } =
        require('../../../../services/invoices/invoice-issue');
      - >-
        const { receivePayment } =
        require('../../../../services/payments/payment-receive');
      - >-
        const { reversePayment } =
        require('../../../../services/payments/payment-reverse');
      - >-
        const { executeRefund, requestRefund } =
        require('../../../../services/refunds/refund-commands');
      - >-
        const { reverseBilling } =
        require('../../../../services/reversals/reversal-commands');
      - >-
        const { findSettlementOfKey, settle } =
        require('../../../../services/settlements/settlement-commands');
      - '} = require(''../../payments-fixtures'');'
      - "\t\tworld.require();"
      - "\t\tnoRule.require();"
      - "\t\t\tconst { required, refusal, settlementRow, fees } = noRule.require();"
      - "\t\t\tconst { outcome } = noRule.require();"
      - "\t\t\texpect(ruleOf(ruled.require())).to.deep.equal({"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\tconst { invoice, outcome } = paid.require();"
      - "\t\t\tconst { invoice, outcome } = paid.require();"
      - "\t\t\tconst { invoice, outcome } = paid.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\tconst { invoice, outcome } = partial.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\tconst { invoice, payment } = direct.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\truled.require();"
      - "\t\t\t\truled.require();"
      - "\t\t\tconst { invoice, outcome, credited } = refunded.require();"
      - "\t\t\tconst { invoice, outcome, reopened } = refunded.require();"
    test_double_declarations: []
---

# Card fees 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 one fee follows eligible card value; required fees block incompatible tenders; failed tender compensates its fee document; return includes its processing-fee share; void eliminates the full associated fee; billing reversal frees its fee share. 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.
