docs(16-01): complete MergePermissions toggle and consolidated CSV export plan

- 16-01-SUMMARY.md created with all task outcomes and verification results
- STATE.md updated with decisions, session info, progress bar (98%)
- ROADMAP.md updated: phase 16 in-progress (1/2 summaries complete)
- REQUIREMENTS.md: RPT-03 marked complete
This commit is contained in:
Dev
2026-04-09 12:35:07 +02:00
parent 28714fbebc
commit 8979becad2
4 changed files with 118 additions and 10 deletions

View File

@@ -25,7 +25,7 @@ Requirements for v2.3 Tenant Management & Report Enhancements. Each maps to road
- [ ] **RPT-01**: User can expand SharePoint groups in HTML reports to see group members - [ ] **RPT-01**: User can expand SharePoint groups in HTML reports to see group members
- [ ] **RPT-02**: Group member resolution uses transitive membership to include nested group members - [ ] **RPT-02**: Group member resolution uses transitive membership to include nested group members
- [ ] **RPT-03**: User can enable/disable entry consolidation per export (toggle in export settings) - [x] **RPT-03**: User can enable/disable entry consolidation per export (toggle in export settings)
- [x] **RPT-04**: Consolidated reports merge rows for the same user with identical access levels across multiple locations into a single row - [x] **RPT-04**: Consolidated reports merge rows for the same user with identical access levels across multiple locations into a single row
## Future Requirements ## Future Requirements
@@ -58,7 +58,7 @@ Requirements for v2.3 Tenant Management & Report Enhancements. Each maps to road
| OWN-02 | Phase 18 | Pending | | OWN-02 | Phase 18 | Pending |
| RPT-01 | Phase 17 | Pending | | RPT-01 | Phase 17 | Pending |
| RPT-02 | Phase 17 | Pending | | RPT-02 | Phase 17 | Pending |
| RPT-03 | Phase 16 | Pending | | RPT-03 | Phase 16 | Complete |
| RPT-04 | Phase 15 | Complete | | RPT-04 | Phase 15 | Complete |
**Coverage:** **Coverage:**

View File

@@ -74,7 +74,7 @@ Plans:
2. When the toggle is OFF, the exported HTML report is byte-for-byte identical to the pre-v2.3 output 2. When the toggle is OFF, the exported HTML report is byte-for-byte identical to the pre-v2.3 output
3. When the toggle is ON, the exported HTML report merges rows for the same user with identical access levels into a single row showing all affected locations 3. When the toggle is ON, the exported HTML report merges rows for the same user with identical access levels into a single row showing all affected locations
4. The toggle state is remembered for the session (does not reset between exports within the same session) 4. The toggle state is remembered for the session (does not reset between exports within the same session)
**Plans:** 2 plans **Plans:** 1/2 plans executed
Plans: Plans:
- [ ] 16-01-PLAN.md — ViewModel properties + XAML Export Options GroupBox + localization + CSV consolidation - [ ] 16-01-PLAN.md — ViewModel properties + XAML Export Options GroupBox + localization + CSV consolidation
- [ ] 16-02-PLAN.md — HTML consolidated rendering with expandable location sub-lists + full test verification - [ ] 16-02-PLAN.md — HTML consolidated rendering with expandable location sub-lists + full test verification
@@ -121,7 +121,7 @@ Plans:
| 6-9 | v1.1 | 25/25 | Shipped | 2026-04-08 | | 6-9 | v1.1 | 25/25 | Shipped | 2026-04-08 |
| 10-14 | v2.2 | 14/14 | Shipped | 2026-04-09 | | 10-14 | v2.2 | 14/14 | Shipped | 2026-04-09 |
| 15. Consolidation Data Model | v2.3 | 2/2 | Complete | 2026-04-09 | | 15. Consolidation Data Model | v2.3 | 2/2 | Complete | 2026-04-09 |
| 16. Report Consolidation Toggle | v2.3 | 0/2 | Not started | — | | 16. Report Consolidation Toggle | 1/2 | In Progress| | — |
| 17. Group Expansion in HTML Reports | v2.3 | 0/? | Not started | — | | 17. Group Expansion in HTML Reports | v2.3 | 0/? | Not started | — |
| 18. Auto-Take Ownership | v2.3 | 0/? | Not started | — | | 18. Auto-Take Ownership | v2.3 | 0/? | Not started | — |
| 19. App Registration & Removal | v2.3 | 0/? | Not started | — | | 19. App Registration & Removal | v2.3 | 0/? | Not started | — |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v2.3 milestone: v2.3
milestone_name: Tenant Management & Report Enhancements milestone_name: Tenant Management & Report Enhancements
status: planning status: planning
stopped_at: Completed 15-02-PLAN.md stopped_at: Completed 16-01-PLAN.md
last_updated: "2026-04-09T09:49:21.960Z" last_updated: "2026-04-09T10:34:56.209Z"
last_activity: 2026-04-09 — Roadmap created for v2.3 (phases 15-19) last_activity: 2026-04-09 — Roadmap created for v2.3 (phases 15-19)
progress: progress:
total_phases: 5 total_phases: 5
completed_phases: 1 completed_phases: 1
total_plans: 2 total_plans: 4
completed_plans: 2 completed_plans: 3
--- ---
# Project State # Project State
@@ -64,6 +64,8 @@ Decisions are logged in PROJECT.md Key Decisions table.
- [Phase 15]: MakeKey declared internal for test access via InternalsVisibleTo without exposing as public API - [Phase 15]: MakeKey declared internal for test access via InternalsVisibleTo without exposing as public API
- [Phase 15]: LINQ GroupBy+Select for consolidation merge instead of mutable dictionary — consistent with functional codebase style - [Phase 15]: LINQ GroupBy+Select for consolidation merge instead of mutable dictionary — consistent with functional codebase style
- [Phase 15-consolidation-data-model]: RPT-04-g test data uses 11 rows (not 10) to produce 7 consolidated rows — plan description had a counting error; 4 unique rows + 3 merged groups = 7 - [Phase 15-consolidation-data-model]: RPT-04-g test data uses 11 rows (not 10) to produce 7 consolidated rows — plan description had a counting error; 4 unique rows + 3 merged groups = 7
- [Phase 16-01]: Consolidated branch uses early-return pattern inside WriteSingleFileAsync to leave existing code path untouched
- [Phase 16-01]: PermissionsViewModel gets MergePermissions as no-op placeholder reserved for future use
### Pending Todos ### Pending Todos
@@ -75,7 +77,7 @@ None.
## Session Continuity ## Session Continuity
Last session: 2026-04-09T09:46:35.243Z Last session: 2026-04-09T10:34:56.207Z
Stopped at: Completed 15-02-PLAN.md Stopped at: Completed 16-01-PLAN.md
Resume file: None Resume file: None
Next step: `/gsd:plan-phase 15` Next step: `/gsd:plan-phase 15`

View File

@@ -0,0 +1,106 @@
---
phase: 16-report-consolidation-toggle
plan: "01"
subsystem: export
tags: [csv-export, consolidation, viewmodel, xaml, localization, tdd]
dependency-graph:
requires: [15-01, 15-02]
provides: [MergePermissions toggle UI, consolidated CSV export path]
affects: [UserAccessAuditViewModel, PermissionsViewModel, UserAccessCsvExportService]
tech-stack:
added: []
patterns: [ObservableProperty, XAML GroupBox binding, optional parameter default, early-return branch, TDD red-green]
key-files:
created: []
modified:
- SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs
- SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs
- SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml
- SharepointToolbox/Views/Tabs/PermissionsView.xaml
- SharepointToolbox/Localization/Strings.resx
- SharepointToolbox/Localization/Strings.fr.resx
- SharepointToolbox/Services/Export/UserAccessCsvExportService.cs
- SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs
decisions:
- "Consolidated branch uses early-return pattern inside WriteSingleFileAsync to leave existing code path completely untouched"
- "PermissionsViewModel gets MergePermissions as a no-op placeholder — PermissionsViewModel uses a different export service (CsvExportService, not UserAccessCsvExportService) so the property is reserved for future use"
- "Export Options GroupBox placed after Scan Options in UserAccessAuditView and after Display Options in PermissionsView — keeps related configuration grouped"
metrics:
duration: ~15min
completed: 2026-04-09
tasks: 3
files-modified: 8
---
# Phase 16 Plan 01: MergePermissions Toggle UI + Consolidated CSV Export Summary
MergePermissions ObservableProperty on both ViewModels, Export Options GroupBox in both XAML tabs, localized EN/FR strings, and consolidated CSV export path using PermissionConsolidator.
## Tasks Completed
| Task | Name | Commit | Files |
|------|------|--------|-------|
| 1 | Add MergePermissions property to both ViewModels and localization keys | ed9f149 | UserAccessAuditViewModel.cs, PermissionsViewModel.cs, Strings.resx, Strings.fr.resx |
| 2 | Add Export Options GroupBox to both XAML views | db42047 | UserAccessAuditView.xaml, PermissionsView.xaml |
| 3 (RED) | Add failing tests for RPT-03-f and RPT-03-g | 4f7a6e3 | UserAccessCsvExportServiceTests.cs |
| 3 (GREEN) | Implement consolidated CSV export path and wire ViewModel call site | 28714fb | UserAccessCsvExportService.cs, UserAccessAuditViewModel.cs |
## What Was Built
### MergePermissions Property
- `UserAccessAuditViewModel`: `[ObservableProperty] private bool _mergePermissions;` — defaults false, no partial handler needed
- `PermissionsViewModel`: same property as a no-op placeholder (PermissionsViewModel uses `CsvExportService`, not `UserAccessCsvExportService`)
### Localization
- `audit.grp.export` — "Export Options" / "Options d'exportation"
- `chk.merge.permissions` — "Merge duplicate permissions" / "Fusionner les permissions en double"
### XAML GroupBoxes
Both views received an "Export Options" GroupBox with a single checkbox bound to `MergePermissions`. The groupbox is always visible (never conditionally hidden). Existing XAML elements are untouched.
### Consolidated CSV Export
`WriteSingleFileAsync` now accepts `bool mergePermissions = false`. When true:
1. Calls `PermissionConsolidator.Consolidate(entries)` to merge rows sharing the same (UserLogin, PermissionLevel, AccessType, GrantedThrough) key
2. Writes a consolidated CSV with header: `"User","User Login","Permission Level","Access Type","Granted Through","Locations","Location Count"`
3. Locations column = semicolon-separated `SiteTitle` values from all merged locations
4. Returns early — existing code path below is completely untouched
`UserAccessAuditViewModel.ExportCsvAsync` now passes `MergePermissions` to the service.
### Tests (TDD)
3 new test methods covering RPT-03-f and RPT-03-g:
- `WriteSingleFileAsync_mergePermissionsfalse_produces_identical_output` — byte-identical to default call
- `WriteSingleFileAsync_mergePermissionstrue_writes_consolidated_rows` — consolidated header + merged rows
- `WriteSingleFileAsync_mergePermissionstrue_singleLocation_noSemicolon` — single location has LocationCount=1
All 8 UserAccessCsvExportServiceTests pass.
## Decisions Made
1. **Early-return consolidated branch** — Plan specified leaving existing code path untouched. Added `if (mergePermissions) { ... return; }` before the existing `var sb = new StringBuilder()` block. The existing block is wrapped in an anonymous `{}` scope for clarity but behavior is unchanged.
2. **PermissionsViewModel as no-op placeholder** — The Permissions tab uses `CsvExportService` (not `UserAccessCsvExportService`), so `MergePermissions` cannot be wired to export logic in this plan. The property is added for XAML binding completeness and future implementation.
3. **GroupBox placement** — Export Options placed immediately before the Run/Export buttons in UserAccessAuditView, and before Action buttons in PermissionsView. This keeps export-related options adjacent to export buttons.
## Verification Results
- `dotnet build` — 0 errors, 0 warnings
- `dotnet test --filter "FullyQualifiedName~UserAccessCsvExportServiceTests"` — 8/8 passed
- `dotnet test` full suite — 296 passed, 26 skipped, 2 flaky timing failures (pre-existing debounce tests, pass when run individually)
## Deviations from Plan
None — plan executed exactly as written.
## Self-Check: PASSED
Files exist:
- SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs — contains `_mergePermissions`
- SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs — contains `_mergePermissions`
- SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml — contains `Export Options`
- SharepointToolbox/Views/Tabs/PermissionsView.xaml — contains `Export Options`
- SharepointToolbox/Services/Export/UserAccessCsvExportService.cs — contains `mergePermissions`
- SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs — 3 new test methods
Commits exist: ed9f149, db42047, 4f7a6e3, 28714fb