Skip to content

refactor(mandaat): rename the mandaat schemas and their data contract to mandate - #817

Merged
rubenvdlinde merged 3 commits into
developmentfrom
feat/english-vocabulary-mandate
Aug 12, 2026
Merged

refactor(mandaat): rename the mandaat schemas and their data contract to mandate#817
rubenvdlinde merged 3 commits into
developmentfrom
feat/english-vocabulary-mandate

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Applies the ratified mandaat = mandate rename to all four schemas, their eight properties, the slug map, the column migration, and every code site that reads or writes those properties.

The 66-vs-716 split

mandaat appears 716 times across 56 files. Only 66 of those break when the schema moves — property reads, filter keys, slug strings. The other ~650 are class names, file names and local variables: nothing resolves through them at runtime.

This PR does the 66. Isolating that subset is what made the slice finishable in one pass; the cosmetic renames can follow without risk.

Schemas — all four owners, one register scope

before after
mandaat mandate
mandaatGebruik mandateUsage
mandaatEscalatie mandateEscalation
mandaatRegeling mandateArrangement

Plus mandaatNummermandateNumber, mandaatIdmandateId, mandaatVersieIdmandateVersionId, targetMandaatIdtargetMandateId, mandaatGroepenmandateGroups, ondermandaatToegestaansubMandateAllowed, mandaatNiveaumandateLevel, mandaatGegevenmandateGranted.

Ownership was checked per property before editing: each is declared by exactly one schema, and all four schemas sit in the procest register — so the register-scoped migration covers every owner. That is the condition #816 established, and it is satisfied here rather than assumed.

Slug map keys follow the new slugs; values deliberately unchanged — each is the appconfig key holding that schema's numeric id on existing installs, and renaming it orphans the id.

Deliberately not moved, each for a measured reason

  • CSV headers (MandaatCsvParser::REQUIRED_COLUMNS, every $row['...']) — an external input contract. I renamed REQUIRED_COLUMNS, then reverted: it would reject every operator import file in the field. Documented in place.
  • ['mandaatId' => ...] in MandaatEscalatieService — an internal return-array key from resolveEscalationPath(), not a schema property.
  • mandaatNiveau inside mandateGranted, and mandaatregelingId — nested under an object property, so they live in that column's JSON rather than as columns. A column rename cannot reach them; they need a JSON-rewrite migration. The outer key moves, the inner does not — and BeschikkingServiceTest now asserts exactly that.
  • akkoord-mandaat — a lifecycle enum value, i.e. stored data. Renaming rewrites every row.

Verification

  • 1882 tests, 6393 assertions green (5 skipped — baseline)
  • Four tests failed on the first run and were fixed: three BeschikkingServiceTest cases on the mandateGranted/mandateGroups fixtures, one MandaatEscalatieServiceTest on targetMandateId
  • php -l clean on every changed file; all JSON parses
  • phpcs: 58 errors across changed files against a 106-error baseline on the two test files — phpcbf cleared pre-existing debt alongside my alignment. Both lib/ services are at 0.
  • 0 procest-scoped schemas or top-level properties still carry mandaat

Follow-ups

The ~650 cosmetic references (the four Mandaat* service classes, MandaatMatrixController, MandaatRegistryService, the Vue file names) and the nested-JSON migration are separate changes.

INCOMPLETE. The four schemas, their eight properties, the slug map and the
column migration are done and verified. The 716 code references across 56 files
are NOT. Merging this state gives every one of them a silent null read: the
schema declares `mandate`, the code still asks for `mandaat`, and OpenRegister
returns null rather than erroring.

Committed so the ownership analysis and the migration boundary are not lost.

DONE — all four owners, one register scope
  mandaat           -> mandate              (61-mandaat-matrix)
  mandaatGebruik    -> mandateUsage         (61-mandaat-matrix)
  mandaatEscalatie  -> mandateEscalation    (61-mandaat-matrix)
  mandaatRegeling   -> mandateArrangement   (30-beschikking)

  mandaatNummer -> mandateNumber        mandaatId -> mandateId
  mandaatVersieId -> mandateVersionId   targetMandaatId -> targetMandateId
  mandaatGroepen -> mandateGroups       ondermandaatToegestaan -> subMandateAllowed
  mandaatNiveau -> mandateLevel         mandaatGegeven -> mandateGranted

Verified after: 0 procest-scoped schemas or top-level properties still carry
`mandaat`. Ownership was checked per property BEFORE editing — each is declared
by exactly one schema, and all four schemas sit in the `procest` register, so
the register-scoped migration covers every owner. That is the condition the
wettelijkeGrondslag slice established and it is satisfied here.

SLUG MAP: keys follow the new slugs, VALUES deliberately unchanged. Each value
is the appconfig key holding that schema's numeric id on existing installs;
renaming it orphans the id and the schema silently resolves to nothing.

DELIBERATELY EXCLUDED
  - `akkoord-mandaat` is a lifecycle ENUM VALUE, i.e. stored data. Renaming it
    rewrites every row — a separate, riskier migration, same call as
    openconnector#1213 and procest#815.
  - `mandaatregelingId` and the `mandaatNiveau` inside `mandateGranted` are
    NESTED under an object property, so they live in that column's JSON rather
    than as columns. A column rename cannot reach them; they need a JSON-rewrite
    migration. Documented in the map.

TO FINISH: 716 references in lib/ and src/ across 56 files — the four Mandaat*
PHP service/controller classes, MandaatRegistryService, MandaatEscalatieService,
MandaatCheckService, MandaatImportService, and the Vue files
(MandaatMatrixTab, MandaatEditor, MandaatImportPanel). Then this is mergeable.
Note MandaatCsvParser::REQUIRED_COLUMNS and the CSV headers are an external
input contract — alias both spellings rather than breaking operator files.
Continues f8a55fa. Renames the schema PROPERTY READS that break when the
schema half lands: mandaatGroepen -> mandateGroups (MandaatVerifier, 3 sites)
and mandaatGegeven -> mandateGranted (BeschikkingService, 2 sites).

MandaatCsvParser::REQUIRED_COLUMNS deliberately NOT renamed and now documented
in place. Those are CSV HEADERS — an external input contract operators' files
already use. I renamed it, then reverted: it would reject every import file in
the field. MandaatImportService maps headers onto the renamed properties and
accepts either spelling, which is the pattern used for wettelijkeGrondslag and
omschrijving.

STILL WIP DO NOT MERGE — the remaining data-contract sites (MandaatCheckService,
MandaatGebruikService, MandaatEscalatieService, MandaatGuard, and 6 Vue files)
are not done.
Every code site that READS or WRITES a renamed schema property now agrees with
the schema. Combined with f8a55fa and 4c5a187, this branch is coherent:
schema, migration and data contract all move together.

WHAT THIS IS NOT. The Mandaat* class names, file names and local variables are
still Dutch — roughly 650 references. They are cosmetic: nothing resolves
through them at runtime, so they can follow in their own change without risk.
The 66 references that actually BREAK are the ones handled here, and isolating
that subset is what made the slice finishable.

DATA SITES MOVED
  MandaatVerifier          mandaatGroepen -> mandateGroups (3)
  BeschikkingService       mandaatGegeven -> mandateGranted (2)
  MandaatGebruikService    mandaatId -> mandateId, mandaatVersieId ->
                           mandateVersionId, and the findAll filter
  MandaatEscalatieService  targetMandaatId -> targetMandateId
  MandaatImportService     the payload key, and two reads of stored objects
  6 Vue files              mandaatNummer -> mandateNumber,
                           mandaatNiveau -> mandateLevel, mandaatGegeven ->
                           mandateGranted

DELIBERATELY NOT MOVED, each for a measured reason
  - MandaatCsvParser::REQUIRED_COLUMNS and every $row['...'] read: CSV HEADERS,
    an external input contract operators' files already use. I renamed
    REQUIRED_COLUMNS, then reverted — it would reject every import file in the
    field. Now documented in place.
  - `['mandaatId' => ...]` in MandaatEscalatieService: an INTERNAL return-array
    key from resolveEscalationPath(), not a schema property.
  - `mandaatNiveau` INSIDE mandateGranted, and `mandaatregelingId`: nested under
    an object property, so JSON within a column rather than columns. A column
    rename cannot reach them; they need a JSON-rewrite migration. The outer key
    moves, the inner does not — asserted that way in BeschikkingServiceTest.
  - `akkoord-mandaat`: a lifecycle ENUM VALUE, i.e. stored data.

VERIFIED
  - phpunit: 1882 tests, 6393 assertions green (5 skipped, same as baseline).
    Four tests failed first and were fixed: three BeschikkingServiceTest cases
    on the mandateGranted/mandateGroups fixtures, one MandaatEscalatieServiceTest
    on targetMandateId.
  - php -l clean on every changed file; all JSON parses.
  - phpcs: 58 errors across the changed files against a 106-error baseline on
    the two test files — phpcbf cleared pre-existing debt while fixing my
    alignment. Both lib/ services are at 0 errors.
  - 0 procest-scoped schemas or top-level properties still carry `mandaat`.
@rubenvdlinde
rubenvdlinde merged commit cb38772 into development Aug 12, 2026
28 of 29 checks passed
@rubenvdlinde
rubenvdlinde deleted the feat/english-vocabulary-mandate branch August 12, 2026 09:29
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 6b418a2

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue3-compile
test-l10n
composer ✅ 100/100
npm ✅ 552/552
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-12 09:45 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde added a commit that referenced this pull request Aug 12, 2026
…ticeOfDefault* (#818)

Replaces #810, which was branched from a stale stack: its diff carried a dozen
files that #803/#804/#806/#809/#816/#817 have since landed, so rebasing it meant
resolving 8 conflicts across controllers, services, tests and a Postman
collection. Branched fresh from development this does the same work as a
40-reference change across 10 files with zero conflicts.

  IngebrekestellingService    -> NoticeOfDefaultService
  IngebrekestellingController -> NoticeOfDefaultController
  registerIngebrekestelling() -> registerNoticeOfDefault()

ROUTE NAMES MOVE, URLs DO NOT. A route name resolves to its controller class, so
`ingebrekestelling#register` had to become `noticeOfDefault#register` or the
router 500s on that endpoint. The URLs stay `/api/termijn/ingebrekestellingen`:
that is the published contract and moving it is a breaking change for every
consumer — a separate decision from this rename. Both route names were verified
to resolve to NoticeOfDefaultController.php after the change.

NOT IN THIS CHANGE: the `ingebrekestelling` SCHEMA in 60-termijnbewaking.json,
its reference property, and the `ingebrekestelling-ontvangen` lifecycle enum
value. The schema is a data contract — renaming it needs an ownership check and
a column migration, and the enum value is stored data. Class names carry no data
and move independently, which is why this is a clean slice.

VERIFIED
  - phpunit: 1882 tests, 6393 assertions green (5 skipped, same as baseline).
  - php -l clean on every changed file; the Postman collection still parses.
  - Route names resolve: both noticeOfDefault#* map to a file that exists.
  - Residual grep finds no IngebrekestellingService / IngebrekestellingController
    / registerIngebrekestelling anywhere in lib/, tests/ or appinfo/.
  - phpcs: 6 errors across the four changed files against a 386-error baseline.
    My edit added 5; phpcbf fixed those and cleared pre-existing debt with them.
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.

1 participant