Skip to content

feat(numbering): per-tenant counter store + runtime + shell settings (N2)#6384

Merged
delchev merged 1 commit into
masterfrom
feat/intent-numbering-n2-store
Jul 22, 2026
Merged

feat(numbering): per-tenant counter store + runtime + shell settings (N2)#6384
delchev merged 1 commit into
masterfrom
feat/intent-numbering-n2-store

Conversation

@delchev

@delchev delchev commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

N2 of first-class document numbering (UPSTREAM_PLAN #11a) — the runtime the DSL (N1, #6382) generates against, plus the application-shell management surface.

New module components/engine/engine-numbering

  • DocumentNumberStore — a per-tenant DIRIGIBLE_DOCUMENT_NUMBERS table (tenant-routed default datasource + SqlFactory, like DIRIGIBLE_CONFIGURATIONS), keyed by (series, scope). allocate() is gap-free — the increment takes a row lock so concurrent allocations of the same counter serialize; the row is created on first use.
  • DocumentNumberService — allocate + the format grammar ({seq}/{seq:0N}, {series}, scope tokens {year}/{<Field>}) + scope-key derivation; list()/setNext() for management.
  • DocumentNumberEndpoint/services/core/numbering (ADMINISTRATOR/OPERATOR): GET the tenant's counters, PUT the next value a counter allocates.

Application shell (resources-application)

A built-in Document Numbering Settings entry (beside Region & Language / Tenant Configuration): lists the counters and lets an admin set each series' next value — reset/seed a sequence (e.g. start invoices at 1000); read-only on a 403.

Verified

Booted instance: GET[]; PUT {series:"SalesInvoice",next:1000} → 204; GET[{series:"SalesInvoice",scope:"",counter:999}] (next allocate = 1000). The settings page + appShell.js serve the new entry. DocumentNumberServiceTest covers the format renderer + scope-key.

Next

  • N3 — the SDK entry (sdk.numbering.*) + generated stamping (stampOn: create/issue) + create-time placeholder + idempotency, wired to the N1 number: attribute.
  • N4 — scope/resetOn (year + field partitioning).

Independent of #6382 (N1) — the DSL and the runtime meet in N3.

🤖 Generated with Claude Code

… shell settings (N2)

N2 of first-class document numbering (kf-catalog UPSTREAM_PLAN #11a): the runtime the DSL (N1,
#6382) will generate against, plus the application-shell settings surface.

New module components/engine/engine-numbering:
- DocumentNumberStore — a per-tenant DIRIGIBLE_DOCUMENT_NUMBERS table (via the tenant-routed default
  datasource + SqlFactory, like DIRIGIBLE_CONFIGURATIONS), keyed by (series, scope). allocate() is
  gap-free: the increment takes a row lock so concurrent allocations of the same counter serialize;
  the row is created on first use.
- DocumentNumberService — allocate + the format grammar ({seq}/{seq:0N} zero-pad, {series}, and scope
  tokens {year}/{<Field>}) + scope-key derivation; plus list()/setNext() for management.
- DocumentNumberEndpoint — /services/core/numbering (ADMINISTRATOR/OPERATOR): GET the tenant's
  counters, PUT the next value a (series, scope) counter will allocate.

Application shell (resources-application) — a built-in "Document Numbering" Settings entry (next to
Region & Language / Tenant Configuration): lists the counters and lets an admin set each series'
next value (reset/seed a sequence, e.g. start invoices at 1000); read-only on a 403.

Verified on a booted instance: GET [] then PUT {series:SalesInvoice,next:1000} (204) then GET shows
counter 999 (next allocate = 1000); the settings page + appShell.js serve the new entry.
DocumentNumberServiceTest covers the format renderer + scope-key. The SDK entry + generated stamping
+ idempotency are N3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

/** The current tenant's counters. */
@GetMapping
public ResponseEntity<List<DocumentNumberStore.Counter>> list() {
.column(QUOTED_SCOPE, DataType.VARCHAR, true, false, false, "(255)")
.column(QUOTED_COUNTER, DataType.BIGINT, false, false, false)
.build();
try (PreparedStatement statement = connection.prepareStatement(sql)) {
.build();
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.executeUpdate();
LOGGER.info("Created per-tenant document-number table using sql [{}]", sql);
@delchev
delchev merged commit bf18ecf into master Jul 22, 2026
9 of 10 checks passed
@delchev
delchev deleted the feat/intent-numbering-n2-store branch July 22, 2026 14:51
delchev added a commit that referenced this pull request Jul 22, 2026
)

* feat(numbering): per-tenant document-number counter store + runtime + shell settings (N2)

N2 of first-class document numbering (kf-catalog UPSTREAM_PLAN #11a): the runtime the DSL (N1,
#6382) will generate against, plus the application-shell settings surface.

New module components/engine/engine-numbering:
- DocumentNumberStore — a per-tenant DIRIGIBLE_DOCUMENT_NUMBERS table (via the tenant-routed default
  datasource + SqlFactory, like DIRIGIBLE_CONFIGURATIONS), keyed by (series, scope). allocate() is
  gap-free: the increment takes a row lock so concurrent allocations of the same counter serialize;
  the row is created on first use.
- DocumentNumberService — allocate + the format grammar ({seq}/{seq:0N} zero-pad, {series}, and scope
  tokens {year}/{<Field>}) + scope-key derivation; plus list()/setNext() for management.
- DocumentNumberEndpoint — /services/core/numbering (ADMINISTRATOR/OPERATOR): GET the tenant's
  counters, PUT the next value a (series, scope) counter will allocate.

Application shell (resources-application) — a built-in "Document Numbering" Settings entry (next to
Region & Language / Tenant Configuration): lists the counters and lets an admin set each series'
next value (reset/seed a sequence, e.g. start invoices at 1000); read-only on a 403.

Verified on a booted instance: GET [] then PUT {series:SalesInvoice,next:1000} (204) then GET shows
counter 999 (next allocate = 1000); the settings page + appShell.js serve the new entry.
DocumentNumberServiceTest covers the format renderer + scope-key. The SDK entry + generated stamping
+ idempotency are N3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(numbering): sdk.numbering.DocumentNumbers — client SDK for first-class numbering (N3a)

The SDK bridge from client-Java to the per-tenant counter runtime (N2, #6384): allocate the next
gap-free number for a series and render it through the format. Both hand-written custom/ code and
the forthcoming generated stamping (N3b) share one engine + one sequence + the same counter the
application shell's Document Numbering settings manage.

- DocumentNumbers.next(series, format, scope) / next(series, format) → the formatted number, via
  Beans.get(DocumentNumberService).
- api-modules-java depends on engine-numbering (same precedent as engine-document for sdk.print).

Verified: NumberingSdkIT drops a client-Java @controller calling DocumentNumbers.next and asserts a
gap-free formatted sequence over HTTP (T-0001, T-0002) in the caller's tenant scope.

N3b (generation): turn a `number: {}` field (N1, #6382) into the create-time stamp/placeholder + the
issue-step stamp delegate + idempotency, calling this SDK. Depends on #6384.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants