Invisible Count
Description
The Invisible Count screen is a specialized verification mode where verifiers count items without seeing the original scanned counts. This prevents bias and ensures accurate recounting. The verifier enters their count for each group, and the system compares it against the total original scans. The screen uses the same base structure as Position Count Verify but hides counts and enforces strict validation logic with limited retry attempts.
Shared Features with Position Count Verify
Invisible Count shares the following with Position Count Verify:
- Scan Groups Fetching: Uses the same GetScanGroups mechanism (see Position Count Verify documentation).
- VerifySelections: Same navigation state persistence system.
- Auditing System: Same quota enforcement and audit status tracking.
- Group Navigation: Same search, selection, and marker functionality.
- UI Structure: Uses the same VerifyScreen and VerifyViewModel base.
Key Differences from Position Count Verify
Hidden Counts
- Original scan counts are hidden from the verifier.
- Individual scan counts within groups are not visible.
- Total group counts are not displayed until after verification.
- This prevents the verifier from being influenced by the original count.
Strict Validation Logic
Unlike Position Count Verify's flexible count editing, Invisible Count enforces exact matching with limited attempts.
Invisible Count-Specific Logic
PerformInvisibleCount - Core Validation Process
This is the main verification function that processes the verifier's entered count:
- Parse Input Count: Converts the entered count string to BigDecimal.
- Get Original Total: Calculates the sum of all original counts in the group (
getOriginalCount()). - Validate Format and Rules:
- Checks regex validation rules from the Count scan flow step.
- Validates numeric format.
- If validations fail and
ignoreValidationsis false, returnsValidationsFailed.
- Compare Counts: Checks if entered count exactly matches the original total.
- Track Attempts:
- If counts don't match, increments
verificationAttemptson all scans in the group. - If
verificationAttemptsreaches 2 or more, throwsCountAttemptsExceededException. - If first attempt failed, throws
InvalidCountException.
- If counts don't match, increments
- Update Scans on Success:
- Uses
updateCount()to distribute the entered count across scans. - Marks all scans as verified.
- Updates
dateModifiedtimestamp.
- Uses
- Return Result: Either
SuccessorValidationsFailed.
ScanDomainEntity - Verification Attempts Tracking
Each scan tracks verification attempts:
data class ScanDomainEntity(
// ...existing fields...
val verificationAttempts: Int, // Tracks how many times incorrect count was entered
)
Key Methods:
restoreVerificationAttempts(): Resets attempts to 0 (used when accepting or keeping counts).- After 2 failed attempts, the system locks the group and shows
CountAttemptsExceededException.
updateCount() - Count Distribution Logic
When a new count is entered, the system distributes it across individual scans in the group:
Case 1: Count Increased (entered > original)
- Adds the difference to the last scan in the group.
- All other scans keep their original counts.
- Example: 3 scans of [2, 2, 1] and verifier enters 7 → becomes [2, 2, 3] (adds 2 to last).
Case 2: Count Decreased (entered < original)
- Subtracts from scans in reverse order (last to first).
- Each scan is reduced but never below 0.
- Example: 3 scans of [2, 2, 3] and verifier enters 4 → becomes [0, 2, 2] (removes 3 from last, then 0 from others).
Case 3: Count Unchanged (entered == original)
- Removes any count changes, restoring original values.
All count modifications are stored in the changes map, preserving original values in properties.
KeepOriginalCount - Accept Original
When the verifier chooses to keep the original count instead of entering their own:
- Restore Original Counts: Calls
setOriginalCount()to clear any changes from thechangesmap. - Mark as Verified: Sets
isVerified = trueon all scans. - Update Timestamp: Sets
dateModifiedto current time. - Reset Attempts: Calls
restoreVerificationAttempts()to clear any previous failed attempts. - Save to Database: Persists all scans in the group.
This allows verifiers to accept the original count without entering it, useful when they're confident the original scan was accurate.
AcceptEnteredCount - Force Accept After Mismatch
When counts don't match and the verifier wants to accept their entered count despite the difference:
- Apply Entered Count: Uses
updateCount()with the verifier's entered count (even though it differs from original). - Mark as Verified: Sets
isVerified = true(bypassing the match requirement). - Update Timestamp: Sets
dateModifiedto current time. - Reset Attempts: Clears
verificationAttemptssince the issue is resolved. - Save to Database: Persists the modified scans.
This is used after InvalidCountException when the verifier is confident their count is correct and the original scan was wrong.
CancelEnteredCount - Discard Changes
When the verifier wants to abandon their entered count and try again:
- Restore Original Counts: Calls
setOriginalCount()to remove changes. - Reset Attempts: Clears
verificationAttemptscounter. - Keep Verification Status: Does NOT change
isVerifiedflag (commented out in code). - Save to Database: Persists the reverted scans.
This allows starting fresh without penalty, giving another chance at entering the correct count.
Invisible Count Workflow
Typical Verification Flow
- Verifier navigates to a scan group (original count is hidden).
- Verifier physically counts the items.
- Verifier enters their count.
- PerformInvisibleCount executes:
- Match: Count is correct → Group marked verified, moves to next.
- First Mismatch: Shows
InvalidCountExceptionwith options:- Try again (CancelEnteredCount).
- Accept entered count (AcceptEnteredCount).
- Keep original count (KeepOriginalCount).
- Second Mismatch: Shows
CountAttemptsExceededException, must choose:- Accept entered count (AcceptEnteredCount).
- Keep original count (KeepOriginalCount).
Verification Attempts States
- 0 attempts: Fresh group, no validation performed yet.
- 1 attempt: First count entry failed, one more try allowed.
- 2+ attempts: Maximum reached, must accept one of the counts (no more retries).
Fields
- Count (when entering): The verifier's counted quantity for the selected group (original count is hidden).
Error Messages
- InvalidCountException: The entered count does not match the original total (first attempt).
- CountAttemptsExceededException: Two incorrect counts entered, must accept entered or keep original.
- Count must be a number: The count value contains non-numeric characters.
- [Custom Validation Message]: Count field-specific error from regex validation rules.
- QuotaNotAchieved: The percentage of verified groups is below the required audit quota.
- NotAllMandatoryVerified: All mandatory items must be verified before checkout.
- StepNotFoundException: The Count scan flow step is missing from configuration.