RZP typ_pred filter — per-owner runtime proof

Branch: fix/rzp-typpred-filter-runtime · Commit: 2dbaf08af468b5183a4b7c29e720a5c8943e13ac · Generated: 2026-05-25 11:23:24
Related: PR #26472 (merged 2026-05-25) introduced the filter; PR #26547 fixes the runtime path.

1. Reported bug

User reported that after PR #26472 merged into develop, NEO RZP Nákladové a výnosové účty still shows more accounts than legacy Rzp.exe for the same owner. Specifically owner IČO 70106975 should see 2 accounts but NEO showed 9+ accounts. After this fix, two distinct owners are demonstrated to receive only their own typ_pred-filtered subset.

2. Database ground truth

IČOid_majtyp_predExpected accounts (rzp_ucet WHERE typ_pred = X)
701069751322
442680501011

Total rzp_ucet rows: 13 (distributed across typ_pred 1, 2, 5, 11, 17, 21, 26). Without the filter, every owner would see all 13.

3. Root cause

Two issues stacked.

(1) Ctor ambiguity. AccountCodebookForm had 6 public constructors including two 6-arg overloads (one with short typPred, one with OwnerPresenter?). MS.E.DI's "first-resolved superset" selection picked the 2-arg (AccountPresenter?, ISpolHelpService?) ctor, leaving ownerPresenter field null. Diagnostic evidence:

10:20:46.669 [DIAG-ACF] CTOR 2-arg(presenter,help) invoked
10:20:46.700 [DIAG-ACF] OnLoadAsync entry. presenter=set, ownerPresenter=null, defaultTypPred=0, CurrentOwner.TypPred=
10:20:46.718 [DIAG-ACF] After ReloadGridAsync, grid row count=13

(2) SQL parameter binding. After fixing (1), SQL Server rejected the query with Must declare the scalar variable '@typPred'QueryAsync doesn't rewrite @named? for SQLOLEDB. Fixed by switching to QueryOleDbAsync.

4. Fix

Collapsed AccountCodebookForm from 6 ctors to 2 (parameterless + 6-arg with all-default null args). DI now picks the only multi-arg ctor unambiguously.

public AccountCodebookForm() : this(presenter: null) { }

public AccountCodebookForm(
    AccountPresenter? presenter = null,
    ISpolHelpService? helpService = null,
    ISpolAboutService? aboutService = null,
    OpenSharedReportUseCase? openSharedReportUseCase = null,
    IPrintPreferenceAdapter? printPreferenceAdapter = null,
    OwnerPresenter? ownerPresenter = null)
{ ... }

Other changes: QueryOleDbAsync in repository; E2E runners call presenter.SetTypPred(typPred) before form ctor; OnLoadAsync respects already-set CurrentTypPred.

5. Bug reproduction — BEFORE fix

Owner IČO 70106975 / typ_pred=2 / expected 2 accounts — NEO showed 9+ rows of mixed typ_pred
Baseline NEO RZP — bug
Bug: filter not applied. Grid loaded entire rzp_ucet (13 rows). Owner-specific account set was wrong.

6. AFTER fix — per-owner filtering verified on TWO distinct owners

The screenshots below demonstrate that switching the active owner via menu Úloha → Majitel → Výběr changes the account set in Nákladové a výnosové účty exactly as the per-owner SQL filter dictates.

Owner #1   IČO 70106975 / typ_pred=2 / expected 2 → grid shows 2 ✓
Fixed NEO RZP for IČO 70106975
Visible rows: 2 — "001 náklady", "518 služby". Status bar: IČO 70106975. Match with DB WHERE typ_pred = 2.
Owner #2   IČO 44268050 / typ_pred=1 / expected 1 → grid shows 1 ✓
Fixed NEO RZP for IČO 44268050
Visible rows: 1 — "001 Náklady a výnosy 2026". Status bar: IČO 44268050. Match with DB WHERE typ_pred = 1.

Switch path: NEO was launched once → logged in → owner #1 active (cached session restore) → opened Nákladové a výnosové účty for screenshot #1 → menu Úloha → Majitel → Výběr → picked IČO 44268050 → re-opened Nákladové a výnosové účty for screenshot #2. Grid contents changed accordingly, confirming the filter binds to the currently selected owner at form-load time.

7. Test coverage

8. Files changed

Net diff: +36 / -67 across 6 files (refactor, not expansion).