Skip to content

Fix successive leave adjustments replacing each other instead of adding up - #46

Merged
karlitschek merged 2 commits into
mainfrom
fix/noid/adjustments-accumulate
Aug 12, 2026
Merged

Fix successive leave adjustments replacing each other instead of adding up#46
karlitschek merged 2 commits into
mainfrom
fix/noid/adjustments-accumulate

Conversation

@karlitschek

Copy link
Copy Markdown
Member

Reported: Lea has 25 days. HR records "+2 wedding" → 27. HR then records "−2, booked in error"23, when it should be back to 25.

What was wrong

Not the sum. getEntitlement() is base + carry_over + manual_adjustment, which is right. The value fed into it was wrong.

manual_adjustment is a running total, but the dialog offered it as a per-correction figure labelled "Manual adjustment (+/−)", and update() assigned rather than added:

$ent->setManualAdjustment($adjustment);   // replaces, never accumulates

So the second correction overwrote the first instead of cancelling it:

Step HR types Stored adjustment Allowance
start 0 25
"+2 wedding" 2 2 27 ✓
"−2 booked in error" -2 -2 (replaces 2) 23

The fix

HR thinks in corrections, so the API now takes them:

  • adjustmentDelta adds to the stored total — +2 then −2 cancel to 0, and the allowance returns to 25.
  • manualAdjustment still sets it outright, for the rare wholesale overwrite.
  • Sending both is refused rather than guessed at.

Applying the delta server-side rather than read-modify-write in the client also means two people adjusting the same entitlement can no longer silently lose one another's correction.

The dialog now asks for the correction and shows the accumulated total beside it, so it is visible that the field adds rather than replaces:

Adjust by (+/−) _____
Adjustments so far: +2 · leaving the field empty changes nothing

Left empty it changes nothing, so saving a base-days edit on its own no longer disturbs the adjustment — which the old absolute field did every time.

Testing

166 tests, 461 assertions, 0 failures (3 new). The regression test walks your exact numbers and, against the old code, fails with precisely the reported result:

Failed asserting that -2.0 is identical to 0.0.

— i.e. 25 + (−2) = 23. eslint 0 errors (no new warnings), stylelint clean, 27/27 vitest, build succeeds. Bundles recompiled in the last commit.

Note on existing data

Rows already saved keep whatever total they hold, and the change history added in #45 starts from here. If Lea currently reads 23, her stored adjustment is −2; one correction of +2 now puts her back to 25 and leaves a recorded reason for it.

🤖 Generated with Claude Code

Frank Karlitschek and others added 2 commits August 12, 2026 15:38
…replacing

Reported: 25 days, "+2 wedding", then "−2 booked in error" left 23 days rather
than the 25 it started from.

manual_adjustment is a running total, but the dialog offered it as a per-correction
figure labelled "Manual adjustment (+/−)" and update() assigned rather than added.
So the second correction did not cancel the first, it overwrote it: the stored
adjustment went 0 → 2 → −2, and the allowance 25 → 27 → 23. The sum itself was
never wrong; base + carry-over + adjustment is right. The adjustment fed into it
was.

HR thinks in corrections, so the API now takes them. adjustmentDelta adds to
what is already stored; manualAdjustment keeps setting the total outright for the
rare wholesale overwrite. Sending both is refused rather than guessed at. Applying
the delta on the server rather than reading-modifying-writing in the client also
means two people adjusting the same entitlement cannot silently lose one another's
correction.

The dialog now asks for the correction and shows the accumulated total beside it,
so it is visible that the field adds rather than replaces. Left empty it changes
nothing, so saving a base-days edit on its own no longer disturbs the adjustment.

The regression test walks the reported numbers exactly and fails on the old
behaviour with the reported 23.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nextcloud-command nextcloud-command added the AI assisted This PR contains AI-assisted commits label Aug 12, 2026
@karlitschek
karlitschek merged commit b7dd1ad into main Aug 12, 2026
29 of 35 checks passed
@karlitschek
karlitschek deleted the fix/noid/adjustments-accumulate branch August 12, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI assisted This PR contains AI-assisted commits

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants