---
id: DOM-ACC-BAT-003
title: Posting
realises: CON-ACC-BAT-003
product_area: accounting
module: batches
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-ACC-BAT-batches
readable_by: []
lifecycle: STATE-ACC-BAT-004
custom_fields: none
identity: >-
  Ordinary posting records use workspace-scoped identities attached to one
  batch; fiscal system postings use the caller event key. Job identity
  incorporates workspace, kind, unit, sorted batch set and request key to
  recognize the same submission.
attributes:
  - name: batch and business unit
    kind: reference
    required: true
    computed: false
    notes: >-
      The completed collection and its business unit, protected by same-unit
      references.
  - name: posted at and by
    kind: date
    required: true
    computed: true
    notes: >-
      The generation timestamp and requesting actor retained on the posting
      record.
  - name: posting job
    kind: reference
    required: false
    computed: false
    notes: >-
      Optional originating job identity; system postings created by fiscal close
      have no batch-posting job.
  - name: reversed at and by job
    kind: date
    required: false
    computed: true
    notes: >-
      The retirement timestamp and reversing job link retained after ordinary
      unposting or fiscal reopening.
  - name: job · kind and subject
    kind: enum
    required: true
    computed: false
    notes: >-
      Posting and unposting are distinct job kinds with batch-set and unit
      subjects.
  - name: job · batches
    kind: collection
    required: true
    computed: false
    notes: >-
      HTTP schemas accept one to one hundred batches. Internal submission and
      storage permit up to two hundred; execution validates membership in the
      requested unit.
  - name: job · empty-batch option
    kind: enum
    required: false
    computed: false
    notes: >-
      Submission retains this option, but empty-batch deletion during generation
      does not honor it.
  - name: job · steps and events
    kind: collection
    required: true
    computed: true
    notes: >-
      Two observable phases cover checking and writing or removal. The console
      interprets structured information from fixed-format progress messages.
  - name: job · result
    kind: computed
    required: false
    computed: true
    notes: >-
      Completion reports posted and errored batch sets, or unposted batches and
      the deleted-entry count.
  - name: resolved account snapshot
    kind: collection
    required: false
    computed: true
    notes: >-
      Posting writes resolved accounts, dimensions, deferral, splits, discounts,
      accounting method and resolution time onto document lines; tax-line
      snapshots retain the payable account.
  - name: inter-unit account pairs
    kind: collection
    required: false
    computed: false
    notes: >-
      Stored receivable and liability mappings between business units, consumed
      during posting. No management writer is established in this module.
relationships:
  - to: DOM-ACC-BAT-001
    cardinality: many-to-one
    ownership: A posting remains a child of its batch.
    cross_service: false
  - to: DOM-ACC-BAT-004
    cardinality: one-to-many
    ownership: The posting generation owns its ledger headers and lines.
    cross_service: false
  - to: DOM-ACC-BAT-005
    cardinality: one-to-many
    ownership: Generated revenue plans belong to the posting that created them.
    cross_service: false
invariants:
  - id: INV-DOM-ACC-BAT-003-01
    statement: The database permits no more than one unreversed posting for a batch.
    enforced_at:
      - database
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/persistence/subledger-entries.integration.spec.js#refuses
      a second unreversed posting of one batch, by the partial unique index
  - id: INV-DOM-ACC-BAT-003-02
    statement: >-
      Submission returns the existing job for the same request, an equivalent
      in-flight batch set, or a completed job that still accounts for the
      requested posted set.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/jobs/submission-identity.integration.spec.js#answers
      a colleague's retry under another key, after the posting finished, with
      the job that posted (DEF-ACT-0514)
  - id: INV-DOM-ACC-BAT-003-03
    statement: >-
      Accounting writes within one posting transaction commit together; a
      refused transactional write rolls them back and fails the job.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/jobs/deployed-task-handler.integration.spec.js#fails
      the job on a step the database refuses: refused once, recorded by the
      failure task, the batch open and nothing written
  - id: INV-DOM-ACC-BAT-003-04
    statement: >-
      Posted-line snapshots preserve resolved accounts, and later configuration
      changes do not rewrite those snapshots or the existing ledger.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/posting/gl-resolution-at-posting.integration.spec.js#alters
      neither October’s posted entries nor its snapshot
  - id: INV-DOM-ACC-BAT-003-05
    statement: >-
      Ordinary unposting retains the posting record with its retirement
      timestamp and unposting job link.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/posting/unpost-deletes-entries.integration.spec.js#keeps
      the posting history: the first posting reversed, the second current
  - id: INV-DOM-ACC-BAT-003-06
    statement: >-
      A successfully read Posted or Downloaded dependent outside the request
      blocks unposting. The implementation omits dependent reads that reject.
    enforced_at:
      - service
    provenance: observed
    source: >-
      services-accounting:modules/batches/services/rules/batch-posting-rules.ts:ensureBatchesCanBeUnposted
  - id: INV-DOM-ACC-BAT-003-07
    statement: >-
      A fiscal event key cannot be reused for a different system posting
      request.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/batches/tests/integration/services/close/post-system-batch.integration.spec.js#is
      refused with other entries (`event_key_reused`)
physical:
  - accounting.batch_postings
  - accounting.batch_posting_jobs
  - accounting.batch_posting_job_steps
  - accounting.batch_posting_job_events
  - accounting.batch_unposting_jobs
  - accounting.batch_unposting_job_steps
  - accounting.batch_unposting_job_events
  - accounting.business_unit_inter_entity_accounts
evidence:
  - >-
    services-accounting at f47cb263: modules/batches/db/batch-postings.table.ts,
    batch-posting-jobs.table.ts, business-unit-inter-entity-accounts.table.ts;
    services/jobs/**; services/engine/post-batches.ts, unpost-batches.ts,
    posted-accounting.ts; services/persistence/batch-postings.ts,
    batch-posting-jobs.ts; services/close/system-batches.ts;
    docs/migrations/batch-posting/DESIGN.md (D3, D6); docs/accounting/batches.md
  - >-
    react-console at baf6dae3:
    components/accounting/batches/batch-posting-panel.tsx,
    batch-posting-model.ts
  - 'FND-ACC-BAT-051: dependent read failure and concurrency limits'
---

# Posting

## What It Models

A posting connects reviewed documents to a recorded accounting generation. The logical object includes the durable execution job and the account-resolution snapshots, because together they explain what ran and which configuration it used.

## Identity and Attributes

Posting history and job identity answer different questions. The former tracks accounting generations; the latter identifies submissions and watched execution. The attribute rows distinguish their boundaries, including the separate HTTP and internal batch limits.

## Relationships

Batches contain posting history, and each generation owns its entries and revenue plans. Platform presents the job records to the console. Snapshot columns remain physically on Transactions document lines while posting controls their accounting content.

## Invariants

The invariant rows cover generation uniqueness, submission reuse, transaction boundaries and retained resolution. Dependent protection applies only to successfully read dependents; it is not a proved concurrency guarantee.

## How It Is Stored and Shared

The Accounting database stores posting records under workspace security and job families under the durable-job storage contract. Job roots deliberately support cross-workspace operational views rather than sharing posting-record row policies. The console follows the Platform job interface.

## Open Design Questions

Start reconciliation is missing. A settlement failure after accounting commit can produce a failed job beside completed accounting. Product also needs a reliable dependency check and a consistent submission-size policy.
