What's New
Stay up to date with the latest features, improvements, and fixes
What's New in Margin Master
Stay up to date with the latest features, improvements, and fixes.
MarginMaster v2026.714.22267 v2026.714.22267
July 14, 2026 30 changes-
Troubleshoot Connection now verifies Eagle IN export file exists
-
Enhanced splash screen reliability with automatic recovery
Added a safety mechanism that monitors the splash screen every second and automatically closes it if it becomes stranded over the main window. This "reaper" provides a last line of defense against splash screen issues, with a 5-second grace period to avoid interfering with legitimate operations. All splash screen operations are now verified complete before continuing.
-
Splash screen heartbeat monitoring
Added a safety-net heartbeat monitor that detects stranded splash screens and automatically closes them after a 5-second grace period. The monitor runs every second and checks whether the splash is visible when no operation has declared busy intent, preventing permanent deadlock even if splash teardown fails through an unexpected code path.
-
Better error messages for misconfigured strategy steps
The step detail log now includes actionable information when a step is skipped due to missing pricing configuration: what was wrong (no executable pricing action), what happened (step skipped with 0 records updated), and how to fix it (edit the step and choose a Set Future Price To level).
-
Cloud sync fails fast when network or Manager API is unreachable
Added connectivity failure detection that distinguishes between environmental issues (store offline, Manager API unreachable) and actual sync defects. When the first table fails due to connectivity, sync now aborts remaining tables and vendors immediately instead of retrying each one. These failures log as warnings rather than errors to prevent offline stores from generating false error telemetry. The sync dialog shows a clear "Cloud sync unavailable — Manager API unreachable" message.
-
Import failures now show actual connection errors
-
Protected critical dialogs from splash screen conflicts
Routed all modal dialogs through a new protected pipeline that guarantees the splash screen is closed before opening. This includes the cloud sync error dialog, excluded store prompts, OLEDB warnings, auto-update notifications, and data aging screens. Each protected modal logs breadcrumbs for diagnostics.
-
Cache location fallback is logged once at startup
When the fallback to per-user storage is triggered, the application now logs a single informational message at startup indicating that the shared ProgramData location is not writable and that the per-user cache location is being used instead. This replaces the previous behavior where every cache write would log an UnauthorizedAccessException, creating excessive noise in support logs while providing no clear indication of the root cause.
-
Splash screen no longer blocks dialogs during sync operations
Resolved a defect where the splash screen could remain visible and topmost while dialogs tried to open beneath it, making the application appear hung. The splash screen is now verified to be fully closed before any modal dialog appears, with automatic recovery if the splash becomes stranded. This particularly affected stores during Do-It-Best catalog updates and long sync operations.
-
Splash screen deadlock during long operations
Fixed MM-1311 where the splash screen could become stranded over modal dialogs during sync, startup, or auto-update checks, making the app appear completely hung. The issue occurred because the debounced hide mechanism shared a single cancellation token across all splash events, allowing unrelated progress updates to silently cancel pending hide requests. Implemented verified splash teardown that waits for the splash to actually close before opening any modal dialog.
-
API cache fallback for restricted user accounts
Fixed issue #1008 where ApiResponseCacheService write operations failed with UnauthorizedAccessException on machines where the Windows user had no write permission to C:\ProgramData\RetailerSoft\MarginMaster\. The failures were caught and logged but otherwise silent, preventing the cache from ever populating and forcing the application to re-fetch catalog-sync-info, version-history, issue-types, and store-contacts from the API server on every launch. The cache now automatically detects when the shared ProgramData location is not writable and falls back to the per-user LocalAppData directory, which is always writable without requiring elevation. The fallback is logged once at startup for visibility in support logs.
-
API cache now works on machines with restricted Windows permissions
Fixed issue #1008 where the API response cache would fail to write on machines where the current Windows user did not have permission to write to C:\ProgramData. The cache writes were failing with UnauthorizedAccessException, which was logged but not visible to users — resulting in the application re-downloading vendor and catalog data from the API on every launch instead of using cached copies. The application now detects when ProgramData is not writable and automatically falls back to the per-user LocalAppData folder, which is always writable and requires no administrator elevation. This is safe for API cache data since it's already encrypted per-user via DPAPI.
-
Strategy steps with no pricing action now skip instead of crashing
Previously, when a strategy step had rounding, lock, or other modifiers configured but no actual "Set Future Price To" level or value, the step would fail with "Not Future Price Setting to Load," get retried multiple times, and terminate the entire strategy run so later steps never executed. This affected store 12217's step 6 ("L&J&7&V&5 FP=2"). Now these steps are detected before execution and skipped with a detailed log entry explaining the issue, and the strategy continues running remaining steps.
-
Strategy steps with no pricing action now skip instead of failing
When a strategy step had no executable pricing action configured (Set To level was "Not Set"), the step would fail with "Not Future Price Setting to Load" and terminate the entire strategy, preventing all subsequent steps from running. These steps now skip gracefully with a detailed log entry explaining why, and the strategy continues to the next step. The step execution log shows "Skipped — No Pricing Action Configured" with guidance on how to fix the step configuration.
-
Epicor INFILE import now uses correct FTP server address
-
Auto-update dialog now waits for splash to close
The hourly auto-update notification dialog now uses verified splash teardown before opening. Previously, if the update check fired during a long sync operation, the dialog could open behind the topmost splash screen, making it unreachable and causing the app to appear hung.
-
Data aging screen now opens after cloud sync completes
The data aging initialization dialog previously started its cloud round-trip while the splash screen was still visible. It now closes and verifies the splash screen first, performs the initialization (bounded to 30 seconds), then opens the dialog through the protected modal pipeline.
-
Cloud sync error dialogs now wait for splash to close
Cloud sync error messages and excluded store prompts now use verified splash teardown, ensuring these modal dialogs are never hidden behind a lingering splash screen.
-
Fail-fast behavior when Manager API is unreachable
Cloud sync now detects connectivity failures (network offline, Manager API unreachable) and immediately aborts remaining table syncs for the current vendor and skips other vendors entirely. Previously, each table would be attempted individually, generating multiple error log entries for a single connectivity issue. A store (1838) had previously generated 14 error telemetry entries from a single offline sync run.
-
Connectivity failures logged as warnings instead of errors
Network and API connectivity failures are now classified as warnings rather than errors, preventing them from generating error telemetry. The system distinguishes these environmental issues (HttpRequestException, SocketException, "Manager API base URL is unavailable") from actual sync defects by walking inner exceptions to detect wrapped network errors.
-
Real-time status updates during connectivity-triggered abort
The sync progress display now shows vendor-specific messages when tables are skipped due to connectivity failures (e.g., "Ace Hardware - Cloud sync unavailable — Manager API unreachable; remaining tables skipped"), providing clearer feedback about why the sync stopped early.
-
Enhanced connectivity error classification
Added IsConnectivityFailure flag to TableSyncResult and logic to detect HttpRequestException, SocketException, and "Manager API base URL is unavailable" errors by walking the exception chain. MultiTableSyncService now uses this flag to abort remaining tables within a vendor and skip remaining vendors entirely when connectivity fails, preventing cascade failures.
-
Improved sync failure messages for connectivity issues
The Sync Dialog now displays a connectivity-specific message when the Manager API is unreachable: "Could not reach the Margin Master cloud service. Check the internet connection and try the sync again." This replaces the generic sync error message and is distinct from the firewall/port message shown for database connection failures.
-
Added pre-flight validation for pricing action lists
Created FuturePriceActionListHelper with HasExecutablePricingAction method that mirrors the modifier token stripping logic in ApplyFuturePriceActionsAsync. This prevents empty action lists (containing only ROUNDING/LOCK/STRATEGYSTEP/ADDSUBTRACT/NODECREASES modifiers) from reaching ApplyFuturePriceSqlAsync where they would fail. Includes comprehensive unit tests covering empty lists, modifier-only lists, and real pricing actions.
-
Path resolution with write permission verification
Added PathHelper.GetWritableApplicationDataSubPath() method that prefers the shared ProgramData location (so all users on a machine can share cached data) but verifies writability by actually creating a probe file—ACL checks alone are insufficient because write failures only surface during the actual write operation. When ProgramData is not writable, the method automatically returns the per-user LocalAppData path. This approach is appropriate for cache data (which is already encrypted per-user with DPAPI) but intentionally not used for data that must be shared across users, such as DatabaseConnections.json.
-
Added write permission detection with automatic fallback
Implemented PathHelper.GetWritableApplicationDataSubPath method that intelligently selects between shared (ProgramData) and per-user (LocalAppData) storage locations based on actual write permission testing. The method performs a real write probe by creating a temporary file rather than just checking folder existence or ACLs, since the permission failures only surface during actual write operations. Added PathHelper.IsDirectoryWritable to test writability without throwing exceptions, and PathHelper.GetLocalApplicationDataRetailerSoftApplicationSubPath to provide the per-user fallback location. All methods include comprehensive unit tests covering normal operation, fallback scenarios, and edge cases.
-
Comprehensive test coverage for permission fallback
Added five new tests (PathHelperWritableFallbackTests) verifying that the writable path resolver returns directories that can actually be written to, that the per-user path is always under LocalApplicationData, that directory writability detection works correctly for both writable and unusable paths, that probe files are properly cleaned up via DeleteOnClose, and that the method handles illegal paths without throwing exceptions.
-
Improved diagnostic logging for Epicor connections
-
Added debouncer behavior tests
Added comprehensive tests documenting how the splash screen's debouncer component behaves under concurrent operations. These tests pin the specific conditions that can cause splash screen hide requests to be lost, ensuring future changes to this component are deliberate and visible.
-
Debouncer behavior characterization tests
Added comprehensive unit tests documenting the Debouncer component's behavior, specifically the shared cancellation token and forced invocation characteristics that led to the splash deadlock. These tests exist to ensure future changes to debouncing behavior are deliberate and visible rather than accidental.
