Skip to content

Require account class and normal side in account editor dialog - #134

Merged
perNyfelt merged 8 commits into
mainfrom
fix/account-editor-unclassified-default
Nov 10, 2026
Merged

perNyfelt merged 8 commits into
mainfrom
fix/account-editor-unclassified-default

Conversation

@perNyfelt

@perNyfelt perNyfelt commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Problem

Fixes #121.

Opening Redigera konto for an account with account_class = null / normal_balance_side = null (e.g. SIE-imported accounts flagged for review, such as 8990 "Resultat") showed Klass = Tillgång and Normal = Debet. Those values are not stored; pressing OK silently saved the account as ASSET/DEBIT, moving a result account into the balance sheet as an asset and changing the year's result without any warning.

Cause: indexOf(null) returns -1, which Math.max(0, …) turned into index 0 (ASSET / DEBIT).

Review follow-up (commit 2): the first fix kept the Math.max(0, …) clamp, which — with the new placeholder at index 0 — still mapped null to ASSET/DEBIT (index 1). The selection now uses initialIndex(values, value) = indexOf(value) + 1, so null and unknown stored values map to the "(not specified)" placeholder.

Fix

In AccountEditorDialog:

  • Both combos lead with a "(not specified)" / "(ej angiven)" entry, selected when the stored value is null or unknown, so the dialog no longer shows a class that isn't there.
  • Pressing OK while class or normal side is unspecified shows a warning and keeps the dialog open — an unclassified account can no longer be saved accidentally. This complements the service-layer validation in AccountService.updateAccount.
  • When a previously unclassified account becomes fully classified in the dialog (both class and side picked), the Granskning checkbox clears — once, and only automatically that one time — matching updateAccountClassification (the MCP path). The user can re-tick it afterwards without the dialog overriding them. Accounts that were already classified keep the flag untouched when their class changes.

The index mapping lives in small package-scope helpers (initialIndex, selectedAccountClass, selectedNormalBalanceSide) alongside an extracted EditorForm, covered by AccountEditorDialogTest.

New i18n keys in messages.properties and messages_sv.properties.

Behaviour change worth noting

An unclassified account can no longer be saved from this dialog until it has a class and normal side — so toggling only Aktiv/Granskning or setting SRU codes on an unclassified account now requires classifying it first. This is consistent with the service layer, which has always rejected null class/side.

Verification

  • New unit tests in app/src/test/groovy/unit/se/alipsa/accounting/ui/AccountEditorDialogTest.groovy cover the index mapping (null/unknown → placeholder, known → own entry, placeholder → null), end-to-end EditorForm construction for unclassified and classified accounts, and the review-flag auto-clear (including the not-twice and classified-account cases).
  • ./gradlew spotlessApply, ./gradlew codenarcMain, ./gradlew codenarcTest, and full ./gradlew build (compilation, all tests, Spotless, CodeNarc) pass.
  • Note: CodeNarc prints an internal UnusedPrivateMethodRule exception for the pre-existing BackgroundTaskRunner.groovy; it does not fail the task and is unrelated to this change.

Review follow-up

  • The account editor remembers the preferred VAT code for the lifetime of the dialog. It temporarily shows “none” for an incompatible class and restores the code if a compatible class is selected later, including during keyboard navigation. Explicit VAT choices, including clearing the code, replace that preference.
  • The OK-button classification rule now uses a package-scope isComplete(EditorForm) helper, with tests for missing class, missing normal side, and a complete classification. VAT preservation and incompatibility are also covered by unit tests.

Screenshots

Sample account 8990 (“Resultat”) with a stored OUTPUT_25 VAT code, shown before and after choosing Income/Credit in the dialog:

Before classification After classification
8990 before classification 8990 after classification

Test suite setting

app/build.gradle sets systemProperty 'java.awt.headless', 'true' for the whole test task. This lets Swing component tests run in headless CI; they use SwingUtilities.invokeAndWait and do not open dialogs.

perNyfelt and others added 8 commits November 9, 2026 16:54
Konton utan klassificering (account_class/normal_balance_side = null)
visades som Tillgång/Debet i Redigera konto eftersom indexOf(null) gav
-1 som Math.max(0, ...) gjorde om till index 0. Att bara trycka OK
sparade då tyst kontot som ASSET/DEBIT.

Dialogen får nu ett '(ej angiven)'-alternativ i båda kombinationsrutorna
som väljs när värdet saknas, och OK meddelar och stänger inte dialogen
om klass eller normalsida lämnats ospecificerade.

Fixes #121
Den första rättelsen behöll Math.max(0, ...) som klämde indexOf(null) = -1
till 0, vilket med den nya platshållaren på index 0 fortfarande blev
ASSET/DEBIT. indexOf(value) + 1 mappar nu null och okända värden till
'(ej angiven)'.

- Extraherade package-scope-hjälparna initialIndex, selectedAccountClass
  och selectedNormalBalanceSide samt EditorForm, med enhetstester som
  täcker mappningen i båda riktningarna.
- Granska-kryssrutan rensas nu automatiskt när ett tidigare oklassat
  konto klassificeras, i linje med updateAccountClassification (MCP).
- Lade till skärmdump av dialogen för konto 8990 med platshållaren vald.
- Granska-kryssrutan rensas nu när kontot blir fullt klassificerat
  (klass OCH sida valda), högst en gång, baserat på initialt
  oklassificerat tillstånd så att även okända lagrade värden täcks.
  Användaren kan kryssa i flaggan igen utan att dialogen åsidosätter.
- Tester för flaggrensning: en gång, inte för redan klassificerade.
- java.awt.headless satt globalt på test-tasken i build.gradle i
  stället för i en statisk block per testklass.
- VatCodeChoice är nu package-scope så EditorForms fälttyp kan namnges.
- Skärmdump flyttad ut ur repot (läggs till som bilaga i PR-beskrivningen).
@perNyfelt
perNyfelt merged commit 218e9ea into main Nov 10, 2026
3 checks passed
@perNyfelt
perNyfelt deleted the fix/account-editor-unclassified-default branch November 10, 2026 21:22
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.

Edit account dialog shows Tillgång/Debet for unclassified accounts and saves it on OK

1 participant