Repository navigation
feat(cmdb-import): archive or soft-delete applications that left the export, revive returning ones - #1281
Open
WilcoLouwerse wants to merge 17 commits into
Open
feat(cmdb-import): archive or soft-delete applications that left the export, revive returning ones#1281WilcoLouwerse wants to merge 17 commits into
WilcoLouwerse wants to merge 17 commits into
Conversation
Proposal, design, tasks and the delta spec for archiving and soft-deleting applications that left a newer CMDB export (REQ-CMDB-015..017, REQ-CMDB-012 and REQ-CMDB-014 modified). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ive sheet The register fragment opts module (0.3.9) and usage (1.5.7) into OpenRegister's archive state. The import profile names the sheet "Gearchiveerde Applicaties" and accepts missingRecords keep and archive, readable before the packs are validated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the workbook has the sheet "Gearchiveerde Applicaties", the reader loads it under the same bounds as the CMDB sheets, resolves only its APPID column and returns the APPIDs next to the rows, with whether the sheet and its key column were found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…export With missingRecords archive, the default, a completed import reconciles the municipality's usages and the modules its import created: an APPID that moved to the archive sheet is archived through OpenRegister's ArchiveHandler, one on no sheet is soft-deleted, and without the archive sheet missing applications are archived only, with a report warning. The step runs under the register lock in its own progress phase, with an error boundary per application. A module or usage matched among archived or soft-deleted objects is unarchived or restored before it is updated, so a returning application is never duplicated. The report counts archived, unarchived, deleted and restored. Without the archive services an archiving import is refused with 503 ARCHIVE_UNAVAILABLE before the file is read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hive The endpoint passes the option to the import, names both accepted values when it refuses a reserved one, and translates ARCHIVE_UNAVAILABLE. The OpenAPI document and the Postman test describe the new values, outcomes and error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uick filter The CMDB import section lets the admin archive or delete applications missing from the export (the default) or keep them, with help text, and shows the archived, unarchived, deleted and restored counts and outcomes. A reconciliation entry has no row number and a deleted module no link, and the progress line says when the import checks missing applications. The Applications and Applications in use pages get an Archived quick filter that lists the archive (_archived=true). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d trip build-fixtures.py derives topdesk-archived-applications.xlsx, a later export in which APPID 1234 moved to the archive sheet and APPID 2 is on no sheet. The reader, the service and the hygiene test cover it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Repeat imports, the section's new choice, the summary and row outcomes, the archive sheet and the ARCHIVE_UNAVAILABLE and MISSING_RECORDS_UNSUPPORTED errors, plus the feature overview and the changelog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mport Imports the archived-applications variant after the anonymised export, checks the archived and deleted counts, the Archived quick filter on the Applications page and the unchanged contact persons, then imports the original again and checks unarchived, restored and no duplicates. The cleanup also looks through the archive and trash lenses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne limit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ciliation The Playwright test of task 7 is written but not run yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ciliation The cancel check ran only at the top of each row, so a cancel pressed during the last row or in the reconciling phase still archived and soft-deleted every missing application while the endpoint reported the cancel as accepted. The reconciliation now checks before it loads its scope and before each application, stops there and marks the report cancelled; what it already archived or deleted stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matching across every state took the first hit. A module deleted by hand before this change was invisible to the match, so the next import created a second one with the same import key; when OpenRegister returned the deleted one first, the import restored it next to the live one. findOne() now takes a working object before an archived one, and an archived one before one in the trash, for modules and usages alike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion with D5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e trash OpenRegister's list search (MagicSearchHandler::convertRowToObjectEntity) hydrates no archive marker and drops every soft-deleted row, whatever _includeDeleted says, because it parses the JSON _deleted marker as a date. A re-import therefore left a returning archived application archived and created a second module for a soft-deleted one. Look an object up working first, then with _archived=true, then in the trash listing (MagicMapper::findDeletedAcrossAllMagicTables), read once per import, and take its state from where it was found. A restored object is unarchived when the object restoreObject() answers is archived, and the update starts from that object. The reconciliation scope reads its usages and modules the same way. The test doubles now model OpenRegister's search results, so the existing round-trip tests fail on the old matching. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bject state Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iliation spec and proposal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ❌ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 133/133 | |||
| npm | ✅ | ✅ 807/807 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ 1253/1253 · 20 skipped | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ✅ |
Quality workflow — 2026-10-09 15:20 UTC
Download the full PDF report from the workflow artifacts.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A repeated CMDB import now reconciles a municipality's applications with the newer TOPdesk export.
archived,unarchived,deletedandrestored. Report rows carry only APPID, name and uuids, never person data.missingRecordsiskeep | archive, defaultarchive. The CMDB import section shows the choice.removestays reserved and answers 422.module(0.3.9) andusage(1.5.7) opt in to archiving throughx-openregister-archive. Run Force Update after installing._archived=true) on the Applications and Usage pages._archived=truefinds the archived ones.cmdb-import-archive-reconciliation: ADDED REQ-CMDB-015..017, MODIFIED REQ-CMDB-012 and REQ-CMDB-014.Jira: WOO-587 (sub-task of WOO-586). Plan: WOO-587 plan. Review and merge are tracked in WOO-590.
How the state of a stored object is read (design D9)
On the current OpenRegister beta (2.1.37,
origin/betaff4dad5c), a search cannot tell this import whether an object is archived or deleted. The cause is inMagicSearchHandler::convertRowToObjectEntity:_archived, so every search result looks live._deletedcolumn as aDateTime. That fails, so_includeDeleted=truenever returns a deleted row.The import therefore reads the state per lens instead:
_archived=true.MagicMapper::findDeletedAcrossAllMagicTables().The unit-test doubles model that beta behaviour. Against the earlier service code, 7 tests fail on exactly the rig symptom; with the fix they pass.
Overlap with #1280 (WOO-588)
Both PRs touch
CmdbImport.vue,openspec/specs/cmdb-export-import/spec.mdand l10n. A local merge of both ondevelopmenthad two trivial conflicts (keep both sides). Whichever PR merges second needsdevelopmentmerged in.Tests
tests/Unit/Service,CmdbImportControllerTest,tests/Unit/Settings,tests/Unit/FixturescmdbArchiveQuickFilter.spec.jsdevelopmentc75dbb2; not touched herecomposer test:unitlocallytests/e2e/spec-coverage/cmdb-import.spec.tsafterAllcleanup lists objects through REST with_includeDeleted=true. That runs into the same OpenRegister converter bug, so soft-deleted test objects may be left behind on the CI instance.Rig smoke
The smoke ran on Nextcloud 35.0.1 with these beta releases:
It used only the anonymised fixtures in
tests/fixtures/cmdb/.topdesk-export-anonymised.xlsx(keep)topdesk-archived-applications.xlsx/api/applicatielandschaphides both, and_archived=trueshows the archived onetopdesk-export-anonymised.xlsxagainThe three imports together took about 12 seconds, including the trash read.
🤖 Generated with Claude Code