fix(export): per-worker pay-code columns in the all-workers report#1604
Merged
Conversation
In the all-workers Excel export, each per-site (per-worker) sheet showed pay-code columns for the GLOBAL union of pay codes across all workers — so whenever any worker had an active pay-rule-set, every worker's sheet got every pay code (filled 0 for codes that weren't theirs). Now each per-site sheet shows only the pay codes DECLARED in that worker's own pay-rule-set (none if the worker has no rule-set). The Total summary sheet is unchanged (keeps the union), and the single-worker export was already correct. - New internal static GetDeclaredPayCodes(PayRuleSet) collects a rule-set's declared codes (day-rule tiers by Order, day-type default + time-band codes, holiday code), de-duplicated, skipping null/empty, empty for null. - The all-workers per-site loop now uses these per-site codes for the sheet header, per-day cells, and totals row (via GetValueOrDefault for declared codes with no hours). The global allPayCodes and siteTotalsByPayCode that feed the Total sheet are untouched. Tests: unit tests for GetDeclaredPayCodes (PlanRegistrationHelperTests, shard f); an all-workers export test seeding two sites with different pay-rule-sets + one with none, asserting each per-site sheet has only its own codes and the Total sheet keeps the union (DagsoversigtWorksheetExportTests, shard g). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes the all-workers Excel export so each per-site (per-worker) worksheet only includes pay-code columns declared by that worker’s own pay-rule-set (or none when no rule-set), while keeping the Total summary sheet behavior unchanged.
Changes:
- Updated the all-workers per-site sheet generation to use per-site
sitePayCodesfor header, daily cells, and totals row. - Added
GetDeclaredPayCodes(PayRuleSet)helper to extract declared pay codes in a stable structural order with de-duplication. - Added unit and E2E export tests to lock in per-site vs Total-sheet pay-code column behavior; added supporting design/plan docs.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn/Services/TimePlanningWorkingHoursService/TimePlanningWorkingHoursService.cs | Adds declared-pay-code extraction helper and switches per-site sheets to per-worker pay-code columns. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/PlanRegistrationHelperTests.cs | Unit tests for GetDeclaredPayCodes (sources, ordering, dedup, null/empty handling). |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/DagsoversigtWorksheetExportTests.cs | E2E regression test ensuring per-site sheets differ by rule-set while Total sheet keeps union. |
| docs/superpowers/specs/2026-06-10-per-worker-paycode-columns-design.md | Design spec documenting intended behavior and constraints (Total sheet unchanged). |
| docs/superpowers/plans/2026-06-10-per-worker-paycode-columns.md | Implementation plan capturing verified facts, steps, and test strategy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+3949
to
+3963
| internal static List<string> GetDeclaredPayCodes(PayRuleSet payRuleSet) | ||
| { | ||
| var codes = new List<string>(); | ||
| if (payRuleSet == null) | ||
| { | ||
| return codes; | ||
| } | ||
|
|
||
| void Add(string code) | ||
| { | ||
| if (!string.IsNullOrWhiteSpace(code) && !codes.Contains(code)) | ||
| { | ||
| codes.Add(code); | ||
| } | ||
| } |
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.
The bug
In the all-workers Excel export, each per-site (per-worker) sheet showed pay-code columns for the global union of pay codes across all workers — so whenever any worker had an active pay-rule-set, every worker's sheet got every pay code (filled
0for codes that weren't theirs).The fix
Each per-site sheet now shows only the pay codes declared in that worker's own pay-rule-set (none if the worker has no rule-set). Workers with different pay-rule-sets get different columns.
internal static GetDeclaredPayCodes(PayRuleSet)— collects a rule-set's declared codes (day-rule tiers byOrder, day-type default + time-band codes, holiday code), de-duplicated, skipping null/empty, empty for null.GetValueOrDefaultfor declared codes with no hours this period).Unchanged (by design)
0elsewhere) — itsallPayCodes/siteTotalsByPayCodeare untouched, so it's byte-identical.Tests
PlanRegistrationHelperTests, shard f):GetDeclaredPayCodesacross all four sources, dedup, tier ordering, null/empty.DagsoversigtWorksheetExportTests, shard g): seeds two sites with different pay-rule-sets + one with none; asserts each per-site sheet has only its own code, the no-rule-set sheet has none, and the Total sheet keeps the union. Verified it fails under the old global-union behavior.🤖 Generated with Claude Code