Version History
A complete record of every Margin Master release
Added test coverage for menu navigation depth; Automatic restoration of known stamped identities; Enhanced error handling for automatic strategy backups.
User Interface
-
Improvement
Added test coverage for menu navigation depth
A new automated test verifies that all menu targets referenced in training lessons are within reach of the menu lookup system. The test analyzes the XAML structure to measure nesting depth and ensures no lesson tries to navigate to a menu that's too deeply nested to be opened programmatically.
-
Bug Fix
Training tours now open nested menu fly-outs
Training lessons that demonstrate nested menu options will now properly open those menus during lesson playback.
-
Bug Fix
Training tours now open nested menu fly-outs
Training lessons that walk through nested menu commands now properly open those menus so you can see what they're demonstrating.
-
Infrastructure
Added test to prevent unreachable menu targets in lessons
Added automated test that parses the main window XAML and validates that all menu items referenced in training lessons are within reach of the menu lookup logic. This prevents future lessons from targeting menus nested too deeply to be opened during playback.
Reporting & Exports
-
Improvement
Splash screen handling during large export prompts
The loading screen now properly hides when you're asked to confirm a large export, making the dialog easier to see and interact with.
-
Bug Fix
Large Westlake Excel export confirmation dialog fixed
When exporting more than 50,000 price changes to Westlake Excel format, you'll now see the confirmation dialog asking if you want to continue. Previously this would fail silently without completing the export.
-
Bug Fix
Large Westlake Excel export confirmation dialog fixed
When exporting large datasets (over 50,000 records) to Westlake Excel format, you'll now see the confirmation prompt asking if you want to continue, and the export will complete successfully after you confirm.
-
Bug Fix
Error messages during Westlake export now display correctly
If an error occurs during a Westlake Excel export, you'll now see an error message explaining what went wrong instead of the export appearing to do nothing.
Performance & Reliability
-
Improvement
Enhanced error handling for automatic strategy backups
Added defensive error handling to the auto-backup service's trigger method. When the system cannot read the backup setting due to database connectivity issues, it now logs a warning and skips the backup attempt rather than propagating the exception to calling code. This prevents unobserved task exceptions at startup and false error reports in save workflows.
-
Bug Fix
Detect store identity contradictions at startup
If you see a message saying your store settings don't match your database, the system will guide you to confirm the correct store information before continuing. This prevents pricing data from the wrong vendor being loaded into your database.
-
Bug Fix
Auto-backup no longer causes false save failure messages
You will no longer see "Failed to save strategy" error messages when your pricing strategies have actually saved successfully. This could happen when the database was slow to respond.
-
Bug Fix
Automatic strategy backup no longer crashes when settings unavailable
Fixed rare crashes during startup or misleading "Failed to save strategy" errors when automatic backups couldn't check their settings due to temporary database issues.
-
Bug Fix
Auto-repair the specific license server failover identity
If your store was affected by the August license server issue, the system will automatically restore your correct store identity on startup.
-
Bug Fix
Organization ID now follows confirmed store identity
When your store identity is validated, the system now ensures your organization settings match your actual store, not a previously incorrect one.
-
Bug Fix
Protect About table from credential sync overwrites
Database credential synchronization now preserves the About table's store identity when it contradicts incoming ApplicationSettings, rather than overwriting the database's own record. This ensures the independent evidence needed for startup validation remains intact until the user confirms the store through Store Configuration.
-
User Interface
Improved Store Configuration warning display
Warning messages in the store setup window now wrap to multiple lines so you can read the full explanation.
-
Infrastructure
Store Configuration writes confirmed identity to About table
When the user validates and saves store credentials through Store Configuration, those values are now recorded in the About table as well as ApplicationSettings. This ensures startup validation won't re-prompt for the same identity on every launch after a legitimate store change.
Infrastructure & Internal
-
Improvement
Automatic restoration of known stamped identities
Implemented automatic recovery for the specific license fallback case (Ace 33859) that affected 24 installations between February and August 2026. When this known stamped identity is detected on a database whose About table names a different vendor's store, the database's own store number is offered as a suggestion in the Store Configuration window, streamlining the correction process.
-
Improvement
Database setup preserves contradicting About records
Modified the database setup wizard to skip synchronizing store identity to the About table when a vendor contradiction is detected. This preserves the database's independent record of its own identity so the startup validation can detect the mismatch and prompt the user to resolve it.
-
Improvement
Store Configuration now updates About table on save
The Store Configuration window now records the user-confirmed store number and vendor in the About table after validation succeeds. This keeps the database's own identity record in sync with ApplicationSettings, preventing repeated prompts on subsequent launches after a legitimate store change.
-
Bug Fix
Store identity contradiction detection at startup
If your store settings were accidentally changed to another company's store number, the app will now catch this at startup and ask you to confirm your correct store information before proceeding.
-
Bug Fix
Database restore now reports SQL Server errors immediately
If a database restore fails, you'll now see the actual error message from SQL Server right away instead of waiting 30 seconds for a vague timeout message.
-
Bug Fix
Demo database upload now blocks unsafe databases
The "Update Cloud Demo Database" workflow now refuses to proceed if any provenance check fails, listing each specific failure reason before any backup is created. Previously, only the database name prefix was checked, which allowed customer data to be published.
-
Bug Fix
Database restore file naming fixed for non-standard backups
Database restores now work correctly even when the backup file name doesn't match the database name inside it, preventing conflicts with your live database files.
-
Bug Fix
Strategy execution tracking disabled for demo databases
Strategy runs on demo databases are no longer posted to the cloud analytics system. Previously, executions on demo databases (which contained real customer data until this fix) were being reported as store 99999's activity, leaking customer pricing strategies and dollar impacts.
-
Bug Fix
Organization ID now updates when store identity is corrected
When your store information is corrected, cloud sync settings will now automatically update to use your correct organization instead of keeping another store's settings.
-
User Interface
Improved Store Configuration window message display
Fixed the context message banner in the Store Configuration window to properly wrap long messages by replacing horizontal StackPanel with DockPanel layout. Messages explaining identity conflicts now display completely instead of being truncated.
-
Infrastructure
Demo database provenance verification system
Implemented DemoDataProvenancePolicy and DemoDataProvenanceReader to verify that demo databases are genuinely synthetic before publication. A database must pass all checks: correct naming prefix, presence of a synthetic-data marker (written only by the scrub script), no POS/server credentials, no connection strings, and no strategies imported from real stores. This was created in response to an incident where both demo databases were discovered to be real customer databases (Ace store 11325 and DIB store 3174) with only store identity changed, including plain-text SFTP passwords.
-
Infrastructure
Demo database provenance verification system
Created DemoDataProvenancePolicy and DemoDataProvenanceReader to verify that a database is provably synthetic before allowing it to be published as a demo database. The system checks four requirements: correct naming (MarginMaster_Demo_*), presence of a synthetic-data marker written only by the scrub script, no populated credential or store-identity settings, and no strategy names indicating imports from real stores (like "11325v0045-PS_imported"). All checks must pass before a database can be uploaded.
-
Infrastructure
Upload gate in Demo Mode workflow
Modified DemoModeWorkflowService to run provenance verification before backing up and uploading a demo database. If verification fails, the upload is blocked and a detailed message explains which checks failed. This prevents repeat of the September 2026 incident where real customer databases (Ace store 11325 and DIB store 3174) containing plain-text SFTP passwords were published to all Demo Mode users.
-
Infrastructure
Strategy execution tracking guard for demo databases
Added check to prevent strategy execution analytics from demo databases being posted to the cloud fleet tracking system. Previously, strategy runs on demo databases (which contained real customer data until this fix) were reported as store 99999's executions, mixing curated demo data with fleet statistics.
-
Infrastructure
Demo database scrubbing script
Added Invoke-DemoDatabaseScrub.ps1 PowerShell script that transforms a customer database into a safe demo database by regenerating all store-specific pricing and sales values from deterministic hashed seeds, removing POS imports and credentials, clearing real-store strategy artifacts, and writing the synthetic-data marker as the final step. The script is kept outside the shipped application's embedded scripts directory.
-
Infrastructure
Demo database scrubbing script
Added PowerShell script Invoke-DemoDatabaseScrub.ps1 that transforms a customer database into a safe demo database by regenerating all store-specific pricing and sales values from deterministic hashes, removing POS imports and credentials, blanking server addresses, and writing the synthetic-data marker as the final step. The script refuses to process any database not named "MarginMaster_Demo_*" and can verify that no values match the original source table.
-
Infrastructure
Comprehensive test coverage for provenance verification
Added 10 unit tests that pin the exact behavior of the provenance policy, including verification that the leaked Ace demo database as-it-was would be refused on every count except the name. Tests ensure all credentials found on leaked databases remain in the checked lists.
-
Infrastructure
Comprehensive provenance policy tests
Added test suite pinning the exact checks that failed on the leaked demo databases, ensuring every credential found on those databases (AFTPIP, AFTPUSER, AFTPPASS, MySql credentials, RSD server addresses, store contact information) remains in the checked lists. Tests verify that databases matching the leaked demos' exact state are refused on every count except the name prefix.
Menu command to reopen Strategy Execution Summary; Strategy execution summary can be reopened from menu; Rename Database window works on any database.
Strategy & Pricing
-
New Feature
Menu command to reopen Strategy Execution Summary
After running a strategy, you can now use Strategy > Show Strategy Execution Summary to bring back the results screen if you closed it. This lets you review the numbers, see which steps ran, and use the "Show Skus Not Priced" or "Show Skus That Changed" buttons without waiting for the strategy to run again.
-
New Feature
Strategy execution summary can be reopened from menu
After running a pricing strategy, you can now go to the Strategy menu and choose "Show Strategy Execution Summary" to bring back the results screen, even if you closed it. This lets you review the numbers, see which steps ran, and drill into the changes without running the strategy again. The menu option is only available after you've run a strategy since opening Margin Master.
-
Improvement
"Show Skus NOT included in Strategy" now works as a composable filter
After choosing "Show Skus NOT included in Strategy," you can now add departments, vendors, or any other selection and press Refresh to narrow down the unpriced items. The filter stays active until you clear it.
-
Improvement
"Show Skus NOT included in Strategy" now persists as an active filter
When you choose "Show Skus NOT included in Strategy," you can now add other filters like department or vendor and press Refresh to see unpriced items within that selection. The filter stays on until you clear it.
-
Improvement
User-requested summary always shows regardless of settings
If you've turned off automatic strategy summaries in settings, the new menu command will still show the summary when you ask for it—the setting only controls whether it pops up automatically after each run.
-
Improvement
All pricing commands now respect the No Pricing Rule filter
Set Future Price, Remove Decreases, and all exports now work correctly with the No Pricing Rule filter—they'll only affect the unpriced items you're viewing.
-
Improvement
Strategy Execution Summary "Show Execution Log" renamed to "Show Execution Logs"
The "Show Execution Logs" button opens the folder with detailed logs from all your strategy runs.
-
Bug Fix
Delete Displayed Skus now works on the unpriced items list
You can now delete the unpriced items if needed—the Delete Displayed Skus command is no longer blocked.
-
User Interface
Summary command bypasses "show after run" setting
If you've turned off the setting that automatically shows the summary after each strategy run, the new menu command still works—it knows you're asking for it specifically.
-
User Interface
No Pricing Rule filter now shows its state clearly
The "No Pricing Rule" filter now shows up either as a ticked BLANK in your PS Rule box (if you have one), or as a pill you can click to turn off. Press F12 to clear it along with everything else.
-
User Interface
Filter appears in PS Rule selection box or as a pill indicator
If you have a PS Rule box, the filter shows as a checked "BLANK" entry you can untick. Otherwise, a "No Pricing Rule" pill appears next to your selection tabs—click it to turn off the filter.
-
User Interface
Command disabled until first run in session
The command is grayed out when you first open Margin Master, with a tooltip explaining it will become available after you run a strategy. It stays available for the rest of your session, even if you close and reopen the summary multiple times.
-
User Interface
Tooltip explains when menu item is disabled
If the menu option is greyed out, hovering over it explains that you need to run a strategy first before the summary can be shown.
-
User Interface
"Show Execution Log" renamed to "Show Execution Logs"
The "Show Execution Log" button is now "Show Execution Logs" to clarify that it opens a folder with multiple log files.
-
Architecture
Introduced NoPricingRuleFilterPolicy to centralize filter logic
Added NoPricingRuleFilterPolicy class to define which column answers "did any step touch this SKU" (PSRuleHistory), which selection box should carry the filter, and the BLANK sentinel value. This ensures the on-screen filter, execution summary count, and Excel export always agree on what "no rule" means, preventing drift between different code paths.
Imports & POS
-
Improvement
Store Identification in Import Progress Messages
Import progress messages now always show a clear store identifier instead of displaying blank spaces for certain store types.
-
Improvement
Merge duration now logged for diagnostics
The support log now records how long each store's POS data merge takes to complete. This allows support staff to distinguish between slow merges (normal for large stores) and truly stuck operations, since the 10-minute command timeout meant both could appear identical in logs.
-
Improvement
Merge Duration Now Logged for Support Diagnostics
Added timing and duration logging for the POS-to-store-table merge operation. With a 600-second command timeout, support logs previously couldn't distinguish between a slow merge and a stuck one. Merge completion is now logged with elapsed time, enabling faster diagnosis of import performance issues.
-
Bug Fix
Import Progress Now Updates During Long-Running Merge Operations
If you're importing a large POS file, you'll now see the import progress through "merging POS data," "rebuilding SKU index," and "finalizing store data" steps instead of the screen appearing frozen on one line.
-
Bug Fix
Progress updates now show during POS merge operations
When importing large Compass stores, the progress screen now shows "merging POS data," "rebuilding SKU index," and "finalizing store data" as separate visible steps instead of appearing frozen during the merge.
-
Bug Fix
Corrected store display name in Compass import progress
Fixed a display issue where Epicor character-based stores showed "Processing Store Data" with a blank space instead of the store identifier. The progress message now uses the same effective store key shown in the main import loop, ensuring consistent labeling throughout the import process.
User Interface
-
Improvement
Added tooltip explanation for disabled "Show Affected Items" button
Hovering over the "Show Affected Items" button now explains that you need to select a step from the list above first, even when the button is greyed out.
-
Bug Fix
Strategy summary drill-in buttons now display correct results
Clicking "Show Skus Not In Strategy" or "Show Affected Items" from the strategy summary now correctly displays only the filtered items you requested, instead of showing all price changes.
-
Bug Fix
Strategy Summary buttons no longer clipped at narrow widths
All buttons in the Strategy Execution Summary are now visible and clickable, even when the dialog is resized smaller.
-
Bug Fix
Strategy Summary dialog width corrected
The Strategy Execution Summary window now opens wider so the Close button and other action buttons all fit on one line without wrapping.
-
Bug Fix
Strategy Execution Summary dialog width increased
When viewing the Strategy Execution Summary, all buttons now appear on one line and are fully visible without any wrapping or clipping.
-
Bug Fix
Strategy summary action buttons no longer clipped
All buttons in the strategy summary dialog are now fully visible and properly arranged, with no text overlap or clipping.
-
Bug Fix
Strategy Summary drill-in results now stay on screen
When you click "Show Skus Not In Strategy" or "Show Affected Items" in the Strategy Execution Summary, the grid now displays the items you requested instead of showing all price changes.
-
User Interface
Dialog sizing refinement
The width calculation now accounts for the measured space requirements: approximately 925 pixels for the six buttons and 300 pixels for the checkbox column. This ensures proper layout without clipping or overlapping elements.
-
User Interface
Dialog size optimization
The dialog dimensions were measured and calculated based on actual button requirements rather than estimated, ensuring the layout remains stable and readable at the new size.
-
User Interface
Show Affected Items button tooltip now visible when disabled
Hovering over the greyed-out "Show Affected Items" button now explains that you need to select a step first.
Infrastructure & Internal
-
New Feature
Rename Database window works on any database
If your database has a generic name like "OlderMM" or still says "MarginMaster3", you can now rename it to something that identifies your store (like "DIB_10368_Woodstock_Hardware_Epicor"). Margin Master suggests the name from your store information and you can edit it. The rename keeps a backup, so nothing is lost.
-
New Feature
Rename any Margin Master database
The Rename Database tool now works on any of your databases, not just the default "MarginMaster3" name. It suggests a name that identifies your store and you can edit it. Your connection switches automatically when you rename the database you're using.
-
New Feature
Closed store detection with title bar indicator
A red warning badge will appear in the title bar if your store number has been retired. Click it to see details and migrate to your current store number.
-
New Feature
Comprehensive store number migration service
The migration tool now moves all your pricing rules, margins, and exceptions to the new store number automatically, not just basic settings.
-
Improvement
Database housekeeping moved to SQL Server Tools
The database housekeeping tools (Optimize/Shrink, Reset Database, Run Maintenance Scripts) are now easier to find: open SQL Server Tools from File > Utilities and look in its Tools menu, right alongside Rename, Migrate and Delete Database.
-
Improvement
Database utilities consolidated under SQL Server Tools
All database tools are now together in File > Utilities > SQL Server Tools. Look in its Tools menu for Rename, Migrate, Delete, Optimize/Shrink, Reset Database, and Run Maintenance Scripts.
-
Improvement
Database naming logic centralized and tested
The convention for building a database name from store information (`{Vendor}_{StoreNumber}_{StoreName}_{POS}`) now lives in one tested place (`DatabaseNameBuilder` in `MarginMaster.Common`) instead of three hand-maintained copies that had drifted. The builder sanitizes each part, validates names against SQL Server's reserved words and character rules, recognizes generic/timestamped names (like "MarginMaster3" or "OlderMM_20260909_160718") that identify no store, and generates unique names when the base name is already taken. This is shared by the Create New Database window, the Rename Database window, and backup file naming, so they always agree on what counts as a valid name.
-
Improvement
Force-refresh organization store list for status checks
GetOrganizationStoresAsync gains a forceRefresh parameter that drops the 30-day cache entry before fetching. Required for closed-store detection since a store retired last week would otherwise report as open for a month. The store identity health check uses this flag to ensure StoreStatus reflects current cloud state rather than stale cached data.
-
Bug Fix
Fixed store scope tokens silently skipped during renumbering
The previous implementation only matched store scope tokens followed by a pipe character (StoreNumber~3605|), causing it to miss tokens in the last position of a rule — precisely the most common shape for per-store pricing rules. Rules scoped to a single store were the most likely to be missed, leaving stores operating under retired numbers. The new StoreScopeTokenRewriter correctly handles tokens at any position including end-of-string.
-
Bug Fix
Prevented accidental SKU and price corruption during store renumbering
Store renumbering previously used a simple string replacement (Replace("3605","10368")), which would silently corrupt any SKU, product group, cost, or margin value that happened to equal the old store number. The new token-based rewriter anchors every change to the "StoreNumber~" prefix, ensuring only actual store scope tokens are modified while leaving all pricing data untouched. Includes 17 new tests specifically guarding against distinct corruption scenarios.
-
Bug Fix
Fixed idempotence flag that caused store conversion to re-run on every import
The EpicorStoreMapStrategiesConverted flag was being written back as "false" instead of "true", causing the entire store number conversion to re-run on every Epicor extract. This was harmless only as long as no store number was ever reused. The flag now correctly latches after successful conversion, and the conversion process properly tracks and logs the number of rules changed.
-
Bug Fix
Store identity repair for organizations with multiple or zero open stores
If your organization has multiple stores, the tool will ask you to confirm which one is correct rather than guessing.
-
Bug Fix
Renaming the active database now switches the connection before dropping the old name
When renaming the database Margin Master is currently connected to (which is allowed), the connection is switched to the new name *before* the old database is dropped. This is required because the drop runs `SET SINGLE_USER WITH ROLLBACK IMMEDIATE`, which would otherwise kill the app's own session. The Rename Database window warns when the selected database is the active one and offers to switch the live connection after the rename succeeds.
-
User Interface
Rename Database Window replaces in-line rename flow
Renaming a database now opens a window where you pick the database, see the suggested name, watch the progress, and get a clear result—no more jumping between message boxes.
-
User Interface
Dry-run preview before migration
Before changing your store number, you'll see a preview of exactly what data will be moved, so you can confirm the migration is safe.
-
User Interface
Rename Database menu item no longer conditionally hidden
The "Rename Current Database" menu item is now always available when you have a database open, regardless of its current name.
-
Database
Store identity read from database for rename suggestions
`IInstanceMigrationService.GetStoreIdentityAsync` reads vendor, store number, store name, and POS system directly from a database's `dbo.ApplicationSettings` table—independent of the running application's settings—so a name can be suggested for any Margin Master database on any instance, even one the app isn't connected to. This prevents the old problem where a rename suggestion depended on the *current* store's settings rather than the database's own identity.
-
Architecture
Shared database copy service powers both rename and migration
Database renaming and instance migration now share a common `CopyDatabaseAsync` service that handles backup + RESTORE-to-new-location + optional drop-source. This generalizes `InstanceMigrationService` so a migration is a copy with the name unchanged, while a rename is a copy to the same server under a new name. The service derives new physical file names from `RESTORE FILELISTONLY` rather than string-replacing the old database name inside the old file name, fixing cases where the .mdf was never named after the database in the first place (the MM-1458 backup was exactly that: database "OlderMM", logical names "MarginMaster2", physical files "DIB_3605_Woodstock_Hardware_Epicor"). This deletes the old `DatabaseRenameService`, whose string-replacement assumption was a no-op whenever the file and database names didn't match.
-
Architecture
Shared database name builder prevents drift
A new `DatabaseNameBuilder` class centralizes the database naming convention ({Vendor}_{StoreNumber}_{StoreName}_{POS}), validation rules, uniqueness logic, and generic-name detection. This logic was previously maintained in three separate hand-written copies (Create New Database, the old rename tool, and backup file naming) that had diverged over time—MM-1458 was the cost of that drift, where a Do-it Best store ran on a database called "OlderMM" and submitted backups that couldn't be identified. The Create New Database window, Rename Database window, and backup services now all use this shared implementation.
-
Architecture
Centralized store number normalization to prevent inconsistent renumbering
Store number comparison logic (leading zero handling) has been consolidated into StoreScopeTokenRewriter.NormalizeStoreNumber in MarginMaster.Common, shared by both WPF migration and DataImport. StoreIdentityRepairPolicy now delegates to this single implementation, eliminating the risk of half-applied renumbering caused by inconsistent "is this the same store" checks across different code paths.
-
Infrastructure
Instance migration service extended for same-server renames
`InstanceMigrationService.CopyDatabaseAsync` is the new general form behind both migrations and renames: it copies a database from one server+name to another server+name via backup and restore, optionally dropping the source afterward. A rename is this operation with the server unchanged and drop-source enabled. The restore step now relocates the physical .mdf/.ldf files to match the destination database name (via RESTORE FILELISTONLY and per-file MOVE clauses), so a renamed database gets files named after its new identity rather than keeping the old MarginMaster3.mdf forever.
-
Infrastructure
Training lesson audio and documentation updated
The sample training lessons for "menu-bar" and "reset-stale-data" have been re-rendered to reflect the menu structure changes (the rename tool now being available for all databases, and the housekeeping tools moving to SQL Server Tools). The SQL Server Setup Window documentation has been updated to describe the new Tools menu and the Rename Database window.
Antivirus and endpoint security exclusions documentation; Background download progress reporting; Background update download with progress callback.
User Interface
-
Improvement
Background update download with progress callback
Enhanced the AutoUpdateService.DownloadUpdatesInBackgroundAsync method to accept a progress callback parameter, allowing callers to receive percentage updates during the download. Progress events are marshaled from background threads to the UI dispatcher, with duplicate percentage values filtered to avoid unnecessary UI updates.
-
User Interface
Update download progress indicator
You'll now see a blue "Installing update…" badge with a percentage in the title bar while updates download in the background. You can keep working normally—nothing restarts until the green "Update Ready" button appears.
-
User Interface
Clarified update badge meanings
The blue "Update Available" badge now means a download failed and clicking it will retry—it's not shown during active downloads anymore.
-
Infrastructure
Update progress tracking across startup and manual check flows
Added update download progress tracking to three code paths: the automatic update timer task (ExecuteAutoUpdateTaskSafeAsync), the snoozed update pill surfacing (SurfaceSnoozedUpdatePillAsync), and manual update checks (CheckForUpdatesAsync). Each path now shows the downloading pill with percentage updates and properly clears it in a finally block to prevent stuck UI state if downloads fail.
Performance & Reliability
-
New Feature
Antivirus and endpoint security exclusions documentation
A new help document is available for your IT staff that explains which folders and files to exclude from antivirus scanning to prevent update and startup problems.
-
Bug Fix
Startup update operations now bounded with timeout protection
If the update server doesn't respond during startup, Margin Master will now give up after a reasonable time and open normally instead of staying stuck on the splash screen. The automatic hourly check will retry the update in the background.
-
Architecture
Progress-based stall detection for update downloads
Introduced DownloadStallWatch, a state machine that monitors download progress signals to distinguish between slow-but-working transfers and genuinely stalled connections. It tracks consecutive seconds without progress rather than total elapsed time, ensuring slow stores can still complete updates while preventing indefinitely stalled transfers from blocking startup. The 90-second threshold was chosen because Velopack's progress callback fires frequently, so prolonged silence indicates bytes have stopped arriving. Comprehensive unit tests validate both thresholds—never abandoning working downloads and always abandoning dead ones.
-
Infrastructure
StartupUpdateGuard service wraps bounded update operations
Created StartupUpdateGuard to encapsulate all timeout logic for startup-path update operations, using TaskTimeoutHelper to race operations against their timeouts and DownloadStallWatch for progress monitoring. The service separates timeout handling from update logic and makes the decision-making testable in isolation. When operations are abandoned, they're allowed to finish or die in the background since Velopack writes to temporary files that the next attempt purges.
Infrastructure & Internal
-
Improvement
Background download progress reporting
Modified DownloadUpdatesInBackgroundAsync to accept an optional progress callback and pass it through to the underlying DownloadUpdatesAsync method. All three silent download call sites (periodic timer check, startup snoozed-update path, and background download after check) now light the pill with percent-complete updates. Each caller clears the pill in a finally block so failed downloads cannot strand the indicator, and SetUpdateDownloadingPill swallows dispatcher errors to prevent masking real exceptions.
-
Bug Fix
Corrected misleading XAML comment
The blue "Update Available" pill now correctly means a download failed and needs to be retried, while the new "Installing update…" pill shows when a download is actively running.
-
User Interface
Update download progress indicator
When Margin Master downloads an update in the background, you'll now see a blue "Installing update…" pill in the title bar showing progress percentage. This lets you know the app is working on fetching a new version, not just running slowly.
-
Infrastructure
Update documentation for download visibility
Updated banners-and-badges.md and update-modes.md to document the new "Installing update…" pill, clarifying the distinction between actively downloading (blue pulsing pill with percent), download complete and ready to apply (green "Update Ready" pill), and download failed (blue "Update Available" pill). Added search keywords for users looking to understand why Margin Master is downloading or showing update progress.
"Show Skus Not In Strategy" button on execution summary; Export not-priced items to Excel with reason column; "Show Skus Not In Strategy" button on execution summary.
Strategy & Pricing
-
New Feature
"Show Skus Not In Strategy" button on execution summary
Click "Show Skus Not In Strategy" on the summary screen to see the items your strategy didn't select—no need to hunt through the menus.
-
New Feature
Export not-priced items to Excel with reason column
Export the full not-priced list to Excel with a Reason column that tells you what to fix for each item. The file isn't limited by your display records setting, so you get the complete list.
-
New Feature
"Show Skus Not In Strategy" button on execution summary
The execution summary now has a "Show Skus Not In Strategy" button that opens the list of items your strategy didn't select, so you can go straight from the number to the actual items.
-
New Feature
Export not-priced items to Excel with reasons
You can now export the complete list of not-priced items to Excel from the execution summary or the Strategy menu. The export includes a Reason column explaining why each item was left alone, and it's not limited by your maximum display records setting.
-
Improvement
Strategy Execution Summary reworded "Items not priced" line
The summary now says clearly that unpriced items are not an error—your strategy just didn't select them. It shows how many had no cost versus how many weren't selected by any step.
-
Improvement
Zone override editor with clear button and validation
The zone override field now has a clear button to remove overrides, and won't let you save a zone number that doesn't exist in the pricing data.
-
Improvement
"Show Skus NOT included in Strategy" is gated until a strategy has run
The "Show Skus NOT included in Strategy" menu item is now disabled until you've run a strategy at least once. If the list is empty after a run, you'll see a message explaining that every item was priced.
-
Improvement
Automatic repair of invalid zone overrides during sync
After each sync, the system automatically fixes any stores with invalid zone overrides and reports which stores were corrected in the import log.
-
Improvement
Added logging for zone pricing failures
Zone pricing operations now log when a store's zone override points to a zone with no data, making it much easier to diagnose pricing issues. Previously these failures were completely silent.
-
Improvement
Strategy Execution Summary rewords and explains "Items not priced"
The execution summary now explains that "Items not priced" is normal, not an error—it just means your strategy's steps didn't select those items. The line shows how many were skipped because no step selected them versus how many have no cost.
-
Improvement
Zone Pricing Failure Now Logged and Reported
If a store somehow ends up with a zone that has no pricing data, you'll now see a clear warning in the import results instead of the problem being silent.
-
Improvement
"Show Skus NOT included in Strategy" only available after a strategy run
The "Show Skus NOT included in Strategy" menu is greyed out until you've run a strategy—before that, nothing has been priced yet so the list would be meaningless.
-
Improvement
Empty "Show Skus NOT included in Strategy" grid now explains itself
If the not-in-strategy screen is empty, you'll see a message confirming that every item was covered—not just a blank grid.
-
Improvement
Execution log reworded unpriced section
The detailed strategy log file now says "ITEMS LEFT WITHOUT A NEW PRICE: N" instead of "SKUS WITH NO PRICING RULE," and explains "Not an error—the strategy's steps did not select these items." It logs the NoRuleCount separately ("N were touched by no step at all (PSRuleHistory is empty). This is what Strategy > Show Skus NOT included in Strategy loads.") so a support reader can reconcile the grid's row count against the file.
-
Bug Fix
Zone Override Validation on Store Manager Screen
When entering a zone override for a store, Margin Master now checks that the zone number you typed is valid before saving it. If the zone doesn't exist, you'll see an error message and the value won't be saved.
-
Bug Fix
Zone override validation prevents invalid pricing zones
Stores with invalid zone overrides will now show an error when you try to enter them, and the system will automatically fix any existing invalid overrides during import.
-
Bug Fix
Zone Override field now rejects invalid zone numbers
If you try to enter a zone number that doesn't exist in your vendor catalog, the system will now warn you and prevent the save. You can also click the X button to clear a zone override completely.
-
Bug Fix
"Show Skus NOT included in Strategy" now identifies the correct items
The "Show Skus NOT included in Strategy" screen now shows the correct list of items your strategy didn't select. Previously, if your strategy had a catch-all step, some items were missing from the list.
-
Bug Fix
Automatic repair of stores with invalid zone overrides
Stores that previously had broken zone overrides (showing zero or invalid zone numbers) will automatically have those bad values cleared, restoring correct zone pricing.
-
Bug Fix
Automatic Repair of Invalid Zone Overrides
If a store has a zone override set to a zone number that doesn't have any pricing data, the system will automatically remove that override during sync and let the store use its assigned zone. You'll see a note in the import results if this happens.
-
Bug Fix
Zone Resolution Fallback Logic
Stores with invalid zone numbers stored from before this fix will now correctly use their Ace-assigned zones instead of pricing at "zone 0."
-
Bug Fix
Zone pricing now reports configuration issues for invalid zones
If a store's zone has no pricing data, you'll now see a clear warning in the import report instead of pricing silently being skipped.
-
Bug Fix
"Show Skus NOT included in Strategy" now counts correctly
The "Show Skus NOT included in Strategy" list now shows all items no step touched, even when your strategy has a catch-all step—it was undercounting before.
-
Bug Fix
Model-level fallback for non-positive zone values
Updated StoreManagerInfo.EffectiveZone to treat zero or negative zone values as "not set" and fall through to the assigned zone, then to national zone 99999. Previously a stored zero was honored as a valid override, resolving to pricing zone "0" which matched no records.
-
Bug Fix
"Unlimited" maximum display records now works correctly
When you set maximum display records to "Unlimited," grids will now actually load all records instead of stopping after just one row.
-
Bug Fix
"Unlimited" maximum display records now works
Setting Maximum Display Records to "Unlimited" now actually loads all records instead of stopping at one.
-
User Interface
Clear Button for Zone Override
You can now click the X button in the Zone Override box to remove an override and let the store use its regular Ace-assigned zone. Before, there was no way to clear an override once entered.
-
User Interface
Strategy Execution Log enhanced with not-priced breakdown
The execution log's unpriced section now reports the NoRule subset separately from the total, labels both populations by what they mean, and names the menu path that reaches them, so a support reader can reconcile the grid's row count against the file.
-
User Interface
Strategy Execution Summary layout additions
Added "Show Skus Not In Strategy" and "Export Not Priced" buttons to StrategyExecutionSummaryView.xaml, shown only when HasUnpriced is true. The view model raises their CanExecuteChanged when HasUnpriced changes via POCO convention. Both buttons set request flags (ShowNotInStrategyRequested, ExportNotPricedRequested) and close the dialog so the grid or export runs without a modal in the way, matching the "Show Affected Items" pattern.
-
Database
Unpriced report now tracks three counts per table
UnpricedSkuTableCount gained a NoRule field—the subset of unpriced rows with an empty PSRuleHistory trail. This is what "Show Skus NOT included in Strategy" loads, reported separately from the total unpriced count (which also includes rows a step claimed but could not price) so the summary can quote the number the grid will actually match.
-
Architecture
Unpriced predicates unified into shared helpers
The execution summary report, the grid loader, and the export were three hand-written WHERE clauses selecting the "not priced" population, and they had already drifted. They are now RoundingSql.NoRuleTouchedPredicate(), UnpricedPredicate(), and UnpricedReasonSql(), interpolated by every reader, so the number the summary quotes and the rows the grid and export load cannot disagree. UnpricedSkuReport gains NoRuleCount so the summary can quote the subset the menu item actually loads, separately from the unpriced total.
-
Infrastructure
Shared predicates for unpriced/not-touched queries
Added RoundingSql.NoRuleTouchedPredicate(), UnpricedPredicate(safeCostSql), and UnpricedReasonSql(safeCostSql) helpers. The unpriced report, the grid loader, the export, and the execution log all call the same expressions, so the counts can never drift. Comprehensive tests in NoRuleTouchedPredicateTests, UnpricedPredicateTests, and UnpricedReasonSqlTests lock the predicates' shape and their relationship (no-rule is a strict subset of unpriced; the predicates are complements across the main table).
-
Documentation
Updated "Reviewing a Strategy" guide
Documented the reworded "Items not priced" line, the new summary buttons, why the menu item is greyed out before a run, the export format and Reason column values, and the distinction between the full unpriced total and the no-rule subset. Added three common questions covering the rewording, the count difference, and how to get the list into Excel.
Imports & POS
-
Improvement
Clear messaging for missing import layouts
If you see an empty import file list, you'll now see a message explaining why and how to fix your POS system settings.
-
Improvement
Enabled chunked writes for MySQL Compass inventory imports
Large MySQL Compass inventory imports (10,000+ items) are now processed in smaller batches to prevent timeouts.
-
Improvement
Chunked write operations reduce database blocking
Inventory writes are now split into batches of 5,000 items with 100ms pauses between batches, matching the proven approach used for Epicor imports. This prevents large imports from being blocked by other database activity and exceeding timeout limits. Previously, all items were written in a single uninterrupted stream which could be blocked past the timeout threshold on busy servers.
-
Improvement
Added transient retry logic for MySQL Compass bulk merge operations
Wrapped the BulkMergeAsync call with SqlTransientRetry to handle command timeouts (-2), which are typically caused by momentary database blocking. Since the merge operation uses the primary key, re-running is safe. This prevents one-off timeout failures from aborting the entire import.
-
Improvement
Corrected logging severity for missing import layouts
Changed the severity of missing import layout messages from Error to Warning, since this is a configuration condition rather than a defect. These warnings are now reported through the store configuration issue collector to notify the appropriate person, while keeping the error dashboard clear of configuration-related messages.
-
Bug Fix
Added retry limit for failed MySQL Compass inventory blocks
If a MySQL Compass inventory import fails repeatedly on the same batch of items, you'll now see an error message after 3 attempts instead of the application appearing frozen.
-
Bug Fix
Import no longer retries failed blocks indefinitely
If a Compass inventory import encounters repeated database errors, you'll now see a clear error message instead of the import hanging indefinitely.
-
Bug Fix
Import dialog now explains why file list is empty for unsupported POS types
If your POS system type isn't supported, the Import Manager now shows a message explaining why no files appear instead of just showing an empty list.
-
Bug Fix
Prevented redundant error logging for missing import layouts
Fixed a memoization bug where failed POS type lookups were never cached, causing the same error to be logged repeatedly. Store 1918 generated 23 identical error reports in 15 minutes by reopening the import dialog. The lookup result is now cached per service instance regardless of success or failure.
-
Bug Fix
Reduced duplicate error logging for missing layouts
Fixed an issue where the system logged the same "no import layout" error up to 23 times when checking import files for a POS type without a layout. The system now checks once per session and reports configuration issues through the proper channel instead of flooding error logs. This particularly affected stores on POS systems like Spruce that don't yet have import layouts.
-
Bug Fix
Corrected connection pooling for bulk inventory writes
Switched to non-MARS (Multiple Active Result Sets) connection strings for MySQL Compass bulk writes to prevent connection interleaving issues. This resolves timeout failures that occurred when bulk copy operations competed with other active queries on the same connection, which was the root cause of failures at specific high-volume stores.
-
Bug Fix
Import layout folder no longer created unnecessarily
Fixed an issue where listing import files for a POS type would create empty directories in the application folder even when no layout existed for that POS system. These orphaned folders accumulated during updates. The system now only reads existing layout directories without creating new ones.
-
Bug Fix
Switched to non-MARS connection for MySQL Compass inventory imports
Changed from ActiveConnectionString to ActiveConnectionStringNoMARS to match the convention used by sibling dw_item imports. MARS (Multiple Active Result Sets) was causing the bulk copy to interleave with other database reads on the same connection, contributing to batch timeout failures at store 17201.
-
Bug Fix
Stopped probing for "Unknown" POS type import layout
The system no longer attempts to load an import layout when the POS type is "Unknown", which is the sentinel value for "not configured yet". This eliminates unnecessary lookups and prevents logging errors during application startup before store settings finish loading.
-
Bug Fix
Prevented folder creation when listing import mapping files
Fixed MappingFilesForPOS to return an empty list when the layout folder doesn't exist instead of creating it. Previously, this created empty Unknown\ and Spruce\ directories in the Velopack "current" folder for any store whose POS had no layout, which were then orphaned after updates.
-
User Interface
Added clear error notifications for repeated MySQL Compass import failures
If a MySQL Compass import fails repeatedly, you'll now see a clear error message explaining what happened instead of a progress bar that never completes.
Enhanced update check logging; Update check activity now logged for diagnostics; Periodic update checker now arms on every launch.
Performance & Reliability
-
Improvement
Enhanced update check logging
Added log entry "Periodic update check armed — next check in {Interval}" when the update timer starts, making it possible to verify from customer logs whether the checker is alive. Previously it was impossible to distinguish between "checked and found nothing" and "never armed at all."
-
Bug Fix
Periodic update checker now arms on every launch
Margin Master will now correctly check for and download updates every hour while running, ensuring you get bug fixes and improvements as soon as they're available instead of waiting until you restart the app.
-
Bug Fix
Update timer cleanup improvements
StopAutoUpdateTimer now properly disposes the cancellation token source and clears all task references. The run loop re-reads the timer field each iteration to handle mid-loop disposal or replacement, preventing potential race conditions when updates are applied or timers are restarted.
Infrastructure & Internal
-
Improvement
Update check activity now logged for diagnostics
Added logging when the periodic update checker is armed, including the configured check interval. This makes it possible to verify from customer logs whether the background checker is running, distinguishing between "checked and found nothing" versus "never started checking" scenarios.
-
Bug Fix
Periodic update check now starts correctly on every launch
Fixed a defect (MM-1454) where the automatic update checker would not activate when the application was launched normally. The issue was caused by pre-creating a timer object in the constructor without a consumer task, which made the startup guard incorrectly believe a checker was already running. The guard now properly tests whether the background check task is active, ensuring updates are discovered automatically every hour rather than requiring a manual restart to pick them up.
-
Bug Fix
Auto-update timer lifecycle management improved
Enhanced cleanup of update checker resources to properly dispose of cancellation tokens and clear background task references. This ensures the checker's running state is accurately reflected and prevents resource leaks during timer restarts.
Azure SQL detection prevents unnecessary shrink operations; Daily automatic optimization disabled on Azure SQL; Optimize/Shrink Database dialog updated for Azure SQL.
Performance & Reliability
-
Improvement
Azure SQL detection prevents unnecessary shrink operations
If you use Azure SQL to host your Margin Master database, optimization now runs faster and generates less transaction log activity. You won't be charged for larger backups caused by unnecessary shrink operations.
-
Improvement
Daily automatic optimization disabled on Azure SQL
On Azure SQL, Margin Master no longer runs automatic database optimization at startup, preventing unnecessary delays when opening the application.
-
User Interface
Optimize/Shrink Database dialog updated for Azure SQL
When you run Optimize/Shrink Database on Azure SQL, the dialog clearly explains that the shrink step will be skipped and asks if you want to rebuild indexes and update statistics instead.
-
User Interface
Optimize Database Indexes reports Azure SQL shrink skip
The "Optimize Database Indexes" command now reports "shrink skipped: Azure SQL" in its completion summary when running against an Azure SQL database, making it clear that the shrink step was intentionally omitted rather than failed.
-
User Interface
Shrink Log Files script removed from Azure SQL maintenance menu
If you use Azure SQL, the Shrink Log Files option will not appear in the Run Maintenance Scripts menu since it doesn't apply to cloud-hosted databases.
-
Infrastructure
Database optimization policy unit tests added
New DatabaseOptimizationPolicyTests pin the Azure SQL detection and shrink-skip behavior with comprehensive unit tests covering Azure SQL Database, Azure SQL Managed Instance, on-premises SQL Server editions, and failed version detection scenarios. The tests ensure that a failed version lookup always preserves on-premises behavior.
-
Infrastructure
Documentation updated with Azure SQL section and daily optimization details
The SQL Optimization documentation now includes a dedicated "Azure SQL" section explaining the shrink skip behavior, documents the automatic daily optimization pass (previously undocumented), and corrects the step order to reflect that shrinking happens before index rebuild (a code change from 2026-08-20).
One-click settings folder repair; Settings folder repair dialog features; Settings folder permissions documentation.
Cloud Sync & Vendor Data
-
New Feature
Added POS import divergence detection and warning
If your "Last Import" date doesn't match the import history in the grid below it, you'll now see a warning explaining the discrepancy and suggesting you import again.
-
New Feature
Point-of-sale data divergence warning added
The Data Aging screen now warns you when the POS import date and import history don't match, just like it does for vendor syncs.
-
Improvement
Rewrote divergence warning messages to report gaps, not verdicts
Warning messages on the Data Aging screen now say when Margin Master couldn't confirm a sync result, rather than claiming your data didn't update when it may have.
-
Improvement
Divergence warning messages revised to report facts, not verdicts
Warning messages on the Data Aging screen now explain that your catalog may already be up-to-date even when dates disagree, rather than claiming the sync failed.
-
Bug Fix
Fixed "Last Synced" date advancing for failed or empty syncs
The "Last Synced" date on the Data Aging screen will no longer move forward unless your vendor catalog data actually updated or was confirmed current.
-
Bug Fix
Last Synced date no longer advances when no tables ran
The "Last Synced" date on the Data Aging screen will no longer move forward after a sync that didn't actually run any tables.
-
Bug Fix
Made sync statistics failures visible without being fatal
If a sync merges your data but can't record the result, you'll now see a notification explaining that your catalog is up to date but the history won't show it until the next successful sync.
-
Bug Fix
Last Synced date requires all tables to succeed when no rows moved
If a vendor sync finds no changes but some tables failed, the date will no longer incorrectly advance, preventing stale data from appearing up-to-date.
-
Bug Fix
Sync bookkeeping failures reported separately and no longer block date stamp
If vendor data syncs successfully but cannot be recorded in the history, you'll see a notification explaining that your data is current even though the sync history looks out of date.
-
Infrastructure
Added comprehensive tests for sync outcome rules
Created VendorSyncOutcomePlannerTests with 7 test cases pinning the rule for when a sync should update the "Last Synced" date, and DivergenceMessageWordingTests that reads the view model source to verify the warning messages never claim the sync failed to update data when only the bookkeeping failed. The tests document the actual store incidents (5645 and 554) that led to this fix.
-
Infrastructure
Sync outcome decision logic extracted and unit tested
Created VendorSyncOutcomePlanner as a pure, tested function to decide whether a sync result should stamp the "Last Synced" date. Includes 169 lines of unit tests covering the empty result, partial success, and "already current" scenarios that previously produced incorrect stamps.
User Interface
-
Improvement
Added export and import path properties
Added ExportPath and ImportPath properties to CostBreakViewModel that provide initial directory paths for file dialogs, resolved through the application settings service. These properties ensure file dialogs open to the user's preferred locations.
-
Bug Fix
Fixed Price toggle now works in Cost Break levels
You can now use the Fixed Price checkbox in cost break levels—it will correctly display existing settings and save your changes. The Fixed Price and Margin % fields now appear and disappear as expected based on the toggle.
-
Bug Fix
Fixed broken data bindings in Cost Break grid
The Cost Break screen will now load cleanly without internal errors.
-
Bug Fix
Restored level numbers in cost break grid right-click menus
When you right-click on a cost break row, the menu options now correctly show the level number (e.g., "Delete Cost Break Level #3" instead of "Delete Cost Break Level #").
-
Bug Fix
Removed non-functional Import and Set Default buttons
The Export menu in the Cost Break screen no longer shows a non-functional Import option.
-
Bug Fix
Rebuild button now applies Break Type and Break Points changes
The Rebuild button beside Break Type and Break Points now works—click it to apply your changes when auto-rebuild is turned off.
-
Bug Fix
Wired up the Rebuild button
The Rebuild button in the Cost Break screen now works correctly to recalculate your cost break levels after changing Break Type or Break Points.
-
Bug Fix
File dialogs now open to correct default locations
When importing or exporting cost break models, the file browser now opens to your configured default import/export folder instead of a random location.
-
User Interface
Removed two non-functional controls
Removed a hidden "Set Default" button and an "Import Cost Break Models" menu item that were bound to commands that never existed. Both were carried over from other screens and could never work. Left comments documenting what would be needed to restore them if the features are implemented in the future.
Performance & Reliability
-
Improvement
Simplified pricing unit reset mechanism
The mechanism that snaps the plus/minus units selector back to "0" after rejecting a "Rounding Points" choice now uses a simpler, more reliable approach. Instead of managing timer lifecycle, the reset is scheduled as a deferred UI operation that runs once the combo box selection update has completed.
-
Improvement
Future Price panel threading safety enhanced
The Future Price panel's plus/minus units reset now properly executes on the UI thread using the WPF Dispatcher. This eliminates potential cross-thread exceptions that could occur when the old timer-based approach modified UI-bound properties from background threads.
-
Bug Fix
Random crashes when editing Cost Break levels
The Cost Break screen will no longer crash when you edit price levels rapidly or while calculations are running in the background.
-
Bug Fix
Fixed crash when editing Cost Break pricing levels
The Cost Break dialog will no longer crash when you quickly edit margin targets or cost boundaries.
-
Bug Fix
Eliminated timer leak in plus/minus units selector
The Future Price panel's plus/minus units selector was creating a new background timer on every selection change without properly disposing of previous timers. Each abandoned timer continued firing every 100ms for the entire application session, writing to UI-bound properties from background threads. This has been replaced with a single deferred dispatcher call that properly executes once on the UI thread with no lingering state.
-
Bug Fix
Future Price panel timer memory leak eliminated
Fixed a critical memory leak where the Future Price panel created a new System.Timers.Timer every time the user attempted to select "Rounding Points" in the plus/minus units dropdown. Each abandoned timer would continue firing every 100 milliseconds for the life of the application, gradually degrading performance. The reset mechanism has been replaced with a single deferred dispatcher call that safely resets the selection without leaking resources.
-
Bug Fix
Cost Break boundaries incorrectly shifting by one cent
When working with Cost Breaks, the price boundaries between levels will now stay exactly where you set them instead of drifting by one cent during automatic recalculations.
-
Bug Fix
Fixed pricing boundary drift in Cost Break levels
Cost Break pricing boundaries will now stay exactly where you set them instead of drifting slightly when the grid updates.
-
Bug Fix
Memory leak from Cost Break background timers
Closing a Cost Break window now fully releases system resources, improving overall application performance especially after opening and closing the dialog multiple times.
-
Bug Fix
Fixed memory leak after closing Cost Break window
Closing the Cost Break dialog will no longer leave background processes running, improving overall application performance.
-
Architecture
Migrated Cost Break timers to UI thread
Replaced System.Timers.Timer with DispatcherTimer throughout the Cost Break dialog to ensure all timer callbacks execute on the UI thread, eliminating threading hazards and making the dialog more stable during user interaction.
Infrastructure & Internal
-
New Feature
One-click settings folder repair
Click "Fix This Now" when you see the settings folder warning—Windows will ask permission, then Margin Master fixes it automatically and tells you to restart.
-
New Feature
Settings folder repair dialog features
The settings warning now shows exactly which files are blocked and gives you a "Copy Details" button to send the fix command to your IT department if you need help.
-
New Feature
Settings folder permissions documentation
Added comprehensive help page at marginmaster.com/documents/support/settings-folder-permissions covering what the alert means, how to use the Fix This Now button, the manual icacls command for administrators, why the problem happens, and common questions. The repair dialog links directly to this page.
-
Improvement
Graded settings folder problems
Old files left behind by previous Margin Master versions won't trigger the "Cannot Save Settings" warning anymore—only files the app actually needs will cause an alert.
-
Improvement
Settings folder repair dialog with automatic fix
When the settings folder alert appears, click "Fix This Now" and choose "Yes" at the Windows prompt — Margin Master will grant the permission and tell you to restart. If you'd rather have your IT department handle it, "Copy Details" gives them everything they need.
-
Improvement
Self-healing release feed
The publish workflow now automatically downloads and re-indexes any packages within the retention window that are missing from the remote feed, allowing the feed to repair itself if entries are lost. This ensures the delta chain remains complete even if previous publishes had issues.
-
Improvement
Critical versus non-critical settings files
You'll only see the settings folder alert when a file Margin Master actually uses is blocked — old files left behind from previous versions won't trigger it anymore.
-
Improvement
Version comparison fixed for retention
Package versions are now compared as semantic versions rather than strings, so version 2026.1001.x correctly ranks above 2026.903.x. Previously, string comparison could cause incorrect packages to be retained or pruned from the feed.
-
Improvement
Updated startup stuck training lesson
Revised the "startup-stuck" training lesson audio and script to describe the new Fix This Now button and clarify that only files Margin Master uses raise the alert, not legacy leftovers.
-
Bug Fix
Delta update chain restored
The release feed merge step was silently failing because the remote feed backup was stored in a directory that the packaging tool clears on each run. This caused 34 of 37 stores updating from one version to the next to download the full 175 MB package instead of a much smaller delta. The backup is now saved outside the cleared directory, and the build will fail loudly if the merge cannot complete, preventing silent degradation.
-
Bug Fix
Blob cleanup now functional
The Azure blob cleanup step was silently failing due to an invalid command-line flag. Cleanup is now feed-driven: only packages not referenced by the uploaded feed are deleted, and failures are reported rather than swallowed.
-
User Interface
Settings blocked title-bar pill
If you close the settings warning without fixing it, a red "Settings Cannot Be Saved" notice stays in the title bar—click it to bring the fix button back.
-
User Interface
Title-bar indicator for blocked settings folder
If the settings folder is blocked, a red "Settings Cannot Be Saved" marker stays in the title bar at the top of the window until you fix it — click it to bring up the repair dialog again.
-
Infrastructure
Velopack CLI version pinned
The Velopack packaging CLI is now pinned to match the exact version of the Velopack library shipped in the application, preventing version mismatches that can break delta patching. Bumping the library version in the central package configuration now automatically updates the CLI version.
-
Infrastructure
New support documentation
Added docs/marginmaster/support/settings-folder-permissions.md (Part VIII, Chapter 20) explaining what the settings folder is, why Windows blocks it, how Fix This Now works, what to do if it fails, and the manual icacls commands for IT departments. The Data Aging page gained clarification about dash values in Last Update columns (normal for POS systems without per-row timestamps) and why both banners appear after extended downtime. The startup lesson's audio for step 4 re-rendered to describe the new button workflow instead of "ask your administrator."
Rounding scheme lookups now deterministic; Added comprehensive test coverage for header consolidation; Settings reload coordination enhanced.
Strategy & Pricing
-
Improvement
Rounding scheme lookups now deterministic
Modified GetRoundingScheme and GetRoundingSchemeAsync to order results by ID, ensuring consistent behavior when multiple header rows exist during the brief window before consolidation runs. This prevents non-deterministic failures where the "wrong" duplicate might be selected.
-
Improvement
Added comprehensive test coverage for header consolidation
Created 232 lines of automated tests covering multiple duplicate header scenarios: trailing space twins, case-insensitive duplicates, empty survivors receiving another header's rows, leading space twins, and schemes with different pricing tables. Tests validate that consolidation preserves all pricing bands, uses the lowest ID as the survivor, and properly trims scheme names.
-
Improvement
Ordered header queries by ID for consistency
Modified RoundingScheme lookups to explicitly order by ID when multiple headers might exist. This ensures consistent behavior during the transition period when duplicates are being discovered and consolidated.
-
Bug Fix
Duplicate rounding scheme headers now consolidated automatically
If your store had a rounding scheme that stopped working after an update, it will now be automatically repaired when Margin Master starts.
-
Bug Fix
Consolidated duplicate RoundingScheme headers before validation
If you had rounding schemes that appeared empty after updates, this fix ensures all pricing bands are preserved when duplicate scheme names are consolidated.
-
Bug Fix
Corrected attribution for August 31st Fremont error
Updated technical documentation to correctly attribute the Fremont store's "1075 duplicate group(s), 2 header row(s), 1075 generated levels" error to duplicate RoundingScheme headers rather than the point table generator stall fixed in PR #1409. Added diagnostic guidance: when duplicates equal generated levels and header row count exceeds one, the cause is duplicate headers, not the generator.
-
Bug Fix
Forced regeneration after header consolidation
Schemes whose headers were just consolidated now skip checksum validation and force a full regeneration. The stored checksum describes the pre-consolidation split table, so merged details must be regenerated under the surviving ID before the system can trust them.
-
Bug Fix
Minor code quality improvements
Fixed a nullable reference warning in TrainingPlayerViewModel by reading the current step once instead of repeatedly dereferencing it. Corrected a column name reference in the download stats SQL query from "StoreName" to "Name" to match the Stores table schema.
-
Infrastructure
Added comprehensive duplicate header consolidation tests
Created six test cases covering trailing space twins, empty survivors receiving merged rows, case-insensitive collisions, no-collision scenarios, leading space handling, and triplet consolidation. Tests use throwaway databases and skip gracefully when the test server is unreachable.
Performance & Reliability
-
Improvement
Settings reload coordination enhanced
Multiple simultaneous reconnection events (from file watchers and explicit callers) are now properly coordinated. When a reload is already in progress, new requests join the existing operation and queue one final pass to load the latest state. The returned task completes only after all queued reloads finish, ensuring consumers never read partial or cleared settings during the reload process.
-
Bug Fix
Settings corruption during database restore prevented
Database restore operations will no longer lose your saved column views, license registration, or other custom settings.
The deployment process now records the exact build version when marking support issues as "Ready for Testing," enabling the backend to automatically track when each store has received the fix through auto-update check-ins.
Read the narration toggle in lesson detail pane; Narration script preview in lesson library; Quoted phrase search syntax.
User Interface
-
New Feature
Read the narration toggle in lesson detail pane
When browsing training lessons, you can now click "Read the narration" to see exactly what the lesson will say at each step before you start it. This works with the new narration search—find a lesson by what it says, then read what it says.
-
New Feature
Narration script preview in lesson library
Click "Read the narration" in the lesson details to see the full script that plays during each step, making it easier to preview lessons before starting them.
-
New Feature
Quoted phrase search syntax
Put quotes around multiple words to search for them as an exact phrase. For example, "price change" will only find lessons containing those two words together in that order.
-
Improvement
Enhanced lesson search with full-content indexing
When searching for training lessons, you can now type any words that appear in the lesson's narration or instructions, not just the title. For example, searching for "price endings" will find lessons that mention price endings in their steps, even if the title doesn't include those words. Use quotes around multiple words like "zone pricing" to find that exact phrase.
-
Improvement
Enhanced lesson search with full-text narration
You can now search for lessons using any word or phrase from the tutorial narration, not just the lesson title. For example, searching for "price endings" will find the Rounding Editor lesson even though that phrase only appears in the spoken narration.
-
Improvement
Background run badge now identifies which data was refreshed
When you open Margin Master after a background update, the title bar badge now tells you exactly what was updated—for example, "Vendor Data updated 3 hours ago" or "Vendor + Epicor Data updated 2 hours ago"—instead of the vague "Data updated" message.
-
Improvement
Background badge identifies specific data updated
When the background service updates your data, the badge now tells you exactly what was refreshed—Vendor catalogs, your POS inventory, or both—so you know which data is current.
-
Improvement
Badge distinguishes between updates and "already current" checks
If the background service checked for updates but everything was already current, the badge now says "Data checked... already current" instead of misleadingly saying data was "updated."
-
Improvement
Badge distinguishes "nothing to do" from actual updates
If the background service checks and finds your data is already up to date, the badge now says "already current" instead of claiming it updated something.
-
Improvement
Refined lesson detail pane layout
Restructured the "What you will do" section header to accommodate the script toggle button on the right side while maintaining the section title on the left. The toggle includes a tooltip explaining its purpose.
-
Improvement
App self-updates no longer trigger data update badges
The "data updated" badge now only appears when pricing or catalog data was actually refreshed, not when the app itself was updated.
-
User Interface
Updated search box placeholder text
The search box now shows helpful instructions explaining you can search lesson content and use quotes for exact phrases.
-
User Interface
Step display enhanced to support narration script
The step list in the lesson detail pane now shows both the numbered step title and optional narration text. When the script view is enabled, narration appears indented and italicized beneath each step. Series headings continue to show only part titles without narration.
-
User Interface
Enhanced step display with collapsible narration
Each lesson step now shows its spoken narration text beneath the step title when narration view is turned on.
-
User Interface
Updated search box placeholder text
The search box placeholder now reads "Search titles and narration — use 'quotes' for phrases" to inform users about the enhanced search capabilities and quoted phrase syntax.
-
Database
Added SidesRefreshed field to background job status
Added a new SidesRefreshed column to the BackgroundJobStatus table that records whether each run refreshed vendor data, POS data, both, or neither. The field is nullable to support backward compatibility with older status records, which fall back to interpreting the job type.
-
Database
Added SidesRefreshed column to background job status
The BackgroundJobStatus table gains a nullable SidesRefreshed column to record which data sources each run touched. The schema migration is idempotent and handles rows written before this feature shipped by falling back to the job type.
-
Architecture
New LessonSearch engine with unit tests
Added a pure static search engine (LessonSearch class) with methods for parsing search terms, matching text against terms, and building searchable text from lesson content. Includes comprehensive unit tests covering term parsing, AND semantics, phrase matching, and cross-field search behavior. The engine ensures phrases never match across field boundaries (fields are newline-separated).
-
Architecture
New BackgroundRunSides vocabulary class
Introduced BackgroundRunSides as a central vocabulary for recording and interpreting which data sources a background run refreshed, with unit test coverage ensuring the composition and display logic remain consistent.
-
Infrastructure
Comprehensive search test coverage
Added unit tests covering term parsing (bare words vs. quoted phrases), match logic (AND semantics, case-insensitivity, phrase ordering), and searchable text construction (including narration content). Tests verify that phrases cannot match across field boundaries and that empty queries disable filtering.
In-app training lessons for POS system imports; Seven new training guides and lessons; Troubleshooting lesson for startup problems.
Strategy & Pricing
-
Improvement
Store Manager repair logic moved to shared service
Refactored the StoreManagerInfo ordinal repair logic from StoreManagerViewModel into StoreManagerInfoWriter as a reusable method, following the MM-1368 headless pattern. The Store Manager window now delegates to this shared implementation, eliminating code duplication and enabling the repair to run in multiple contexts.
-
Improvement
Comprehensive test coverage for data repair
Added unit tests that verify the repair logic is safe to run repeatedly (idempotent), never resurrects invalid sentinel values as literal store numbers, always clears corruption markers, and correctly skips Epicor databases where the affected field serves a legitimate purpose.
-
Bug Fix
Zone pricing now repairs corrupted store data automatically
If your store has multiple yards and items were pricing incorrectly at $19.99 when they should be $26.99 (or similar zone-based price differences), this is now fixed automatically.
-
Bug Fix
Automatic repair of legacy store number corruption
If your store was pricing items at the wrong zone, zone pricing will now automatically use your correct assigned zone after the next sync or import.
-
Architecture
Centralized repair logic
Moved the char-ordinal repair SQL statement from StoreManagerViewModel to StoreManagerInfoWriter so both the Store Manager window and the headless zone pricing pipeline can share the same validated repair logic, reducing code duplication and maintenance burden.
-
Infrastructure
Added comprehensive tests for store data repair
Added StoreManagerOrdinalRepairTests with five test cases that verify the repair logic: restores correct POS store numbers, never creates invalid "99999" store numbers, always clears corruption markers, only touches corrupted rows (idempotent), stamps update timestamps, and safely no-ops for Epicor systems where the data structure is legitimate.
User Interface
-
New Feature
Seven new training guides and lessons
Seven new guides are now available in Training Mode (lessons 1020-1022, 2023-2025, and 3005) that walk you through multi-computer setup, adding catalog items, importing spreadsheets, cost break pricing, manual price entry, price sensitivity codes, and Ace MAP pricing.
-
Improvement
Excel import documentation rewritten for accuracy
The Excel import help now correctly explains that importing custom spreadsheets is an advanced feature best done with support assistance the first time.
-
Improvement
MAP/IMAP pricing documentation corrections
The MAP and IMAP pricing documentation now accurately describes which columns appear automatically and how they're labeled in the Future Price panel.
-
Improvement
Price sensitivity code documentation updates
Updated price sensitivity code documentation to clarify that Do-It-Best's OneClick Statistics shows awareness codes A through E plus a "Not Assigned (X)" row, and corrected the Add from Catalog menu caption to match the actual implementation.
-
Infrastructure
39 narration clips rendered for new training content
Rendered 39 audio narration clips for the seven new training lessons and guides using text-to-speech synthesis, enabling the interactive walkthrough experience with voice guidance.
Infrastructure & Internal
-
New Feature
In-app training lessons for POS system imports
Turn on Training Mode from the Help menu and type the lesson number (4006 for BisTrack, 4007 for Paladin, 4009 for RockSolid, or 4008 for Transact) to learn how to import your store data step by step.
-
New Feature
Troubleshooting lesson for startup problems
If Margin Master gets stuck while starting up, the new lesson explains what each startup message means and how to fix it.
-
New Feature
Lesson explaining column view behavior after updates
If your columns look different after an update, the new lesson shows how to restore them and how to prevent changes in the future.
-
New Feature
Lesson on beta and general release update modes
The new lesson explains how you get on beta testing, how to tell if you're on it, and how you automatically return to regular updates.
-
New Feature
Lesson on recurring price changes
If the same price changes keep coming back week after week, the new lesson explains why it happens and how to stop it.
-
New Feature
Lesson on narrowing price change scope
The new lesson shows how to work on just one department at a time or apply changes to only specific items.
-
Improvement
Extended lesson coverage for existing content
More common questions now have step-by-step lessons available in Training Mode.
-
Improvement
Documentation cross-references to new lessons
Added "Walk through it in the app" callout boxes to 8 handbook pages (edit-columns.md, printing-and-exporting.md, selection-boxes.md, update-modes.md, and four POS import pages) directing readers to the corresponding interactive lessons with their lesson numbers.
-
Infrastructure
Training backlog progress tracking
Automated backlog tracking now shows 93 completed lessons (up from 64), 91 open tasks (down from 122), covering 29 newly-addressed support topics including stuck logins, column resets, beta mode, duplicate price changes, and POS-specific imports.
Training guide for software updates; Interactive guide for software updates; Moving to a new computer series (guides 1011-1013).
Imports & POS
-
Improvement
Drive path handling distinguishes between system and mapped drives
Added logic to differentiate between the system drive root (typically C:\, which standard users cannot write to) and other drive roots like mapped network drives. Bare drive letters are stored with trailing backslashes to ensure Windows interprets them as drive roots rather than current directories on those drives.
-
Improvement
Increase SQL timeout for large import data moves
Large store imports on slower servers are now much less likely to timeout during the final data processing steps.
-
Improvement
Clear per-store error tracking in multi-store imports
Multi-store imports now clear error state between each store so that one store's processing failure does not incorrectly trigger data-loss protection for subsequent stores in the batch.
-
Improvement
Better error reporting for database operation failures
The SQL service now records exceptions from failed ExecuteNonQueryAsync calls so that downstream code can distinguish between "zero rows affected" and "operation failed with timeout/error," enabling more accurate diagnostics in import processing.
-
Bug Fix
Mapped drive root paths now persist correctly in export settings
If you export files to a mapped drive like M:\, that path will now stay saved in your settings instead of changing back to C:\MarginMaster every time.
-
Bug Fix
Export path configuration now supports mapped drive roots
If you configure a mapped network drive (like M:\) as your export folder, Margin Master will now remember and use that location instead of switching it back to C:\MarginMaster.
-
Bug Fix
Prevent silent data loss when import times out
If a Paladin multi-store import is interrupted by a database timeout, you'll now see a clear error message and your store's existing data will remain unchanged, instead of silently losing all inventory data for that store.
-
Bug Fix
Prevent silent data wipe on SQL timeout during multi-store import
If your database runs slowly during a multi-store import, the import will now wait long enough to complete successfully instead of accidentally deleting your store's data.
-
Bug Fix
Drive root paths now stored with trailing backslash
Non-system drive roots are now canonicalized with a trailing separator (M:\ instead of M:) because Windows interprets "M:" as "current directory on M:" rather than the root. This ensures the configured path always points to the intended root directory.
-
Bug Fix
Record SQL failures for proper error attribution
Import error messages now correctly identify which store failed in multi-store imports, making it easier to diagnose and re-run specific stores.
User Interface
-
New Feature
Training guide for software updates
The new guide walks you through how Margin Master checks for updates automatically, what to do when the Update Available badge appears, and how to check for updates yourself from the Help menu whenever you want.
-
New Feature
Interactive guide for software updates
When you open Training Mode, you'll find a new guide under Getting Started that explains how updates work, what to do when you see the blue Update Available badge, and how to check for updates yourself using the Help menu.
-
New Feature
Moving to a new computer series (guides 1011-1013)
When setting up Margin Master on a new computer, three new training guides show exactly what to do: first back up your old database, then install on the new PC, then restore the backup.
-
New Feature
New PC migration guide series
Training Mode now walks you through moving Margin Master to a new computer step-by-step, including backing up your data, installing the software, and getting your database back.
-
New Feature
Ten new training guides added to the in-app tutorial catalog
The Help menu now includes ten new step-by-step guides covering common tasks like recovering from a failed update, understanding why price change counts differ between screens, creating pricing rules, troubleshooting unexpected strategy results, and connecting to your Epicor system.
-
New Feature
Ten training guides added to What's New catalog
The What's New dialog now offers ten new step-by-step training guides covering common tasks like setting up Epicor connections, troubleshooting pricing strategies, understanding price change counts, and recovering from failed updates—each with audio narration and on-screen guidance.
-
New Feature
11 new training lessons and guides
The Help menu's Lessons & Guides now includes 11 new walkthroughs covering common tasks like setting up a new computer, building pricing strategies, fixing frozen programs, and moving your work to another machine. Each guide narrates the steps and highlights what to click.
-
New Feature
Training / Guide Mode available to all users
You can now turn on Training / Guide Mode from the Help menu to access step-by-step guides that walk you through tasks right inside Margin Master.
-
New Feature
Price change day series (guides 2002-2004)
Three new guides teach the complete price change process: running the strategy, sending the file and printing tags, then finalizing in your point-of-sale system.
-
New Feature
Price change day workflow guides
New guides show the complete price change process from executing your strategy through printing tags and finalizing in your POS.
-
New Feature
Audience-gated training guides for specific vendors and POS systems
Training guides now appear based on your store's configuration—for example, Ace Hardware stores see zone pricing guides, while Epicor users see Eagle-specific connection instructions.
-
New Feature
Lesson 1017 — Your regular data routine
Learn your regular routine: update vendor data from the cloud, then import your point-of-sale inventory, and understand why the same record count each time is normal.
-
New Feature
Clearing stale or orphaned data guide (5001)
A new guide explains how to clear out old SKUs or vendor data that won't go away, starting with the gentlest fix and working up to deeper resets.
-
New Feature
Data reset and cleanup guide
A new guide explains how to clear stale SKUs or fix pricing data that won't update, from gentle fixes to deeper resets.
-
New Feature
Lesson 2016 — Setting up your pricing (roadmap)
Get a roadmap of Margin Master's pricing setup: which features do what, and which lessons explain each part.
-
New Feature
Lesson 2017 — When tags print wrong
Troubleshoot tag printing: learn why unchanged items got tags, how to pick the right printer, and how to reprint missed labels without wasting sheets.
-
New Feature
Lesson 2018 — Importing competitor prices
Load competitor prices from a spreadsheet into your grid's Comp columns to compare your pricing against other stores.
-
New Feature
Lesson 3004 — Updating your Do-it Best data
Do-it Best stores: learn how to update your vendor catalog and pricing from the cloud, and what to do if something doesn't sync.
-
New Feature
Lesson 4003 — Getting price changes into Paladin
Paladin users: send your price changes to Paladin by exporting the text file it imports, then finish the price change in Paladin.
-
New Feature
Lesson 4004 — Getting price changes into RockSolid
RockSolid users: Margin Master writes price changes directly into RockSolid's import table — learn the paths that matter and how to finish the change.
-
New Feature
Lesson 4005 — Importing your Propello data
Propello users: import your inventory directly from Propello's cloud, or set up the connection if you haven't already.
-
New Feature
Lesson 6002 — When SQL Server stops after a Windows update
If Margin Master can't reach its database after a Windows update, learn how to restart the SQL Server service and get back to work.
-
New Feature
Lesson 6003 — When the store list looks wrong
Fix a missing or extra store in your store list by re-importing POS data or adjusting the Exclude setting in Store Manager.
-
New Feature
Lesson 6004 — Letting support see your screen
Learn how live support sessions work: what you're allowing, what needs administrator approval, and how you stay in control.
-
Improvement
Training lesson wording refinement
The training guide now better explains how What's New works after updates and reminds you it's always available on the Help menu.
-
Improvement
Removed confusing optional clean-up step from training
The training guide no longer includes an optional clean-up step that many found confusing, making the lesson easier to follow from start to finish.
-
Improvement
Training backlog tracking
Updated training backlog tracking to mark the `run-software-update` task as completed (moved from 376 open sessions to the done list). The task covered update procedures, the update badge, and Help > Check for Updates functionality, now fully addressed by the new guide.
-
Improvement
Training backlog updated
The "Update Margin Master to the latest version" task (run-software-update) has been marked as complete in the training backlog, moving from 376 open support sessions to the done list now that the interactive guide is available. This was the most frequently requested training topic across all classified support chats.
-
Improvement
Enhanced update failure recovery instructions
The training guide now gives clearer instructions on what to do if an update doesn't complete successfully.
-
Improvement
Extended existing lessons with additional coverage
Several existing training guides now cover additional related topics and one correction was made to accurately describe the Rounding Schemes editor layout.
-
Improvement
Expanded training catalog organization with new topics and sections
Reorganized the training catalog to include five top-level topics (previously three): Getting Started, Pricing & Analysis, Vendor-Specific, POS Systems, and Database. Added new sections within Pricing & Analysis (Strategies, Troubleshooting) to accommodate the growing guide library. The catalog structure now supports 134 total entries with clear subtopic organization.
-
Improvement
Training content covers most-requested support topics
The ten new guides directly address the most frequently asked support questions identified from 7,893 chat sessions: reinstalling after a failed update (96 sessions), creating pricing rules (88 sessions), troubleshooting strategy results (84 sessions), investigating count discrepancies (81 sessions), fixing pricing mismatches (55 sessions), setting up Epicor connections (44 sessions), managing SKU exceptions (42 sessions), troubleshooting SKU prices (41 sessions), excluding items from price changes (38 sessions), and configuring zone pricing (31 sessions). This reduces the need for live support on these common workflows.
-
Improvement
Training catalog reorganization
Training topics are now better organized, with database tasks in their own section and price change day broken into clear steps.
-
Improvement
SKU exception guide clarifies permanent behavior
SKU exceptions now have a dedicated training guide explaining that they stay in effect permanently until you remove them—they don't expire on their own.
-
Improvement
Comprehensive exclusion methods guide
A new guide explains all four ways to exclude items from price changes, from temporary exclusions in a single rule to permanent protections for specific SKUs.
-
Improvement
Lesson content updates and corrections
Improved existing lessons with better coverage mapping and fixed several documentation errors about printing, filtering, and menu locations.
-
User Interface
Training lesson clarification for What's New behavior
The training guide now correctly explains that What's New appears after updates based on your settings, and reminds you it's always available on the Help menu.
-
User Interface
Updated summary step to hand off to part 2
The final step of the training now clearly guides you to the next part where you'll send price changes and print tags.
-
User Interface
Training catalog reorganized with new topics
Training topics are now organized into five clear categories including vendor-specific and POS system guides, making it easier to find relevant help for your store's setup.
-
User Interface
Help menu integration
The guide shows you exactly where to find Check for Updates in the Help menu and what happens when you click it.
-
User Interface
In-app guide callouts added to handbook pages
Handbook pages now show which in-app guides walk you through each task, making it easier to launch the right narrated walkthrough.
-
User Interface
Training catalog reorganization
Training guides are now better organized with new sections for database tasks and price change day workflows.
-
Infrastructure
Updated training audio files and rendering metadata
Regenerated audio file for step 6, removed the audio for the deleted step 7, and updated the render.json manifest to reflect the new step structure and voice settings.
-
Infrastructure
New Support topic category in lesson catalog
Expanded the lesson catalog structure to include a sixth topic category "Support" with initial subtopic "Troubleshooting", housing lesson 6001 (frozen program). Updated lesson catalog tests to reflect 33 total lessons across 6 topics (Getting Started, Pricing & Analysis, Vendor-Specific, POS Systems, Database, Support).
-
Infrastructure
Training backlog progress
These seven guides cover 11 keys from the support chat backlog (migrate-mm-to-new-pc, backup-database-and-strategy-files, restore-database-from-backup, execute-price-changes, print-price-tags-labels, export-price-changes-to-pos, finalize-price-changes, reset-database-to-fix-data-issues, clear-orphaned-skus-after-import), reducing the open backlog from 186 to 177 items. Every fact in the guides was verified against window titles, menu paths, and current documentation.
-
Infrastructure
Training audio assets
Added 49 narrated audio files (.mp3) and rendering manifests for the seven new lessons, using the en-US-AvaMultilingualNeural voice for consistent narration across all training steps.
-
Infrastructure
69 narration audio clips rendered
Rendered 69 MP3 narration clips for the new lessons using en-US-AvaMultilingualNeural voice, with hash-based render manifests to track text changes. Re-rendered 3 existing clips where narration text was updated (rounding-schemes-4, sku-price-tools-3, when-an-update-fails-4).
-
Infrastructure
Training audio narration rendering
Rendered 72 new narration audio clips using Azure text-to-speech (en-US-AvaMultilingualNeural voice) for the 11 new lessons. All render hashes tracked in .render.json files for reproducibility. Training tests updated (33/33 passing) to include new lesson in catalog validation.
Infrastructure & Internal
-
New Feature
Ten new training lessons for common support scenarios
Added 10 new interactive lessons covering frequently-requested support topics: managing and moving strategies (#2011, #2014), building rounding schemes from scratch (#2013), using custom groups (#2012), handling strategies after updates (#2015), reconnecting feeds on new computers (#1015), changing database server connections (#5002), fresh store setup roadmap (#1016), frozen program troubleshooting (#6001), Epicor store exclusion (#4002), and Ace Hardware data updates (#3003). Each lesson includes multi-step audio narration, on-screen UI targeting, and auto-advance for guided workflows.
-
Improvement
Simplified price execution tutorial
The guided tutorial for executing pricing strategies now has one fewer step, making it quicker to complete while still covering all essential tasks.
-
Improvement
New Support topic section in training catalog
Added "Support" as a sixth topic category in the training catalog alongside Getting Started, Pricing & Analysis, Vendor-Specific, POS Systems, and Database, providing better organization for troubleshooting and maintenance lessons.
-
Improvement
Enhanced documentation with training lesson references
Updated 8 documentation pages to reference relevant training lessons, including auto-updates, cloud vendor sync, database setup, installation, POS connections, store manager, custom groups, pricing strategies, rounding schemes, and strategy backup/restore. Each page now points users to the specific lesson number they can launch from the Help menu.
-
Improvement
Expanded lesson coverage tracking
Extended lesson metadata to cover 20+ additional support chat tasks including strategy troubleshooting, connection issues, server moves, fresh installations, frozen programs, store exclusions, antivirus conflicts, and more. Lessons now explicitly track which support scenarios they address.
-
User Interface
Updated tutorial audio
Re-recorded step 6 audio to remove references to the cleanup operations and now directs users to click Finish to proceed to sending changes and printing tags. Removed step 7 audio file entirely.
-
User Interface
Audio narration for all new lessons
Generated and embedded MP3 audio files (80+ audio segments) for all new lessons using Azure text-to-speech (en-US-AvaMultilingualNeural voice), providing consistent narration across the expanded training library.
Rounding scheme editor now shows saved changes immediately; Future price panel rounding dropdown refreshed properly.
User Interface
-
Bug Fix
Rounding scheme editor now shows saved changes immediately
When you edit a rounding scheme and save it, those changes now appear immediately if you reopen the editor. Previously, you would see the old values until you closed and restarted Margin Master, even though your changes were actually saved.
-
User Interface
Future price panel rounding dropdown refreshed properly
The rounding scheme dropdown in the future price panel now always shows up-to-date scheme settings after you make changes.
Topic-organized lesson catalog; Topic-organized lesson catalog; Lesson library with tree view and detailed descriptions.
Strategy & Pricing
-
Improvement
Enhanced validation and automatic repair of rounding schemes
Rounding schemes with data corruption are now automatically repaired when Margin Master starts up, ensuring consistent pricing calculations.
-
Improvement
Enhanced duplicate detection and cleanup after regeneration
Improved the duplicate detection logic that runs after regenerating rounding schemes to distinguish between duplicates caused by the generator (now impossible) versus duplicates from multiple scheme header rows sharing the same name. The system now logs detailed diagnostics showing the number of duplicate groups, header rows, and generated levels, then automatically cleans up any duplicates found, using the same cleanup process as when saving schemes.
-
Bug Fix
Generator stall when prices round below themselves
Certain rounding scheme configurations would previously stop working partway through the price range, leaving higher-priced items unrounded. These schemes now generate complete pricing tables that cover the full product catalog.
-
Bug Fix
Generator stall in rounding schemes with round-down rules
If you had a rounding scheme that seemed to stop working above a certain price (leaving prices unrounded), this has been fixed. All prices will now round correctly according to your scheme rules.
-
Infrastructure
Force regeneration of all rounding schemes on upgrade
Incremented the rounding scheme generation version from 2 to 3, which triggers a one-time regeneration of all rounding schemes on upgrade. This ensures any existing schemes with stalled pricing tables are automatically repaired. All 850 user schemes tested regenerate identically (byte-for-byte) except for previously stalled tables, which now complete correctly.
-
Infrastructure
Comprehensive test coverage for generator stall scenarios
Added 150+ new test cases covering all known triggers for the generator stall bug, including right-side rounding fallbacks below the maximum point, rollback rules without supporting right-side rounding, rollbacks landing inside range overrides, and property-based testing with 500 random rule combinations. These tests ensure the generator never creates backwards-stepping bands and always reaches the upper price limit.
-
Infrastructure
Comprehensive test coverage for generator edge cases
Added 150+ lines of test coverage including specific reproduction cases for each stall trigger pattern, a seeded property test that generates 500 random rounding configurations, and validation helpers that detect stalled walks and verify band integrity. The property test reproduced the issue 192 times out of 4,000 random schemes on the old engine; all now pass on the fixed engine.
-
Infrastructure
Rounding scheme generation version bumped to v3
Incremented the rounding scheme generation version to force regeneration of all existing schemes on upgrade, ensuring any schemes affected by the stall bug are automatically rebuilt with the fix applied.
User Interface
-
New Feature
Topic-organized lesson catalog
The lesson library is now organized by category making it easier to browse and find relevant training for your needs.
-
New Feature
Topic-organized lesson catalog
The lesson browser now organizes lessons by topic and subtopic, making it easier to find lessons on a specific subject. Topics you don't have access to won't appear in your catalog.
-
New Feature
Lesson library with tree view and detailed descriptions
You can now browse all available lessons in a tree organized by topic and series, click any lesson to see what it covers and where you left off, then press Start when ready.
-
New Feature
Lesson library with tree and description panel
Browse lessons in a new library view with a tree on the left and full details on the right, including all steps and where you left off. Search for lessons by name, click one to read about it, then press Start when ready.
-
New Feature
Lessons vs. Guides distinction
When browsing training content, you'll now see items marked as either lessons or guides. Lessons show you around without changing anything; guides walk you through real tasks step-by-step.
-
New Feature
Lessons vs. Guides distinction
Lessons teach concepts by showing you around the screen. Guides walk you through real tasks like creating a database or importing data – you do each step yourself, and the guide waits for you to complete it before moving on.
-
New Feature
Lessons & Guides library with narrated walk-throughs
Click the new training button to access guided lessons and step-by-step guides that teach you how to use Margin Master. Lessons explain features with narration and spotlights, while guides walk you through real tasks like setting up a new database or importing your sales data.
-
New Feature
In-app lesson editor for developers
Internal development tool only—not visible to customers.
-
New Feature
Multi-part lesson series with navigation
Related lessons can now be linked together in multi-part series that automatically guide you from one part to the next.
-
New Feature
Multi-part lesson series
Some lessons are now organized into multi-part series that you can navigate through step-by-step, with automatic skip over any parts you don't have access to.
-
New Feature
Speech-bubble callout mode during lesson playback
During lessons, the training card becomes a small speech bubble that automatically moves to point at each step's target, staying out of your way while guiding you through the task.
-
New Feature
Speech-bubble callout mode during lessons
During a lesson, the window becomes a speech bubble that sits next to whatever you need to click, with an arrow pointing at it. It follows each step automatically, or you can drag it aside if it's in your way.
-
New Feature
Creating a New Database guide
Use the new "Creating a new database" guide to set up a fresh database for your store step-by-step, with voice narration explaining each choice.
-
New Feature
Main window overview lesson series
The new "Main window overview" training series walks you through every part of the main screen, from menus to buttons to the pricing grid, explaining what each area does and how to use it.
-
New Feature
Main window overview lesson series
A new six-part lesson series explains every part of the main screen: menus, selection boxes, buttons, the grid, the summary and the pricing panel.
-
New Feature
"Creating a new database" guide
You can now use Training / Guide Mode to walk through creating a brand new database for your store. The guide highlights each field and button as you fill out the form.
-
New Feature
Database creation and POS import guides
New step-by-step guides walk you through creating a database for your store and loading your point-of-sale data, so you can get started with Margin Master quickly and confidently.
-
Improvement
Smarter bubble positioning for menus
The training bubble now stays out of the way of menus and dialogs, making it easier to follow along with each step.
-
Improvement
Lesson numbering reorganized into topic blocks
Lesson numbers have been reorganized so the number itself indicates what topic it covers (1000s = Getting Started, 2000s = Pricing & Analysis, etc.).
-
Improvement
Lesson numbering convention
Lesson numbers now indicate their topic area—for example, lessons starting with 2xxx are about pricing and analysis, while 1xxx covers getting started.
-
Improvement
Centred initial placement with monitor awareness
The training card now opens in the centre of your screen and stays visible even if you unplug a monitor, and it remembers where you last put it.
-
Improvement
Narration bar for lessons while library is open
You can keep the lesson library open while a lesson plays using the narration bar at the bottom, or switch to the speech bubble by clicking "Back to lesson" in the header.
-
Improvement
Narration bar while library is open during lessons
You can now keep the lesson library open while a lesson plays—controls at the bottom let you step through the lesson while seeing the full lesson list.
-
Improvement
Smart bubble placement avoids menus and dialogs
The training bubble now automatically moves out of the way of menus and windows, so you can always see what you're clicking.
-
Improvement
Guided database creation and data import
New training guides now walk you step-by-step through setting up a fresh database and importing your store's sales data.
-
Improvement
Lesson browser pane auto-hides on narrow screens
On smaller screens, the lesson list temporarily hides itself when a dialog opens, then reappears when you close the dialog.
-
Improvement
Automatic dialog avoidance
On smaller screens, the training card automatically moves aside when a dialog opens so you can see both, then returns when you close the dialog.
-
Improvement
Enhanced lesson progress indicators in tree
Lessons now show icons indicating whether you've started them, finished them, or are currently playing them, and you can see at a glance how many lessons in each topic you've completed.
-
Improvement
Smart training window behavior
Training bubbles now stay out of your way when you switch to another program, and during guided walkthroughs you can click the actual buttons and menus being explained.
-
Improvement
Lesson series support and simplified progress tracking
Lesson series now always start from the beginning, making it easier to review any part.
-
Improvement
Series navigation and progress display
When working through a multi-part lesson series, you'll see which part you're on and can easily jump to the previous or next part using the new buttons.
-
Improvement
Intro lesson updated for new interface
The intro lesson now explains how to use the lesson library and speech bubble instead of the old training interface.
-
Improvement
Simplified progress tracking
Each lesson and guide now starts from the beginning every time, making it easy to refresh your knowledge whenever needed.
-
Improvement
Training overlay respects application focus
Training bubbles now step aside politely when you switch to another program, then come back when you return to Margin Master.
-
Improvement
Training mode introduction lesson rewritten
The first-time training introduction now shows you how to move the lesson window and find lessons in the new browser layout.
-
Improvement
Persistent layout and browse state
The training window remembers whether you had the lesson list open or closed and reopens that way next time.
-
Improvement
Intro lesson updated for new interface
The introductory "Training Mode" lesson now explains the new library and speech-bubble interface.
-
User Interface
Lesson browser and player combined into one window
The lesson list now stays open next to the lesson player so you can see what other lessons are available while learning. Click "Lessons ▸" in the header to show or hide the list.
-
User Interface
Single training window with collapsible lesson browser
The lesson list now appears beside the lesson card instead of in a separate window, so you can browse other lessons while one is playing.
-
User Interface
Pricing Equation Analysis button removed from toolbar
The toolbar button for Pricing Equation Analysis has been removed to simplify the interface. If you need this feature, it's still available in the Strategy menu.
-
User Interface
Training window position and size remembered
Drag the training window to any spot on your screen — it will reappear there the next time you open lessons, even after restarting the application.
-
User Interface
Improved lesson browser organization
Lessons are now organized by topic with your progress shown on each one, and multi-part lessons have a "Start Series" button that takes you through them in order.
-
User Interface
Training window sized for smaller displays
The training window now fits completely on laptop screens — you'll always see every button and control without needing to resize your application.
-
User Interface
Enhanced catalog metadata
The lesson catalog now supports additional metadata fields including topic, subtopic, order (for sorting within topics), summary (one-sentence description), series information (series ID, part number, series title), and maintains the existing audience filtering. Catalog entries are sorted by order, then number, then series part within each topic section.
-
User Interface
Window sizing and placement improvements
The library mode defaults to 820×560 (up from 700×420) to accommodate the tree and description panes. The callout mode uses a fixed 400×300 size. Both modes remember their last user-dragged position separately and clamp to the monitor's work area on startup, ensuring the window remains accessible on smaller screens like laptops.
-
User Interface
Renamed Training Mode to Training / Guide Mode
The Training Mode feature has been renamed to "Training / Guide Mode" to better reflect that it includes both lessons and hands-on guides.
-
User Interface
Updated Training Mode labels and terminology
Look for "Training / Guide Mode" in the Help menu and the "Lessons & Guides" button in the title bar when training mode is on.
-
User Interface
Series navigation and context
Multi-part lessons now show which part you're on and have Previous and Continue buttons to move through the series.
-
User Interface
"Lessons ▸" button toggles between library and callout modes
The "Lessons" button in the header now switches between the full library and the compact speech bubble while a lesson plays.
-
User Interface
Updated narration voice and lesson structure
Lessons now start by telling you exactly what they cover, and the welcome tour only plays once a day.
-
User Interface
Updated welcome lesson
The first-time training tour now shows you how to move the card and find lessons by topic.
-
User Interface
Tree row styling and state indicators
Tree rows now show chevrons (▸/▾) for expandable groups, and state glyphs for lessons: empty circle for not started, half-filled circle (◐) in accent color for in-progress, checkmark (✓) in green for completed, and filled circle (●) in accent color for currently playing. The selected lesson is highlighted with a semi-transparent accent background. Part numbers (e.g., "1.") appear before lesson titles in multi-part series.
-
User Interface
Enhanced element targeting for spotlights
Adds named targeting for button bar items, data flyouts, toolbar containers, and menu items, allowing lessons to accurately spotlight specific UI elements. Resolves visual tree containers to find actual spotlight targets, improving the precision of visual guidance during training.
-
User Interface
Speech bubble tail positioning
The bubble's tail is a WPF `Path` element positioned outside the 14px margin grid to avoid WPF's layout clipping, and dynamically placed on the right, left, bottom, or top edge depending on which side of the target fits best within the monitor's work area. The tail points directly at the center of the spotlighted control.
-
Database
Training content delivery infrastructure
Training lessons and audio are stored as embedded resources with a content mirror system that downloads JSON and MP3 files to a local cache folder. The render sidecar tracks SHA256 hashes of narration text to detect which audio files need re-rendering when wording changes. Content is served from the `marginmasterdownloads/training` blob container.
-
Architecture
Lesson browser refactored to library view model
Replaced `LessonBrowserViewModel` (172 lines) with `LessonLibraryViewModel` (291 lines), which maintains a flattened tree of `LibraryNode` and `LibraryRow` objects for efficient rendering without a WPF TreeView control. The view model now loads lesson content on demand to populate the description pane, tracks expansion state for topics and series, supports filtering, and handles selection separately from playback state.
-
Architecture
Lesson browser refactored to library viewmodel
Replaced LessonBrowserViewModel (172 lines, flat topic/series/lesson lists with expand/collapse) with LessonLibraryViewModel (291 lines, tree-based with LibraryNode/LibraryRow hierarchy, selection state, search filtering, and LessonDetail for the description panel). The new architecture flattens the expanded tree into rows for rendering without a TreeView control, enabling custom styling and single-click selection with double-click activation.
-
Infrastructure
Documentation updated for button row
The button row documentation has been updated to reflect the removal of the Pricing Equation Analysis button from the toolbar's technical reference.
-
Infrastructure
Backward-compatible catalog format
All new catalog fields (topic, subtopic, order, summary, series, part, seriesTitle) are optional, ensuring existing lesson catalogs and the content sync system continue working without modification. The flat lesson list remains functional, and the LessonCatalog.Topics() method derives the browsable tree from the new fields when present. Cloud catalog will need to be re-uploaded after deployment to take advantage of the new organization features.
-
Infrastructure
Developer training hooks
Added MM_TRAINING_LESSON environment variable for developers to start a specific lesson at launch, bypassing the intro. Named UI elements in the Create New Database dialog (cboPrimaryVendor, txtStoreNumber, cboPosSystem, txtDatabaseName, btnValidateLicense, btnCreateDatabase) so they can be targeted by training steps.
-
Infrastructure
Guide authoring rules and validation
Added test-enforced authoring rules: guides cannot use command targets (they never perform steps for the user), must include a summary explaining what they do, and if they change data must mention "End" in the narration. Lessons (tours) cannot use waitFor signals since they advance on Next only. Added x:Name attributes to Create New Database window controls (cboPrimaryVendor, txtStoreNumber, cboPosSystem, txtDatabaseName, btnValidateLicense, btnCreateDatabase) to support guide targeting.
-
Infrastructure
Developer lesson editor with Azure TTS integration
On development machines where the lesson source folder is detected, adds an in-app editor (✎ button on the bubble) for changing step titles and narration. The workflow is: edit text → Read it back (renders with Azure text-to-speech en-US-AvaMultilingualNeural voice and plays preview) → Approve and publish (updates source JSON, saves MP3, updates render sidecar, mirrors to content folder, and uploads to Azure blob storage via `az` CLI). The media player is released before file replacement to avoid locks. Uses AZURE_SPEECH_KEY or falls back to Azure CLI authentication.
-
Infrastructure
Training window spotlight targets added
Added targetable elements for spotlight highlighting within the training window itself: TrainingWindowHeader (drag handle), btnBrowseLessons (toggle button), LessonBrowser (scrolling list), AllLessonsHeading, and LessonIdBox. The overlay sits under the card so spotlights on the card itself are narration-only without visual highlighting.
-
Infrastructure
TrainingWindowMoved signal for interactive lessons
Added TrainingWindowMoved signal raised when the user drags the training card to a new position, enabling lessons to wait for and teach window repositioning as an interactive step (used in the revised training-mode introduction lesson).
Performance & Reliability
-
Improvement
Export error messages now include operating system reason
Export error messages now explain why the operation failed (for example, "access denied" or "file is locked"), not just which file was affected.
-
Improvement
Backup directory now derives from import path setting
The automatic backup folder (used for database and strategy backups) is now recalculated each time from the current import path setting rather than cached at startup, ensuring Options changes take effect immediately. Falls back to ProgramData when the derived path cannot be created.
-
Bug Fix
Export path resolution unified across all operations
When no custom export or import folder is configured, Margin Master now consistently uses C:\MarginMaster for all operations instead of sometimes trying to write to the C:\ drive root (which Windows blocks for standard users).
-
Bug Fix
Settings folder permission check prevents silent save failures
If Margin Master can't save settings because of Windows permissions, you'll now see an error message at startup that lists exactly what's wrong and tells you to ask your administrator to grant Modify access to the settings folder.
-
User Interface
Clear permission error dialog with actionable guidance
The error message shows exactly which files can't be written and tells you who to contact to fix the permissions.
-
Infrastructure
Comprehensive permission validation
The new ProgramDataAccessCheck helper performs two validation steps: creates a test file to verify the directory is writable, then attempts to open every existing *.json file in the folder root for write access. This two-tier approach catches the specific scenario where folder ACLs allow new file creation but existing files have restrictive permissions from being created under a different user account. File locking by other processes is explicitly treated as non-fatal (contention is not a permissions problem).
-
Infrastructure
Path resolution logic consolidated and tested
Replaced the IGlobalFileConfigService.DefaultExportPath / DefaultImportPath properties and their internal GetValidPath / TryCreateDirectory helpers with new extension methods on IApplicationSettingsService (ApplicationSettingsPathExtensions) and IImportSettingsProvider (ImportSettingsProviderPathExtensions). Added MarginMasterPaths.ResolveImportExportFolder and NormalizeImportExportFolder as the single pure resolver all 67 call sites now share, with 16 test cases pinning normalization, fallback, and creation behavior.
Infrastructure & Internal
-
New Feature
SQL Server Authentication Setup Guide for IT Administrators
Stores with their own IT departments can now share official setup instructions for configuring SQL Server when running Margin Master on multiple computers.
-
Improvement
Export error messages now include the full file path and reason
Export failures now surface the operating system's error message (access denied, file in use, path not found) alongside the full file path, making it easier to diagnose export problems without guessing which folder was attempted.
-
Improvement
Updated Firewall Requirements Documentation
Modified the firewall and network requirements guide to link to the new customer-facing SQL Server setup guide instead of the support-only script documentation. The script reference has been moved to a support-only section so it remains available to internal staff but doesn't create broken links for customers.
-
Improvement
Bare drive roots (C:\) rejected as import/export folders
The path normalizer now treats a bare drive letter (C:\ or C:) the same as a blank setting and substitutes the default folder. This prevents the original MM-1446 condition where a malformed or incomplete setting resulted in write attempts to the drive root.
-
Improvement
Cross-Referenced SQL Remote Access Script
Added a related link from the internal support script documentation to the new customer-facing guide, making it easy for support staff to direct customers to the appropriate resource.
-
Bug Fix
Export path now resolves consistently across all operations
Exports that previously failed with "Access denied" will now succeed. The export path shown in Options will match the path actually used by all export operations.
-
Architecture
Centralized import/export path resolution logic
Created MarginMasterPaths.ResolveImportExportFolder() and extension methods on IApplicationSettingsService (GetDefaultImportPath/GetDefaultExportPath/SetDefaultImportPath/SetDefaultExportPath) so all 34 readers of these settings see the same normalized value. Removed duplicate path-resolution code from GlobalFileConfigService and individual ViewModels.
The auto-update system now measures and reports download performance for every update, tracking bytes transferred, download duration, and whether delta patches or full packages were used. This telemetry is sent to Manager on the next check-in to help determine if stores are benefiting from small…
Interactive training system with spoken narration; Azure Neural TTS narration for training lessons; Training Mode toggle with visual indicator.
User Interface
-
New Feature
Interactive training system with spoken narration
When you start a training lesson, a small window appears with spoken instructions. The screen dims except for the button or menu you need to click, which pulses with a highlight. After you complete each step, the lesson moves forward automatically or when you click Next.
-
New Feature
Azure Neural TTS narration for training lessons
Training lessons now play with a professional voice instead of robotic text-to-speech, making them easier to follow.
-
New Feature
Training Mode toggle with visual indicator
Turn on Training Mode from the Help menu to see lessons. The window gets a glowing blue border and the title bar shows a "Show Lessons" button.
-
New Feature
Lesson reference numbers for documentation and support
When working with support, you can now use lesson numbers like "1001" to quickly start the right training.
-
New Feature
Welcome to Training Mode lesson (Lesson 1000)
When you first turn on Training Mode, a welcome lesson plays automatically to walk you through how to find lessons, understand lesson numbers, and navigate the training system.
-
New Feature
Help buttons offer "Walk me through it" option
Click the blue "?" button on any screen to choose between reading the help page or launching an interactive training lesson that walks you through the task.
-
New Feature
Screen-aware lesson list
When you click "Show Lessons," you'll see lessons for the screen you're on first, then all other available lessons.
-
New Feature
Sample lesson: Opening Options and finding Miscellaneous tab
The sample training lesson walks you through opening the Tools menu, clicking Options, and finding the Miscellaneous settings page.
-
New Feature
Dialog detection for lesson steps
The training system now automatically detects when new dialogs open by monitoring the application's window collection and raising "Dialog:{title}" signals. This allows lessons to wait for specific windows to appear before advancing, enabling multi-step workflows that cross dialog boundaries.
-
New Feature
Visual tree element search for lesson targets
Lesson steps can now target any named element in the application, including those inside UserControls, by walking the WPF visual tree. Previously only elements directly accessible through Window.FindName were reachable.
-
New Feature
Rounding Schemes training lesson
A new lesson shows how to open the Rounding Schemes editor where you set price endings like 99 cents.
-
Improvement
Training player remains enabled during modal dialogs
The training assistant now stays interactive when guiding you through screens like Options, so you can continue following instructions without the tutorial freezing.
-
Improvement
Auto-advance support for navigation steps
Training lessons now advance automatically after certain actions, making tutorials flow more smoothly without extra clicks.
-
Improvement
Enhanced coordinate conversion for spotlight targets
Added ToLocal method that properly converts spotlight target rectangles from the main window's DPI context into the overlay's local coordinate system, accounting for different DPI scaling on each display. This ensures the dimmed areas and highlight outlines draw precisely around the intended UI elements.
-
Improvement
"Lessons..." menu added to all help buttons
Click any help button (?) and select "Lessons..." to see all available training, even if there's no specific lesson for the current screen.
-
Improvement
Intro lesson waits for catalog refresh
The welcome lesson waits to make sure all content is loaded before starting, so it won't fail if you enable Training Mode right after opening the app.
-
Improvement
Automatic dialog avoidance
When you open a dialog during training, the player automatically moves aside so both windows stay visible, then returns to its original spot when you close the dialog.
-
Improvement
Intro lesson plays once per session
The welcome lesson only plays the first time you turn on Training Mode each day—toggling it off and on again won't replay the introduction.
-
Improvement
Enhanced z-order management for training player
The training player now reliably stays on top and clickable even when other windows are open, so you can follow along with lessons without interruption.
-
Improvement
Shared spotlight overlay between training components
The spotlight overlay (which dims the screen and highlights the target) is now shared between Training Mode's glowing frame and active lesson steps, rather than creating a new overlay for each lesson. This prevents visual conflicts and ensures smooth transitions.
-
Improvement
Lesson list window stays accessible during training
Applied ModalSurvivor to the lesson list window so it remains usable when other dialogs are open, consistent with the training player window behavior.
-
Bug Fix
Spotlight overlay positioning when maximized
When using interactive training while Margin Master is maximized, the spotlight overlay now properly fits the window without extending past the screen edges.
-
Bug Fix
Spotlight overlay positioning on mixed-DPI displays
When using multiple monitors with different display scaling settings, training spotlights previously appeared offset from the highlighted area. This is now fixed and spotlights align correctly.
-
Bug Fix
Removed window glow effect in training mode
The blue glow that appeared around the window edges during training lessons has been removed because it was spilling onto other monitors in multi-screen setups.
-
Bug Fix
Training overlay positioning on maximized windows
When using training mode with Margin Master maximized, the spotlight overlay now appears in the correct position on your screen.
-
Bug Fix
Rounding schemes lesson dialog detection
The interactive training for rounding schemes now correctly waits for the Edit Rounding Scheme dialog to appear before continuing.
-
Bug Fix
Training windows survive modal dialogs
Training lessons now work properly when walking you through dialog windows—the training instructions stay visible and usable.
-
Bug Fix
Spotlight overlay repositions after DPI changes
The training spotlight effect now stays properly positioned when you move Margin Master between monitors with different scaling settings.
-
User Interface
Modern card-style training player design
The training player now looks more modern with a sleek, rounded design and shows your progress through each lesson with a visual progress bar at the bottom.
-
User Interface
Step counter added to training progress indicator
When following a training lesson, you'll now see "Step 3 of 7" (for example) displayed next to the progress bar, making it easy to know exactly where you are in the lesson.
-
User Interface
Draggable training player with persistent positioning
You can now drag the training player to any position on screen by clicking and dragging the top bar, and it will stay where you put it.
-
User Interface
Resizable training player window
You can now resize the training window by dragging the corner to make it larger or smaller.
-
User Interface
Help menu adds "Training (preview)" option (Debug builds only)
In preview builds, you'll see a "Training (preview)" option in the Help menu that starts the sample lesson.
-
User Interface
Refined lesson instructions
Updated the sample Options lesson with clearer wording, instructing users they can close the Options window at their convenience rather than requiring it before clicking Finish.
-
User Interface
Lesson list elements now targetable
Added x:Name identifiers to lesson list UI elements (AllLessonsHeading, LessonIdBox) and the main window's "Show Lessons" button (btnShowLessonsPill), allowing the introductory lesson to highlight and reference these interface elements directly as part of its interactive tutorial.
-
User Interface
Redesigned training player controls and layout
Reorganized button layout with new pill-style buttons, moved the Exit button to the header for quicker access, added a resize grip in the bottom-right corner, and implemented a StepDots visual progress indicator that shows completed steps in accent color, the current step wider and white, and upcoming steps dimmed.
-
User Interface
Training mode activates window glow effect
When training mode is active, the main window shows a subtle cyan glow around its border.
-
Architecture
Lesson asset extraction system
Enhanced Lesson.LoadEmbedded method to extract embedded audio files (MP3) to the local file system on first use, with file existence and size validation to avoid re-extraction. Audio paths in lesson steps are resolved to absolute local paths when an asset folder is provided, enabling the narrator to play pre-rendered audio instead of synthesizing speech at runtime.
-
Architecture
Training library independent of DevExpress and UI framework
MarginMaster.Training is a standalone library with no dependencies on DevExpress or MarginMaster.UI.WPF. The host application implements ITrainingHost (perform actions, locate UI elements) and ITrainingLauncher (start lessons), while the library handles lesson playback, narration, spotlight overlay, and progress tracking. WpfTrainingHost reuses ScreenshotRunner's menu/reflection helpers to drive the UI consistently.
-
Architecture
Updated lesson catalog structure
LessonCatalog.FindById() now accepts both slug-style IDs ("rounding-schemes") and short numeric references ("1002" or "#1001"), improving flexibility for support scenarios and documentation references.
-
Infrastructure
Lesson audio rendering script
Added Render-LessonAudio.ps1 PowerShell script for authoring-time rendering of lesson narration. The script reads a lesson.json file, sends each step's text to Azure Speech REST endpoint, and writes MP3 files to the lesson's audio folder. Supports configurable voice selection (default: en-US-AvaMultilingualNeural), region, and speaking style.
-
Infrastructure
Added overlay lifecycle tracing
Added diagnostic trace logging to the spotlight overlay to track when the frame is shown or hidden, when the overlay window appears, and when fallback positioning logic is used. This will help diagnose any future issues with the training overlay not appearing correctly or following the main window properly.
-
Infrastructure
Developer testing hook for training mode
Added a debug-only environment variable (MM_TRAINING_MODE=1) that automatically enables training mode at startup, making it easier for developers to test overlay behavior without manual interaction.
-
Infrastructure
Training diagnostic logging
Added trace logging throughout the training system that reports step transitions, signal satisfaction, and lesson progress to the application log. This helps diagnose lesson authoring issues and player behavior during development and support scenarios.
-
Infrastructure
Training progress stored per-machine
Implements LessonProgressStore that saves lesson progress (current step index, completion status) to a JSON file in CommonApplicationData. Lessons automatically resume where the user left off, and completed lessons are marked as done.
-
Infrastructure
JSON-based lesson format with embedded catalog
Defines a lesson format supporting step narration (text-to-speech or pre-recorded audio), targets (menu items, commands, Options tabs, named elements), wait conditions, and auto-advance. Lessons are cataloged by documentation slug so help buttons can find the matching lesson. The sample catalog and lesson are embedded as resources.
-
Infrastructure
Spotlight overlay window with click-through transparency
Implements SpotlightOverlay as a transparent, topmost, click-through window that dims the entire screen except for the target rectangle, which pulses with an animated outline. Uses Win32 extended window styles (WS_EX_TRANSPARENT, WS_EX_LAYERED) to allow interaction with the main window while the overlay is visible.
-
Infrastructure
Windows Speech API integration for narration
Adds System.Speech package reference (10.0.11) and implements WindowsNarrator using SpeechSynthesizer for text-to-speech and MediaPlayer for optional pre-recorded audio files. Prefers natural-sounding English voices when available, supports cancellation, and runs on the UI thread as required by MediaPlayer.
Infrastructure & Internal
-
New Feature
Cloud-hosted training content with local caching
Training lessons automatically update from the cloud when you turn on training mode, so you'll always have the latest content without needing to update the application. If you're offline, the app uses built-in lessons so training always works.
-
New Feature
Lesson audience targeting system
Training lessons may now be customized for your specific vendor, POS system, or even your individual store.
-
New Feature
Launch lessons directly by ID
You can now type a lesson ID from the documentation into the lesson list and click Start to jump straight to that lesson.
-
Improvement
Background training content synchronization
When you open Margin Master, it now quietly downloads the newest training lessons in the background so they're ready whenever you need them, even if you go offline later.
-
Improvement
Training Mode access control
Training Mode menu visibility changed from a debug-only compile-time flag to runtime check based on IsSupportMachine property. The menu item now appears only on machines registered in RS_Data.SupportMachines and verified via the /api/support/machines/check endpoint, ensuring training features are restricted to authorized support personnel.
-
Improvement
Graceful failure handling for content refresh
The background refresh task logs any failures but allows the application to continue using cached or embedded lessons without interruption. Screenshot mode automatically skips the refresh to avoid external network calls during automated testing.
-
Improvement
Automatic catalog refresh after content sync
When training mode is activated, the app syncs content from the cloud and then reloads the lesson catalog, ensuring newly published lessons appear immediately. The TrainingLauncher now exposes a ReloadCatalog method to refresh the catalog from the updated content folder without restarting the application.
-
Cloud Sync
Selective training content download
The cloud sync process now downloads the lesson catalog first, filters it by the current store's context (vendor, POS system, store number, and organization), then downloads only the applicable lesson files and their audio narration. This reduces bandwidth usage and local storage while enabling vendor-specific or store-specific training content.
-
User Interface
Help menu simplification
Removed IsTrainingPreviewVisible property from MainMMViewModel and simplified XAML binding to directly use IsSupportMachine. This eliminates technical debt from the training mode spike and aligns the feature with the application's existing support machine authorization system.
-
User Interface
Removed DevExpress glow effect from training mode
The blue glow effect around the window in training mode has been removed for a cleaner look.
-
User Interface
Filtered lesson catalog display
The training lesson list now shows only lessons relevant to your store's vendor and point of sale system.
-
Infrastructure
Training context integration
The training host now provides the store's configuration context (vendor type, POS system type, store number, and organization ID) to the training launcher. This context is used to filter the lesson catalog when loading from either embedded or cloud-synced content.
-
Infrastructure
TrainingContentSyncService for cloud synchronization
A new service pulls training content from Azure blob storage, comparing blob modification times against local files and downloading only what has changed. Files are written to a temporary .download file and moved atomically to prevent corruption. Failures are logged but never disrupt the user experience since embedded content remains available.
Introduction and Core Concepts Page; Installation Prerequisites and SQL Server Setup Pages; Saved selections documentation expanded.
User Interface
-
Improvement
Updated Propello documentation
Updated the Propello import guide documentation to reflect the new confirmation message wording, ensuring consistency between the application and help documentation.
-
Improvement
Enhanced Propello failure reasons
Failure reasons in the push report now include more detailed validation messages from the Propello library itself, providing better context when items cannot be uploaded during bulk operations or retry attempts.
-
Bug Fix
Propello push report formatting corrected
When a price update fails to push to Propello, the error report now clearly shows which SKU and store were affected instead of running the numbers together.
-
User Interface
Clearer Propello pre-send confirmation dialog
When you send prices to Propello Price Review and some items are already waiting there, the confirmation message now more clearly explains that sending again is safe: any SKU you're re-sending will have its price updated, but other items already waiting won't be removed.
-
User Interface
Clarified Propello pre-check prompt wording
Before sending prices to Propello, if some items are already waiting, you'll see a clearer explanation that re-sending a SKU replaces its pending price without removing anything else from the queue.
Reporting & Exports
-
Bug Fix
Propello push report formatting improved
When pricing updates fail to upload to Propello, you'll now see each failed item clearly labeled with "SKU [number] @ store [number]: [reason]" instead of confusing columns that ran together.
Infrastructure & Internal
-
New Feature
Introduction and Core Concepts Page
New *How Margin Master Thinks* page introduces the three foundational ideas behind the application: vendor pricing as a baseline (not the final answer), hierarchical strategy execution, and rounding as a margin improvement tool. Serves as the handbook's conceptual introduction before installation chapters.
-
New Feature
Installation Prerequisites and SQL Server Setup Pages
Added *Prerequisites* page covering system requirements, SQL Server versions (2022/2025 supported), network needs, and pre-installation checklist. New *Install or Upgrade SQL Server Express* and *Install or Upgrade SQL Server Management Studio* pages document the SQL Server Tools window's guided installation process, including instance naming (`MARGINMASTER`), backup behavior during upgrades, and reboot handling. The older in-app installer documentation is now support-only.
-
New Feature
Saved selections documentation expanded
Expanded "Load Saved Selection" documentation to "Save and Load Saved Selections," now covering the camera button workflow for saving the current selection boxes and Future Price panel settings as a named snapshot, and explaining how saved selections serve as both reusable filters and strategy steps.
-
New Feature
Main Window Component Pages
Split the main window orientation into focused pages: *The Menus* (every menu item with keyboard shortcuts), *The Button Row* (all 10 toolbar buttons numbered with explanations of vendor SKU vs. non-vendor SKU filtering), *The Main Data Grid* (column meanings, color coding, symbol columns, right-click actions), *The Summary Section* (Displayed/All/None modes, monthly impact columns, export options), and *Banners and Badges* (every title-bar pill and banner with meanings and actions). *Main Window Orientation* is now the chapter's landing page linking to each detailed page.
-
New Feature
Store Manager Reframed as Data Processing Hub
The Store Manager guide now clearly explains why matching your stores to vendor store numbers is essential for correct pricing, and how to fix stores that show "needs setup" or import zero items.
-
New Feature
Supported POS Systems master list
You can now look up your point-of-sale system in the handbook's POS Systems chapter and find either a complete import guide or a page confirming the system is supported with next steps.
-
New Feature
Strategy hierarchy guide
Added documentation explaining how pricing strategies execute top-to-bottom with last-step-wins behavior, using a worked example of a hardware store pricing paint at 42% margin while holding sensitive items to Level 1 price. Emphasizes general-to-specific ordering and how PSRule shows which step finally priced each SKU.
-
New Feature
Stub Pages for Cross-References
Added first-draft *Printing and Exporting* and *Rebuild Data* pages so new pages' links resolve; these will be expanded in later phases. All pages carry proper frontmatter matching `handbook-map.json` structure (part, chapter, order).
-
New Feature
Supported POS Systems Complete List
You can now see a complete list of every point-of-sale system Margin Master works with, even if detailed setup instructions are still being written.
-
New Feature
Creating strategy steps guide
Added step-by-step documentation for creating a strategy step from the main window: set selection boxes, configure the Future Price panel action, then press the camera to save the snapshot as the newest step in the active strategy. Explains all "Set Future Price to" options including vendor price levels, target margin, cost breaks, fixed retail, and margin snapshot.
-
New Feature
Vendor Settings and POS Connections tab documentation
The handbook now explains how to set up Do it Best mailbox connections, test them, and configure Ace Direct SKU handling through the Options window.
-
New Feature
Updating and deleting steps guide
Added documentation for managing existing strategy steps in the Strategy Manager, including re-ordering with Up/Down buttons (Ctrl for 5 places, Alt for top/bottom), activating/deactivating steps, renaming, editing conditions and rounding, and the Load workflow for changing a step's core selection or action.
-
New Feature
Troubleshooting Vendor Sync Guide
New guide helps you diagnose and fix issues when vendor data sync fails or doesn't update prices as expected.
-
New Feature
Advanced topics: Store Grouping and Troubleshooting Vendor Sync
The handbook now covers how to group stores for shared pricing and how to diagnose why vendor data sync might fail or appear incomplete.
-
New Feature
Reviewing and executing strategies guide
Added documentation covering pre-run strategy review (checking step order, SKU counts, active status), executing with Ctrl+X, interpreting the Strategy Execution Summary (sitting margin, profit impact, "Not priced" warnings), and using "Show Skus NOT included in Strategy" to find items no step priced.
-
New Feature
Store Grouping Advanced Topic
Advanced multi-store users can now learn how to group stores together for unified pricing across locations in the same market.
-
Improvement
Store Manager repositioned as data-processing hub
The Store Manager guide now explains clearly why matching your stores to vendor numbers is required for accurate pricing and how to fix stores that won't import.
-
Improvement
Troubleshooting sections added to 17 POS import guides
Each POS import guide now includes a troubleshooting table showing what to check when imports fail or data doesn't appear.
-
Improvement
POS Import Troubleshooting Sections
Every POS import guide now includes a troubleshooting table to help diagnose common issues like "no files found" or imports that complete but don't update the grid.
-
Improvement
Reworked SQL optimization documentation with symptom-first approach
The database troubleshooting guide now starts with common symptoms like slow refreshes and tells you which tool to run first, making it easier to fix performance problems without needing database expertise.
-
Improvement
Cloud Vendor Data Sync Updates
The vendor sync documentation now clearly shows which vendors are fully supported and which are in development.
-
Improvement
Vendor sync guide updated for True Value and Emery Jensen
The vendor sync guide now mentions True Value members and Emery Jensen stores and explains that your chosen vendor determines which catalog data is synced.
-
User Interface
Options Window and Settings Documentation
The handbook now includes step-by-step guides for every setting in Tools > Options, making it easier to configure import paths, export formats, vendor connections, and data preferences.
-
User Interface
Options Window documentation suite
The handbook now explains every setting in Tools > Options, where to find import/export paths, how to test POS connections, and what each vendor-specific option does.
-
User Interface
Selection boxes documentation
Added complete guide explaining how selection boxes work on the main window, including left-click include vs right-click exclude behavior, Shift-range selection, type-to-scroll navigation, how boxes combine (OR within, AND across), and special comparison boxes for price, cost, margin, quantity, and date fields. Also documents the PSRule box, Store Number display options, and the F12 clear-all shortcut.
-
User Interface
New handbook chapter: How Margin Master Updates
You can now read about how Margin Master updates itself and choose the update method that works best for your computer in the new handbook chapter.
-
User Interface
Margin Master branding consistency sweep
User-facing text now says "Margin Master support", "Margin Master cloud" and "Margin Master licensing server" instead of RetailerSoft. RetailerSoft remains where it names the company (installer signature, file paths under %ProgramData%\RetailerSoft). The engineering notes file at the docs root gained internal-only frontmatter so it no longer publishes publicly; the firewall guide is now in the search index.
-
User Interface
POS / Connections Tab Documentation
Clear guidance now available on where to configure your point-of-sale connection based on which system your store uses.
-
User Interface
New handbook chapter: Importing from Excel
The Excel import feature now has its own detailed guide showing how to map spreadsheet columns to Margin Master fields and save those maps for reuse.
-
User Interface
New handbook chapter: Cost Break Strategies
You can now read step-by-step instructions on how to use cost break models in your pricing strategies to apply sliding margins based on item cost ranges.
-
User Interface
New handbook chapters: Catalog Lookup, What's New, and Help Buttons
New handbook pages explain how to look up vendor catalog information for any SKU, view what changed in each version update, and use the help buttons found on most Margin Master windows.
-
User Interface
Button Row Screenshot
Added numbered `button-row.png` screenshot with 10 labeled buttons; main window screenshots updated with support-only icons redacted from toolbar (Implementation Plan and Pricing Equation Analysis buttons blanked in manifest).
-
Infrastructure
Handbook reading order established
Every doc under docs/marginmaster/ now carries part / chapter / order frontmatter mirroring the new docs/handbook-map.json, which defines Introduction + Parts I–VIII across 21 chapters. HandbookMapTests in MarginMaster.Tests fails the build when a doc is missing from the map, frontmatter disagrees with the map, two docs share an order in a chapter, or a user-only doc is parked in the appendix. Reference material (installation scripts, catalog-file layouts, engineering notes) stays in an Appendix on purpose.
-
Infrastructure
User handbook expansion - selection boxes and strategy building
The online help now includes detailed guides on using selection boxes, saving your work with the camera button, and building pricing strategies step-by-step with real examples.
-
Infrastructure
Handbook map tests enforce documentation structure
Added HandbookMapTests.cs with four enforcing tests: every doc is placed in a chapter or listed in the appendix on purpose, frontmatter matches the map, orders are unique within each chapter, and user-only docs are not parked in the appendix. Drift between the map and the files now fails the build instead of silently scrambling the handbook's reading order.
-
Infrastructure
Handbook Map Synchronization Script
New `docs/sync-handbook-map.py` Python script regenerates `handbook-map.json` and `index.json` from document frontmatter, ensuring the table of contents, navigation links, and search index stay in sync with the docs. Handbook now has Introduction (Part 0) plus Parts I–VIII with 21 chapters.
-
Infrastructure
Completed handbook first pass
This phase completes the handbook's first full pass with Introduction plus Parts I–VIII, every chapter now populated. Includes 826 lines added across 12 documentation files, updating the handbook map, search index, and changelog. Co-authored with Claude.
-
Infrastructure
Handbook structure and navigation
Updated handbook-map.json and index.json to organize the new pages into Chapter 13 (Selection Boxes) and Chapter 15 (Building Pricing Strategies) within Part VI (Learning Margin Master), with proper ordering, search keywords, and cross-references.
-
Infrastructure
Handbook structure and index regeneration
Updated handbook-map.json with 213 new lines placing all new pages into the correct Parts/Chapters (Part III Initial Configuration gains Chapter 6 Tools > Options with 6 docs, Chapter 7 POS Systems gains 46 docs, Chapter 8 Store Manager gains store-grouping cross-reference; Part VII Advanced Topics gains Chapter 18). Regenerated index.json with 2,254 new lines covering all new pages, updated timestamps, corrected titles, and refreshed body excerpts. All 17 modified POS guides and 8 new/modified Getting Started pages carry last_updated "2026-08-28".
-
Infrastructure
Options Window Screenshot Manifest
Added options.manifest.json defining screenshot capture specifications for the Options window (window-relative crops at 1600×1000, showing navigation, tabs, and buttons) with shots for overview, Miscellaneous tab, Export Options tab, and Ace Hardware tab.
-
Infrastructure
Handbook Map and Search Index Updates
Updated handbook-map.json with 213 new entries organizing the Options, POS Systems, and Store Manager chapters; regenerated index.json with 2,254 additions reflecting all new pages, updated titles (Store Manager → "Store Manager: The Hub of Data Processing"), reordered items (Supported POS Systems now order 2 in Chapter 7), and search keywords for every new guide.
Damaged .NET runtime detection at startup; Automatic damaged-runtime detection at startup; Propello Options tab: Save & Test connection.
Strategy & Pricing
-
Bug Fix
Cost break target margin input now stores values correctly
When setting up cost break pricing levels, typing a target margin percentage like "70" now correctly saves as 70% instead of 7,000%, and the calculated prices will be correct.
-
Bug Fix
Cost break Target Margin calculation error
If you previously entered a Target Margin like "70" and saw strange negative prices, those cost breaks will now calculate correctly. Any affected cost break strategies will automatically heal when you view them.
-
Bug Fix
Self-healing logic for existing misconfigured cost breaks
Cost breaks that were previously saved with incorrect margin values (showing thousands of percent) will automatically fix themselves and start working correctly.
-
Bug Fix
Culture-invariant cost break SQL generation
Changed BuildCostBreakSQL to emit From/To/TargetMargin values using InvariantCulture formatting to prevent localization issues where decimal separators could corrupt the generated SQL on systems with different regional settings.
-
User Interface
Target Margin input mask added
When editing Target Margin in cost break levels, the cell now guides you to enter values as percentages and prevents incorrect entries.
-
Infrastructure
Cost break validation tests
Added comprehensive unit tests (CostBreakTargetMarginTests) to verify that whole-percent values (1 or greater) are correctly converted to fractions, while existing fractional values and edge cases remain unchanged.
-
Infrastructure
Test coverage for target margin normalization
Added comprehensive unit tests (CostBreakTargetMarginTests) to verify that whole percent values (70, 42.5, 100) are converted to fractions (0.70, 0.425, 1.00) while existing fractional values remain unchanged, preventing regression of this critical pricing bug.
Imports & POS
-
New Feature
Propello Options tab: Save & Test connection
Go to Tools > Options > Propello, enter your Propello URL (for example "anchorace" or "https://anchorace.epicorretailcloud.com/"), username and password, then click Save & Test. Margin Master will verify the connection and save it. If the test reports a permissions problem, ask your Propello administrator to grant the listed rights to the user, then test again.
-
New Feature
Direct Propello cloud connection
Set up the connection once in Tools > Options > Propello with your store's Propello web address and login. After that, Get POS Data downloads your inventory automatically.
-
New Feature
Direct POS download from Propello
After connecting Propello in Tools > Options, click Data > Get POS Data. Margin Master will download the product export from Propello and show how much time is left. If it fails, you can still import an Excel file you exported from Propello yourself.
-
New Feature
Price Review upload from Print dialog
Use Print/Export and choose "Propello Price Review" to send your price changes straight into Propello — they land in Price Review for you to approve in the portal.
-
New Feature
Propello Price Review upload from Print/Export
Select the rows you want to change in Propello, click Print/Export, choose "Propello Price Review" and enter the date you want the new prices to take effect. Margin Master will send the changes to Propello Price Review (they will not be finalized automatically) and show you what was uploaded.
-
Improvement
Guided setup prompt for unconfigured Propello connections
If you haven't set up Propello yet, clicking "Get POS Data" will now show a helpful message asking if you want to set up the connection now, making first-time setup easier.
-
Improvement
Cloud connection availability check for Propello
When you open Propello settings, Margin Master now checks what connections are saved in the cloud and updates the Restore from Cloud button accordingly.
-
Improvement
RscGate enforces one RSC rule across all import paths
A new centralized RscGate decision point now applies the same RSC validation rule at every Do it Best per-store build site: the drain rebuild, BisTrack Direct SQL and CSV imports, legacy BCP ingest, Propello, and Compass catalog merges. This ensures no import path can bypass the RSC requirement or accidentally build against the wrong catalog.
-
Improvement
RSC lookup logic simplified and documented
The GetSpecificRSCResponse model now includes IsResolved and RequiresRsc properties that clearly indicate whether a store can be built. The fallback ladder (ResolveEffectiveRsc) that borrowed RSCs from other sources has been removed. A new RscGate service provides a single, testable decision point used by all import paths (drain, BisTrack preload, legacy BCP ingest, Propello/Compass merges) to enforce the "no RSC means not built" rule consistently.
-
Improvement
Restore button disabled when no connections available
The Restore from Cloud button is now disabled until you've successfully saved at least one Propello connection, with a clear explanation of why it's unavailable.
-
Improvement
Propello progress message formatting refinement
Progress messages during Propello imports now display time information more cleanly without duplication.
-
Improvement
Propello API export compatibility
Propello's Inventory Viewer export (requested through the API with the "Margin Master (Auto)" saved view) uses different column headers than the hand-exported Products grid ("Store Number" vs "Store #", "curr_month_less_0_sales_units" vs "Feb-26"). Import column definitions now recognize both spellings through aliases, so cloud downloads and manual exports import through the same code path without requiring schema changes.
-
Improvement
Connection test and restore from cloud
The new Propello tab in Options includes a "Save & Test" button that validates credentials by logging in and creating/repairing the saved view Margin Master needs. Propello connections are backed up to the RetailerSoft cloud after a successful test and can be restored from the cloud if the local settings are lost, matching the workflow for other POS connections.
-
Improvement
Duplicate removal now runs after every store build
RemoveDuplicatesFromMainTable now runs after every per-store build (previously skipped by some import paths), is guarded to safely handle missing tables, and orders by [ID] to keep the first-inserted row rather than picking arbitrarily. This ensures exactly one row per (StoreNumber, SKU) in every main table.
-
Improvement
User-friendly Propello failure messages
When a Propello operation fails, Margin Master explains the problem in store-owner terms: "bad credentials" if the username/password is wrong, "permissions issue" if the Propello user lacks required rights (with a list of the rights needed), and "portal or network" for timeouts or connectivity problems. A manual fallback lets stores import a hand-exported file if the cloud download fails.
-
Bug Fix
Fixed BisTrack CSV imports creating duplicate SKUs
If you use BisTrack CSV imports and noticed the same item appearing multiple times in your pricing grid after import, this fix ensures each SKU loads only once. Verified with a 22-store customer file: 23,712 SKUs now correctly produce 23,702 distinct entries instead of 93,459 duplicated rows.
-
Bug Fix
Fixed BisTrack CSV import creating duplicate SKUs
Previously, after importing BisTrack CSV files, you would see the same SKU repeated multiple times in the pricing grid. This has been fixed—each SKU now appears only once after import.
-
Bug Fix
RSC is now store-specific and never borrowed
Do it Best stores must now have their own RSC assigned in Store Manager to import correctly. If a store is missing its RSC, it will appear in the "NOT IMPORTED" list at the end of the import with instructions to set the RSC and re-import.
-
Bug Fix
Do it Best RSC enforcement prevents incorrect pricing
If your Do it Best store doesn't import, check the import results screen for "no RSC set in Store Manager" — open Store Manager, set the correct RSC for that store, and re-import.
-
Bug Fix
Excel header range expanded to support full Propello API exports
When importing Propello API exports, all 240 columns of data are now successfully imported. Previously, the last five columns were silently lost.
-
Bug Fix
BisTrack stores no longer exempt from RSC filter
BisTrack Direct SQL stores were previously exempt from RSC filtering (skipRscFilter flag), which caused every SKU to appear multiple times when multiple RSCs existed in the catalog. This exemption is removed—all Do it Best stores now filter by their assigned RSC.
-
Bug Fix
Main table duplicate removal now keeps deterministic rows
The RemoveDuplicatesFromMainTable SQL query now keeps the first-inserted row (lowest ID) when deduplicating on StoreNumber and SKU, rather than letting SQL Server pick arbitrarily. The query is now guarded to safely run on tables that may not exist. All Do it Best import paths (BisTrack 1040, BisTrack 6828, legacy BCP, drain refresh) now run this deduplication step.
-
Bug Fix
RSC predicate now correctly applied in legacy BCP imports
The legacy BCP ingest's RSC filter targeted outdated SQL syntax that the query builder no longer emitted, causing the filter to silently fail. The replace logic now targets the correct JOIN syntax and validates that it matches what the builder actually generates.
-
Bug Fix
BisTrack Direct SQL RSC filter now applies correctly
The RSC filter for BisTrack Direct SQL stores was silently failing because the string replacement targeted outdated SQL syntax that the query builder no longer emits. The replacement now targets the current "LEFT JOIN [MMVendorData] ON [MMVendorData].[SKU] = " syntax and includes validation to detect future mismatches. BisTrack Direct SQL is no longer exempt from RSC filtering — stores at multi-RSC organizations now receive correct, filtered pricing.
-
Bug Fix
Connection save now awaited to update cloud count immediately
Changed the cloud backup during Save & Test from fire-and-forget to awaited, ensuring that CloudConnectionCount is immediately updated to reflect the newly saved connection. This guarantees the Restore button becomes enabled right after a successful save operation.
-
Data Import
Propello header alias support for API exports
When importing Propello files, the system now automatically recognizes different header names from API downloads and manual exports, so you no longer need to worry about which export method was used.
-
Data Import
Comprehensive alias mapping for Ace Hardware and Do-It-Best columns
All Propello column variations for Ace Hardware and Do-It-Best imports are now recognized automatically.
-
Data Import
Import Manager now reads wider Excel files
Both the general Excel file reader and the Propello-specific import service have been updated to handle wider spreadsheets, ensuring compatibility with current and future Propello API export formats.
-
User Interface
Import workflow improved for first-time Propello users
New users will see a clear explanation of how to connect to Propello, with the option to go directly to the settings screen.
-
User Interface
Dynamic tooltips for Restore from Cloud button
Hovering over the Restore from Cloud button now shows helpful information about whether saved connections are available and how many exist for your store.
-
User Interface
Store configuration errors reported consistently
Stores that cannot be built due to missing or invalid RSC mappings are logged at Warning level and added to the store configuration issue collector with severity "NotImported". The import results screen displays these stores in a "NOT IMPORTED" section with actionable messages like "no RSC set in Store Manager — set it and re-import" or "RSC '04' is set but the synced vendor data has no rows for it — sync vendor data for RSC 04 and re-import".
-
User Interface
Store configuration issues now report missing RSCs
After importing, any Do it Best stores missing an RSC will be listed in the "NOT IMPORTED" section with instructions on how to fix the issue in Store Manager.
-
Database
Propello credentials in settings
Three new application settings store the Propello connection: PropelloUrl (normalized https tenant URL), PropelloUsername, and PropelloPassword (DPAPI-encrypted per machine). The password is excluded from the settings-transfer delete-on-default list so it always persists, and all three are backed up to the cloud after a successful test.
-
Architecture
Added BuiltMainTables flag to POS import handlers
Introduced a new property on the POS import handler interface that allows handlers to signal whether they built the per-store main tables during the ingest phase. This flag is now passed from the handler through the Import Manager to the main import process, ensuring the rebuild step has accurate information about what work has already been completed. Added comprehensive unit tests to prevent future regressions by ensuring this flag travels the correct path through the application.
-
Architecture
GetSpecificRSCResponse simplified to resolved/not-resolved
GetSpecificRSCResponse now carries RequiresRsc, MappedRsc, and IsResolved properties instead of fallback tracking (UsedFallback, FallbackSource). The ResolveEffectiveRsc ladder method and its tests are deleted—there is no longer any RSC borrowing logic.
-
Infrastructure
Added test coverage to prevent flag-reading regression
Introduced comprehensive unit tests (PosIngestBuiltMainTablesFlagTests) that enforce the correct path for the "main tables built during import" flag. These tests verify that MainMMViewModel never reads the flag from its own service instance, that ImportFilesViewModel correctly retrieves it from the handler, and that all BisTrack handlers properly report whether they built the tables. This prevents future regressions of the quadruplication bug.
-
Infrastructure
MarginMaster.Propello library integration
The MarginMaster.Propello library (sibling repo, cloned by publish.yml next to FileHelpers.Core) is referenced as a ProjectReference and wrapped behind one interface (Services/Propello/IPropelloConnectionService implemented by PropelloConnectionService). No other Margin Master file sees the library namespace — all consumers (ViewModels, tests) talk in library-free DTOs (PropelloConnectionSettings, PropelloProgressInfo, PropelloTestResult, PropelloDownloadResult, PropelloPushOutcome, PropelloUserError). The pure helpers (PropelloUrlNormalizer, PropelloUserMessages, PropelloSplashProgress, PropelloPriceChangeBuilder) are unit-tested in MarginMaster.Tests/Propello/PropelloIntegrationTests.cs (34 tests) without needing a live Propello tenant. Credentials are backed up to api/pos/credentials (new PosCredentialDescriptor.ForPropello, AuthMode=Web) and reported after each import like the other POS types. Documentation added: propello.md, import-propello.md, index.json, version-map.json, CLAUDE.md updates.
-
Infrastructure
Test coverage for header alias resolution
Added PropelloHeaderAliasTests validating that the 240-column API export header row resolves correctly, that hand-exported headers remain unchanged, and that alias matching is case-insensitive. Added integration test ensuring the progress message formatting handles library-appended elapsed time correctly.
-
Infrastructure
Propello library integration
A new sibling library (MarginMaster.Propello) handles all direct interaction with the Epicor Retail Cloud portal: login, saved-view creation, report export download, Price Review status checks, and price-change upload. The library is referenced only by PropelloConnectionService; the rest of the application (ViewModels, tests) works with library-free DTOs, keeping the portal-specific logic isolated and unit-testable.
Cloud Sync & Vendor Data
-
Improvement
Auto-load Propello credentials from cloud
If you install Margin Master on a new computer, your Propello connection settings will be automatically filled in from your cloud-saved configuration. You'll see a message showing when the connection was last validated, and you just need to click "Save & Test" to confirm it still works.
User Interface
-
Improvement
Propello setup shortcut
When setting up Propello for the first time, clicking "Yes" on the connection prompt will now take you directly to the Propello settings tab instead of making you find it yourself.
-
Improvement
Clearer URL placeholder text
The Propello URL field now shows a clearer example of what to type.
-
Improvement
Repositioned permissions reminder
The message about contacting your Propello administrator for permissions issues was moved from the static help text to an italicized note at the bottom of the contextual help panel, making it visible regardless of which field is focused.
-
User Interface
Dynamic help panel in Propello settings
When setting up your Propello connection, click into any field to see specific instructions about what to enter there. The help panel on the right updates automatically to guide you through each step.
-
User Interface
Legal document menu added
Click Help > Legal to open any of the three legal documents in your web browser.
-
User Interface
Legal submenu added to Help menu
The Help menu now includes a Legal submenu where you can view the End User License Agreement, Privacy Policy, and Terms of Use by clicking on any of these options.
-
Infrastructure
License file updated to proprietary terms
Replaced the placeholder MIT license template in LICENSE.txt with the actual proprietary licensing terms. The file now clearly states that Margin Master is licensed software (not sold), references the online EULA, and notes that vendor data is confidential proprietary information that may not be disclosed or duplicated except as permitted by the EULA.
-
Infrastructure
License file updated to reflect proprietary licensing
The LICENSE.txt file has been replaced with a proprietary license notice indicating that Margin Master is licensed software owned by RetailerSoft, Inc. The file now references the EULA and related policies available at marginmaster.com, establishing the website as the authoritative source for license terms.
Performance & Reliability
-
New Feature
Damaged .NET runtime detection at startup
When you open Margin Master, if Windows runtime files are missing (often due to antivirus quarantine or a failed Windows update), you'll see a dialog listing exactly what's missing with a button to repair it automatically.
-
New Feature
Automatic damaged-runtime detection at startup
On launch, Margin Master now checks that all the Windows system files it needs are intact. If something is missing, you'll see a clear message explaining what's wrong instead of cryptic errors later.
-
New Feature
Red ".NET Runtime Damaged" title-bar pill
A red warning badge stays in the title bar until the runtime is actually fixed — you can't accidentally dismiss it and forget about it.
-
New Feature
One-click runtime repair from dialog and title-bar pill
When Margin Master finds a problem with the Windows runtime, a red warning appears in the title bar. Click it to run an automatic repair — Windows will ask for permission, then the script downloads and fixes the issue. The warning disappears once the repair finishes.
-
Improvement
Enhanced version gate safety handling
Improved the version gate logic to treat declining as an expected, safe user choice rather than an error condition. The application now properly cleans up and hides the loading splash screen when users choose not to proceed with opening a newer database.
-
Improvement
Cloud sync failure now offers runtime repair when applicable
If cloud sync keeps failing with every table erroring out, Margin Master now checks whether a Windows runtime file is missing and walks you through the repair instead of just saying "check the log."
-
Improvement
Enhanced Install-DotNetRuntime.ps1 script with integrity check and repair mode
The "Install .NET Runtime" support script is now smarter — it checks what files are missing, repairs the existing installation if it's up-to-date, or installs a newer version if available, then verifies the fix worked.
-
Improvement
Global exception handlers offer runtime repair
If Margin Master crashes with a missing-file error while you're working, it now recognizes when the problem is a damaged Windows runtime and offers the repair tool rather than a cryptic error message.
-
Improvement
Install-DotNetRuntime.ps1 now repairs the current runtime
The repair script now checks your installed runtime first and tells you exactly which files are missing, then either installs a newer version or repairs the current one, and re-checks afterward to confirm the fix worked.
-
Bug Fix
Version gate decline no longer crashes application
If you see a warning that a database was created by a newer version of Margin Master and click "No," the app will now stay open normally instead of crashing.
-
Bug Fix
Application crash when declining version gate prompt
If you're asked whether to open a database file from a newer version of Margin Master and click "No," the app will now continue running normally instead of crashing.
-
Cloud Sync
Detect damaged runtime during sync and offer immediate repair
If a cloud sync fails because Windows system files are missing, Margin Master now tells you exactly that and offers the repair button on the spot — no need to restart the app or contact support to figure out what's wrong.
-
User Interface
Global exception handlers detect runtime damage and surface repair dialog
Even if an unexpected error happens elsewhere in the app due to missing Windows files, Margin Master now recognizes the signature and shows the repair dialog instead of a confusing crash message.
-
Database
Enhanced documentation and search keywords for runtime repair
The support script's documentation (`docs/marginmaster/support/scripts/install-dotnet-runtime.md` and the script's own `.md`) now explains the repair workflow, the startup check, and the title-bar pill. New search keywords: "repair dotnet", "runtime damaged", "missing assembly", "System.Threading.Tasks.Parallel", "vcruntime140_cor3", "corrupt runtime". The troubleshooting section covers what to do when antivirus keeps re-quarantining the file.
-
Architecture
FrameworkIntegrity detection shared across app layers
The missing-assembly detector moved from RowVersionTableSync (CloudSync layer) to a new FrameworkIntegrity class in Common, now shared by the WPF app's startup check, sync error handler, and global exception handlers. It walks the exception chain for FileNotFoundException, BadImageFormatException, and DllNotFoundException, filters to System.* / Microsoft.* assemblies and known shared-framework native libs (vcruntime140_cor3.dll, etc.), and provides a CheckCurrentRuntime() method that reads the process's own NETCore.App + WindowsDesktop.App deps.json manifests and stats every declared runtime/native file. RuntimeRepairService in the WPF layer orchestrates the UI (one dialog, one script runner, one main-window pill) for all detection sites.
-
Infrastructure
Centralized runtime-integrity logic in FrameworkIntegrity helper
A new `FrameworkIntegrity` class provides pure, testable functions for reading `.deps.json` manifests, checking files on disk, and detecting framework-load exceptions. The bulk-upsert engine's existing `FindMissingFrameworkAssembly` logic was moved here and extended to handle `DllNotFoundException` for native libraries (`vcruntime140_cor3.dll`). Detection now covers managed assemblies, native DLLs, and both the `Microsoft.NETCore.App` and `Microsoft.WindowsDesktop.App` shared frameworks.
Infrastructure & Internal
-
New Feature
Automated documentation screenshot generation
No direct user impact—this is an internal documentation tool.
-
New Feature
Automated screenshot generation for documentation
A new `--screenshot --manifest=<file>` launch mode starts Margin Master like a headless run (no mutex, no startup dialogs), shows the main window at a manifest-specified size on a pinned theme, opens each listed dialog or menu through view-model commands, captures it as a PNG, and exits. Manifests live in `docs/<category>/screenshots/` beside each doc and specify which screens to open (main window, Options tabs, Print dialog, effective-date picker, or drop-down menus), optional view-model method invocations, property overrides to hide real store identifiers, and crop rectangles. A PowerShell runbook (`Update-DocScreenshots.ps1`) builds Debug and runs the capture against a test database. Screenshots are deterministic across machines (visual captures render at a pinned DPI), version-controlled, and served by Manager for web/PDF/Word rendering.
-
New Feature
Automated screenshots for Getting Started documentation
Documentation pages now include actual screenshots from Margin Master showing exactly where to find features and buttons, with numbered callouts matching the text.
-
Improvement
Propello integration guide restructured with screenshots
The Propello guide is now easier to follow with screenshots showing each step of setting up the connection, importing your data, and sending prices back to Propello.
-
Improvement
Screenshot harness supports command invocation and highlights
Extended the screenshot manifest to support `command` targets (invoking any public MainMMViewModel method), highlight annotations with optional numbered badge labels (red rounded outlines that draw attention to specific fields), automatic prompt dismissal during dialog closure, and settle delays for windows that load asynchronously. Commands can run to completion for setup steps (e.g., refreshing the grid so later dialogs have data) or capture the dialog they open.
-
Improvement
Propello guide restructured with screenshots
The Propello setup guide now has pictures showing exactly where to enter your Propello URL, username, and password, and where to click to import your data and send price changes back.
-
Bug Fix
DIB member-retail error message corrected
The error message when a DIB price file is missing now correctly refers to DIB files instead of Propello.
-
Bug Fix
Corrected error message for missing DIB member retail file
The "No DIB Price File Files Found" message now correctly reads "No DIB Price File (mbrxxxx.csv) Found" and instructs users to place "the DIB Member Retail Price File" in the import directory (was "Propello Export File").
-
User Interface
Database and support documentation screenshots
Added automated screenshots to seven documentation guides: SQL Optimization (Help menu, Database Utilities menu, Missing Index Recommendations window, Maintenance Scripts dialog), Resetting Data (Utilities menu), System Diagnostics window, Issue Submission (Help menu, Support Issues window, Contact step), and SQL Server Tools window. Menu paths corrected throughout documentation to reflect actual application structure (e.g., maintenance scripts live under File > Database > Utilities, not Help > Database Utilities).
-
User Interface
Screenshot mode suppresses startup prompts and auto-update
When `ScreenshotMode.IsActive` is true (set during screenshot startup), the What's New dialog, data-aging view, database rename prompt, and auto-update check are all suppressed so nothing modal lands on top of a capture. Startup checks still run to ensure a valid database and schema, but every dialog is headless-suppressed.
-
User Interface
Ace Hardware pricing feature screenshots
Replaced six placeholder SVG images in the MAP/IMAP pricing guide with real screenshots showing MAP Price and IMAP Price columns in the data grid (overview and close-up), Future Price panel with Ace MAP Price Amount selected, and the Data menu with "Update Ace Hardware Data" highlighted. Added screenshots to the Critical Retail Pricing guide showing the Strategy menu and configuration dialog with price mode toggle and comparison operators highlighted.
-
User Interface
Documentation images with numbered callouts and flexible layouts
Help documentation now shows zoomed-in screenshots of specific buttons and fields right next to the text explaining them, with numbered circles matching numbered instructions.
-
Infrastructure
Pricing documentation screenshots
Added 19 generated screenshots to 14 Pricing docs covering strategy manager, premade-strategy catalog, rounding editor and scheme check, custom groups, SKU exceptions, min/max strategies, cost breaks, Profit Analyzer, One Click Statistics, all three Future Price tabs, backup/restore pickers, wildcard selection, and lock column. Each screenshot is automatically captured from the running application using manifest files that script the UI, ensuring documentation stays current with the software.
-
Infrastructure
Screenshot harness enhancements
Extended the automated screenshot system to support nested dialogs (a shot that invokes a method opening a further dialog now captures that nested window with `opensDialog: true`), dotted property paths for setting view model state (`"FuturePricePanel.SelectedTabIndexFuturePriceRounding": "1"` navigates child view models), screen-level `set` executed before opening dialogs, and per-shot `settleMs` delays for asynchronous content. Automatic strategy backup is now suppressed during screenshot runs to avoid uploading demo-store data to the cloud.
-
Infrastructure
Documentation maintenance
Updated 14 pricing documentation files with embedded screenshots, numbered highlight badges linking images to text legends, and metadata refresh. The `docs/index.json` search index and `CHANGELOG.md` now reflect the new screenshots. This builds on the Getting Started screenshot work from the previous release.
-
Infrastructure
Screenshot harness supports nested menu navigation
Enhanced the screenshot automation system to accept nested menu paths using slash notation (e.g., "mnuFile/mnuDatabaseManagement/mnuDatabaseUtiltities"). The harness now opens each menu level sequentially and properly closes them in reverse order, enabling automated capture of deeply nested menu structures.
-
Infrastructure
Screenshot manifest and conventions
Documentation screenshots are defined in JSON manifests committed alongside docs (e.g., docs/marginmaster/pos-systems/screenshots/propello.manifest.json). Each manifest specifies window size, render scale, screens to open (main, options tabs, dialogs, menus), view-model methods to invoke, placeholder property values (to avoid showing real store identifiers), and crop rectangles. Output must be a .png inside a screenshots/ folder—the runner refuses to write anywhere else. Conventions and technical details added to docs/CLAUDE.md.
-
Infrastructure
Screenshot manifest format and safety rules
Screenshot manifests are JSON files specifying window size, render scale, and a list of screens (each naming a target: `main`, `options` + tab name, `print`, `effective-date`, or `menu` + BarSubItem name). Shots can invoke public view-model methods (e.g. `ShowFieldHelp`), set properties (to show placeholders instead of real store identifiers), and crop. The runner refuses to write any file that is not a `.png` inside a folder named `screenshots`, preventing accidental overwrites elsewhere. Tests enforce this rule and validate manifests against incomplete or unsafe configurations.
-
Infrastructure
Screenshot manifest validation and annotation rendering
Manifest validation ensures command targets name a method, highlights have positive dimensions and valid hex colors, and setup-only commands (those that run to completion without opening a dialog) are allowed to have zero shots. Visual and screen-mode captures both render highlights with anti-aliased outlines, badge circles, and centered bold labels over the captured pixels before applying crop.
-
Infrastructure
Documentation index and version tracking updated
Updated docs/index.json with new Propello guide structure (headings, body excerpt, keywords including "import propello data", "restore from cloud", "options"), docs/version-map.json source file tracking, and docs/CHANGELOG.md entry. Documentation last-updated dates refreshed to 2026-08-27.
Automatic first-run vendor data download; Automatic first-run vendor data download; Added timeout protection for database connection loading.
Imports & POS
-
Bug Fix
Store identifier corruption during legacy upgrade
Your store number will now be recognized correctly after upgrading from an older version.
-
Bug Fix
Legacy Compass data migration failure on new databases
If you had multiple stores using Compass with older Margin Master versions, your historical per-store inventory data will now properly migrate to the new unified format even on first-time database upgrades.
-
Bug Fix
Legacy MySQL/Compass stores now preserve POS data during upgrade
If you're upgrading from an older version with MySQL/Compass, your pricing data will now appear in the grid immediately after the upgrade instead of showing an empty table.
-
Bug Fix
Empty main table after MySQL/Compass upgrade
After upgrading, all your existing item data will now appear in the pricing grid immediately instead of showing an empty table.
-
Bug Fix
Corrected migration sequence to prevent storematchup corruption
Fixed the order of migration steps so that legacy store-number normalization runs before the storematchup table is read. Previously, a legacy 3.9.x store number stored as the raw POS character (e.g., "1") would be misinterpreted as ordinal 1 instead of the correct ASCII value 49, creating incorrect storematchup entries that would never match Compass data. This sequencing fix prevents the corruption from occurring during the upgrade.
Cloud Sync & Vendor Data
-
Improvement
Automatic first-run vendor data download
On first launch or after a database upgrade, vendor catalog data now downloads automatically in the background. You'll see a status message on the splash screen but won't need to click Yes to continue.
-
Improvement
Automatic first-run vendor data download
When you first install Margin Master or reset your database, the vendor catalog will download automatically during startup instead of asking you to confirm. The splash screen will show "No [Vendor] data found — updating your vendor data now…" while the download completes.
-
Bug Fix
Main table now rebuilds after automatic vendor download
After the first-time vendor data download, your pricing grid will now show up-to-date costs and retail prices immediately instead of stale data.
-
User Interface
Updated splash screen messaging
The startup screen now shows a clearer message explaining that your vendor catalog is being downloaded automatically.
User Interface
-
User Interface
Incremental search for Store Information dropdowns
When selecting your Primary Vendor, RSC, or POS System in Settings, you can now type the first letter (like "O" for Orgill) to jump directly to that option instead of clicking through the entire list.
Performance & Reliability
-
Improvement
Added timeout protection for database connection loading
Synchronous database connection loads on the UI thread now have a 10-second timeout limit. If the load lock cannot be acquired within this window, the system logs a warning and proceeds with loading to avoid UI stalls. This provides a safety mechanism against potential threading issues while maintaining normal fast-path performance.
-
Improvement
Background feature check handles database transitions gracefully
The application will no longer crash with "Invalid object name" errors when switching between databases or during restore operations.
-
Improvement
Background feature flag reads gracefully handle database transitions
Added error handling to the background feature flag check that runs on a timer from the UI thread. During database restore or switching operations, settings reads can temporarily fail while the database is in transition. The flag now safely degrades to "disabled" rather than surfacing as an unhandled exception, preventing potential UI crashes during restore operations.
-
Improvement
Skip redundant maintenance after first-run vendor sync
When the application performs a first-run vendor sync (automatically downloading vendor catalogs for an empty database), it now skips the subsequent shrink and index rebuild maintenance since those tables were just freshly created. This optimization reduces startup time on the slowest launch scenario a customer experiences—the very first time opening a new database.
-
Improvement
Optimized first-run startup performance
When the first-run vendor sync rebuilds all main tables during startup, deferred database maintenance (shrink and index rebuild) is now skipped since those tables were just rebuilt seconds ago. This eliminates wasted time on the slowest launch customers experience. The once-a-day maintenance gate will run it on the next startup.
-
Improvement
Strategy loading completes before maintenance status updates
The pricing strategy loader now completes before database maintenance begins, preventing the "Shrinking database..." status message from being immediately overwritten by "Strategy loading completed." This provides clearer feedback about what operations are taking longer during startup.
-
Improvement
Database maintenance no longer overwrites strategy loader status
The strategy loader now completes before deferred maintenance begins, preventing multi-minute "Shrinking database..." status messages from being immediately overwritten by "Strategy loading completed" messages.
-
Bug Fix
Eliminated deadlock during restore-from-backup operations
The application will no longer freeze on the "Calculating Rounding Points" screen when restoring a database backup. The restore process now completes smoothly without requiring the application to be force-closed.
-
Bug Fix
Eliminated deadlock during restore-from-backup operations
Restore-from-backup operations will no longer cause the application to freeze or hang when reconnecting to the database.
-
Bug Fix
Database connection pool cleared after restore
After restoring a backup, the application will now properly reconnect to the database instead of showing login errors or configuration screens.
-
Bug Fix
Connection pool cleared after database restore
Database restore operations now complete cleanly without triggering unexpected errors or configuration screens.
-
Bug Fix
Database readiness checks now block main screen display
When opening Margin Master or switching databases, you'll now see a "Bringing this database up to date" message while necessary updates complete, instead of seeing an empty pricing grid that fills in later.
-
Bug Fix
Database ready checks now run before selection panel loads
When opening Margin Master or switching databases, the pricing grid will now wait to appear until all necessary data is ready, eliminating the brief "No Items Found" message that previously appeared while vendor catalogs were being loaded.
-
Bug Fix
Database readiness check now verifies restored database
The "Waiting for database to be ready" step after a restore now accurately reflects when the database is actually accepting connections.
-
Bug Fix
Database readiness check now validates restored database
The restore process now waits for the database to be fully ready before continuing, preventing connection errors.
-
Bug Fix
Database switch now properly migrates legacy databases
The StoreManagerInfo migration (converting legacy per-store POS mapping to the unified table) only ran during cold startup, meaning switching to a legacy database via the watcher or menu never converted it. This migration now runs through RunDatabaseReadyChecksAsync, which both startup and ReinitializeForDatabaseChangeAsync reach, so a switch to a legacy database converts exactly like a cold start.
-
Bug Fix
Database maintenance no longer interferes with database switching
Fixed an issue where database maintenance operations (index rebuilds and shrinking) started on one database could continue running against a different database after switching. The application now waits for any in-flight maintenance to complete before switching databases, preventing maintenance commands from landing on the wrong database. Wait time is bounded by the shrink operation's 600-second timeout.
-
Bug Fix
Prevented database maintenance from affecting wrong database during switch
Database maintenance (shrink and index rebuild) could start on one database and finish its index pass on the next database after a switch, because the task ran asynchronously without tracking. The maintenance task is now stored in _deferredMaintenanceTask, and ReinitializeForDatabaseChangeAsync waits for it to complete with a "Waiting for database maintenance to finish..." message before switching databases.
-
Architecture
Improved async/await patterns in database connection service
Added ConfigureAwait(false) to all async operations in the database connection service to prevent unnecessary context switching and reduce the risk of dispatcher-related deadlocks. This follows best practices for library-style code that doesn't require UI thread affinity.
-
Infrastructure
Added defensive timeout for database connection loading
Implemented a 10-second maximum wait time for synchronous database connection loads. If the lock cannot be acquired within this timeframe, the system logs a warning and falls back to a direct load operation. This ensures that any future regression degrades gracefully to a logged warning rather than a frozen application.
Infrastructure & Internal
-
Bug Fix
Replaced blocking re-import dialog with callback to prevent service hangs
If you leave an Epicor import paused overnight and the system runs an automated import, the system will now download fresh data instead of potentially freezing.
-
Architecture
Epicor FTP extractor moved to DataImport library
The EpicorFTPFileExtractorService has been relocated to the MarginMaster.DataImport library as part of ongoing modularization. The service now uses interfaces (IImportDatabaseService, IApplicationSettingsService) instead of concrete dependencies, enabling better separation and reuse across different host applications including the WPF desktop app, background services, and diagnostic tools.
-
Infrastructure
DatabaseService now directly implements import interface
DatabaseService now implements IImportDatabaseService directly through explicit interface members (DatabaseService.ImportSeam.cs), allowing DataImport-side services to accept the interface while WPF callers continue passing DatabaseService unchanged. The existing adapter remains for dependency injection scenarios. This eliminates an unnecessary wrapper layer while maintaining compatibility.
-
Infrastructure
Supporting utilities moved to Common library
MessageRotator and SqlTransientRetry (now public) have been moved to MarginMaster.Common along with their tests, making them available to the DataImport library and other components. StoreManagerInfoWriter and EpicorConnectionFailureMessage were moved to DataImport as they're required by the Epicor extractor service.
Resumable upload protocol for support issue attachments; Resumable block-based attachment uploads; Strategy restore now reports what was actually restored.
Strategy & Pricing
-
Improvement
Strategy restore now reports what was actually restored
After restoring a strategy backup, the completion message now tells you exactly what came back—such as "Restored 11 rule steps, 3 custom groups, and 53 SKU exceptions for: 05598-PS_imported." If no rules were restored, you'll see a warning explaining why and what to check.
-
Improvement
Strategy execution summary explains when no prices changed
If you run a strategy and no prices change, the summary now explains why—such as "The active strategy 'DEFAULT' has 1 rule(s), but none of them matched any item. Another strategy in this database does have rules: '05598-PS_imported'. If that is the one you meant to run, select it in the strategy list first."
-
Improvement
Strategy execution summary displays empty run warnings
The strategy execution summary now highlights when no prices were changed and suggests which strategy you should use instead.
-
Bug Fix
Strategy restore now reports actual results instead of file contents
When you restore a strategy backup, Margin Master now tells you exactly how many rules, custom groups, and exceptions were actually restored, and warns you clearly if nothing was brought back.
-
Bug Fix
Empty strategy runs now provide actionable guidance
If you run a pricing strategy that changes nothing, Margin Master now explains why and tells you which other strategy contains your actual rules, turning a support call into a two-click fix.
-
Bug Fix
Prevented duplicate GlobalFileConfig rows on repeated restores
Restoring the same backup file multiple times no longer creates duplicate copies of your pricing rules and settings.
-
Bug Fix
Restoring the same backup file multiple times no longer duplicates strategy rules
Restoring the same strategy backup multiple times now works correctly—it won't create duplicate copies of your strategy rules.
-
User Interface
Strategy execution summary screen shows "No prices changed" notice
The summary screen after running a strategy now includes a warning section at the top if no prices were changed, explaining why and what to do next.
-
Infrastructure
Consolidated strategy restore completion messages
Unified three copy-pasted completion message blocks (local file restore, cloud restore, legacy file restore) into a single ShowStrategyRestoreCompleteMessage method that cannot drift apart. All three entry points now use the same logic to report what was actually restored.
-
Infrastructure
Strategy restore result tracking
Introduced BackupRestoreResult model to capture what a restore operation actually wrote (strategies, steps, groups, exceptions) rather than inferring success from the backup file's contents. All restore code paths (local file, cloud, legacy formats) now return this detailed result, enabling accurate user-facing reporting regardless of which options were selected or which per-strategy skip logic applied.
-
Infrastructure
Empty strategy run notice helper
Added EmptyStrategyRunNotice helper class to generate consistent user-facing explanations for strategy runs that changed no prices. The helper queries for other strategies with rules and produces messages like "The active strategy 'DEFAULT' contains no pricing rules. Another strategy in this database does have rules: '05598-PS_imported'. If that is the one you meant to run, select it in the strategy list first."
Performance & Reliability
-
Improvement
TypeMismatch differences now track nullability
The TypeMismatch schema difference now records ModelIsNullable and DatabaseIsNullable fields, matching the pattern already used by NullabilityMismatch. When model nullability is unknown, the generator falls back to the database's current nullability to make the ALTER statement nullability-neutral, and only when both are unknown does it choose the non-destructive NULL direction. This ensures that "unknown" never means "tighten."
-
Improvement
NULL scrub uses current column type, not model type
When tightening a nullable column to NOT NULL, the generated UPDATE statement that clears existing NULLs now uses a default literal appropriate for the column's current type rather than the model's target type. The scrub runs before the ALTER COLUMN executes, so writing an empty string into an int column would have been silently converted to 0 rather than the intended empty value. A new SchemaColumnSql helper class centralizes this logic for both TypeMismatch and NullabilityMismatch scenarios.
-
Improvement
Database migration version now advances correctly
The application will start faster since database schema commands only run once instead of repeating on every launch.
-
Improvement
Enhanced schema command validation
Extended the schema update validation logic to recognize both ALTER TABLE and UPDATE commands when determining if they target a view. Previously, only ALTER TABLE commands were checked, allowing NULL-scrub UPDATE statements to fail repeatedly. The validation now correctly identifies all commands that target table-like objects and verifies their applicability.
-
Improvement
Self-healing for previously tightened columns
Columns that were incorrectly tightened to NOT NULL by previous versions will automatically heal on the next startup. With ModelIsNullable now properly populated, the comparer detects model-nullable-vs-database-NOT-NULL as a NullabilityMismatch and generates the corrective ALTER COLUMN NULL statement.
-
Bug Fix
Schema comparer forced NOT NULL on all type changes
Fixed a database schema issue that could cause startup errors or prevent certain fields from accepting empty values.
-
Bug Fix
Schema migration nullability handling corrected
Database updates will no longer fail when column types need to change, preventing startup errors that previously blocked the application from running.
-
Bug Fix
Schema migration now skips UPDATE commands targeting views
Database updates no longer fail repeatedly at startup when vendor data views are present in the database.
-
Bug Fix
Schema updates now successfully add NOT NULL columns to populated tables
Database schema updates that previously failed repeatedly during startup will now complete successfully.
-
Bug Fix
NULL value scrubbing during column tightening
When the database schema needs to change a column from optional to required, existing empty values are automatically filled in so the update can complete successfully.
-
Bug Fix
Fixed error adding non-nullable columns to populated tables
New database columns are now added successfully even when your database contains existing transaction data.
-
Bug Fix
Schema commands no longer attempt to modify database views
Startup diagnostic logs will no longer show repeated schema update failures for vendor data tables.
-
Bug Fix
Type change literal uses current column type
NULL scrub statements now use the column's existing database type to generate the replacement literal, rather than the model's target type. This prevents silent type conversions where writing an empty string into an integer column would be converted to 0 instead of the intended empty value.
-
Architecture
Centralized column SQL generation
Extracted nullability clause and NULL scrubbing logic into a new SchemaColumnSql helper class with comprehensive unit tests (130 lines of test coverage). Both the TypeMismatch and NullabilityMismatch code paths now use the same tested logic, ensuring consistent handling. Unknown nullability now falls back to the database's current state rather than incorrectly defaulting to NOT NULL.
-
Infrastructure
Added comprehensive schema SQL generation tests
Added 27 new unit tests in SchemaColumnSqlTests covering nullability clause generation, NULL scrubbing logic, default literal selection for all SQL types, and edge cases like unknown nullability states. Full test suite now has 1,871 passing tests.
Infrastructure & Internal
-
New Feature
Resumable upload protocol for support issue attachments
Implemented a complete resumable upload system that breaks large files into 8 MB blocks and tracks which blocks have already been uploaded to Azure. When a connection drops mid-upload, the next attempt scans Azure to identify which blocks are already staged and only sends the missing ones. Azure retains uncommitted blocks for seven days, allowing uploads to resume even after connection failures. The system uses deterministic block IDs based on file offset and upload tag to ensure blocks from different attempts of the same file can be correctly matched and assembled.
-
New Feature
Resumable block-based attachment uploads
When attaching large files to support tickets (especially database backups that can take hours), if the upload is interrupted you can simply retry and it will pick up where it left off instead of starting from zero.
-
Improvement
Smart credential renewal during long uploads
Long-running uploads now proactively renew their Azure credentials before they expire, using the server's clock to measure and compensate for clock skew on the store PC. The refresh buffer is now proportional to upload duration rather than a fixed five minutes, preventing uploads from failing halfway through with expired credentials. When Azure refuses a credential, the cached token is immediately invalidated so retries fetch a fresh one instead of reusing a poisoned entry.
-
Improvement
Intelligent retry logic for transient Azure failures
Upload failures are now classified into credential issues (403, authentication errors), transient conditions (timeouts, 429, 5xx errors), and fatal errors (invalid requests, missing containers). Transient failures retry automatically with exponential backoff and jitter to prevent concurrent blocks from retrying simultaneously. Credential issues trigger automatic SAS token renewal. Fatal errors stop immediately with clear error messages rather than wasting time on futile retries.
-
Improvement
Enhanced upload progress reporting with resume indicators
The upload status now shows transfer rate, time remaining, and—most importantly—how many bytes were resumed from a previous attempt. Database backup uploads display human-readable progress ("4.5 MB/s - 38 min left - 500 MB already uploaded") instead of just a percentage, giving users meaningful feedback during multi-hour transfers.
-
Improvement
Enhanced upload progress reporting with resume metrics
Upload status now shows transfer speed, time remaining, and how much data was already uploaded when resuming an interrupted upload.
-
Improvement
Intelligent retry policy with exponential backoff
Failed blocks are now retried up to eight times with exponential backoff and jitter (starting at 2 seconds, capped at 60 seconds). The system distinguishes between transient failures (network timeouts, server errors) that warrant retry, credential problems that need a fresh token, and fatal errors (missing container, invalid request) that should stop immediately. This prevents wasting time on hopeless retries while recovering from temporary connection issues.
-
Improvement
Server clock skew compensation for SAS token expiration
The client now learns the server's clock time with each SAS token response and calculates local clock skew. This prevents store PCs with incorrect clocks from treating valid tokens as expired (if running fast) or continuing to use expired tokens (if running slow). SAS tokens are also refreshed proactively based on expected upload duration rather than waiting for a 403 response mid-upload.
-
Improvement
Upload slot persistence across retry attempts
Each resumable upload opens a server-managed slot that assigns a unique blob name and block ID format. The slot is cached by issue ID, file path, file size, and last-modified timestamp. Retrying the same file reuses its slot (enabling resume), while a recreated database backup at the same path correctly gets a fresh slot to prevent assembling mismatched blocks.
-
Improvement
Extended blob client network timeouts
Azure SDK blob client network timeout increased from the default 100 seconds to 10 minutes, with exponential retry configured. This prevents legitimate slow transfers on store uplinks from timing out prematurely, especially for 8 MB blocks on connections with intermittent packet loss.
-
Improvement
Upload slot fallback logic for older servers
The uploader now explicitly checks whether the server supports resumable uploads (via 404/405 responses) before falling back to the legacy direct-upload path. When a server understands the slot request but declines it (e.g., file over size limit, expired token), the real error message is preserved instead of being replaced by a different error from the fallback path. This fixes cases where a 466 MB backup was reported as "over the 128 MB limit" when the actual problem was an expired credential.
-
Improvement
Graceful fallback for legacy API servers
New upload slot endpoint requests are classified by UploadPathDecider: 404/405 responses fall back to the legacy upload-target path (non-resumable but functional), while understood refusals (expired token, file too large, missing issue) report their actual error rather than silently switching paths. This prevents MM-492-style misdiagnosis where an authorization failure on the resumable path fell through to a different path whose unrelated size limit complaint became the user-facing message.
-
Bug Fix
Corrupted backup uploads from short reads
Fixed a critical bug in AzureBlobService where short file reads would stage blocks padded with trailing zeros, producing database backups that were the correct length but silently corrupt—invisible until someone tried to restore them. The uploader now stages only the exact bytes returned by each read operation.
-
Bug Fix
Incorrect progress bar calculations
Fixed progress calculations that truncated instead of rounding up block counts, causing progress bars and ETAs to run against a denominator that was one too small. Also fixed SupportIssuesViewModel showing percentages calculated from file counts instead of bytes, driving the progress bar to 2500% when uploading two files.
-
Bug Fix
SAS token cache invalidation on credential refusal
Added InvalidateToken method to IBlobAccessService. When Azure refuses a credential, the cached token is immediately evicted so the next request mints a fresh one. Previously a poisoned cache entry would remain until it expired naturally, causing every retry to fail identically until the expiration window passed.
-
User Interface
Support Tools screen attachment upload status
The Submit Issue dialog now displays detailed upload progress including phase name, transfer rate, estimated time remaining, and resumed byte count during attachment uploads. The status text adapts to each phase (Preparing, Scanning, Staging, Committing, Verifying, Registering) rather than showing a percentage alone during non-transfer phases.
-
Architecture
New blob upload service abstractions
Introduced IResumableBlobUploader interface and ResumableBlobUploader implementation in MarginMaster.Common with supporting types: BlobUploadProgress, BlobUploadOutcome, BlobUploadPhase, BlobUploadFailureKind, ResumableUploadRequest, BlobSasLease, ResumableBlockPlan, BlobRetryPolicy, and UploadPathDecider. These enable testable, pure functions for planning, retry decisions, and outcome classification separate from I/O concerns.
-
Infrastructure
Comprehensive test coverage for upload protocol
Added five test suites (2,614 lines total) covering retry classification, block ID agreement with the server, resume reconciliation, progress adaptation, and upload path decisions. The block ID tests use golden vectors copied verbatim from the server's own tests, ensuring the client and server implementations stay synchronized—critical because a disagreement silently commits blobs assembled from mismatched blocks.
-
Infrastructure
Comprehensive retry policy and block plan test coverage
Added extensive unit tests pinning retry classification logic, exponential backoff calculations with jitter, block ID format agreement with server (golden vectors), block plan arithmetic, resume reconciliation, upload slot identity rules, and progress adapter behavior. These tests prevent silent correctness regressions that would corrupt uploaded blobs by assembling mismatched blocks.
-
Infrastructure
Configurable Azure SDK timeouts and retry behavior
Configured BlobClientOptions throughout the application for the first time—previously every blob operation ran on the SDK's default 100-second network timeout. Network timeout is now 10 minutes with exponential retry (3 attempts, 2-30 second backoff), appropriate for large blocks on slow or intermittent store uplinks.
Blob name returned for partial upload failures; Reduced error logging noise from label printing; Enhanced diagnostic accuracy for import troubleshooting.
Imports & POS
-
Improvement
Enhanced diagnostic accuracy for import troubleshooting
The Import Manager now better distinguishes between different types of database errors during vendor data updates. Previously, both permanent structural errors (like missing columns or tables) and exhausted retry attempts were reported identically, making troubleshooting difficult. Error messages now acknowledge that the detailed cause has already been logged and direct support teams to the correct log entry rather than suggesting an incorrect root cause.
-
Bug Fix
Corrected misleading error messages during vendor data import failures
When a vendor data update failed during import, the error message incorrectly claimed "Retrying did not resolve the timeout" even when the actual problem was a structural SQL error (such as a missing table) that was never retried. The system now accurately reports the failure and directs users to check the log for the specific cause. This corrects misdiagnosis issues encountered at stores 3174 and 3875, where investigators were looking for non-existent timeout problems when the real issue was SQL errors like missing database tables.
Performance & Reliability
-
Improvement
Reduced error logging noise from label printing
The previous implementation caused a single bug to generate 78 of 84 distinct error groups in seven days because each SKU produced its own error signature. By using a parameterized query with constant SQL text, all errors now collapse into a single fingerprint, dramatically reducing log noise and making real issues easier to identify.
-
Improvement
Orphan detection runs on every startup
Even if your store was renumbered in the past, the system will detect and fix any mismatched table names the next time Margin Master starts.
-
Improvement
Automatic orphan detection runs on every sync
The orphaned table check now runs on every single-store sync pass rather than only when a renumber occurs. This ensures databases where metadata was already repaired days or weeks earlier will still have their orphaned tables corrected, matching the real-world scenario where the issue was reported after the repoint had already completed.
-
Bug Fix
Label printing UPC fallback no longer throws database errors
When a SKU has no vendor GTIN barcode data, label printing falls back to reading the UPC from the Store table. The previous query selected the entire Store row into a data structure that expected OrderMultiple to be an integer, but on 168 of 170 live databases that column contains text values like "1.00". This caused Dapper to throw a mapping error for every row. The query now reads only the UPC column as a string, eliminating the type mismatch. Additionally, the SKU is now passed as a parameter rather than interpolated into the SQL, which prevents each SKU from creating its own unique error fingerprint in logs.
-
Bug Fix
Label printing no longer crashes when falling back to store inventory for UPC codes
Label printing will now work reliably even when UPC codes need to be looked up from your store's inventory data, fixing crashes that could occur when printing multiple labels at once.
-
Bug Fix
Orphaned main table after store renumber
If your store was renumbered, the main pricing table will now automatically update to use the new store number instead of keeping the old one, and the store selection dropdown will show only the correct current number.
-
Bug Fix
Rename orphaned main table after store renumbering
If your store number changes, the pricing table automatically updates to the new number so you won't see your old store number appearing in dropdown lists.
-
Bug Fix
Added safety guard for UPC string slicing
Added a LEN >= 2 check in the WHERE clause to ensure the UPC value is long enough before slicing it with [2..], preventing potential index out-of-range errors. Previously this was implicitly handled by a catch block that has now been removed.
-
Data Import
Re-stamp store number column after table rename
After renaming a per-store main table, the StoreNumber column in every row is updated to the new number and SelectionLists is cleared to force regeneration. Without this, the store selector would continue reading the old number from the column data even after the table was renamed.
-
Database
Clean up stale indexes after table rename
When a per-store main table is renamed, any managed indexes are dropped and removed from the ManagedIndexes registry, then recreated under the new table name. This prevents carrying stale "RSIX_9645_*" indexes on a table now named for store 19532, which would impact query performance.
-
Infrastructure
Safe rename with multiple validations
The rename operation includes several safety checks: refuses to act unless there is exactly one orphaned table candidate, verifies the target table name is available (won't overwrite an existing table), uses a rename lock to prevent concurrent operations, and reuses the existing rename sequence for leading-zero fixes. Also drops and rebuilds RSIX indexes to prevent stale index cost.
-
Infrastructure
Safety checks prevent destructive renames
The rename logic includes multiple safeguards: it only renames when exactly one candidate table exists, refuses to rename if a table already exists under the target name, and ignores StoreGroup compound tables or other POS systems' tables. These checks ensure automatic renames never destroy data when the database has multiple per-store tables or other ambiguous conditions.
Infrastructure & Internal
-
New Feature
Blob name returned for partial upload failures
When a file successfully uploads to Azure blob storage but fails to register against the support ticket, the response now includes the blob name. This allows future retry logic to re-register the existing blob rather than re-uploading a multi-gigabyte file.
-
Improvement
Server-controlled upload size limits
The application now reads upload size limits from the server instead of using hardcoded values. This allows the server to advertise its actual multipart body limit (which increased from 128 MB to 256 MB in recent versions) and ensures older clients don't incorrectly reject uploads that newer servers can handle.
-
Improvement
Server-controlled upload size limits
The maximum file size for the legacy multipart upload method is now retrieved from the server rather than using a hard-coded client constant. The 128 MB constant remains only as a fallback for older servers that don't advertise their limit. Non-positive values are treated as "not advertised" rather than "nothing allowed."
-
Improvement
Resume support for interrupted uploads
Removed the DeleteIfExistsAsync call before blob uploads, which was discarding staged uncommitted blocks and destroying Azure's ability to resume interrupted transfers. The UploadAsync method already overwrites existing blobs by default, so the delete was unnecessary and harmful for large multi-gigabyte files.
-
Improvement
Better upload resume capability for large files
Removed pre-upload blob deletion that was destroying Azure's uncommitted block tracking. Large multi-gigabyte uploads can now properly resume from partial progress if retried, rather than restarting from zero every time.
-
Bug Fix
More accurate vendor update error messages
Changed the error message shown when vendor catalog updates fail to avoid incorrectly naming "timeout" or "retries" as the cause. The underlying database operation returns the same error code for both structural database errors (like a missing table) and genuine timeouts, so the application cannot distinguish between them. Now the message directs users to check the detailed log for the actual cause rather than making an incorrect assumption. This change was prompted by two support investigations (stores 3875 and 3174) where the message incorrectly blamed timeouts when the real issue was a dropped database table.
-
Bug Fix
Accurate error reporting for failed attachment uploads
When attaching large files to support tickets fails, you'll now see the real reason (like "connection timed out" or "credentials expired") instead of always being told the file is too large.
-
Bug Fix
Accurate error reporting for failed attachment uploads
When a large file upload to support fails, the error message will now tell you the real reason (like "upload location expired" or "server unavailable") instead of incorrectly saying the file is too big.
-
Bug Fix
Restore large file uploads for stores without dedicated containers
Stores that don't have dedicated cloud storage can now successfully upload large files to support tickets (this was broken and always failed with a size error).
-
Bug Fix
Shared container uploads now work correctly
Support file uploads now work correctly for all stores, including those without dedicated cloud storage containers.
Store identity conflict detection and logging; Store identity conflict detection; Reusable numeric editor with format presets.
Strategy & Pricing
-
Improvement
Enhanced error logging for barcode lookup failures
Added detailed warning logging when VendorGTIN or Store table UPC lookups fail during label printing. The system now logs the specific SKU and exception details, making it easier to diagnose why individual labels might print without barcodes.
-
Bug Fix
Label barcode printing failure caused by data type mismatch
Fixed an issue where labels would print without any barcode when certain products were missing vendor information. Now barcodes print correctly by looking up the UPC from your store's product data.
-
Bug Fix
Rollback of UPC lookup improvements
Reverted PR #1334 which attempted to fix a data exception when printing labels by reading only the UPC column from the Store table. The fix inadvertently caused issues, so the system has been returned to the previous UPC fallback implementation that queries the full Store record when VendorGTIN lookup fails.
-
User Interface
Label printing UPC behavior restored
Label printing now uses the original UPC lookup method. When generating barcodes for labels, the system first checks VendorGTIN, then falls back to the Store table UPC field, using the previous query approach.
Imports & POS
-
Improvement
Enhanced SQL error logging for structural issues
The database service now logs the complete SQL error message (including table and column names) when encountering structural errors like missing tables or columns, rather than truncating to a generic preview. This ensures diagnostic telemetry captures the full context needed to identify which specific object is missing.
-
Bug Fix
Improved diagnostic accuracy for vendor update failures
When vendor data updates fail, the error message now tells you to check the log for specific details instead of always blaming a timeout.
Cloud Sync & Vendor Data
-
Improvement
Enhanced error logging for sync failures
Sync error logs now include the full exception details with stack traces instead of just error messages. This ensures connectivity issues like SQL Server timeouts are properly recorded in telemetry for support diagnosis, preventing scenarios where errors appeared as "Unknown" type with no diagnostic information.
-
Bug Fix
SQL Server timeouts now treated as connectivity failures
If your database server stops responding during sync, you'll now see one clear message saying "a server could not be reached" instead of multiple confusing error messages for each table being synced.
-
Cloud Sync
Reused proven connectivity detection logic
Cloud sync now uses the same SQL error classification logic already tested and proven in the POS import system, ensuring consistent handling of connectivity issues across the application. Added test coverage to prevent genuine sync defects (missing tables, columns, deadlocks) from being misclassified as connectivity problems and suppressed from error telemetry.
-
User Interface
Clearer connectivity failure messages
Error messages during sync are now more accurate about which server couldn't be reached, helping you troubleshoot the right system.
User Interface
-
Improvement
Reusable numeric editor with format presets
Margin and price fields now display consistently throughout the application.
-
Improvement
Display scale conversion handles all DevExpress mask types
Added logic to correctly interpret DevExpress numeric mask scaling rules: predefined "p" (lowercase) divides by 100 while "P" (uppercase) does not; bare "%" in custom masks divides by 100 while "%%" or "\%" do not. Currency ("c2") and plain number ("n2") masks are correctly identified as non-scaling. This ensures the spinner increment adjustment applies only to true percent masks and not to fields like Future Price → Margin % which use an escaped literal percent sign.
-
Improvement
Added display scale detection for numeric masks
Implemented logic to detect when a numeric mask scales the displayed value differently from the stored value. The system now correctly identifies that lowercase "p" masks and bare "%" symbols in custom masks scale by 100x, while uppercase "P", escaped "\%" literals, and "%%" sequences do not. This ensures spinner increments are calculated in the correct value space.
-
Improvement
Enhanced caret position tracking across value changes
Split increment resolution logic into ResolveExponent and Pow10 functions, with CaretIndexForExponent as the inverse operation. This allows the system to restore caret position by place value (ones, tenths, hundredths) rather than character position, maintaining correct behavior when formatted text grows or shrinks.
-
Improvement
Converted caret-aware spinning to reusable attached properties
Replaced the MMNumericEdit custom control with NumericEdit.CaretAware and NumericEdit.FormatMode attached properties that work on standard SpinEdit instances. This architecture allows any spin editor in the app to opt into caret-aware behavior via XAML attributes without breaking DevExpress theme rendering.
-
Bug Fix
Caret-aware numeric stepping for margin and price editors
When you're editing a margin percentage or dollar amount and press the up or down arrow (or use the mouse wheel), the number now changes at the digit where your cursor is blinking, not always by whole numbers.
-
Bug Fix
Numeric editors rendered blank after MM-1403 merge
Margin %, Fixed Retail, and Manual amount fields now display correctly instead of appearing blank.
-
Bug Fix
Numeric spin editors no longer render as blank controls
Margin percent and fixed retail price editors now display correctly instead of appearing as blank boxes.
-
Bug Fix
Percent field spinner applies correct increment
When using the up/down arrows on Current Margin and similar percent fields, the value now changes by the expected amount (like 0.10%) instead of jumping by 10 full percentage points.
-
Bug Fix
Percent field spinners stepped 100 times too large
When you click the up or down arrow buttons on percent fields like Current Margin, the value now changes by the correct small amount (like 0.1%) instead of jumping by a full 10%.
-
Bug Fix
Caret drifted between digits when spinning repeatedly
Holding the Up or Down arrow key now consistently steps the same digit instead of jumping around.
-
Bug Fix
Caret position now stays locked to the same digit during repeated spins
Holding down the Up or Down arrow key now repeatedly steps the same digit instead of jumping to different digits each time.
-
User Interface
Caret-aware stepping for numeric spinners
When you click into a margin or price field and use the up/down arrow keys or spinner buttons, only the digit where your cursor is positioned will change—making it much easier to fine-tune prices to the nearest cent or tenth of a percent without retyping the entire value.
-
User Interface
Applied caret-aware spinners to Future Price Panel
Updated the Margin % and Fixed Retail spinners in the Future Price Panel to use MMNumericEdit with FormatMode="Percent" and FormatMode="Currency" respectively. Removed the attached behavior markup in favor of the control's built-in functionality.
-
User Interface
Format presets for common numeric types
MMNumericEdit introduces a FormatMode property with presets for Currency, Percent, and Number formats, automatically stamping the appropriate mask and format settings. FormatMode defaults to Inherit so existing call sites that assign Mask from code-behind (like UC_MMCostSelectionBox) continue to work unchanged. The Percent preset uses a literal "%" suffix rather than a P-mask to avoid the 100x scaling issue—margin is stored in percentage points throughout the application.
-
User Interface
Applied caret-aware spinners to selection box controls
Updated UC_MMSelectionBox and UC_MMCostSelectionBox to use MMNumericEdit with FormatMode="Inherit". These controls assign their masks from bindings or code-behind at runtime, so the Inherit mode preserves that behavior while adding caret-aware stepping.
-
User Interface
Updated Future Price and selection box editors
All numeric input fields in Future Price calculations and item selection now work consistently.
-
User Interface
Updated all affected editors to use new attached property syntax
Migrated editors in UC_MMCostSelectionBox (range From/To fields), UC_MMSelectionBox (specific value field), and FuturePricePanel (margin percent and fixed retail editors) from the now-removed MMNumericEdit tag to SpinEdit with NumericEdit.CaretAware and NumericEdit.FormatMode attached properties. Functionality remains identical but rendering now works correctly.
-
Architecture
Custom control replaces attached behavior
Converted the CaretAwareSpinBehavior attached behavior into MMNumericEdit, a SpinEdit subclass. This simplifies XAML (no longer requires explicit Interaction.Behaviors tags), improves testability (the control exposes its increment resolution logic as a static method), and provides a cleaner extension point for format presets. The control inherits SpinEdit's default theme style so it renders identically to standard editors while adding the caret-aware increment calculation in the Spin event handler.
-
Infrastructure
Test coverage for mask scaling behavior
Added comprehensive test cases covering all DevExpress mask types including "p2", "P2", "#,##0.00%", escaped literal "\%", currency, and number formats to verify the display scale calculation returns 100 for rescaling masks and 1 for non-rescaling masks. Includes hands-on verification test that a "p2" editor configured like Current Margin now steps by fractions (≤0.01) instead of whole percentage points.
-
Infrastructure
Expanded test coverage for numeric increment resolution
Added MMNumericEditTests and MMNumericEditIncrementTests with 16 test cases, expanding on the 7 cases the old behavior tests covered. New tests pin DevExpress assumptions the control depends on (that Increment assigned during the Spin event is applied, that fractional increments survive), verify that negative signs and decimal separators are handled correctly, confirm that FormatMode presets stamp the expected masks, and ensure the Percent mask is a literal suffix rather than a scaling mask.
-
Infrastructure
Comprehensive test coverage for increment resolution
Added 15 test cases covering caret position resolution, including edge cases like negative numbers, caret on decimal separator, deep fractions, currency symbols, group separators, and text with no digits. Verified that DevExpress SpinEdit respects Increment assigned during the Spin event and that fractional increments survive the spin operation.
-
Infrastructure
Expanded test coverage for caret restoration logic
Added comprehensive unit tests for the new caret position restoration algorithm, including round-trip verification that a caret index for a given place value resolves back to the same exponent, and that the caret correctly follows digits when text length changes (e.g., 9.99 becoming 10.00).
Performance & Reliability
-
Improvement
Store identity conflict detection and logging
The store identity repair process now detects and logs a warning when the vendor configured in application settings contradicts the vendor recorded in the database's About table. This mismatch can occur when a failed-over license answer writes another company's identity into settings. The repair correctly refuses to proceed (preventing data corruption), but now explicitly logs the conflict with both vendor names and instructions to correct it manually in Store Configuration. Previously, this protective refusal was silent, making the issue impossible to diagnose from logs.
-
Improvement
Error logging added to label printing diagnostics
Added warning-level logging to both the vendor GTIN lookup and Store UPC fallback paths. Previously, exceptions were silently swallowed, making it impossible to diagnose why certain labels printed without barcodes. The new logging will surface these issues in diagnostic reports, helping identify data quality problems before they affect label printing.
-
Improvement
Better error messages when servers are unreachable
The fail-fast message when sync cannot reach a server no longer incorrectly states "Manager API unreachable" in cases where the local SQL Server is the actual problem. It now says "a server could not be reached" to avoid sending users to investigate the wrong system.
-
Improvement
Added detailed progress reporting during SKU exception loading
When opening a store's SKU-level exceptions, you'll now see exactly how many have loaded, the percentage complete, and how much time is left—so you know the system is working and not frozen.
-
Improvement
Exception details now included in cloud sync error logs
Three sync logging points that previously omitted exception details now include full stack traces: per-table failures, SQL timeout errors, and the summary when multiple tables fail. This ensures diagnostic information reaches error telemetry instead of appearing as "Unknown" exception types.
-
Bug Fix
Fixed multi-minute freeze when opening SKU-level exceptions screen
The SKU-level exceptions window now opens in seconds instead of minutes, even for stores with thousands of exceptions.
-
Bug Fix
Barcodes now print correctly when vendor GTIN is unavailable
If a product didn't have vendor catalog information, its label would print without a barcode. This is now fixed—labels will show the correct barcode from your store's product data when vendor information is missing.
-
Bug Fix
SQL Server connectivity failures now treated as environmental issues
If your SQL Server becomes temporarily unavailable during cloud sync, you'll now see one clear warning message instead of multiple confusing errors.
-
Bug Fix
Fixed 30-second UI freeze when closing SKU-level exceptions screen
Closing the SKU-level exceptions window is now instant, even after working with thousands of exceptions.
-
Bug Fix
Save button now enables after rounding scheme changes
The Save button now lights up correctly when you change a rounding scheme on the SKU-Level Exceptions screen.
-
Bug Fix
Short UPC codes no longer cause errors during label printing
Labels with unusually short UPC codes will now print reliably instead of potentially failing.
-
Bug Fix
Removed non-functional Apply and Save buttons from Future Price panel tabs
Confusing Apply and "Save" buttons that did nothing have been removed from the Future Price panel's Rounding and Advanced tabs in the SKU-Level Exceptions window.
-
Bug Fix
Fixed progress bar staying empty during SKU exception load
The progress bar now fills smoothly as SKU-level exceptions load, giving clear visual feedback.
-
Bug Fix
Fixed column auto-sizing freeze on large exception lists
The SKU-level exceptions grid now sizes its columns instantly, even with tens of thousands of exceptions loaded.
-
Bug Fix
Fixed Save button not re-enabling after bulk rounding scheme changes
After changing the rounding scheme for multiple SKU exceptions at once, the Save button now becomes available immediately so you can save your changes.
-
User Interface
Added accurate progress reporting during exception load
When loading SKU-level exceptions, you'll now see exactly how many have loaded, the percentage complete, and how much time is left, instead of a frozen progress screen.
-
User Interface
Hid non-functional Save/Snapshot buttons in SKU exception Future Price panels
The Future Price panel in SKU-level exceptions no longer shows misleading "Save" buttons that don't work—use the Save button at the top of the window instead.
-
Performance
Dramatically improved screen open time for large exception counts
Opening a store's SKU-level exceptions now takes seconds instead of minutes, even when there are tens of thousands of exceptions to display.
-
Infrastructure
Store identity repair policy validation
Added validation logic to distinguish between benign "nothing to do" scenarios and actual vendor contradictions during store identity repair. The system now treats Ace Hardware and Emery Jensen as the same vendor family (since EJ stores are carried as Ace in vendor tables), and recognizes Unknown vendor values as non-contradictions to avoid false alarms for pre-About databases. No behavior changed—repairs that previously succeeded still succeed, and repairs that were refused are still refused, but contradictions are now visible.
-
Infrastructure
Cloud sync reuses existing connectivity detection logic
The cloud sync engine now delegates SQL connectivity failure detection to the same curated error-number list already used by POS imports (including error 258 for network unavailability), ensuring consistent behavior across the application and preventing divergent maintenance of duplicate logic.
-
Performance
Optimized grid column sizing for large datasets
The SKU-Level Exceptions grid no longer freezes for several seconds after loading when there are many exceptions.
-
Infrastructure
Added performance logging for SKU exception load times
The system now logs the total time and row count for each SKU-level exception load operation, providing diagnostic data for performance monitoring and future optimization efforts.
Infrastructure & Internal
-
Improvement
Store identity conflict detection
Added detection and logging for cases where the vendor configured in Store Configuration (e.g., Ace Hardware) contradicts the vendor recorded in the database (e.g., Do-It-Best). This condition was previously detected and correctly refused for safety reasons, but the refusal was silent, making customer issues impossible to diagnose from logs. The system now logs a clear warning message when this contradiction is found, directing the user to correct the vendor in Store Configuration. The safety behavior is unchanged — the system still refuses to automatically overwrite store identity when vendors conflict.
-
Bug Fix
Support diagnostics for failed license failover
Resolved a specific diagnostic gap (MM-1393) where a failed-over license could write an incorrect vendor into application settings, leaving the application configured for one vendor while the database belonged to another. This state was correctly refused by the automatic store-renumber repair, but produced no log output, preventing support from identifying the root cause. The new logging makes these cases immediately visible in customer logs.
Remote SQL Access Configuration Script; Remote SQL Access Setup Script; Automatic post-publication catch-up.
Imports & POS
-
Improvement
Main table ownership clarified with run-scoped flag
Replaced a file-existence probe (which was true for every BisTrack store) with a run-scoped flag (`BuiltMainTablesDuringIngest`) set only by the two BisTrack CSV preload builds. Those handlers use a custom SQL script that is not column-equivalent to the generic rebuild—it writes different columns (Lock, PSRule, Discontinued) and computes StoreCost and CMargin differently—so the rebuild must leave their tables untouched to avoid silently changing customer data.
-
Improvement
SelectionLists no longer cleared during import
Selection boxes (vendor, category, etc.) will no longer go blank if a background import runs while you're using Margin Master.
-
Improvement
SelectionLists table no longer cleared during BisTrack Direct SQL ingest
The SelectionLists table (which populates dropdown selection boxes) is no longer truncated mid-ingest, preventing the UI from showing empty dropdowns when a background import runs while the app is open. The rebuild process now owns this cleanup step, performing it at the appropriate time.
-
Bug Fix
POS import no longer drops main tables during background runs
If a background import runs while you're using Margin Master, your pricing grid and selection boxes will no longer be cleared. All table rebuilds now happen during the post-processing step that waits until you close the app or click OK.
-
Bug Fix
BisTrack Direct SQL main tables now rebuilt during post-processing
BisTrack Direct SQL was the last POS system whose ingest destroyed and rebuilt its own main tables before the post-processing rebuild could run. The table build is now handled by the standard rebuild process, using the same SQL builder against the same Store rows the ingest loads. This prevents the app from dropping pricing tables while open with a background import in progress—a scenario that previously left stores with no main tables at all.
-
Bug Fix
Failed store configuration no longer stops entire import run
If one store has a configuration problem during import, the other stores will still complete their imports successfully.
-
Bug Fix
RSC lookup failures no longer halt entire import runs
When a single store's RSC lookup failed during main table rebuild, the entire import run would stop with a modal error, silently skipping all remaining stores. This was particularly problematic for unattended background runs. The rebuild now logs the error, reports the affected store in the post-import summary, and continues processing remaining stores.
-
Bug Fix
Epicor MySQL-Compass import no longer drops all main tables
When importing selected Epicor stores (Shift-click), stores you didn't select will keep their pricing data instead of being cleared and left empty.
-
Bug Fix
Selection lists no longer cleared mid-ingest
Dropdown menus in the pricing grid will no longer go blank during a background import.
-
Architecture
BisTrack Direct SQL main table ownership transferred to rebuild
BisTrack Direct SQL imports previously built per-store main tables during the ingest phase, which could leave stores without main tables if a background import ran while the app was open and the subsequent rebuild was deferred indefinitely. The import now loads only the [Store] staging tables and lets the unified rebuild process create main tables using the same generic SQL builder as other POS systems. This fixes edge cases like store 16254 ending up with no main tables at all.
-
Architecture
New PosMainTableOwnershipPolicy defines which import phase owns tables
Introduced PosMainTableOwnershipPolicy to explicitly define whether the ingest or rebuild phase builds each POS system's main tables. Almost all POS systems (Epicor, Mi9, Falcon, RockSolid, TransAct, Propello) now use rebuild-owned tables. Only BisTrack and WestLake remain ingest-owned because their drain logic does not yet rebuild their tables. The policy includes fail-safe tests to prevent new POS systems from accidentally inheriting ingest-owned behavior.
-
Architecture
BisTrack CSV preload builds now explicitly flag their main table ownership
The two BisTrack CSV preload paths (standard and DIB 6828 format) use a specialized SQL script that computes columns differently than the generic rebuild process. These handlers now set an explicit flag indicating they built the main tables, replacing a file existence check that incorrectly applied to all BisTrack stores including Direct SQL. This ensures the rebuild correctly skips or processes main tables based on what actually happened during ingest, not POS type assumptions.
-
Infrastructure
Comprehensive tests prevent future main table ownership regressions
Added PosIngestOwnsNoMainTablesTests to mechanically enforce that ingest-layer code does not touch main tables or SelectionLists. The test scans all files in the ingest services directory and fails if any unauthorized file contains main table DDL or SelectionLists truncates. An explicit allowlist documents the four remaining files that still build tables (BisTrack, WestLake, and their supporting code) with reasons why each exception exists and what needs to happen to remove it.
Cloud Sync & Vendor Data
-
New Feature
Automatic post-publication catch-up
Stores scheduled before the vendor publishes will now automatically catch up mid-morning with a quick vendor-only sync (seconds), instead of waiting until the next overnight run.
-
New Feature
Post-publication vendor catch-up
If your nightly sync runs before vendors publish (most stores do), you'll now automatically get the current catalog mid-morning without waiting until the next night, and it won't re-import your POS data.
-
New Feature
Unattended updates are now reported on next launch
When you open Margin Master after the background service updated your data overnight, you'll see a green badge and a notification confirming the update happened and when.
-
Improvement
Once-per-day vendor sync guard
Margin Master now tracks exactly what vendor data you have, not just when you last synced. If you reset your data or restore a backup, the sync will run normally without a prompt.
-
Improvement
Background updates apply in place from a badge
When new data downloads in the background, an amber "Click to update data" badge appears at the top of the screen. Click it when you're ready—you'll be asked once whether to run your pricing strategy too, then the data updates and your grid refreshes. The app no longer closes and restarts, so your session stays open.
-
Improvement
In-place rebuild from activity badge
When new pricing or catalog data downloads in the background, you'll see an amber badge at the top of the screen. Click it when you're ready to load the new data—the app stays open and shows progress just like a manual import.
-
Improvement
Run outcomes distinguish parked work from completed work
Run history now clearly shows when new data has been downloaded but is waiting for you to apply it, instead of reporting "completed" when the tables haven't been rebuilt yet.
-
Improvement
Configurable publication cutoff per store
Added VendorPublicationCutoffTime setting (format "HH:mm", default 09:00) so support can adjust the cutoff for stores in unusual timezones or when vendor publication timing drifts. Unparseable values fall back to the default rather than throwing—a typo in a setting must not stop a store from syncing. Erring late is the safe direction; a cutoff set too early would close the guard on a sync that ran before the catalog was finished.
-
Improvement
Configurable publication cutoff time
Support can now adjust when the system expects vendor catalogs to be published, if your region's timing differs from the 09:00 default.
-
Improvement
Vendor-only data update mode
Introduced --vendor-only command-line switch for headless data updates, which drops the POS import leg and fetches only vendor catalogs. Used by the post-publication catch-up to avoid redundant full POS imports. Recognized in all spellings (--vendor-only, --vendoronly, /vendor-only, case-insensitive).
-
Improvement
Strategy leg of rebuild is bracketed as destructive
The pricing strategy rewrites FuturePrice across the main tables and ran unflagged, so an app starting up mid-strategy could open onto half-written prices. The background runner now brackets the strategy phase with SetStrategyPhaseDestructiveAsync so concurrent startups wait rather than binding to incomplete data. The drain already brackets itself; this closes the gap for the strategy leg that runs after the drain has cleared its own flag.
-
Improvement
Accurate status reporting for parked rebuilds
The Background Jobs history now clearly shows when data was downloaded but not yet applied, making it easier to understand your store's current state.
-
Bug Fix
Publication cutoff replaces date-based sync guard
If your store syncs early in the morning (before ~9 AM), you were getting yesterday's catalog and staying a day behind. This is now fixed—the system knows when catalogs are published and waits for them.
-
Bug Fix
Badge click now reloads the grid with new data
Clicking the badge after a background update now reloads the grid with the new data, not just the filter dropdowns.
-
Bug Fix
Background updates resume after machine restarts
If your computer restarts or Margin Master closes unexpectedly while a background update is waiting, the next scheduled update will now complete automatically—your data stays current without manual intervention.
-
Bug Fix
Scheduler no longer wedges when work is parked with no session present
Background updates now resume correctly after a reboot or unexpected shutdown, even if a previous update was waiting to be applied.
-
Cloud Sync
Publication cutoff-based freshness rule
If your store syncs early in the morning before vendors publish their catalogs, the system now correctly recognizes when you need to fetch the day's catalog instead of treating yesterday's data as current.
-
Cloud Sync
Background service skips redundant vendor syncs
The scheduled background update will no longer interrupt you to rebuild vendor data that hasn't changed since the last sync.
-
Cloud Sync
Vendor data fingerprint for drift detection
A new VendorSyncFingerprint captures the row count and highest RowVersion of each synced vendor table and is written alongside the sync timestamp. Comparing the recorded fingerprint to the current state detects when data changed underneath a stored timestamp — such as after Reset All Data, a database restore, or external edits — and reopens the guard automatically. The fingerprint is measured in 41-242ms on real customer databases and is cheap enough to run on every sync and every service tick.
-
Cloud Sync
Fingerprint check unchanged; reopens guard after reset/restore
The existing fingerprint-based evidence check (comparing recorded vs. current table row counts and checksums) is untouched and still required alongside the timestamp. This is what reopens the guard after Reset All Data or a restore-from-backup, where the timestamp alone would lie and suppress the most-needed sync.
-
User Interface
Confirmation prompt before repeating same-day sync
If you click Update Vendor Data and you already synced earlier today, Margin Master will ask "Are you sure?" before downloading the catalog and rebuilding your tables again.
-
User Interface
Color-coded activity badge states
The activity badge color tells you what clicking it will do: blue means a background job is running, green means the data is already loaded (quick refresh), and amber means new data is ready to apply (takes a few minutes).
-
User Interface
Repeat-sync prompt now shows actual sync time and publication status
When you manually sync vendor data that's already current, the confirmation message now clearly shows when you last synced and confirms you already have the latest catalog.
-
User Interface
Improved sync confirmation message
When manually syncing vendor data that's already current, the confirmation now shows exactly when you last synced (date and time) and explains that you already have the latest published catalog.
-
Database
New SyncVendorDataFingerprint application setting
A new ApplicationSettingKey.SyncVendorDataFingerprint stores the vendor data fingerprint alongside the existing SyncVendorData timestamp. The two are written together atomically in RecordVendorSyncSucceededAsync after every successful vendor sync, whether interactive or headless, and are read together to evaluate the guard.
-
Database
Vendor catch-up tracking
Added VendorCatchUpLastRunDate application setting to store the local date the catch-up last ran, ensuring it fires at most once per day even across service restarts. An in-memory flag would allow a restart to re-trigger the catch-up on the same day.
-
Architecture
Removed restart-based rebuild infrastructure
Removed the `--rebuild-and-restore` command-line switch and `RebuildAndRestoreRunner` class that orchestrated the child process spawn, twenty-minute pipeline lock wait, and session restoration. The rebuild now uses the same `DrainPostProcessingAsync` flow triggered by manual POS imports, eliminating special-case logic and simplifying background coordination.
-
Infrastructure
Vendor table lists and publication cadence
A new VendorSyncTables class in MarginMaster.Common maps each vendor to the tables its sync populates, intentionally duplicating VendorSyncRequest.GetTablesForVendor so the background service can evaluate the guard without referencing MarginMaster.CloudSync. Drift tests pin the two lists together and enforce that every table added to a vendor sync also appears in the fingerprint. The class also records that Do-it Best publishes Monday-Friday, so a Friday sync remains current through the weekend.
-
Infrastructure
Comprehensive test coverage for cutoff logic and vendor-only flag
VendorSyncGuardTests rewritten with 19 test cases covering both sides of the 02:00 case (stale after cutoff, current before it), the Friday-before-cutoff weekend case, reset/restore scenarios, and fingerprint evidence. New VendorOnlySwitchTests pins the --vendor-only flag recognition—failure here would be silent, causing the catch-up to run a full POS import every morning instead of a seconds-long vendor sync. Full suite green: 1,727 passed.
-
Infrastructure
Removed restart-based rebuild flow
Deleted OfferParkedRebuildAsync, CaptureSessionAndRestartAsync, LaunchRebuildAndRestoreChild, RestoreCapturedSessionAsync, RebuildAndRestoreRunner, the RebuildAndRestore command, --rebuild-and-restore and --restore-session command-line switches, and the MaxDeferrals/DeferFor deferral machinery. AppLaunchSource.Restore is deliberately kept: the server validates LAUNCHSOURCE against a fixed list and discards unknown values, so dropping the member would put the client out of step with the server contract, and it still appears in historical rows.
-
Infrastructure
Freshness evaluation in background service
Background service now evaluates vendor sync decision conservatively (treats all vendors as daily-publishing) when resolving whether to launch the app, with the actual headless run re-evaluating using the real vendor type and stopping if nothing is due. Prevents the service from being overly cautious and missing legitimate runs.
User Interface
-
Bug Fix
Caret-aware spinning for margin and retail price editors
When editing margin percentages or fixed retail prices, you can now position your cursor at any digit and use the up/down arrows to adjust just that digit. For example, in "41.30%", placing your cursor after the "3" and clicking the up arrow changes it to "41.40%", not "42.30%".
-
User Interface
Improved precision control in pricing fields
This improvement works across all pricing screens where you set future margins or retail prices, making it easier to make small adjustments like changing cents or tenths of a percent.
-
Infrastructure
Comprehensive test coverage for spin increment calculation
Added 18 test cases covering place-value resolution logic, including handling of currency symbols, group separators, mask literals, edge cases like empty text and out-of-bounds cursor positions, and verification that DevExpress SpinEdit correctly applies fractional increments assigned during the Spin event.
Performance & Reliability
-
New Feature
"Update Waiting on Background Service" dialog with one-click fix
When the background service blocks an update, you'll see a new dialog that lets you stop it with one click and install the update right away.
-
New Feature
Stop Service for Update dialog
When an update needs the background service stopped, you'll see a clear explanation and can authorize it with one click, or choose to turn the service off so it never blocks updates again.
-
New Feature
Headless file import bypasses Import Files dialog
Scheduled POS file imports will now work reliably for stores using file-based imports.
-
Improvement
Service relocated to prevent update failures
The background service has been moved to a permanent location so updates can install even when it's running, preventing the "could not stop the background service" errors that previously blocked updates.
-
Improvement
Background service relocated outside program folder
The background service now runs from a permanent location, so updates can install even while it's running scheduled imports.
-
Improvement
Multi-step unlock process before updates
If an update can't install because something is holding the program folder, Margin Master now tries several ways to fix it automatically before asking for your help.
-
Improvement
Epicor Compass connection errors now handled in headless mode
Stores running Epicor Compass will now properly log connection errors during scheduled imports instead of hanging.
-
Improvement
Stale vendor data check skipped during scheduled imports
Scheduled imports will now proceed even when vendor data is slightly out of date, rather than skipping the import entirely.
-
Improvement
Escalating stop methods for background service
The unlock process now tries three progressively stronger methods before giving up: (1) polite stop via the Authenticated-Users grant (no UAC), (2) force-kill the service process by PID from 'sc queryex' (still no UAC), (3) hand back ServiceStopFailed so the UI can offer elevated stop or disable. Steps 1-2 run unattended in silent/headless update paths. The force-kill step clears exactly the case where the grant self-heal hasn't run yet—it needs no service rights, only rights over the process, so it succeeds when the user installed the service. Implemented in new InstallDirectoryUnlocker class with full test coverage (14 new/rewritten tests, 1,684 passing total).
-
Improvement
Failed unlock outcomes carry specific explanations
Error messages about blocked updates now correctly identify what's actually preventing the update, making it easier to resolve the issue.
-
Improvement
Orphaned store table cleanup moved to rebuild
Moved the cleanup of main tables belonging to excluded or removed stores from the ingest to the rebuild phase for Epicor MySQL-Compass. This work now happens silently (matching prior behavior where a wildcard drop removed them unconditionally) but only after all active store tables are safely rebuilt, and includes the same store-list validation fail-safes used in the prompted cleanup path.
-
Bug Fix
Update abort errors now identify the correct subsystem
Previously, when an auto-update had to abort because the install directory was locked, it always reported "Could not stop the background service" regardless of the actual cause. In reality, there were two distinct reasons for failure: either another Margin Master instance (typically a headless import launched by the service) was still running, or the background service itself wouldn't stop. This led to misleading error reports—one store (Niemann Ace 13329) that had been updating successfully every day for a week reported a service stop failure when the actual issue was a data-update import in progress. The error messages now correctly reflect which subsystem caused the abort, making troubleshooting and support tickets more accurate.
-
Bug Fix
Update failure when background service blocks install directory
Updates that couldn't install because the background service was running will now ask you to stop the service instead of just failing silently. The update will complete once the service stops.
-
Bug Fix
Background imports no longer drop active pricing tables
Background price updates will no longer clear your pricing data if Margin Master is open when they run. Previously, scheduled imports could leave you with empty price tables until you manually approved a rebuild.
-
Bug Fix
Prevent background service hangs from hidden dialogs
Scheduled updates no longer freeze when encountering problems that would normally show a popup dialog. Issues requiring attention now appear in logs and error reports instead of silently hanging.
-
Bug Fix
Headless runs no longer hang on dialogs in session 0
Scheduled imports and data updates will no longer get stuck when encountering errors that would normally show a dialog, preventing overnight updates from failing silently.
-
Bug Fix
SelectionLists no longer cleared during ingest
Dropdown menus throughout the application will no longer go blank during background imports.
-
Bug Fix
Enable scheduled imports for file-based stores
Scheduled automatic imports now work correctly for stores importing from files, even when vendor data hasn't been synced recently.
-
Bug Fix
Partial imports now preserve unselected store data
When rebuilding specific stores using Shift+click, other stores' pricing data will remain intact instead of being accidentally deleted.
-
Bug Fix
Deferrals no longer counted as update failures
Choosing "Not Now" on an update, or having an import running when an update tries to install, no longer counts as a failure that could block future automatic updates.
-
Bug Fix
Update deferrals no longer counted as failures
Margin Master now correctly distinguishes between an update that's waiting its turn (like when an import is running) and one that actually failed, so temporary delays won't block future automatic updates.
-
Bug Fix
Startup checks now fail fast instead of hanging headless
Added headless guards to StartupCheckService for license status changes, database connection validation, and schema upgrades. These operations require user confirmation or desktop windows, so headless runs now log clear error messages and throw InvalidOperationException instead of blocking forever on dialogs nobody can see. This prevents the service scheduler from pausing with no diagnostic information.
-
Bug Fix
Service restart sentinel now set before stop, not after
Fixed a race where AutoUpdateRestartBackgroundService was set after WaitForStatus, so a stop that timed out but completed left the sentinel unwritten and the service stayed down until reboot. Now sets wasRunning = true before calling Stop(), so the restart obligation is recorded the moment the stop is issued.
-
User Interface
Update health tracking now exempts deferrals
UpdateHealthState.RecordFailure is no longer called for IsDeferral outcomes (sibling process or user-declined stop). The startup post-update check skips recording when LastUnlockResult.IsDeferral is true. Silent update runs (UpdateInstaller) mark the version in UpdateBlockedByServiceLock when the service is specifically what stopped the apply, so the next interactive launch offers the fix immediately. ClearUpdateBlockedByServiceLock runs on every successful update, regardless of route, so the prompt can't outlive the problem.
-
Database
New ApplicationSettingKey entries for service relocation
Added UpdateBlockedByServiceLock (marks when a specific version is blocked by the service so the next launch offers the fix immediately), BackgroundServiceRelocated (remembers the one-time migration prompt was accepted), and clarified that AutoUpdateRestartBackgroundService is set only when a running service was stopped by the update process.
-
Architecture
Import phase separation enforcement
Introduced PosMainTableOwnershipPolicy to formally define which phase of an import owns the per-store main tables, with mechanical tests (PosIngestOwnsNoMainTablesTests, PosMainTableOwnershipPolicyTests) that fail if new code attempts to modify main tables or SelectionLists during the ingest phase. Almost all POS systems now correctly defer main table work to the rebuild; BisTrack and WestLake remain ingest-owned because their rebuild logic currently declines to build them.
-
Architecture
Install directory unlock logic extracted to dedicated class
Moved unlock orchestration from AutoUpdateService into new InstallDirectoryUnlocker class, injected as a singleton. AutoUpdateService now exposes LastUnlockResult (InstallDirectoryUnlockResult) so callers can distinguish deferrals from faults before recording failures. TryUnlockInstallDirectory returns typed outcomes instead of collapsing to bool, and logs deferrals at Warning (below ErrorReportingSink threshold) while genuine service failures log at Error. Added InstallDirectoryUnlockResult.IsUserActionable to identify the one outcome the stop-service dialog can fix. Surface-area contract pinned in MainMMViewModel.surface.approved.txt (EnsureBackgroundServiceRelocated added).
-
Infrastructure
Test coverage added for both update abort scenarios
Added comprehensive test coverage to ensure both abort paths—sibling process running and service stop failure—report their own distinct error messages and cannot regress to the generic message. The tests verify that the abort decision logic remains unchanged (maintaining safety of the fleet-wide update mechanism) while the diagnostic accuracy improves.
-
Infrastructure
Add LaunchContext.IsHeadless flag and safety tests
Introduced a process-wide LaunchContext.IsHeadless flag set by every headless command (--data-update, --import-vendor, --import-pos, etc.) to identify unattended runs. Defaults to false (the safe direction: showing a dialog to an interactive user costs a click; hiding one loses information). Added HeadlessDialogHangGuardTests with code scanning to prevent raw MessageBox.Show calls in POS import code paths and verify all headless commands properly set the flag, ensuring these hangs cannot silently return.
-
Infrastructure
Background service binaries now signed and staged separately
The service executable is now signed individually (in addition to living inside the signed app folder) since it's copied to %ProgramData% and registered as an auto-start service—exactly the shape SmartScreen scrutinizes. The publish pipeline stages it into a service\ subfolder (not flat in PUBLISH_DIR) with its own secrets-injected appsettings.json. Localization satellite assemblies are stripped from both the app folder and the service subfolder. BackgroundWindowsServiceController now exposes StagedServiceFolder, InstalledServiceFolder, and StagedServiceExePath to distinguish the staging location from the run location.
-
Infrastructure
Service binaries staged separately in publish
The background service is now published to a service\ subfolder of the install rather than flat into the program directory, and is signed independently. The publish workflow copies secrets to both the app's appsettings.json and service\appsettings.json, and strips localization folders from both trees.
-
Infrastructure
Added comprehensive test coverage for headless dialog guards
Created HeadlessDialogHangGuardTests with regex-based scanning of import partials to detect raw MessageBox.Show calls, verification that all headless command-line arguments set LaunchContext.IsHeadless, and confirmation that the safe default is interactive. The tests guard the rule that an unattended run never raises a dialog and document the specific hang signature: "Launching headless run" with no matching "exited with code" in service logs.
-
Infrastructure
Uninstall hook removes service folder
The uninstall hook now removes the service's binaries from %ProgramData% after stopping and deleting the service registration. Best-effort to avoid leaving orphaned files after uninstall, since Velopack only removes what it installed.
Infrastructure & Internal
-
New Feature
Remote SQL Access Configuration Script
Multi-PC stores can now use File > Utilities > Installation Scripts > Enable Remote (LAN) Access to automatically set up the host computer so other workstations can share the same database.
-
New Feature
Remote SQL Access Setup Script
Support can now run a single automated script on the main store computer to set up database sharing for additional PCs. The script checks everything needed for remote access and reports what's wrong, then fixes it when you run it again with -Apply.
-
Improvement
Enhanced diagnostic logging for update failures
The auto-update service now captures and logs the specific reason each update attempt is aborted, making it easier to diagnose why updates are deferred at particular stores. This addresses a real-world triage issue where Niemann Ace 13329 was reported as having service-stop failures despite successfully auto-updating every day for a week.
-
Improvement
Encrypted Password Storage
Database passwords are now stored encrypted for better security.
-
Improvement
Expanded SQL Server install/upgrade documentation
Clarified critical safety rules in the SQL Server installation documentation, including the ownership guard that prevents touching any SQL instance the application cannot prove belongs to Margin Master, instance naming behavior differences between the in-app installer and support scripts, and authentication mode (Windows-only by default). Added 30 lines of new content covering when and why a technician would need to enable remote SQL access.
-
Improvement
Documentation for multi-PC database setup
Added comprehensive documentation page "Enable Remote (LAN) SQL Access" explaining how Margin Master shares databases across multiple store PCs, when the setup script is needed, what it checks, how to set up the workstation side, and troubleshooting for common connection failures (SQL error 18456, error 53, SQL Browser issues). Updated Database Setup guide to reference the script and explain that SQL Server Express defaults to Windows-authentication only. Updated Firewall and Network Requirements to document the inbound TCP/1433 and UDP/1434 rules required for multi-PC stores, scoped to Domain and Private profiles only.
-
Bug Fix
Auto-update abort messages now identify the correct cause
When an automatic update is postponed, you'll now see a more accurate explanation of why — whether it's because a background task is running or because an import is in progress.
-
Bug Fix
Installation Scripts console path resolution
Fixed the Enable-SQLRemoteAccess.ps1 script to provide the correct command for applying SQL fixes. When launched from the Installation Scripts dialog, the PowerShell console starts in C:\WINDOWS\system32, not in the script folder, so the previously documented relative path (.\Enable-SQLRemoteAccess.ps1 -Apply) would fail. The script now prints the full path from $PSCommandPath at the end of each audit run, which correctly resolves regardless of working directory. Documentation updated to explain why the full path is required and to show the correct cached location.
-
Bug Fix
Remote access script now prints correct -Apply command
The Enable-SQLRemoteAccess.ps1 script, launched from the Installation Scripts dialog in Support Tools, opens a PowerShell console that starts in C:\WINDOWS\system32 rather than the script's folder. Previously, instructions told users to run ".\Enable-SQLRemoteAccess.ps1 -Apply" which would fail with "is not recognized" because the relative path couldn't resolve. The script now prints the exact command with full path at the end of the audit: "& 'C:\ProgramData\RetailerSoft\MarginMaster\Scripts\Enable-SQLRemoteAccess.ps1' -Apply". Users can simply copy and paste this line to apply the fixes.
-
Bug Fix
Database Setup window SSMS upgrade button now resolves required script dependencies
The "Upgrade SSMS" button in Database Setup now works reliably on all machines.
-
Bug Fix
Database Setup window SSMS upgrade now resolves required scripts
The Database Setup window's "Upgrade SSMS" button was downloading only the Upgrade-SSMS.ps1 shim but not the Install-SSMS.ps1 script it depends on, causing failures with "Install-SSMS.ps1 not found". Both scripts are now downloaded together, matching the behavior of the guided SQL Server Setup window which already handled this correctly.
-
Bug Fix
SQL Authentication Credentials Lost After Restart
Workstations connecting to a shared database with SQL authentication now stay connected across restarts instead of reverting to Windows authentication and requiring credentials to be re-entered.
-
Bug Fix
SQL authentication credentials now persist across restarts
When connecting to a shared database on another PC, your SQL login username and password now stay saved. Previously you had to re-enter them every time you opened Margin Master.
-
Bug Fix
PowerShell Script Encoding Compatibility
Fixed Install-OleDb12.ps1 containing two em-dash characters (U+2014) that caused "Missing closing '}'" parse errors under Windows PowerShell 5.1. Files are UTF-8 without BOM, which 5.1 mis-decodes. All ten support scripts now verified ASCII-only and parse clean under both Windows PowerShell 5.1 and PowerShell 7+.
-
User Interface
Updated documentation with full path requirement explanation
Documentation for the Enable-SQLRemoteAccess script now explains why the full path is required and includes a note at the top of the usage section. The docs clarify that Margin Master always caches the script at the documented location regardless of whether it came from the cloud, local cache, or embedded in the application, and that the console is already elevated so no additional setup is needed.
-
User Interface
Remote access script added to Installation Scripts dialog
The Installation Scripts window now includes a tool for setting up database sharing when you have multiple PCs in the store.
-
User Interface
Installation Scripts Dialog Entry
Added "Enable Remote (LAN) Access" to the Installation Scripts dialog with full description explaining it checks and configures host requirements for multi-PC setups, reports only by default, and requires -Apply to make changes.
-
Infrastructure
PowerShell script analysis suppression
Added a justified PSAvoidUsingPlainTextForPassword suppression to the -Password parameter. The password is a fixed credential compiled into the shipped client and must reach SqlConnectionStringBuilder as a plain string; using SecureString would add unnecessary complexity and break the unattended -NonInteractive execution path. The value is already masked in all output.
-
Infrastructure
Added comprehensive documentation for Upgrade-SSMS script
Created complete documentation (Upgrade-SSMS.md) clarifying that this script is a thin shim delegating to Install-SSMS.ps1, explaining when it's used (guided setup, Database Setup window, Diagnostic Tool), its parameters, exit codes, and troubleshooting. Also added the script to the documentation index with appropriate search keywords and metadata. Intentionally not added to the Installation Scripts catalog since Install-SSMS already covers that entry point.
-
Infrastructure
Added documentation for Upgrade-SSMS support script
Created comprehensive documentation explaining that Upgrade-SSMS is a thin shim that delegates to Install-SSMS, where it's used in the application, and how to troubleshoot missing sibling script errors. Documentation added to both the public docs site and the scripts folder.
-
Infrastructure
Encrypted password storage for SQL logins
Added EncryptedPasswordConverter JSON converter that encrypts SQL Server passwords at rest in DatabaseConnections.json using AES with machine-specific keys. Handles migration transparently—passwords written before this converter existed are read as plaintext and re-encrypted on the next save. Failed decryption (from a regenerated machine key or moved file) yields an empty password rather than garbage, so the app prompts for credentials instead of mysteriously failing authentication. Applied to SqlServerDatabase.Password property.
-
Infrastructure
Documentation metadata updates
Updated last_updated timestamps on database-setup.md and firewall-network-requirements.md to reflect recent edits made during this work.
-
Infrastructure
Corrected SQL Server installation documentation inaccuracies
Fixed three outdated claims in sql-server-install-upgrade.md dating from February 2026: (1) SQL Server 2025 Express is no longer preview and is now the default with 2022 as fallback, not a user choice, (2) documented the ownership guard rule that prevents the installer from touching any SQL instance it cannot prove belongs to Margin Master, and (3) clarified that new instances use Windows Authentication only with no sa account, pointing to the remote access documentation for multi-PC scenarios. Also documented the instance naming behavior (defaults to SQLEXPRESS, uses dedicated name only when occupied) and how it differs from the Install-SQLExpress.ps1 script (which always defaults to MARGINMASTER).
-
Infrastructure
Updated documentation search index
Added the new Upgrade-SSMS documentation to the searchable index with appropriate keywords including "Install-SSMS not found", "shim", "ssms 18", "ssms 19", "ssms 20", and "ssms 22" to help support staff find troubleshooting guidance.
-
Infrastructure
Documentation for Multi-PC Database Setup
Added comprehensive documentation including support script guide (enable-sql-remote-access.md), updates to database-setup.md and firewall-network-requirements.md covering the shared MarginMaster login and host configuration requirements, troubleshooting guide for common connection failures (error 18456, 53), and search metadata for "second PC", "workstation", "login failed", etc.
-
Infrastructure
Comprehensive test coverage for authentication persistence
Added DatabaseConnectionAuthenticationTests with eight test cases covering SQL authentication detail extraction from connection strings, Windows authentication clearing stored credentials, handling empty/unparseable connection strings, connection string rebuilding from stored records, and encrypted password JSON serialization round-trips. Pins the regression where authentication mode was hard-coded to Windows-only.
-
Infrastructure
Test Coverage for Connection Authentication
Added DatabaseConnectionAuthenticationTests with 188 lines covering SQL authentication persistence, Windows authentication credential clearing, empty/unparseable connection string tolerance, connection string rebuilding, and encrypted password round-tripping. Pins the regression where authentication details were discarded on save.
Epicor SFTP session leak causing self-worsening connection failures; Misleading Epicor connection error guidance; Data Aging View showing contradictory day counts.
Infrastructure & Internal
-
Bug Fix
Epicor SFTP session leak causing self-worsening connection failures
Epicor Eagle imports now properly close their connections, preventing the "server disconnected" error from appearing after multiple retries.
-
Bug Fix
Misleading Epicor connection error guidance
When an Epicor import fails, the error message now tells you what actually went wrong (network issue, server problem, or bad credentials) instead of always saying to check the server address.
-
Bug Fix
Data Aging View showing contradictory day counts
The Data Aging View now clearly shows vendor data ages in "business days" while POS data ages in "days"—both are correct, just counting different ways.
-
Bug Fix
Data Aging View header overstating vendor data freshness
If vendor sync runs but doesn't actually update catalog tables, the Data Aging View now shows a red warning telling you the real merge date and to run Get Vendor Data again.
Added numeric formatting to cost and quantity selection boxes; Applied proper numeric formatting to all value entry fields; Migration safety guarantees.
User Interface
-
Improvement
Added numeric formatting to cost and quantity selection boxes
Dollar amounts and quantities in strategy filters now display with proper formatting—dollar signs for costs, commas for large numbers, and percentages for margins.
-
Improvement
Applied proper numeric formatting to all value entry fields
All number entry fields now display with proper formatting: dollar signs for prices, percent symbols for margins, and decimal formatting for quantities. This makes it clearer what type of value you're entering.
-
Improvement
Selection boxes now seed default values for empty editors
When entering price ranges or manual amounts, empty fields now start at "$0.00" instead of blank, and clicking in a field selects the number so you can type right over it.
-
Improvement
Preserved user-entered values across checkbox state changes
If you uncheck the Manual option and then check it again, your previously entered amount will still be there instead of being erased.
-
Bug Fix
Manual amount entry now hides properly when unchecked
Unchecking "Manual" in price comparisons now correctly hides the amount entry box. Your typed amount is saved if you check Manual again.
-
Bug Fix
Manual amount entry visibility now follows checkbox state
The Manual amount entry box now appears only when the Manual option is checked and disappears when you uncheck it. Your previously entered amount is remembered if you check Manual again.
-
Bug Fix
Margin fields now format consistently with grid columns
Margin filters now show percentages matching the grid columns (e.g., "35.00%"). Note: Old margin rules may display incorrectly (3,000% instead of 30%) if they were saved with wrong values—these rules weren't working correctly before, but the issue is now visible.
-
Bug Fix
Fixed Current Margin comparison to use percentage format
When setting up rules that compare Current Margin or other percentage fields, the value entry box now shows percentages (like "10.00 %") instead of plain numbers, matching what you see in the grid.
-
Bug Fix
Comparison operators now seed with default value instead of blank
When you select a comparison operator like "Greater Than," the value box now starts with 0 instead of being blank, and the number is pre-selected so you can just start typing your amount.
-
Bug Fix
Fixed percentage value storage to use fractions, not scaled display values
Percentage-based pricing rules now save and filter correctly. Previously, a rule like "Current Margin < 10%" wouldn't match any products because it was actually comparing against 10.0 instead of 0.10.
-
User Interface
Manual amount editor repositioned for clarity
The Manual amount entry box now appears directly under the "Manual" option instead of at the bottom of the panel, making it clearer which field you're filling in.
-
User Interface
Manual amount editor moved to its own line
The Manual amount entry box now appears on its own line below the Manual checkbox, making it easier to see and use without text getting cut off.
-
User Interface
Future Price panel fields restyled for consistency
The Future Price panel's Margin % and Fixed Retail fields now have consistent styling with a cream background and gold border.
-
Architecture
Added SelectionValueEntryPolicy with comprehensive test coverage
Introduced SelectionValueEntryPolicy as a pure, testable decision function that determines which value editor to show based on row state. Added 15 unit tests pinning the behavior, including the specific "Manual unchecked shows nothing" case that was the original bug. Separated presentation logic from decision logic to enable reliable testing of the UI state machine.
Performance & Reliability
-
Bug Fix
Background service infinite loop on data updates
Fixed a critical defect where the DataUpdate job could not record its last-run timestamp due to an incorrect mapping, causing the background service to re-download vendor catalogs every five minutes indefinitely until manually stopped. The job-to-setting mapping is now exhaustive and logs an error if a job type has no marker rather than silently using another job's key.
-
Bug Fix
Fixed infinite data-update loop
The background service was repeatedly relaunching the DataUpdate job every five minutes because it was writing the last-run timestamp to a retired setting key. The job could not record that it had run, so the schedule stayed permanently due. Added exhaustive mapping to ensure every job type writes to its own last-run marker, with loud failures if a new job is added without one.
-
Bug Fix
Rebuild workflow now waits for pipeline lock instead of abandoning
When you agree to a data rebuild, the system now waits for any background work to finish before applying it, instead of asking you again.
-
Bug Fix
Prevented duplicate rebuilds when prior rebuild is pending
The background service now checks whether a rebuild from the previous run is still awaiting user consent before ingesting data again. Previously, if the user hadn't responded to the first prompt, the service would re-download the data, stack a second prompt, and race any rebuild the user eventually agreed to.
-
Bug Fix
Prevented duplicate rebuild prompts during active sync
You will no longer see multiple rebuild prompts stacking up while waiting to respond to the first one.
-
Bug Fix
Rebuild now waits for pipeline lock instead of abandoning
After agreeing to a data update, the rebuild will now wait for any background jobs to finish rather than asking you to restart again.
-
Bug Fix
User session now correctly restored after successful rebuild
Your saved filters and selections are now properly restored after a data rebuild completes successfully.
-
Bug Fix
Restored user screen selections after rebuild
Your table filters, selections, and grid view are now properly restored after agreeing to a data update and restart.
-
Bug Fix
Grid data now loads when restoring captured session
When your session is restored after a data update, the pricing grid now automatically reloads with your filters applied instead of appearing empty.
-
Infrastructure
Added comprehensive last-run marker mapping tests
Added contract tests that walk the BackgroundJobType enum and verify each job has its own unique last-run setting key. Prevents future jobs from being added without proper scheduling markers, which would cause infinite launch loops.
-
Infrastructure
Improved test reliability for multi-instance scenarios
Interactive session presence tests now adapt to whether Margin Master is already running on the test machine instead of asserting "no instance present" unconditionally, which previously caused test failures on machines where someone had the app open during testing.
Infrastructure & Internal
-
Improvement
Migration safety guarantees
The migration explicitly sets the Execute Strategy step to false, ensuring that unattended repricing is never enabled during migration since the retired schedule model did not imply consent to automatic price updates. Migration failures now retry on next startup rather than marking themselves complete, preventing stores from being left permanently unmigrated.
-
Bug Fix
Schedule migration now runs from the background service
Fixed a critical path where stores updated silently by the background service never migrated their schedules. The service relaunches through --post-update-start-service which exits before the database opens, preventing app-side migration from running. The service now migrates schedules on its own startup, ensuring stores that never open the app can still convert to the new schedule format and continue importing overnight.
-
Bug Fix
Schedule migration now runs from Windows service
The migration that converts legacy Vendor and POS schedules to the new Data Update job format now executes from the Windows service itself, not just the app. This fixes a critical gap where stores updated silently by the service (without the app ever launching) would never migrate, causing them to silently stop importing overnight data. The service-side migration runs before the first schedule evaluation, ensuring stores remain operational.
-
Bug Fix
App update check schedule is now migrated
The automatic app update check was reshaped from mode/interval to days-and-time but was not being migrated. This would have caused stores to never auto-update again after taking this release, as the service would find no days selected and treat the job as unrunnable. All three background schedules (vendor sync, POS import, and app updates) are now properly converted, with all seven days selected to preserve the previous daily behavior.
-
Bug Fix
App update check schedule migration
The migration now also converts the app update check schedule from the retired interval-based format to the new days-and-time format. Without this conversion, stores would stop checking for updates entirely, preventing them from receiving future fixes. The migration defaults to checking all seven days to preserve the existing daily check behavior.
-
Architecture
Single shared migration implementation
Created a unified BackgroundScheduleMigrator class used by both the desktop app and Windows service, ensuring they can never disagree about a store's schedule configuration. The migrator accepts get/set delegates so it can work against either the app's settings service or the service's SQL reader without creating dependencies between them.
-
Architecture
Unified schedule migration implementation
The app and background service now share a single BackgroundScheduleMigrator implementation rather than maintaining separate copies. This prevents the two components from disagreeing about a store's schedule configuration, which would be worse than either being wrong independently. The shared migrator is tested with 191 test cases covering all migration scenarios.
-
Infrastructure
Comprehensive migration test coverage
Added 191 lines of tests covering all migration scenarios including idempotency, edge cases with missing settings, the critical safety property that migration never enables unattended repricing, and verification that both the app and service call the shared migrator. Also added reachability tests to ensure the migration runs on every possible update path.
Add WPF services (1 new); Update MarginMaster.BackgroundService (4 updated); Update view models (4 updated).
Strategy & Pricing
- New Feature Add WPF services (1 new)
- Improvement Update MarginMaster.BackgroundService (4 updated)
- Improvement Update view models (4 updated)
- Improvement Update WPF views (1 updated)
Shared strategy catalog and download; Shared strategy catalog and download; Strategy Comparison Report dialog.
Strategy & Pricing
-
New Feature
Shared strategy catalog and download
Open Strategy > Get Premade Strategies to see ready-made pricing strategies for your vendor. Click "Download / Update" to install one, then open it in the Strategy Manager. To customize it, use the "Copy Current Strategy" button to create an editable copy.
-
New Feature
Shared strategy catalog and download
Instead of building pricing strategies from scratch, you can now download starter strategies built by RetailerSoft for your vendor. Open Strategy > Get Premade Strategies, select a strategy, and click Download. The downloaded strategy is read-only — open it in the Strategy Manager and use "Copy Current Strategy" to make an editable copy you can customize.
-
New Feature
Strategy Comparison Report dialog
Open Strategy > Compare Strategies to capture snapshots of your pricing results and compare them side-by-side. The report shows how much profit each strategy gains and which one wins.
-
New Feature
Shared strategy catalog and installer
The Strategy menu now has "Get Premade Strategies" — a library of ready-to-use pricing rules you can install with one click. Installed strategies are read-only templates; use "Copy Current Strategy" to make an editable version.
-
New Feature
Strategy Comparison Report dialog
Open the Strategy menu and select "Compare Strategies" to capture your current pricing results with a custom label (e.g., "2023 Current Rules"), then run a new pricing strategy and capture it again (e.g., "2024 Test Strategy"). Select both snapshots, choose whether to view results Overall, By Store, or By Department, and click "Build Comparison" to see which strategy makes more money and by how much per year.
-
New Feature
Strategy Utilities hub
Look for "Strategy Utilities…" in the Strategy menu to access all strategy tools in one place.
-
New Feature
Strategy Utilities hub
A new "Strategy Utilities" option in the Strategy menu provides one-click access to all pricing strategy tools in a single dialog.
-
New Feature
Unified sensitivity scoring engine
Price sensitivity analysis is now available for both Ace Hardware and Do it Best stores, showing which departments are most "blind" (eligible for price increases) versus most "sensitive" (requiring careful pricing).
-
New Feature
Copy custom groups from another strategy
On the Manage Custom Groups screen, click the hamburger menu and choose "Copy Group from Another Strategy..." Pick a strategy from the left list, then pick the group to copy from the right list. The system will suggest a name for the copied group. Click "Copy Group" and the group will be added to your current strategy with all its SKUs and settings intact.
-
New Feature
Copy custom groups from another strategy
On the Manage Custom Groups screen, click the hamburger menu and choose "Copy Group from Another Strategy..." to copy a group from a different pricing strategy into the current one. The original group is not changed.
-
New Feature
Bulk "Resolve Unassigned" actions for SKU exceptions
When SKU exceptions are missing a price level, the hamburger menu now shows "Resolve Unassigned" with options to delete them all, inactivate them all, or assign a price level to all of them at once. This fixes the common problem where imported strategies contain hundreds of exceptions that can't price anything.
-
New Feature
Bulk "Resolve Unassigned" menu in SKU Level Exceptions
If you have active SKU exceptions with no price level (which the strategy pre-flight warns about), you can now fix them all at once using the "Resolve Unassigned" menu instead of editing each one individually.
-
New Feature
Import Competitor Prices dialog
Open File > Utilities > Import Competitor Prices, click Download Template to get a correctly formatted spreadsheet, fill in your SKU and competitor price columns, then browse to your file and click Import. The prices appear in Competitor 1 through Competitor 5 columns.
-
New Feature
Import Competitor Prices from spreadsheet
Open File > Utilities > Import Competitor Prices, select your spreadsheet, review what was found, and click Import. Your competitor prices will load into the Competitor 1–5 fields where you can use them for pricing analysis and strategies.
-
New Feature
Replace or Add mode for each competitor price column
When importing competitor prices, you can now choose "Add" or "Replace" for each column. Use Replace when your POS already fills the field and you want only your own prices there, or when reloading a shop report and old prices should not remain. The window shows how many items already have values so you can make an informed choice.
-
New Feature
Added option to hide Strategy Execution Summary after runs
Check or uncheck "Show this summary after each strategy run" to control whether this report appears. You can also find this setting in Options > Miscellaneous. The strategy still runs the same way and logs everything normally — only the summary report is hidden.
-
New Feature
Below-cost pricing warning on SKU exceptions
When saving SKU exceptions that price below cost, you'll see a warning listing which items and why (e.g., "1005412 — its -25% margin prices below cost"). You can review and choose "Save anyway" if it's intentional.
-
New Feature
Below-cost warning when saving SKU exceptions
When saving a SKU exception that prices below cost, you'll see a warning listing which items and why (e.g., "1005412 — its -25% margin prices below cost"). You can review and choose to save anyway if it's intentional.
-
New Feature
Read-only strategy state for downloaded strategies
Strategies you download from the premade catalog are read-only and show a banner explaining this. Click "Copy Current Strategy" to make an editable version you can customize.
-
New Feature
Shared strategy installation and versioning
Downloaded strategies show a banner "Shared strategy vN — read-only" in the Strategy Manager. You can execute, activate, export, and back them up, but to make changes you must use "Copy Current Strategy" first. When a newer version is available, re-download it from the catalog — since the original cannot be edited, no local changes can be lost.
-
New Feature
Shared strategy publisher (support machines only)
Support staff can publish local pricing strategies to the shared catalog for all stores to use.
-
New Feature
Local snapshot storage for strategy results
Your captured pricing snapshots are saved locally on your computer and remain available even after syncing with the cloud, so you can compare strategies weeks or months apart.
-
New Feature
Automatic strategy result snapshots
Every time you run a strategy, the system automatically saves a snapshot of what changed. You can later compare these snapshots to see how different strategy runs affected your pricing. Only the most recent automatic snapshot for each strategy is kept.
-
New Feature
Auto-capture strategy comparison snapshots
Every time you run a strategy, Margin Master now saves a snapshot of the price changes in the background. You can turn this off in the Compare Strategies dialog if you prefer to capture snapshots manually.
-
New Feature
Find and resolve duplicate SKUs across groups
On the Manage Custom Groups screen, click the hamburger menu and choose "Find Duplicate SKUs..." to see any SKUs that appear in more than one group. Click the X next to a group name to remove that SKU from that group immediately. This helps prevent pricing conflicts where the same item is assigned to multiple groups.
-
New Feature
Find duplicate SKUs across custom groups
Click the hamburger menu and choose "Find Duplicate SKUs..." to see which items appear in more than one custom group. Click the X next to a group name to remove that item from that group.
-
New Feature
Bulk "Resolve Unassigned" actions for custom groups
When custom groups are missing a price level, the hamburger menu now shows "Resolve Unassigned" with options to delete them all, inactivate them all, or assign a price level to all of them at once.
-
New Feature
Bulk "Resolve Unassigned" menu in Manage Custom Groups
If you have active custom groups with no price level, you can now delete them, inactivate them, or assign a price level to all of them at once using the new "Resolve Unassigned" menu.
-
New Feature
Replace or Add choice per competitor column
When importing competitor prices, you can now choose "Replace all existing values" to clear out prices that came from your POS system, so filters like "Competitor 1 greater than 0" return only the items in your spreadsheet.
-
New Feature
Automatic column enablement for strategy requirements
When you open or run a pricing strategy, Margin Master will now automatically show any columns that strategy needs, so you can see and edit all the price levels the strategy uses.
- New Feature Automatic column view reconciliation for pricing strategies
-
New Feature
Auto-repair offer for margin groups with recognizable names
If you have a custom group named something like "25%Margin" that stopped pricing, the app will now offer to restore the 25% margin setting when you open or close the custom groups screen.
-
New Feature
Below-cost pricing warning on custom groups
When saving custom groups that price below cost, you'll see a warning listing affected groups and the reason (e.g., "Clearance Items — it prices from cost and then subtracts").
-
New Feature
Below-cost warning when saving custom groups
When saving a custom group that prices below cost, you'll see a warning listing which groups and why (e.g., "Clearance Items — it prices from cost and then subtracts"). You can review and save anyway if it's intentional.
-
New Feature
Shared strategy publishing (support machines only)
Support users can share a pricing strategy with all stores by opening it in the Strategy Manager and selecting "Update or Create Shared Strategy" from the menu.
-
New Feature
Shared strategy publishing (support machines only)
(Support machines only) You can publish a local strategy to the shared catalog using the "Update or Create Shared Strategy" menu item in the Strategy Manager. Margin Master will validate the strategy and warn you about anything that might not work on all stores before publishing.
-
New Feature
Multi-grain comparison rollups (Overall, By Store, By Department)
View your comparison across the entire organization, broken down by individual store, or broken down by department — the dollars always add up to the same overall total.
-
New Feature
Strategy result freshness detection
The Compare Strategies screen now shows whether each saved strategy result is "Current" or "Not Current" based on whether your data or the strategy itself has changed since it was last run.
-
New Feature
Combine stores toggle for cross-store pricing analysis
When analyzing strategies, you can now check "Combine stores" to see departments and classes rolled up across all your stores—useful when you price all stores the same and don't need to see each store separately.
-
New Feature
Combine-stores view for strategy comparison
You can now check "Combine stores" to group pricing by department and class across all your stores at once, since most stores price everything the same way anyway.
-
New Feature
Price level picker for bulk assignment
When assigning a price level to multiple exceptions or groups at once, you'll see a picker showing only price levels that work without additional settings.
-
New Feature
Automatic column display after import
After importing, Margin Master asks if you want to display the competitor columns you just loaded so you can see the prices right away.
-
New Feature
Pre-flight validation for rules that cannot price
Before running a strategy, you'll now see a warning if any custom groups or SKU exceptions are incomplete and won't price anything, giving you a chance to fix them before the run.
-
New Feature
Excel export of comparison results
Click "Export to Excel" to save the comparison table for sharing with management or further analysis in Excel.
-
New Feature
Automatic rerun of stale strategies
If you select strategies with outdated results, the system offers to automatically rerun them before showing the comparison, ensuring you're always comparing current numbers.
-
New Feature
Smart value parsing and validation
The import understands prices like "$1,234.567" (rounds to $1,234.57) and skips blank cells instead of zeroing them out, so your existing prices stay safe.
-
New Feature
Comprehensive import logging
Every import creates a log file showing exactly what happened—which prices were loaded, which cells were skipped, and which SKUs weren't found in your database. Click "Open Log" to review it.
-
New Feature
Strategy Comparison Report dialog
Open the Strategy menu and select "Compare Strategies" to capture your current pricing results with a custom label (e.g., "2023 Current Rules"), then run a new pricing strategy and capture it again (e.g., "2024 Test Strategy"). Select both snapshots, choose whether to view results Overall, By Store, or By Department, and click "Build Comparison" to see which strategy makes more money and by how much per year.
-
New Feature
Local snapshot storage for strategy results
Your captured pricing snapshots are saved locally on your computer and remain available even after syncing with the cloud, so you can compare strategies weeks or months apart.
-
New Feature
Multi-grain comparison rollups with Excel export
View your comparison across the entire organization, broken down by individual store, or broken down by department — the dollars always add up to the same overall total. Click "Export to Excel" to save the comparison table for sharing with management.
- New Feature Docs: add ECI hosting-migration advisory to the VPN requirement doc
- New Feature Docs: add ECI NAT-over-tunnel requirement and an IT question checklist
- New Feature Add Import Competitor Prices ΓÇö load a spreadsheet into Comp1-Comp5
- New Feature Add an end-to-end cloud sync fidelity harness
-
Improvement
Relative sensitivity scoring for easier comparison
Sensitivity scores now range from 0 (least sensitive) to 100 (most sensitive) within each group, making it much easier to spot which areas are most affected by price changes.
-
Improvement
Relative sensitivity scoring within peer groups
Each row's sensitivity score now shows how it ranks against its peers—100 means most price-sensitive in its group, 0 means least sensitive—making it easier to spot which departments or classes need the most careful pricing.
-
Improvement
Honest sensitivity score display with confidence-based coloring
Sensitivity scores now show the real number instead of exaggerating small differences between stores. The color helps you spot which items are more price-sensitive (red) versus less sensitive (green), but only when there's enough data to be confident.
-
Improvement
MAP and IMAP always available at Ace stores
At Ace stores, "MAP Price" and "IMAP Price" are always available when setting future prices, so you can correct critical pricing violations with one click.
-
Improvement
"Just Run" now applies pricing corrections automatically
When you click "Just Run" in Ace Critical Pricing, Margin Master now automatically fixes the pricing violations and shows you what was changed, instead of just listing the problems. You'll see a breakdown of how many items were corrected in each category (below-cost, below-MAP, below-IMAP).
-
Improvement
"Just Run" applies corrections automatically
When you click "Just Run" in the Ace Critical Pricing tool, Margin Master now immediately fixes pricing violations and sets future prices for you. You'll see a summary of how many items were corrected in each category (below-cost, below-MAP, below-IMAP), and the grid will display the items with their new future prices ready to export to your POS.
-
Improvement
Margin suggestion prompts also show step numbers
When the system suggests margin percentages for your pricing groups, it now shows the step number so you can easily find which group it's referring to.
-
Improvement
Specific error messages for each RockSolid export failure condition
When a RockSolid price export fails, you'll now see exactly what's wrong (like "RockSolid.RS is marked read-only" or "another program has the file locked") instead of a list of possibilities to check.
-
Improvement
Preserved pricing strategy configuration over view changes
Your saved pricing strategies will continue working with all their original settings even after you customize which fields are visible in your workspace.
-
Improvement
Add service method to create individual price level items
Added a new CreateFuturePriceSetToLevel method to PriceLevelListService that builds a single set-to level item outside the normal offered-list filter, enabling the restoration of price levels that exist in saved rules but aren't currently surfaced by the active view.
-
Improvement
Redesigned strategy comparison with staleness detection
When comparing strategies, you now select them by name, and the system tells you if their results are out of date. Out-of-date strategies are automatically rerun before the comparison shows, so you always see accurate results.
-
Improvement
Three-way strategy comparison
You can now compare up to three pricing strategies side-by-side instead of just two, making it easier to evaluate multiple options at once.
-
Improvement
Per-row checkbox state management
Each strategy picker row now tracks its own IsEnabled state independently, allowing the UI to dynamically enable or disable individual checkboxes based on the current selection count. This provides clear visual feedback about which strategies can be selected at any given moment.
-
Improvement
Visual feedback for selection cap
Added an IsEnabled property to strategy picker rows that dynamically updates as selections change. Unselected strategies become visually disabled (greyed out) when the three-selection cap is reached, while previously selected strategies remain enabled and can be deselected.
-
Improvement
Strategy names now appear in column headers
Column headers now show your actual strategy names instead of "Baseline" and "Candidate."
-
Improvement
User-controlled restoration after strategy comparison
After comparing strategies, you'll be asked whether you want to recalculate your original strategy's prices (which can take a while), clear the prices, or leave them alone—no more waiting for automatic recalculations you might not want.
-
Improvement
User-controlled restore after comparison runs
After comparing strategies, you now choose whether to reapply your original strategy (which reruns it completely), clear the Future Prices, or keep them as-is—no more waiting for automatic reruns you might not need.
-
Improvement
Simplified column labels
Column headers are now simpler and easier to read, showing just the metric type since the strategy name appears in the group header above.
-
Improvement
Enhanced diagnostic logging for Future Price panel failures
Improved the error log message when Future Price panel initialization fails at startup to clearly indicate that the panel will be unavailable for the session and that no strategy steps can execute. This helps support staff quickly identify the root cause when users report strategy execution failures.
-
Improvement
Better error messaging for incomplete pricing rules
When reviewing pricing rules, you'll now see a clear message telling you "it is a Set-to-SKU rule with no SKU entered" instead of a generic error, making it easier to fix the problem.
-
Improvement
Warnings when min/max strategy models are missing
You'll now see a warning message if a pricing strategy tries to use a min/max model that doesn't exist in your database.
-
Improvement
Skip remaining batches when anchor lookup fails
Since the anchor SKU lookup is group-level and deterministic (every batch in the group uses the same missing anchor), the system now short-circuits execution after detecting the first failure instead of attempting to process each remaining batch with identical failures. This reduces unnecessary processing and log noise.
-
Improvement
Strategy execution behavior unchanged when summary is hidden
Hiding the summary doesn't change how the strategy runs or what information is saved — it only hides the report window.
-
Improvement
Better error logging when exception loading fails
When SKU exception loading fails, the error log now includes the strategy name, SKU (if filtering to a specific SKU), and how many exceptions had successfully loaded before the failure. This helps distinguish between "no exceptions exist" and "the load failed partway through," since both previously resulted in an empty grid with no visible error.
-
Improvement
Better error logging for SKU exception load failures
Enhanced error logging to report which pricing strategy was being loaded, which SKU (if filtering to one), and how many exceptions had successfully loaded before the failure. This helps distinguish between "no exceptions exist" and "the load crashed partway through."
-
Improvement
Dynamic "Set Future Price to" level list
The "Set Future Price to" list now updates automatically when you change column views or selection boxes — extended price levels appear only when their fields are visible.
-
Improvement
Strategy comparison setting persists immediately
The auto-capture checkbox in the Compare Strategies dialog now saves its state immediately when toggled, rather than waiting for the dialog to close. Since the dialog has no OK/Cancel buttons, this prevents the setting from being lost when the user closes the window.
-
Improvement
Three-way comparison support
You can now compare up to three pricing strategies side by side instead of just two.
-
Improvement
Enhanced sensitivity tooltips
Hovering over a sensitivity score shows both the relative ranking and the detailed breakdown of price sensitivity metrics.
-
Improvement
Pricing panel prevents saving incomplete set-to-SKU rules
The Future Price panel now matches the behavior of margin and fixed retail rules by not emitting action tokens when the SKU field is left blank, preventing the creation of malformed pricing rules at the point of entry.
-
Improvement
Missing min/max strategies no longer silently fail
If a pricing step references a min/max strategy that isn't set up in your database, you'll now see a clear warning instead of having the setting silently removed.
-
Improvement
Grid reloads in place after Apply
After applying price changes to Ace Critical Pricing items, the list stays on screen with the new future prices shown, and the Summary panel updates to reflect your changes.
-
Improvement
Documentation updated to reflect new behavior
The Critical Retail Pricing documentation now describes "Just Run" as "Instant Correction" rather than "Instant Analysis," clarifying that it applies price changes immediately instead of just displaying a list for manual review.
-
Improvement
Completion message now leads with SKUs applied
The import completion message now clearly tells you how many SKUs from your file were successfully applied to your pricing data.
-
Improvement
Import log now records Replace/Add choices and cleared values
The log file now includes which columns were Replaced vs. Added, how many values were erased before the file was applied (per table and per column), and clarifies that SKUs "not in any main table" (rather than "not in Store") were skipped. The completion message and log both remind users that competitor prices are cleared by the next main-table rebuild (POS import, cloud sync, or manual rebuild) and must be re-imported afterwards.
-
Improvement
Added safeguards to prevent empty store routing filters
Introduced MainTableSelectionPolicy.RoutingListIsEmpty and RemoveEmptyRoutingKeys methods to consistently detect and remove empty store routing filters before they can cause discovery failures. GetFiltersDictionary now omits empty StoreGroup values rather than publishing them, matching the existing behavior for StoreNumber. The system logs a warning when empty routing keys are removed, helping identify misconfigured store grouping settings.
-
Improvement
Enhanced validation and range checking for price level lookups
Added safety checks when looking up price levels by index position. The system now validates that indexes are within valid ranges before using them, and falls back to the recorded price level enum when available. Competitor price levels (Comp1-5) are now resolved by identity rather than list position, preventing the same type of mismatch that caused the main defect.
-
Improvement
Conservative detection to avoid warning fatigue
The below-cost warning only appears when the system is certain the price will be below cost, so you won't see unnecessary alerts on normal pricing rules.
-
Improvement
Sitting margin query available as standalone service
Introduces ISittingMarginQueryService, which runs the shared sitting-margin bucket query against every resolved main table and returns the raw per-grain rows (Store/VendorOwned/Velocity/Dept/Class with additive CP/FP/COGS dollars). This is the sitting-margin calculation as a first-class product — no Profit Analyzer ViewModel spin-up required — so the Strategy Comparison dialog can capture results independently of the Profit Analyzer screen.
-
Improvement
Clarified snapshot capture message
The message when capturing a new snapshot now correctly states it captures all store pricing data, not just selected items.
-
Improvement
Automatic strategy reruns with awaited snapshot capture
When you compare strategies that need updating, the app runs them one by one automatically, shows progress for each, then displays the comparison when all are finished.
-
Improvement
Sensitivity heat tinting only for reliable scores
Sensitivity scores based on limited data now appear without color highlighting, so you know they're less reliable.
-
Improvement
Unassigned entry detection and menu visibility
The "Resolve Unassigned" menu appears automatically when SKU exceptions or custom groups are missing price levels, and shows the exact count of affected items.
-
Improvement
Strategy pre-flight now suggests bulk resolution
The strategy pre-flight warning now tells you about the "Resolve Unassigned" menu when it finds pricing rules that won't work.
-
Improvement
Count message displays after splash screen closes
The "Found X critical pricing items" message box now opens only after the loading splash screen is fully closed, following the application's splash-before-modal rule. Previously the message could appear while the splash was still visible.
- Improvement Column reconciliation runs before strategy editor and execution
-
Improvement
Strategy Comparison math is dollar-weighted and reconciles exactly
The A/B comparison aggregates detail rows to the selected grain using the same SittingMarginMath roll-up, ensuring the grand total is dollar-weighted (not an average of per-grain percentages) and reconciles exactly with the per-store and per-department rows. Candidate-vs-baseline dollars is the incremental profit the new strategy makes over the old one (candidate annual $ − baseline annual $), and when a grain is absent from the baseline snapshot (e.g., a new department), the baseline dollars fall back to zero and the sitting anchor comes from the candidate's current price.
-
Improvement
Documentation updated with Replace/Add guidance and POS caveats
Help documentation now includes a "Replace or Add" section explaining when to use each mode, notes that Epicor and Paladin POS systems pre-fill Comp1–Comp5, clarifies that prices are cleared by main-table rebuilds (not just POS imports), corrects the technical detail that main tables are what matters (not [Store]), and adds staged multi-file import instructions (first file Replace, subsequent files Add).
-
Improvement
Stable template key derivation for strategy identity
Shared strategies are identified by a stable template key derived from the strategy name (lowercase, spaces/punctuation to hyphens, deduplicated hyphens, trimmed). This key is used for upsert operations during publishing and for matching installed strategies to catalog updates, allowing strategies to be renamed in the catalog without breaking the link to already-installed copies.
-
Improvement
Full documentation with troubleshooting
Adds comprehensive user documentation at docs/marginmaster/pricing/import-competitor-prices.md covering file format, recognized column names, value parsing rules, the import workflow, how to use competitor prices in strategies and variance columns, log location and contents, and common questions including the POS import durability caveat and SKU matching behavior. Indexed with 18 search keywords including "shop report", "market price", and "load competitor prices".
-
Improvement
Strategy comparison auto-capture with freshness stamping
The fire-and-forget snapshot capture after each strategy run now stamps the snapshot with the current freshness marker via the new optional dataVersion parameter. The capture method is also exposed as an awaited Task<int> for the compare orchestrator to call synchronously between back-to-back runs, preventing the race where fire-and-forget capture overlapped with the next run's FuturePrice reset.
- Improvement One Data Update job, scheduled by day and time
- Improvement Update DevExpress components to 26.1.4
-
Bug Fix
Custom group margin percentages preserved on save
If you previously set up a custom group with a margin percentage and found it wasn't pricing anything, you'll need to open it, re-enter the margin %, and save it again. The app will now keep your settings.
-
Bug Fix
SKU exceptions with blank store scope now display correctly
If you saw a padlock icon showing an exception exists but couldn't see it in the SKU Detail tab, those exceptions will now appear correctly.
-
Bug Fix
SKU exceptions with blank store scope no longer crash the exceptions tab
If a SKU had a pricing exception but the Sku Level Exceptions tab showed nothing, it will now display correctly.
-
Bug Fix
Fixed negative margin rules incorrectly flagged as unrunnable
Pricing rules with negative margins (like -25% to price below cost) now save and run correctly instead of showing a "will be skipped" error.
-
Bug Fix
Negative margins now run correctly for SKU exceptions
If you set a negative margin percentage to price below cost, the exception will now apply correctly when your pricing strategy runs.
-
Bug Fix
Old version detection prompt crash resolved
The application will no longer crash when checking for old Margin Master versions during startup.
-
Bug Fix
Custom group warnings now include step number to prevent misidentification
When you save custom groups, any warnings about missing price levels or below-cost pricing now show both the step number and group name (like "step 6 - PLUMBING L2"), making it easier to find the right row when you have groups with the same name in different strategies.
-
Bug Fix
Group identification in pricing validation warnings
When you save pricing groups and see a warning, it will now show "step 2 - PLUMBING L2" instead of just "PLUMBING L2", making it easy to find the exact row that needs fixing.
-
Bug Fix
Export now validates file access before clearing MMImport table
If a price export to RockSolid fails, your existing queued prices in the POS will no longer be lost.
-
Bug Fix
Restored missing reference in Profit Analyzer
Added back the System.Text reference required by ProfitAnalyzerViewModel, which was causing a compilation failure after the strategy comparison code was recovered.
-
Bug Fix
Strategy steps no longer silently fail when targeting hidden price levels
If you saved a strategy step to update zone pricing or a custom field, then later hid that field from your view, the step will now still work correctly instead of silently skipping all items.
-
Bug Fix
Restore hidden price levels when loading saved pricing rules
When you load a pricing rule that uses a price level not currently shown in your view (like a zone price when zone columns are hidden), the rule will now work correctly instead of silently failing. Your pricing strategies will apply as configured even when you switch between different column views.
-
Bug Fix
Restored price levels now inserted in correct dropdown position
When opening a saved pricing rule, zone pricing levels and other special levels now appear in the right spot in the dropdown menu instead of at the bottom of the list.
-
Bug Fix
Restored pricing levels now insert at enum-ordered position
When you open a saved future price rule, any pricing levels that were previously selected but aren't normally shown will now appear in their correct position in the dropdown list instead of at the very bottom.
-
Bug Fix
Strategy picker checkboxes now update immediately
When you check or uncheck a pricing strategy in the comparison picker, the selection now registers right away. Previously, you had to click somewhere else before the selection would take effect and enable the Compare button.
-
Bug Fix
Strategy picker checkboxes now respond immediately
When selecting strategies to compare, the checkboxes now respond instantly when clicked. The Compare button and the limit of 3 selections will update right away instead of after clicking elsewhere.
-
Bug Fix
Strategy Comparison column headers now render correctly
Fixed a rendering issue where the Strategy Comparison screen's column headers displayed internal system text ("System.Windows.Controls.StackPanel") instead of the intended two-row format with strategy name and metric label. The fix restructures how headers are defined using HeaderTemplate instead of direct Header content, allowing the TreeListControl to properly display strategy names bound from the view model. All nine comparison columns (Baseline and Candidate strategy metrics for projected percentage, delta points, and annual dollars) now show the correct formatted headers.
- Bug Fix Strategy Comparison header rendering corrected
-
Bug Fix
Strategy Comparison tree performance improvement
The comparison tree no longer feels sluggish when scrolling through pricing strategies with many low-coverage items.
-
Bug Fix
Strategy Comparison screen performance improvement
The Strategy Comparison screen will feel more responsive and smoother, especially when scrolling through large lists of items.
-
Bug Fix
Pricing strategy execution now handles initialization failures gracefully
If a pricing strategy fails to run and shows a message about the Future Price panel not being initialized, restart Margin Master. If the problem continues, contact support—there may be an issue loading your store's rounding schemes or cost break data.
-
Bug Fix
Guard against null Future Price panel during strategy execution
If you see an error about the Future Price panel not being initialized when running a pricing strategy, restart Margin Master. If the error continues, contact support as there may be an issue loading your store's pricing configuration data.
-
Bug Fix
Pre-flight check now matches execution logic for custom groups
You'll no longer see warnings about custom group rules that wouldn't actually run anyway.
-
Bug Fix
Pre-flight dialog now excludes inactive custom groups with ACTIVE~FALSE token
The warning dialog before running a strategy will no longer show custom groups that won't actually run.
-
Bug Fix
Empty SKU field no longer terminates pricing strategy execution
If you accidentally left the SKU field blank in a "Set to SKU" pricing rule, that step will now be skipped instead of stopping your entire pricing strategy. You'll see a warning in the pre-flight check so you can fill in the missing SKU before running the strategy.
-
Bug Fix
Blank Set-to-SKU rules no longer terminate pricing strategies
If you previously created a pricing rule with "Set to SKU" selected but forgot to enter a SKU number, the entire pricing strategy would stop working. Now that rule will simply be skipped, and your strategy will continue processing remaining rules normally.
-
Bug Fix
Restored one-click Active checkbox toggling
The Active checkbox now responds immediately when clicked, allowing you to quickly enable or disable SKU exceptions and custom groups without extra steps.
-
Bug Fix
Restore checkbox editing in SKU Exceptions grid
In SKU Exceptions, you can now click once on the Active checkbox to enable or disable an exception instead of having to navigate to the cell first.
-
Bug Fix
Min/max strategies now apply to all store group tables
When you run a pricing strategy with min/max limits across multiple store groups, those limits now correctly apply to all groups instead of only the first one.
-
Bug Fix
Min/max strategies now apply to all main tables in multi-table groups
When running pricing strategies on store groups with multiple tables, min/max rules (like MAP enforcement) now correctly apply to all tables instead of only the first one.
-
Bug Fix
Display warning when Set-to-Sku anchor is missing
If you run a custom pricing group that's set to match another item's price, but that item has been deleted from your POS system, Margin Master will now show a clear "SKIPPED" warning explaining what happened instead of appearing to succeed with no changes.
-
Bug Fix
MAP and IMAP always available in Future Price panel at Ace stores
When reviewing Ace Critical Pricing items, you can now always choose "MAP Price" or "IMAP Price" from the Future Price panel's dropdown to quickly correct pricing violations.
-
Bug Fix
Execute Strategy confirmation now distinguishes deliberate clicks from automatic reruns
When you deliberately run Execute Strategy again within 2 minutes of finishing the previous run, the system will no longer ask you to confirm — it knows you meant to do it. The confirmation only appears for unexpected automatic runs.
-
Bug Fix
Individual SKU exception saves now work reliably
When editing a single SKU exception, your changes will now save properly. If a save fails, you'll see which SKUs had problems and can try again — changes won't be silently lost.
-
Bug Fix
SKU exception Type column now updates immediately after price assignment
When you set a price level for a SKU exception that previously showed "U" (unpriced), the Type column will now immediately show the correct letter (R/M/D/C/S) representing the assigned price level, without needing to close and reopen the dialog.
-
Bug Fix
Import now reports accurate SKU match counts on all POS systems
If you use Epicor or Compass POS, competitor price imports will now show the correct "SKUs applied" count instead of falsely reporting that your items weren't found.
-
Bug Fix
Pricing strategies now process inventory when Store Grouping enabled without groups
If you accidentally turned on Store Grouping without setting up any groups, automatic pricing will now work correctly instead of silently skipping all items.
-
Bug Fix
Strategy rules now save the correct price level
Fixed MM-1397 where a rule set to "55% Margin" could be saved as "Store Cost" and reprice items incorrectly. Store 5088 had a rule that should have set 55% margin but instead repriced 395 items to cost on every strategy run. The root cause was that the system saved which position a price level was in a list, not which level was actually selected. When zone price levels were restored into one list but not another, the positions fell out of sync and the wrong level was serialized. The system now records the actual price level selected, making the save process immune to list position changes.
- Bug Fix Fixed critical strategy serialization error when required columns were hidden
-
Bug Fix
Margin cost basis now retained when loading custom groups
Custom groups set to calculate margin from Average Cost or Replacement Cost will now stay on that cost basis when you reopen and save them.
-
Bug Fix
Active status filter now correctly filters exceptions
The Active filter now correctly shows only active exceptions instead of showing everything.
-
Bug Fix
Active/Inactive filter now works correctly in SKU exceptions
Filtering SKU exceptions by Active or Inactive status now shows the correct records without changing their active state.
-
Bug Fix
Unreachable modal dialog behind splash screen
The old version uninstall prompt can now be clicked and responded to instead of being stuck behind the startup screen.
-
Bug Fix
Strategy comparison snapshot selections now persist after refresh
When you refresh the list of saved pricing snapshots, your currently selected baseline and candidate snapshots will stay selected instead of resetting.
-
Bug Fix
Pre-flight check now matches execution logic for SKU exceptions
Pre-flight warnings for SKU exceptions now accurately reflect which rules will actually run.
-
Bug Fix
Pre-flight dialog now only shows SKU exceptions that will execute
The warning dialog before running a strategy will no longer show SKU exceptions that won't actually run.
-
Bug Fix
Restore checkbox editing in Custom Groups grid
In Custom Groups, you can now click once on the Active checkbox to activate or deactivate a group item instead of having to navigate to the cell first.
-
Bug Fix
Null price level columns no longer break min/max calculations
Min/max strategies now work correctly even when comparison or zone price columns are empty for some items.
-
Bug Fix
Apply button now targets only the critical pricing list
Clicking "Apply" in the Future Price panel now updates only the critical pricing items shown in the grid, not every item in your store. The list stays on screen after Apply so you can see the corrected prices immediately.
-
Bug Fix
Apply now targets the critical pricing list, not the whole store
When viewing Ace Critical Pricing results, clicking Apply in the Future Price panel now changes only the items shown in the list, not every item in your database.
-
Bug Fix
Critical pricing steps skip safely when selection rules cannot load
If any pricing rule can't be applied safely (for example, if MAP data is missing), that correction is skipped and reported in the results message, preventing accidental store-wide price changes.
-
Bug Fix
Custom group store condition deletions now persist
When you remove stores from a custom group's conditions, those changes now save correctly instead of being lost.
-
Bug Fix
Resolved Unassigned filter now updates correctly after fixing SKUs
In the Resolve Unassigned workflow, SKUs you've just fixed will now disappear from the list immediately after you save, making it easier to track your progress through unassigned items.
-
Bug Fix
Import no longer reports false "SKUs not found" failures
The import now correctly tells you how many prices were applied. Previously it could report "SKUs not found" even when the prices had successfully loaded into your pricing grid.
-
Bug Fix
Main table discovery now handles missing store routing information correctly
The pricing grid and reports now find your inventory correctly when store filters aren't set, rather than showing empty results.
-
Bug Fix
Product codes with apostrophes no longer cause export failures
Products with apostrophes or quotes in their codes (like 1/2" X 6') now export correctly to RockSolid.
-
Bug Fix
Corrected service dependency lifetime registration
Changed SittingMarginQueryService and StrategyComparisonService from singleton to transient registration to match the lifetime of ISelectionService, preventing potential dependency injection errors.
-
Bug Fix
OneClick Pricing Sensitivity Mix corrected for vendor and labels
OneClick statistics now show the correct price sensitivity labels and categories for your vendor (Ace Hardware or Do it Best), with all sensitivity codes properly displayed.
-
Bug Fix
Custom group edits no longer lost when switching groups
When editing custom groups, switching between groups no longer asks if you want to save, and your changes are kept until you click Save or close the window.
-
Bug Fix
Switching custom groups no longer discards unsaved changes
You can now edit multiple custom groups without saving after each one—your changes stay in place until you click Save or close the window.
-
Bug Fix
Preserve min/max configuration when model is temporarily missing
Loading and re-saving a strategy in a database that's missing the referenced min/max model no longer permanently deletes the step's min/max configuration. The InstructionSet and StrategyFormulaService now keep the ACTIONMINMAX reference even when the model lookup fails, preventing accidental data loss.
-
Bug Fix
Summary panel now populates for critical pricing lists
The Summary panel at the bottom now shows how many critical pricing items have been corrected (have a future price set).
-
Bug Fix
Price level selection properly detects unsaved changes
If you select a pricing method but leave the value blank, the Save button will now activate so you can be prompted to complete or discard your change.
- Bug Fix Strategy serialization now uses recorded level instead of list position
-
Bug Fix
Null-safe handling of missing rule text in legacy exceptions
Added null safety when processing the RuleText field during legacy exception migration. Exceptions with missing rule text no longer crash the migration process.
-
Bug Fix
Prices now export correctly on non-US regional settings
Computers configured with European number formats (comma as decimal separator) now export prices correctly to RockSolid.
-
Bug Fix
Removed vendor- and POS-specific always-show overrides
All stores now see the same consistent behavior: price levels appear in the dropdown only when the matching field is visible in your current layout.
-
Bug Fix
Handle null pricing levels in min/max calculations
The min/max case expression now NULL-guards the level column (Comp5, zones, etc.) so that NULL values are read as 0 (no clamp) instead of propagating NULL into FuturePrice. Previously, a NULL Comp or zone level would cause the entire CASE statement to evaluate as UNKNOWN and write NULL into the FuturePrice column.
-
Bug Fix
Active flag now persists correctly on save
The Active column in the database is now updated alongside rule text during saves. Previously only the rule text was written, causing the Active flag to diverge and break pre-flight filtering queries.
-
Bug Fix
Disabled ACE connection pooling to prevent inherited read-only sessions
Import and export built byte-identical connection strings, so ADO.NET handed the export the import's pooled ACE session. Because an ACE session's open mode is fixed when first opened, a read-only import session made the export fail with no filesystem evidence. The connection string now includes `OLE DB Services=-4` to disable pooling, ensuring each operation gets its own session with the correct access mode.
-
Bug Fix
SKU-level exceptions rounding scheme now preserved
SKU exceptions with specific rounding schemes will now keep those schemes when you reopen them.
-
Bug Fix
Strategy run timestamp only updated after actual execution
If you cancel a strategy run before it starts, the app will no longer think you just ran it and ask if you want to run it again immediately.
-
Bug Fix
FuturePricePanel level-list refresh on view change
The FuturePricePanel now exposes RefreshPriceLevelList(), called by MainMMViewModel when the active column view or selection box view name changes (OnActiveColumnViewName_Changed / OnActiveSelectionBoxViewName_Changed event handlers). The refresh captures the selected enum, rebuilds the ItemsSource from the service, re-applies the specific-value captions (Cost Break, Margin, Fixed Retail, SKU), and restores the selection to avoid a transient TwoWay binding swap. MainMMViewModel's own PriceLevelList (indexed against the panel's selection in CanTakeSnapshot) rebuilds in lockstep. The Edit Columns and Edit Selection Boxes dialog closes also trigger the refresh (MainMMViewModel.Dialogs3.cs) so membership changes take effect immediately.
-
Bug Fix
Price level preserved when not in current column view
If you configured a custom group or SKU exception using a price level that isn't currently visible on this computer, it will now keep that price level setting instead of losing it when you save.
- Bug Fix A strategy turns on the columns its rules price from
- Bug Fix A licence confirms a store's identity, it never redefines it
- Bug Fix An empty store-routing list means no filter, not zero stores
- Bug Fix Give the grid and strategy path the same fallback
- Bug Fix A fallback must fall back to something real
- Bug Fix Never drop a database table we do not recognize
- Bug Fix Competitor price import reported a false failure, and add Replace/Add per column
- Bug Fix Fix the seed index that could never be created, and the duplicate rebuild pass
- Bug Fix Reconciler DELETE was ambiguous on every run
- Bug Fix Heal a store whose vendor renumbered it
- Bug Fix Refresh the SKU exception Type column after a future price is set
- Bug Fix Fix self-perpetuating startup index rebuild (shrink was running last)
- Bug Fix Fix silent save failures on individual SKU exceptions and custom groups
- Bug Fix Fix MM-1387 + MM-1392: custom-group rounding display, Mi9 User4 recency window
- Bug Fix Stop DMV index bloat on main tables, auto-disable failing indexes
- Bug Fix Fix app lockup after Ace Critical Pricing "Save as Strategies"
-
Cloud Sync
Shared strategy API endpoints
Added three new API endpoints under api/v2/SharedStrategy: GET (catalog list filtered by vendor type), GET /{templateKey} (full definition including steps and bundled rounding schemes), and POST (publish with machine-hash authorization). Catalog items include metadata only; full definitions are fetched separately to minimize bandwidth. The server stores definitions as opaque JSON, allowing step RuleText content to evolve without server changes.
-
Data Import
Smart value parsing and validation
If a cell is blank or contains text like "N/A", that price is skipped and the existing value is kept — nothing is ever accidentally zeroed. Every import writes a log showing what was recognized, what was ignored, and any rows that couldn't be imported.
-
Data Import
Export service now supports tree views
`ExportService` now binds to `DataViewBase` instead of `TableView`, enabling Excel export from both grid and tree list controls. This allows users to export the new hierarchical comparison results while preserving the existing flat-grid export functionality elsewhere in the application.
-
Data Import
Durable storage in POS data
Competitor prices are stored with your POS data and will be replaced the next time you import POS data — keep your spreadsheet and re-import after each POS import.
-
Data Import
Template download for correct file format
Click "Download Template" to get a pre-formatted Excel file you can fill in with your competitor prices—the headers and format are already correct.
-
User Interface
Removed duplicate title from Strategy Execution Summary
The Strategy Execution Summary now has a cleaner look with just one title instead of two.
-
User Interface
Dynamic "Set Future Price to" filtering based on active views
Extended price levels like Level3, Comp prices, or zone pricing now appear in the "Set Future Price to" dropdown only when you've added those fields to your column layout or selection boxes. Basic options like Current Price, Future Price, and Store Cost are always available.
- User Interface Dynamic "Set Future Price to" dropdown filtering
-
User Interface
Relocated strategy commands to Strategy Manager toolbar
The buttons to browse premade strategies and compare strategy results are now at the top of the Strategy Manager screen instead of in the Strategy menu.
-
User Interface
Consolidated strategy tools into Strategy Manager
To access premade strategies or compare results, open Strategy Manager (Ctrl+S)—the buttons are now in the toolbar at the top of that window.
-
User Interface
Maximum selection limit enforced in strategy comparison
When selecting pricing strategies to compare, you can now pick up to three. After checking three strategies, any unchecked boxes will grey out. Simply uncheck one of your selections to enable the others again.
-
User Interface
Selection limit enforced in Strategy Comparison picker
When you select three pricing strategies to compare, the checkboxes for other strategies will grey out so you know you've reached the limit.
-
User Interface
Renamed baseline columns to "Current" throughout comparison grid
The comparison grid now uses "Current" instead of "Sitting" to describe your store's existing prices, and shows how much money each strategy would gain or lose "vs Current" prices.
-
User Interface
Renamed baseline columns to clarify comparison context
When comparing pricing strategies, columns now clearly show they're comparing against your current prices, making it easier to understand potential margin impact.
-
User Interface
Replaced flat comparison grid with hierarchical tree view
Comparison results now appear as a tree you can expand and collapse. Start with stores, then click to see departments within each store, then classes within each department.
-
User Interface
Hierarchical tree view replaces flat comparison grid
Results now show as a tree you can expand: stores at the top level, departments inside stores, and classes inside departments. Collapsed stores show the store total; expand to see the breakdown.
-
User Interface
Clearer confirmation message before strategy comparison reruns
Before rerunning strategies for comparison, the confirmation message now tells you if your active strategy will need to be restored afterward, so you won't be surprised by an extra step.
-
User Interface
Clearer explanation of active strategy restore during comparison
Before running a comparison, you'll now see a clear explanation if your active strategy needs to be rerun afterward to put your prices back the way they were.
-
User Interface
Two-row comparison headers with color-coded strategy columns
Strategy comparison results now show clearer column headers with strategy names in bold and color-coded columns (blue, green, amber) to make it easier to compare multiple pricing strategies.
-
User Interface
Color-coded comparison columns with two-row headers
Each strategy in the comparison now has its own color (blue, green, or amber) with the strategy name shown above each column group, making it much easier to compare results at a glance.
-
User Interface
Grouped strategy column headers
Each pricing strategy's columns are now grouped together with a clear header showing the strategy name, making it easier to compare results across different strategies at a glance.
-
User Interface
Enhanced column organization with header bands
Each pricing strategy now has a clear header label spanning its columns, making it easier to compare "Proj %", "Δ pts", and "vs Current $/yr" values across different strategies without confusion.
-
User Interface
Honest sensitivity score display
Sensitivity scores now show the real number (like 56) instead of exaggerating tiny differences. The color still shows how it compares to similar stores, but only when we have enough data to be confident.
-
User Interface
Strategy menu reorganization
When you click the Strategy menu, you'll now find Strategy Utilities at the very top instead of at the bottom, making it faster to access common utility functions.
- User Interface Automatic refresh after view changes
-
User Interface
Removed strategy-versus-strategy comparison columns
Removed confusing columns that compared one pricing strategy to another — now every strategy just shows its impact compared to what you're charging today.
-
User Interface
Simplified Strategy Comparison grid layout
Removed redundant dollar amount columns that showed both absolute values and comparisons to baseline. The comparison now displays only the "vs Current $/yr" columns for each strategy, reducing visual clutter and focusing users on the meaningful comparison metric.
-
User Interface
Improved progress message during strategy restore
The progress message when restoring your active strategy after a comparison now makes it clear this is a restore step, not another comparison run.
-
User Interface
Enhanced progress message during strategy restore
When the app restores your active strategy's prices after a comparison, the progress message now clearly explains what's happening.
-
User Interface
Sensitivity and Blind % columns added to strategy comparison tree
Strategy comparison reports now show price sensitivity scores and blind percentages for each store, department, and class, helping identify where small price increases are safest.
-
User Interface
Strategy Comparison screen header improvements
Column headers in the Strategy Comparison grid now properly bind to strategy names (BaselineName, CandidateName, CandidateCName) and render them with consistent formatting: bold strategy name on the first line with text trimming for long names, and a semi-transparent metric label on the second line.
- User Interface Improved header text display
-
User Interface
Streamlined header templates
Removed redundant strategy name labels from individual column headers since the band headers now provide this context. Column headers now display only their metric type (e.g., "Proj %", "Δ pts"), making the grid more compact and easier to scan.
-
User Interface
SKU counts added to row names
Each store, department, and class row now shows how many SKUs it contains in parentheses.
-
User Interface
SKU counts displayed in row names
Each department and class now shows how many products it contains directly in its name.
-
User Interface
Clearer sitting margin column labels
The comparison screen now clearly labels margins as "Sitting %" so you know exactly what type of margin you're looking at.
-
User Interface
Clearer "sitting margin" column labels
Column headers now say "Sitting %" to make it clearer these are sitting margin percentages, not other types of margins.
-
User Interface
Pre-flight validation now identifies missing SKU in set-to-SKU rules
Before running a pricing strategy, you'll now see a clear warning if any step has "Set to SKU" selected but the SKU field is empty, so you can fix it right away.
-
User Interface
Progress splash screen during "Just Run"
While applying corrections, a splash screen displays progress through each category (e.g., "Setting future prices: CP<MAP [1 of 3]"). After completion, the results message shows a detailed breakdown of items priced per category, or notes if any step was skipped due to missing data.
-
User Interface
Import Competitor Prices dialog
The Import Competitor Prices window shows you exactly what it found in your file before importing, and warns you to re-import after each POS data import since competitor prices are stored with POS data.
-
User Interface
Dropdown refreshes automatically after view edits
When you add or remove columns or selection box fields and save your changes, the "Set Future Price to" dropdown updates instantly to reflect the new available options.
-
User Interface
Auto-capture toggle added to Compare Strategies dialog
You can turn automatic snapshots on or off using a checkbox in the Compare Strategies screen.
-
User Interface
Updated grand total label in Strategy Comparison
The grand total section now displays "Current:" instead of "Sitting:" to maintain consistent terminology throughout the screen.
-
User Interface
Improved restoration dialog messaging
Dialog messages now better explain what happens to your pricing data after a comparison and what each option does.
-
User Interface
Updated comparison run confirmation message
The confirmation dialog before running stale strategies now accurately describes the new restore behavior, explaining that the user will choose whether to reapply their active strategy rather than stating it will automatically rerun.
-
User Interface
Enhanced sensitivity tooltips
Hovering over a sensitivity score now shows both the easy-to-read relative score and the detailed absolute score with full breakdown.
-
User Interface
Enhanced Manage Custom Groups hamburger menu
Two new options are available in the Manage Custom Groups hamburger menu: copying groups from other strategies and finding duplicate SKUs.
-
User Interface
"Unassigned" status filter added to SKU Level Exceptions
You can now filter the SKU exceptions list to show only "Unassigned" rows—active exceptions that have no price level and never price anything.
-
User Interface
Enhanced run summary message for missing anchor SKU
The run summary will now tell you exactly which item is missing and remind you to edit your pricing group to choose a different price level.
-
User Interface
Completion message shows per-category pricing results
The results message now shows exactly how many items were corrected in each category, making it easy to see what changed.
-
User Interface
Read-only state enforcement in Strategy Manager
The ManagePricingStrategyV2View displays a read-only banner ("Shared strategy vN — read-only. Use 'Copy Current Strategy' to make an editable copy.") above the step list when the loaded strategy has a shared-strategy provenance marker. The step detail panel and bottom grid controls are disabled (IsEnabled bound to IsCurrentStrategyShared via BooleanNegationConverter). All mutating commands (add/edit/delete step, rename strategy, save changes) check BlockIfShared and show an informational message directing the user to copy the strategy first. The publish menu item is visible only when IsSupportMachine is true (gated on the ApplicationSettingsService flag set by CheckIsSupportMachine during startup). Strategy export, execution, activation, and backup remain fully enabled for shared strategies.
-
User Interface
Removed grain selector dropdown from results toolbar
The "View by" dropdown is gone—just expand or collapse tree rows to see the level of detail you want.
-
User Interface
Added help text when no min/max strategies exist
The pricing panel now shows helpful guidance when you need to create a min/max strategy.
-
User Interface
Just Run now shows Summary panel
The Just Run flow now calls BuildSummaryAsync with the critical pricing predicate after loading the grid, so the Summary panel displays the count of items with Future Price <> 0 within the critical pricing set. This provides immediate feedback on how many violations have been addressed.
-
User Interface
Updated documentation reflects new "Just Run" behavior
The Critical Retail Pricing documentation now describes "Just Run" as "Instant Correction" rather than "Instant Analysis," clarifying that the button applies pricing changes immediately and explaining that both "Just Run" and "Save as Strategies" produce identical corrections—the difference is timing (immediate one-time fix vs. automated workflow integration).
-
User Interface
Automatic column display offer
After importing, Margin Master asks if you want to add the imported competitor columns to your current view so you can see the prices right away — click Yes and they appear in the grid and selection boxes.
-
User Interface
Import window shows Replace/Add controls and existing value counts
The import window now tells you how many items already have prices in each competitor field, so you can decide whether to add your prices or replace what's there.
-
User Interface
Import dialog shows existing value counts before import
When a file is loaded, the dialog queries the main tables to count how many items already carry values for each Comp level, displaying for example "101,391 of 106,565 items currently have a Competitor 1 price." This count appears next to the Replace/Add choice and is what makes the choice informed rather than blind. A note explains when existing values come from the POS (common on Epicor and Paladin). The query is non-blocking and the import can proceed even if the count fails.
-
User Interface
Visual indicators for groups that cannot price
Incomplete custom groups will now show a red error icon in the list, so you can see which ones need attention without opening each one.
-
User Interface
Manage Pricing Strategy dialog enhancements
The Manage Pricing Strategy dialog now displays a banner above the step list when the loaded strategy is a shared install ("Shared strategy v{N} — read-only. Use 'Copy Current Strategy' to make an editable copy."). All mutating operations (Add Step, Delete Step, Reorder, Edit Step, Delete Strategy) are blocked with a friendly message directing users to copy the strategy first or manage it from the catalog. Support machines see a new "Publish Shared Strategy" menu item; the dialog surfaces build-time warnings (view-dependent operands, missing groups/exceptions) and prompts for confirmation before uploading.
-
User Interface
Improved Future Price panel min/max selection
The pricing panel now shows a helpful message when no min/max strategies exist, with instructions on how to create one.
-
User Interface
Unassigned status filter in Sku Level Exceptions
You can now filter the SKU exception list to show only entries with no price level set, making it easier to review what will be affected by bulk actions.
-
User Interface
Replace mode requires confirmation before clearing values
When at least one column is set to "Replace all existing values," the Import button shows a confirmation dialog stating how many existing prices will be erased and from which fields. This prevents accidental data loss. The dialog clarifies that values from the POS will return on the next POS import, but user-entered prices are not recoverable.
-
User Interface
User notification when strategy columns are auto-enabled
When the system automatically adds columns for a strategy, users now see a message identifying which strategy needed the columns and which ones were added. This prevents confusion from layouts silently rearranging and provides transparency about why the view changed.
- User Interface User notification when strategy columns are added
-
User Interface
Excel export for comparison results
The Strategy Comparison dialog includes an "Export to Excel" button that exports the comparison grid (all rows plus the grand total) to a spreadsheet, allowing users to share the A/B analysis with stakeholders or archive it for review.
-
User Interface
Strategy comparison picker and results states
The Compare Strategies window now starts with a list of all your strategies showing their status, making it easier to pick which ones to compare.
-
User Interface
Improved snapshot labeling
Comparison snapshots now prefer the strategy name (when available) over the custom label when displaying in the comparison picker and results grid, making it clearer which strategy each result represents.
-
User Interface
Strategy Manager read-only banner and menu integration
The Strategy Manager displays a banner above the step list for shared strategies ("Shared strategy vN — read-only. Use 'Copy Current Strategy' to make an editable copy") and disables the step detail panel, bottom bar controls, and all mutating menu items. Support machines see a new "Update or Create Shared Strategy" menu item; all users see the "Get Premade Strategies" menu item in the main Strategy menu.
-
User Interface
Demo mode restriction
The Import Competitor Prices command is disabled in demo mode to prevent modification of sample data, consistent with other import and data-modification features.
-
User Interface
Snapshot management controls
After capturing a new snapshot, it automatically becomes the "Candidate (B)" compared against your previous snapshot as "Baseline (A)", making it easy to test a new strategy against what you were doing before.
-
Database
StrategyResultSnapshot and StrategyResultSnapshotDetail tables
Introduces two new local-only tables (StrategyResultSnapshot header and StrategyResultSnapshotDetail rows) that store labeled snapshots of the sitting-margin query. Each snapshot captures the current-price sales, future-price sales, and COGS at the Store/Dept/Class/Velocity/VendorOwned grain, preserving the exact dollar totals so they roll up to any grain (department → store → org) without rounding error. Snapshots survive the rebuild between two strategy runs and are never sent to the cloud. The tables are created automatically on first use via idempotent CREATE IF NOT EXISTS scripts.
-
Database
Shared strategy provenance tracking
Installed shared strategies write a provenance marker to GlobalFileConfig (Section=SHAREDSTRATEGY, Name=strategy name, Key=Origin) containing the template key, version, SharedStrategyId, and install timestamp as JSON. The presence of this marker is what makes a strategy read-only; the installer queries it to determine install state (not installed / current / update available) and the Strategy Manager queries it to enable/disable edit controls. Install and update operations trigger automatic strategy backups with reason "shared-strategy-install" or "shared-strategy-update".
-
Database
Strategy snapshot freshness stamp storage
Adds a DataVersion column to the StrategyResultSnapshot table to store the freshness stamp at capture time. Includes an idempotent ALTER migration for existing customer databases that were created before this feature. Pre-feature snapshots have null DataVersion and are treated as never current.
-
Database
StrategyResultSnapshot.DataVersion column
Adds a nullable DataVersion column to the StrategyResultSnapshot table to store the freshness stamp at capture time. An additive migration ensures existing customer databases pick up the new column. Snapshots captured before this feature (DataVersion = null) are always treated as Not Current.
-
Database
Shared strategy models and API endpoints
Adds SharedStrategyModels.cs (SharedStrategyCatalogItem, SharedStrategyDefinition, SharedStrategyStep, SharedStrategyOrigin, PublishSharedStrategyRequest/Response) and three new API client methods: GetSharedStrategyCatalogAsync (filters by vendor type, returns metadata only), GetSharedStrategyDefinitionAsync (fetches the full body by template key), and PublishSharedStrategyAsync (upserts with machine-hash validation). The server stores definitions as opaque JSON blobs — only Margin Master parses RuleText, so step content can evolve without server changes. Rounding schemes travel only when not auto-seeded (KnownSchemeType schemes are skipped); the installer creates missing schemes but never overwrites same-name local schemes. Custom groups, SKU exceptions, and min-max strategies deliberately do not travel — they are store-specific.
-
Database
Dual-table update strategy
Imported prices appear in your grid immediately and are saved with your POS data, but remember to re-import after each POS data import since that replaces the [Store] table.
-
Architecture
Pure policy class with comprehensive test coverage
The filtering logic is isolated in a new FuturePriceSetToLevelPolicy class with 107 lines of unit tests covering pseudo-levels, core levels, extended fields, view membership rules, Bloom Retail suppressions, and the removal of vendor/POS escape hatches. The policy receives a unified set of fields from both the column view and selection box view and makes purely functional decisions about each level's availability.
-
Architecture
Tree building logic added to comparison math service
New `BuildTree` method in `StrategyComparisonMath` constructs the three-level hierarchy by grouping baseline, candidate, and optional third-candidate rows by store, department, and class keys. Each node applies the same sitting-margin and profit-delta calculations as the flat rows, ensuring exact reconciliation. Unit tests verify that store totals sum to the grand total and department/class children sum to their parent nodes.
-
Architecture
Added run attribution tracking to identify deliberate vs. automatic strategy executions
Implemented a new ExecuteStrategyFromMenu command that wraps the core ExecuteStrategy method and explicitly marks runs as "Menu"-triggered. The system now defaults to marking runs as "Unattributed" instead of assuming they came from the menu, making it easier to identify and diagnose unexpected duplicate executions. This tracking also feeds into telemetry for better diagnosis of the rare duplicate-execution issue.
-
Architecture
Thread-safe modal dialog helper added
Added ShowModalSafeAsync method that ensures message boxes can be safely shown from any thread by first closing the splash screen verifiably (via EnsureSplashClosedAsync) and then marshaling the dialog call to the UI thread. This replaces unsafe HideSplashScreen calls that could not be verified and left modals unreachable.
- Architecture Policy-based level offering logic
-
Architecture
Sitting margin calculation extracted to SittingMarginMath and SittingMarginQueryBuilder
Extracts the sitting-margin roll-up (gross profit / sales at current price and future price) from SittingMarginTelemetryService into a standalone static class, SittingMarginMath, and the Profit Analyzer's bucket SQL (the SELECT…GROUP BY that sums last-12-months sales/COGS into price bands) into SittingMarginQueryBuilder. This makes the sitting-margin calculation a single source of truth shared by the on-screen Profit Analyzer, the deferred telemetry post, and the new Strategy Comparison product, eliminating duplicated logic and ensuring all three measure identically. The shared valid-item filter excludes obvious pricing errors symmetrically for both current and future prices.
-
Architecture
Tree node math reconciles at every level
Every tree node—store, department, and class—computes its measures (projected margin, delta points, annual dollars) using the same dollar-weighted sitting margin math over its own subset of items. Each parent's totals exactly equal the sum of its children's totals, ensuring perfect reconciliation from class level up to store level. A new test verifies this reconciliation property.
-
Architecture
Below-cost detection logic added
Added BelowCostPriceDetector helper class that analyzes pricing rule text to identify below-cost scenarios: negative margins, cost-based pricing with subtractions (e.g., Store Cost minus 10%), and flat retail prices below item cost. The detector reads the stored rule text directly rather than UI state, following the same discipline as MissingPriceLevelDetector to ensure what's checked cannot drift from what's stored. Only certain shapes are reported to avoid false positives that would train users to click through warnings. Includes 106 unit tests covering all detection scenarios.
-
Architecture
Shared strategy provenance tracking and machine-hash validation
Each installed shared strategy writes a provenance marker (SharedStrategyOrigin: template key, version, server ID, install timestamp) into GlobalFileConfig (Section=SHAREDSTRATEGY, Key=Origin); the presence of this JSON is what makes a local strategy "shared" (static/read-only). Strategies without the marker — every pre-existing strategy — behave exactly as before. The publisher and the CheckMachine support-machine probe share the same machine-hash algorithm (SHA256 of "RS-SupportMachine-2024-Verify!" + uppercased machine name, lowercase hex); the server validates every publish request against the SupportMachine registry and returns 403 for non-support machines. Template keys are derived from strategy names (lowercase, trimmed, hyphen-separated) and serve as the upsert identity — publishing to the same key updates the existing shared strategy for all stores.
-
Architecture
Refactored dialog services for Strategy Manager
The dialog services for the Shared Strategy Catalog and Strategy Comparison views have been moved from MainMMViewModel to ManagePricingStrategyV2ViewModel, aligning with the UI reorganization. The frozen-surface contract test has been updated to reflect the removal of the two public methods from the main window's viewmodel.
-
Architecture
Removed obsolete strategy menu commands
Removed ShowSharedStrategyCatalog and CompareStrategies commands from MainMMViewModel and their associated dialog service registrations in MainMMWindow.xaml. These commands and dialogs have been relocated to ManagePricingStrategyV2ViewModel, streamlining the main window's responsibilities.
-
Architecture
Table-driven sensitivity mapping with SQL generation
Implemented table-driven code-to-score mappings with generated SQL CASE statements, pinned by unit tests. Moving a code between rungs (e.g., adjusting DIB "E" from 50 to 25) requires only a one-number change in the map, automatically reflected in all SQL queries. Unit tests lock the contract: shared rung values, units-weighted math, null (never zero) scores when no assigned volume exists, additive roll-ups, and the blind/sensitive share and coverage companion metrics.
-
Architecture
New StrategyColumnRequirementPolicy service
Introduced StrategyColumnRequirementPolicy to determine which columns a strategy requires based on its rules. The policy is deliberately minimal—it only requests columns when adding them would actually make a level usable, avoiding unnecessary layout changes. For example, it won't request Retail/Level1/Level2 columns at Bloom Retail stores where those levels are suppressed regardless of view settings. Includes 23 new unit tests covering boundary conditions and ensuring the policy adds exactly what's needed and nothing extra.
-
Architecture
Standalone sitting-margin query service
Extracted the sitting-margin bucket query (the SELECT…GROUP BY that aggregates last-12-months sales/COGS into price bands at current and future price) from ProfitAnalyzerViewModel into a standalone, reusable SittingMarginQueryService. The query logic now lives in SittingMarginQueryBuilder as a single source of truth, and the roll-up math (gross profit / sales) lives in SittingMarginMath, ensuring the on-screen Profit Analyzer, the sitting-margin telemetry post, and the new Strategy Comparison product all measure margins identically. Added comprehensive unit tests (StrategyComparisonMathTests) locking the A/B diff math: dollars are additive so overall = Σ store = Σ dept, the grand total is dollar-weighted (not an average of per-grain percentages), and candidate-vs-baseline dollars is the incremental profit the new strategy makes over the old one.
-
Architecture
Price level assignment policy for bulk actions
A new BulkAssignableLevelPolicy class defines which price levels the "Assign Price Level" action may offer. Only self-contained levels (Retail, Level 1, Level 2, CurrentPrice, StoreCost, vendor-specific levels like Ace_MSURetail, and zone levels) are offered; levels that require a per-rule value (Margin %, Fixed Retail, Cost Break, Set-to-SKU) are excluded because assigning them in bulk would recreate the exact "cannot price" state the action exists to fix. Unit tests pin this exclusion list.
-
Architecture
Removed legacy synchronous ExportRockSolid method
Dropped the dead sync ExportRockSolid method, which carried a second copy of the concatenated DELETE/INSERT pattern with the same apostrophe and culture bugs. All export operations now route through ExportRockSolidAsync with the corrected, parameterized approach.
-
Architecture
Strategy freshness service
Introduces StrategyFreshnessService and StrategyFreshnessStamp to compute and validate freshness stamps. The stamp is composed from vendor catalog RowVersion (for Ace/DIB/EJ), POS ImportProcessing max date, and a SHA-256 content hash of the strategy's GlobalFileConfig rows (which have no modification timestamps). Unit tests lock the contract: snapshots with missing stamps are never current, and any component change invalidates the stamp.
-
Architecture
Standalone sitting-margin query service and math
Extracted the sitting-margin bucket query (the SELECT…GROUP BY that aggregates last-12-months sales/COGS into price bands at current and future price) from ProfitAnalyzerViewModel into a standalone, reusable SittingMarginQueryService. The query logic now lives in SittingMarginQueryBuilder as a single source of truth, and the roll-up math (gross profit / sales) lives in SittingMarginMath, ensuring the on-screen Profit Analyzer, the sitting-margin telemetry post, and the new Strategy Comparison product all measure margins identically. Added comprehensive unit tests (StrategyComparisonMathTests) locking the A/B diff math: dollars are additive so overall = Σ store = Σ dept, the grand total is dollar-weighted (not an average of per-grain percentages), and candidate-vs-baseline dollars is the incremental profit the new strategy makes over the old one.
- Refactor Finish the store-settings move out of GlobalFileConfig
- General Merge pull request #1310 from retailersoft/fix/schedule-migration-at-startup
- General Migrate the background schedule on startup, not on opening Options
-
Infrastructure
Custom groups service enhancements
Extended CustomGroupsService with new methods to support the copy and duplicate-finder features: GetGroupCountsByStrategyAsync returns the count of custom groups per strategy for the picker list; GetGroupsWithSkuCountsAsync loads all groups in a strategy with their SKU counts for the picker grid; CopyGroupToStrategyAsync performs the transactional copy of one group's settings and SKU list to a new GroupID in another strategy; GetGroupSkuRowsAsync retrieves all SKU memberships for duplicate detection; and RemoveSkuFromGroupAsync deletes a single (GroupID, SKU) row. Two new helper classes handle naming (GroupCopyNameHelper picks the next free "- Copy" variant) and duplicate detection (DuplicateSkuFinder groups SKUs by membership count and filters to those in 2+ groups).
-
Infrastructure
Added regression tests for derived column notifications
Implemented source contract tests that verify all editing paths that reshape SKU exception rules properly notify the grid's derived columns (Type and FuturePriceAction). These tests prevent future code changes from reintroducing the same notification oversight by scanning the view model source for instruction mutations that mark the row dirty and ensuring they include the required property change notifications.
- General Merge pull request #1309 from retailersoft/fix/update-stops-service
-
Infrastructure
Added null-safety throughout exception loading
Added null checks and null-coalescing throughout the exception loading and migration code path to prevent any single malformed exception record from crashing the entire load. Null or empty RuleText fields are now handled gracefully, and null rows are filtered out before processing.
-
Infrastructure
Export service widened to support tree exports
ExportService.View property type changed from TableView to DataViewBase (the common base class for both TableView and TreeListView) so Excel export now works for both flat grids and hierarchical tree lists.
-
Infrastructure
Added comprehensive test coverage for store routing normalization
Added 251 lines of tests in StoreRoutingKeyNormalizationTests to pin the meaning of empty store routing lists and prevent regression. Tests cover the exact incident scenario (store 12180), single-store and multi-store configurations with no groups defined, and all database shapes found across customer sites. Full test suite remains green at 1,502 tests.
- General Do not swap the install folder while a headless import holds it
-
Infrastructure
Shared strategy models and API endpoints
New model classes (SharedStrategyCatalogItem, SharedStrategyDefinition, SharedStrategyStep, SharedStrategyOrigin, PublishSharedStrategyRequest/Response) define the wire format and local provenance structure. ApiClientService adds three endpoints: GET api/v2/SharedStrategy (catalog list filtered by vendor type), GET api/v2/SharedStrategy/{key} (full definition), and POST api/v2/SharedStrategy (publish with machine hash). SupportMachineHasher centralizes the SHA256(salt + MACHINENAME) computation used by both CheckIsSupportMachine and publish authorization. SharedStrategyInstallService and SharedStrategyPublishService encapsulate all materialization, validation, and round-trip logic. PricingStrategyService adds RegisterInstalledStrategyAsync to notify the cached strategy list of a directly written strategy without activating it. Comprehensive unit tests (SharedStrategyTests) pin the machine hash algorithm, template key derivation, provenance JSON round-trip, and catalog row state logic.
-
Infrastructure
Updated approved test baseline
Added the CompareStrategies command to the MainMMViewModel frozen-surface contract test, keeping test expectations in sync with the new feature.
-
Documentation
Clarified Just Run does not respect prior selections
Updated the Ace Critical Pricing documentation to clarify that "Just Run" always analyzes every store and item, clearing any active selection-box filters first to ensure nothing is silently excluded from the compliance check. The previous docs incorrectly suggested prior selections would be respected.
-
Infrastructure
Tests pin MAP/IMAP always-offered policy at Ace stores
FuturePriceSetToLevelPolicy tests now verify that MAP and IMAP are offered at Ace Hardware stores even with empty column views (the deliberate vendor exception for the Critical Pricing workflow), while other extended fields remain view-gated and non-Ace stores retain view-gating for MAP/IMAP.
-
Infrastructure
Header-driven mapping with comprehensive tests
The new CompetitorPriceFileReader class is deliberately free of WPF and database dependencies and is covered by 32 unit tests that pin the header-mapping logic, rounding rules, ignore-not-zero behavior, duplicate-SKU handling, and delimited-file parsing. Tests verify that headers are matched case/space/underscore insensitively, that column order doesn't matter, that unrecognized columns are safely ignored and reported, and that duplicate or missing required headers abort before any write occurs.
- General Merge pull request #1308 from retailersoft/feature/rebuild-consent
-
Infrastructure
Added comprehensive SQL generation tests
Added 183 lines of unit tests (`CompetitorPriceImportSqlTests.cs`) that pin the SQL generated for Replace (multi-table SKU matching, per-level clearing, COALESCE updates) and verify that only Replace-mode levels supplied by the file are cleared, that the clear is unfiltered so absent SKUs end up empty, and that SKU matching requires presence in at least one main table rather than just [Store].
- General Ask before a rebuild destroys what is on screen
-
Infrastructure
Comprehensive test coverage for export preflight checks
Added RockSolidExportPreflightTests to verify each blocker condition is detected separately and produces distinct remedy text. Tests confirm shared file access is not reported as a lock (the false diagnosis this change removes), folder probes never touch the POS's .ldb lock file, and permission problems name elevation rather than closing the POS.
-
Infrastructure
Comparison orchestration refactored to MainMMViewModel
The Compare Strategies flow (showing picker, running strategies, showing results) is now orchestrated from MainMMViewModel.StrategyUtilities.cs using a post-close dispatch pattern (the hub dialog records the chosen action and closes; MainMMViewModel dispatches afterward), preventing nested modals. The comparison dialog service is now registered on MainMMWindow instead of ManagePricingStrategyV2View.
- General Merge pull request #1307 from retailersoft/feature/data-update-job
-
Infrastructure
Shared strategy install service
SharedStrategyInstallService materializes downloaded definitions into local GlobalFileConfig strategy rows, validates step parseability before writing anything, installs bundled rounding schemes only when no same-name scheme exists locally, and refuses to overwrite existing strategies or update/remove the active strategy. Warnings are collected for view-dependent operands (Comp1-5, Ace_MSURetail) that only resolve when the field is in the active column view, informing users of potential portability limitations.
-
Infrastructure
Comprehensive unit test coverage
Adds 379 lines of tests (CompetitorPriceFileReaderTests) pinning the import rules: header mapping by name not position, case/space/underscore normalization, decimal rounding, duplicate header detection, missing column validation, price parsing with currency symbols, and the "invalid values are ignored, never zeroed" contract.
-
Infrastructure
Unit tests for shared strategy pipeline
Added SharedStrategyTests pinning the machine hash algorithm (must match server's SupportMachineService), template key derivation, provenance JSON round-trip, catalog row status logic, and definition JSON serialization preserving step order. These tests ensure the publish/download pipeline stays in lock-step with the server and that provenance markers remain readable across versions.
- General Merge pull request #1306 from retailersoft/feature/service-safety-gates
-
Documentation
Import Competitor Prices user guide
Adds a complete help article (docs/marginmaster/pricing/import-competitor-prices.md) documenting the file format, recognized column names, value parsing rules, import steps, how to use the imported prices in strategies and comparisons, the log format, and common questions. The article is indexed and searchable under "Pricing & Analysis".
- General Stop the service and the app colliding over a rebuild
- General Merge pull request #1305 from retailersoft/feature/service-heartbeat
- General Service checks in with the Manager and executes queued commands
- General Merge pull request #1304 from retailersoft/feature/launch-attribution
- General Report how the app was launched, and let short headless runs check in
- General Merge pull request #1303 from retailersoft/fix/MM-1397-strategy-column-requirements
- General Merge pull request #1302 from retailersoft/fix/MM-1393-store-identity-source-of-truth
- General Merge pull request #1301 from retailersoft/fix/MM-1399-empty-routing-keys
- General Merge pull request #1300 from retailersoft/docs/eci-hosting-migration-advisory
- General Docs: re-stamp verified_sha for eci-vpn-requirement
- General Merge pull request #1299 from retailersoft/fix/MM-1399-main-table-selection
- General Merge pull request #1298 from retailersoft/fix/MM-1399-table-cleanup-policy
- General Merge pull request #1297 from retailersoft/perf/reconcile-count-gate
- General Gate key-set reconciliation on a row count, and watch every vendor table
- General Merge pull request #1296 from retailersoft/docs/lock-column-and-tooltips
- General Explain the lock icons: tooltips in the grid + a doc for the "*" column
- General Merge pull request #1295 from retailersoft/docs/eci-vpn-nat-requirement
- General Docs: stamp verified_sha for eci-vpn-requirement
- General Merge pull request #1294 from retailersoft/docs/testing-lesson
- General Record the targeted-testing correction in lessons
- General Merge pull request #1292 from retailersoft/feature/nsoftware-bump-and-drift-detection
- General Merge pull request #1293 from retailersoft/fix/MM-1396-competitor-price-import
- General Bring unlicensed packages up to latest stable
- General Bump nsoftware to current builds and make drift fail the build
- General Merge pull request #1291 from retailersoft/fix/vendorgtin-reconciler-and-sync-tail
- General Actually populate TombstonesKept and MaxRowVersionSyncedHex
- General Cut two pieces of collateral work out of the post-sync tail
- General Surface a failed sync table instead of hiding it behind the ones that worked
- General Merge pull request #1290 from retailersoft/chore/approve-import-competitor-prices-surface
- General Approve ImportCompetitorPrices on the MainMMViewModel surface
- General Correct stale docs publishing instructions
- General Merge pull request #1289 from retailersoft/feature/import-competitor-prices
- General Merge pull request #1288 from retailersoft/fix/MM-1395-store-renumber
- General Merge pull request #1287 from retailersoft/fix/MM-1394-sku-exception-type-refresh
- General Merge pull request #1283 from retailersoft/perf/cloud-sync-proxy-compression
- General Merge pull request #1286 from retailersoft/fix/refresh-without-drop
- General Merge pull request #1285 from retailersoft/fix/key-set-reconciliation
- General Merge pull request #1284 from retailersoft/fix/sync-engine-correctness
- General Merge pull request #1282 from retailersoft/test/cloud-sync-fidelity-harness
- General Skip the drift check when the proxy cannot answer it
- General Refresh in place, index the local table, validate counts over the proxy
- General Remove local rows the vendor hard-deleted
- General Stop the sync skipping rows it can never come back for
- General Negotiate compression on cloud sync proxy requests
- General Merge pull request #1280 from retailersoft/fix/dib-level5-edlp-zero
- General Stop the MMVendorData view inventing a DIB EDLP price
- General Merge pull request #1281 from retailersoft/fix/green-main-di-baseline-and-surface-snapshot
- General Get main green: refresh the surface snapshot and baseline PriceLevelSelectViewModel
- General Merge pull request #1279 from retailersoft/fix/startup-db-maintenance-shrink-order
- General Merge pull request #1278 from retailersoft/docs/poco-house-style-guard
- General Pin runtime POCO as the ViewModel house style
- General Merge pull request #1277 from retailersoft/chore/devexpress-26.1.4
- General Merge pull request #1276 from retailersoft/fix/MM-sku-exception-individual-save
- General Merge pull request #1275 from retailersoft/fix/strategy-rerun-prompt-deliberate-click
- General Stop asking a deliberate Execute Strategy click to confirm itself
- General Merge pull request #1274 from retailersoft/fix/MM-1387-MM-1392-mi9-rounding-display-user4
- General Merge pull request #1273 from retailersoft/fix/MM-1391-index-bloat
- General Merge pull request #1272 from retailersoft/fix/startup-cost-reduction
- General Cut startup DB cost: batch index seeding, cached blank flags, gated scans
- General Merge pull request #1271 from retailersoft/fix/sitting-margin-single-scan
- General Remove background sitting-margin scans (fleet slowness reports)
- General Merge pull request #1270 from retailersoft/feature/acp-just-run-applies-steps
- General Ace Critical Pricing "Just Run" now applies the corrections
- General Merge pull request #1269 from retailersoft/fix/ace-critical-pricing-just-run
- General Make Ace Critical Pricing "Just Run" a workable pricing flow
- General Merge pull request #1268 from retailersoft/fix/data-aging-pill-clock-icon
- General Use clock icon on the Data Aging title-bar pill
- General Merge pull request #1267 from retailersoft/fix/ace-critical-pricing-splash-lockup
Imports & POS
-
Improvement
Enhanced RockSolid export error messaging
If the RockSolid export fails, you'll now see clear instructions telling you to close RockSolid on all computers, check if the file is read-only, and verify you have permission to update files in that folder.
-
Improvement
Enforce required Alternate SKU column for RockSolid
The Alternate SKU column now appears automatically in all your saved column views and cannot be hidden, since RockSolid requires this field for syncing data with your POS system.
-
Improvement
Compass incremental sync now works correctly from first import
Compass imports after the first one now complete faster by only loading changed items instead of reloading everything.
-
Improvement
Export error messages now show the full file path
Error messages now show exactly which file couldn't be updated, making it easier to locate and fix permission issues.
-
Improvement
Text export performance improved for large exports
The UPC lookup now runs one bulk query per export instead of two database queries per row, significantly improving export speed for files with hundreds or thousands of items.
-
Improvement
Store Manager Epicor store sorting by character ordinal
Enhanced Store Manager query to order Epicor stores by their character ordinal value while non-Epicor stores continue to sort numerically when possible, ensuring consistent and logical store ordering in the grid.
-
Improvement
Common questions expanded for migration timing
Added three new FAQ entries covering whether stores should still build tunnels given the temporary nature, what ECI Connect is and whether it works with Margin Master, and how to request an earlier migration slot from ECI. Includes practical guidance that stores needing pricing data now should still build since the firewall purchase isn't wasted and only tunnel reconfiguration is required.
-
Improvement
Setup process guidance strengthened
Added a tip to send WAN IP and subnet information in writing on the case thread and keep a copy, after a case where ECI stated they never received network details while the store believed they had sent them, causing a month-long delay. Updated technical details to note that server addresses are site- and era-specific and will change post-migration.
-
Bug Fix
First-time Compass import error eliminated
The first Compass import at a new store now completes cleanly without generating error reports.
-
Bug Fix
Compass first-import crash resolved
If you're setting up Margin Master for the first time with Compass, the initial import will now complete successfully instead of failing with an error.
-
Bug Fix
Comprehensive error message for RockSolid export failures
If a price export to RockSolid fails, you'll now see a checklist of all three things to verify, not just one, making it faster to find and fix the actual problem.
-
Bug Fix
UPC column in text exports now writes actual codes instead of X's
When you export pricing to a text file, the UPC column will now show the correct UPC codes for your products instead of all X's. If a product doesn't have a UPC in the system, it will still show X's as a placeholder, and the export will note how many products are missing UPCs.
-
Bug Fix
Manual catalog SKU additions now persist correctly
When you used "Add From Catalog" to manually add a vendor SKU to your pricing grid, the item appeared to be added successfully but would disappear the next time you rebuilt your catalog. This is now fixed—manually added items will stay in your grid as expected.
-
Bug Fix
Fixed RSC hijacking when vendor store numbers match Epicor character ordinals
Stores at Do-It-Best Epicor Compass sites now receive pricing from their correct RSC code instead of accidentally using another store's RSC when store numbers overlap with internal character codes.
-
Bug Fix
RockSolid export failures no longer appear on app-error dashboard
File access issues during RockSolid export are now logged as warnings rather than errors, preventing them from appearing on the application error dashboard. This change recognizes that write-refused conditions are environmental issues on the store's machine, not application faults, consistent with how connectivity failures are already handled in cloud sync.
-
Bug Fix
Fixed Store Manager hiding case-distinct Epicor store pairs
Store Manager now correctly displays all Epicor stores, including those whose store identifiers differ only by uppercase/lowercase letters (which represent different physical stores in Epicor).
-
Bug Fix
Mi9 required columns now correctly enforced
Fixed an inverted logic condition that prevented the SKU and Store Group columns from being automatically added for Mi9 users when missing from a view. The force-add logic now correctly triggers when these columns are absent rather than when they are present.
-
Bug Fix
Backstop ensures required columns in saved views
Added validation when saving or copying column views to automatically append any missing required columns (such as Alternate SKU for RockSolid) to the end of the view. This prevents edge cases where saved view configurations could be persisted without mandatory columns.
-
User Interface
Alternate SKU column enforced for RockSolid
The Alternate SKU column will automatically appear in your Main Table grid right next to the SKU column and will always stay visible.
-
User Interface
ECI hosting migration warning added to VPN documentation
The VPN setup guide now warns that ECI is moving to new servers — if you set up a tunnel now, you'll need to reconfigure it in a few months when the migration finishes.
-
User Interface
Column removal blocked in Edit Columns dialog
If you try to hide the Alternate SKU column in Edit Columns, you'll see a message explaining it's required for RockSolid and the column will remain checked.
-
User Interface
Prevent removal of Alternate SKU column in Edit Columns dialog
When customizing columns, you'll see a message if you try to hide the Alternate SKU column, explaining that RockSolid requires it to stay visible.
-
User Interface
ECI Connect service documented with compatibility questions
ECI has a new service called ECI Connect that might replace VPN tunnels, but we don't yet know if it will work with Margin Master — please let us know what ECI tells you about it.
-
Database
Automatic repair of missing database defaults
Added a startup healing routine that detects and repairs existing databases missing the CreateDate default constraint on ManualCatalogItems table. The fix runs idempotently on every startup, ensuring all installations are automatically corrected without manual intervention.
-
Infrastructure
Correct logging level for file permission failures
RockSolid export failures caused by file permissions, read-only attributes, or locked files are now logged as warnings instead of errors. This prevents store-specific machine configuration issues from appearing on the application error dashboard as though Margin Master itself were broken. Genuine application failures continue to log as errors.
-
Infrastructure
Schema generator now emits DEFAULT constraints
Enhanced MigrationBasedSchemaCreator to emit DEFAULT constraints for all model-defined defaults (both SQL expressions and CLR default values), preventing the same class of failures on future fresh database installations. CLR defaults are formatted as culture-invariant T-SQL literals to ensure cross-locale compatibility.
Cloud Sync & Vendor Data
-
New Feature
Manual Ace zone refresh command
If your Ace zone assignments change at the corporate level, you can now use Options > Refresh Ace Zones in Store Manager to immediately update all your stores' zones without waiting for the next sync. The system will tell you how many stores had their zones updated.
-
New Feature
Manual Ace zone refresh command
Click Options > Refresh Ace Zones to re-check the assigned zone for all your stores against the latest Ace data. You'll see a summary of how many zones changed.
-
New Feature
Data rebuild consent flow
When new vendor or POS data arrives while you're working, Margin Master will now ask before restarting to apply it, instead of wiping your screen without warning. You can postpone up to 3 times if you're in the middle of something.
-
New Feature
Session capture and restore
After a data update restart, Margin Master will automatically restore your grid selection and return you to exactly where you were before the update.
-
New Feature
Session capture and restore
When you accept a data update, Margin Master saves what you have on screen, applies the update, and automatically reopens with your selection and pricing strategy restored.
-
New Feature
Deferral limits on parked updates
You can postpone a data update up to 3 times. After that, it will be applied automatically to ensure your pricing stays current.
-
Improvement
Periodic refresh now updates in-place instead of dropping tables
During the monthly catalog refresh, you'll no longer see a period where catalog data temporarily disappears from the system.
-
Improvement
In-place table refresh replaces drop-and-recreate
Scheduled monthly vendor catalog refreshes now happen seamlessly in the background. Pricing data remains accessible throughout the refresh instead of briefly disappearing.
-
Improvement
Consent prompt before destructive rebuild
If a data update runs while you're working, Margin Master now asks permission before applying it instead of disrupting your screen. You can apply it immediately, postpone it for 2 hours, or let it apply automatically after being postponed 3 times.
-
Improvement
Better timeout diagnostics in sync logs
When sync issues occur, support staff will receive clearer information about what went wrong and how to fix it.
-
Improvement
Made reconciliation failures non-fatal to sync operations
If the cleanup step encounters an issue, your pricing data will still sync successfully rather than failing the entire operation.
-
Improvement
Enhanced zone lookup with cache control
Extended the GetAceZonesToSync API method with a forceRefresh parameter that drops the 7-day cache, allowing manual refresh operations to fetch fresh data from the server while preserving normal cache behavior for automatic lookups.
-
Improvement
Unified zone lookup logic across Store Manager
Refactored zone resolution into a single LookupAceZoneAsync method shared by both the auto-fill-on-entry path and the new manual refresh command. This ensures consistent behavior: local AceStoreDepartmentZoneRecords rows are checked first (minimum zone across departments), and if the store isn't found there, the cloud API is queried. The forceRefresh parameter controls whether the 7-day cache is bypassed.
-
Improvement
Data Aging screen flags stale sync dates from recent failures
In the Data Aging screen, tables that failed their most recent sync attempt are now highlighted in red with an explanation, so you can tell the difference between "no new data" and "sync is broken".
-
Improvement
Reconciliation failures no longer block entire table sync
Sync now completes successfully even if the cleanup step encounters an error. The data you need is synced correctly, and cleanup will be retried next time.
-
Improvement
Separate ingest from rebuild
Data downloads now complete in the background even while you're working. Only the final table rebuild step waits for your approval.
-
Improvement
Epicor import data preserved during store renumbering
If your Epicor store gets renumbered, your pricing data will rebuild automatically from existing import files without waiting for a new data import.
-
Improvement
Enhanced Epicor store data migration during renumbering
When an Epicor store is renumbered, the system now preserves historical POS data by moving staging table records, purchase order data, and the main table itself to the new vendor store number. This prevents data loss and ensures continuous pricing history across the renumbering event.
-
Improvement
Sync statistics now record watermark and tombstone metrics
SyncStatistics now captures MaxRowVersionHex (the highest RowVersion synced) and TombstonesKept (count of soft-deleted rows retained locally) for each table sync. These metrics enable fast diagnosis of tables that appear to re-transfer the same rows on every sync—previously this required cross-database reconstruction to distinguish a regressing watermark from the producer re-stamping rows.
-
Improvement
MMVendorData view health checks now 400x faster
Post-sync verification now queries the view's input tables (DIBCatalogRecords and DIBPriceLevelRoundingDetails) directly instead of materializing the entire MMVendorData multi-join view. The old COUNT(*) FROM MMVendorData took 6.7 seconds and contributed the majority of total sync time on some stores. The new indexed checks run in ~16ms and detect the same failure condition (missing SchemeID=2 rounding rows).
-
Improvement
Duplicate index rebuild eliminated after catalog add
Rebuilding the main table via catalog add (UPDATE-style rebuild) now skips the managed index rebuild when CreateTopPanel is also queued, since CreateTopPanel runs the identical rebuild pass moments later. This eliminates redundant index recreation and ~3 seconds of selection box cache rebuilding on every sync for DIB stores using per-store POS tables.
-
Bug Fix
Increased timeout for table structure operations
Sync operations will no longer fail with timeout errors when working with large vendor catalogs on slower computers.
-
Bug Fix
Do-It-Best EDLP column now displays accurate data
The Do-It-Best EDLP price column in the pricing grid now correctly shows zero when EDLP pricing is not available, instead of displaying an incorrect calculated price.
-
Bug Fix
DIB EDLP column showing fabricated prices
When viewing Do-It-Best items, the "DIB EDLP" column was showing prices that looked real but were actually calculated from a pricing formula. Since Do-It-Best doesn't provide EDLP pricing, this column now correctly shows zero.
-
Bug Fix
Out-of-order transaction commits no longer cause permanent data loss
Catalog and zone pricing updates now always arrive, even when the vendor's database processes multiple updates simultaneously.
-
Bug Fix
Prevent false drift detection during version mismatches
Fixed an issue where a store running newer Margin Master software would incorrectly detect data drift when syncing with an older cloud server. The newer client requests an active-only row count (excluding deleted records), but older servers silently ignore this flag and return a count including tombstones. The client would compare this inflated count against its own live count, conclude it was missing data, and force a full resync of the entire partition on every sync. This was particularly problematic for AceZoneRecords tables where 90% of cloud rows are tombstones. The client now returns -1 for "cannot answer" and skips validation rather than triggering unnecessary resyncs.
-
Bug Fix
Sync engine no longer skips rows during concurrent updates
When vendor catalogs were being loaded while sync was running, some price or product updates could be skipped and never appear in Margin Master. This is now fixed—all updates will be captured, even during busy catalog import periods.
-
Bug Fix
Store renumbering now fully reconciles all internal references
If your vendor gives you a new store number, the system will now automatically update all internal references after you enter it in Store Configuration. You'll no longer experience incorrect pricing due to mismatched store numbers.
-
Bug Fix
Automatic repair when vendor renumbers a store
If your vendor changes your store number, the system will now automatically update all internal records to match after you validate the new number. You no longer need to manually correct store mappings or worry about pricing at the wrong zone.
-
Bug Fix
Fixed SQL ambiguity error in VendorGTIN reconciliation
When vendors like Ace Hardware or Do-It-Best permanently remove products from their catalogs, those deletions will now correctly sync to your local database instead of leaving old records behind.
-
Bug Fix
Failed sync tables now reported when other tables succeed
When syncing vendor data, you'll now see a notification listing any tables that failed to sync, even when other tables succeeded. Previously, these failures were invisible unless all tables failed.
-
Bug Fix
VendorGTIN reconciliation failure resolved
VendorGTIN and catalog data now properly clean up deleted items during sync. Previously, items removed by the vendor would remain in your database indefinitely.
-
Bug Fix
Newly entered store numbers now auto-populate zones correctly
When you enter an Ace store number for a new store location, the Ace Zone field will now always populate automatically, even if that store hasn't been through a vendor sync yet.
-
Bug Fix
Auto zone fill now works for newly added stores
When you type in a vendor store number for a new store, its Ace Zone now fills in automatically right away, even if that store hasn't gone through a vendor sync yet.
-
Bug Fix
Removed incorrect READPAST hint that skipped locked rows
The sync no longer skips catalog rows that are being updated at the same time, ensuring all changes are captured.
-
Bug Fix
Eliminated duplicate label printing from retired GTINs
Products with reassigned barcodes will no longer print extra labels showing old, retired barcodes.
-
Bug Fix
Retry logic now correctly detects when sync is complete
Sync will now correctly continue until all pending changes are downloaded, even when the server is under heavy load and individual queries need to be retried with smaller batches.
-
Bug Fix
Duplicate barcode labels from retired GTINs eliminated
SKUs with updated barcodes will now print only one label with the correct, current barcode instead of printing extra labels with old retired barcodes.
-
Bug Fix
Manual vendor store number corrections now persist correctly
When you change a store's Vendor Store # in Store Manager, the change will now stick instead of reverting when you restart the application.
-
Bug Fix
Store Manager vendor store number changes now update all related records
Changes to vendor store numbers in Store Manager now save correctly and persist across restarts.
-
Bug Fix
Database connection error message corrected for SQL query defects
Error messages during sync now accurately describe what went wrong instead of incorrectly blaming database connection issues.
-
Bug Fix
Query timeout retry now correctly resumes sync loop
After a temporary timeout, sync now correctly downloads all remaining changes instead of stopping partway through.
-
Bug Fix
Count validation now works for firewalled stores using proxy mode
The system can now automatically detect and repair incomplete syncs for stores behind firewalls, improving data accuracy.
-
Bug Fix
Epicor per-store table reconciliation now runs consistently
Stores using Epicor will no longer see duplicate store entries or incorrect zone pricing from leftover data tables.
-
Bug Fix
Fixed orphaned Epicor main tables when using Store Manager without store mapping
Epicor stores will no longer show duplicate entries in reports or price incorrectly due to leftover old pricing tables.
-
Bug Fix
Count validation handles server version differences gracefully
When an older Manager version doesn't support the activeOnly flag on count queries, the proxy now returns -1 to signal "cannot answer" rather than an incorrect tombstone-inclusive count. This prevents false-positive drift detection that would trigger unnecessary full resyncs on every sync cycle.
-
Bug Fix
Scheduled refresh no longer forces reconciliation unconditionally
Scheduled syncs now run more efficiently and avoid SQL errors that previously affected some Ace Hardware catalog tables.
-
Bug Fix
Removed obsolete 'NoChanges' sync status
Dropped references to the 'NoChanges' status value in sync history queries, as SyncStatisticsManager only ever writes 'Success' or 'Failed'. The Data Aging query previously filtered for both 'Success' and 'NoChanges', but the latter was never produced.
-
Bug Fix
Critical composite index now created correctly
Fixed the Store table's composite index on [StoreNumber, SKU] (RSIX_Store_StoreNumberSKU), which was registered but never actually created due to a SQL guard that could not match multi-column definitions. The index now builds correctly on non-WestLake stores. Existing stores will have their stale seed definitions refreshed automatically. This index supports faster lookups when filtering the pricing grid by store and SKU together.
-
Bug Fix
Prevent rebuild loops on persistent failures
If a rebuild fails during the background apply phase, the parked work record is still cleared and the application is still relaunched. This prevents the user from being restarted in a loop on a rebuild that would fail the same way every time. The failure is logged to history where the user can see it, but they are not left without an application.
-
Bug Fix
Per-store POS tables no longer truncate global mainTable
DIB stores using RockSolid, Transact, or non-MySQL Epicor build per-store main tables and never write to the global [mainTable]. The rebuild process now skips truncating [mainTable] and clearing SelectionLists for these stores, eliminating an unnecessary 3+ second selection box rebuild on every sync.
-
Cloud Sync
Key set reconciliation for hard-deleted vendor records
When vendors completely remove products from their catalogs, those products are now automatically removed from your local database during sync.
-
Cloud Sync
Key set reconciliation for hard-deleted vendor records
When vendors completely remove products from their systems (not just mark them deleted), those items are now properly removed from your local database instead of staying forever.
-
Cloud Sync
Intelligent cleanup gate prevents unnecessary work during sync
Syncs complete faster when no vendor catalog records have been removed, especially for large tables.
-
Cloud Sync
Server response now indicates whether active-only filter was applied
The cloud sync proxy now checks whether the server actually applied the activeOnly filter when counting rows. If the server response doesn't confirm the filter was applied (indicating an older Manager), the count is treated as unreliable and drift validation is skipped for that partition.
-
Cloud Sync
Failed table syncs now reported even when other tables succeed
You'll now see a notification if any vendor data table fails to sync, even when other tables sync successfully. This helps catch partial sync failures that were previously invisible.
-
Cloud Sync
Hard-deleted vendor records now cleaned up automatically for all tables
Removed vendor items and outdated catalog data are now automatically cleaned up across all vendor tables, preventing issues like printing labels with retired barcodes.
-
Cloud Sync
Opt-in reconciliation per table with safety guards
Reconciliation is deliberately opt-in via the ReconcileKeys flag because it reads every in-scope key from the cloud. For a narrow table like VendorGTIN (three columns, ~88k rows) this is negligible; for large tables like AceZoneRecords it would be expensive. The reconciler also refuses to act on an empty cloud key set, preventing catastrophic data loss if a network failure or truncated read returns zero records—it will not interpret that as "the vendor retired everything."
-
Cloud Sync
Opt-in reconciliation with safety guardrails
Reconciliation is opt-in per table via the ReconcileKeys flag because it reads every in-scope key from the cloud, which is inexpensive for narrow tables like VendorGTIN (~88k rows, 3 columns) but would be costly for large tables like AceZoneRecords. Added a safety guard that refuses to act on an empty cloud key set, preventing catastrophic data loss if a cloud read fails or returns no results.
-
Cloud Sync
Count validation now works in proxy mode
The system now automatically detects and corrects incomplete vendor data downloads, even for stores behind firewalls.
-
Cloud Sync
Reconciliation runs even when no changes detected
Reconciliation executes on the "nothing changed" sync path as well as normal updates. This is critical: a hard delete bumps no RowVersion, so the sync where reconciliation needs to fire is precisely the one where the watermark reports zero rows to fetch. Both direct SQL and HTTPS proxy modes are supported; proxy mode pages through the existing rows endpoint requesting only key columns plus RowVersion.
-
Data Import
Verified Do-It-Best catalog feed structure
Confirmed that the Do-It-Best FTP catalog feed contains only CTLD, PCD, PRDCD, EstimatedNetCost, and order/promo files—no EDLP or everyday-low-price data is provided. This validation ensures the system accurately reflects the vendor's actual data structure.
-
User Interface
Updated Store Manager documentation
Updated store-manager.md documentation to describe the new Refresh Ace Zones feature and clarified that zone auto-population works for newly entered stores via cloud fallback when local sync data is unavailable.
-
User Interface
Refresh Ace Zones button in Store Manager toolbar
Look for the new "Refresh Ace Zones" button in the Store Manager toolbar when working with Ace Hardware stores.
-
User Interface
Sync failure notification uses non-blocking toast instead of modal dialog
Failed table notifications now appear as non-blocking notifications rather than modal dialogs, because the sync splash screen is still visible and post-processing tasks are queued. A modal dialog would strand the background work behind the splash, preventing completion. The notification lists which tables failed and directs users to the application log for details.
-
User Interface
Sync history grid now highlights stale success dates
The data aging screen now clearly marks when a table's sync date is stale because a later attempt failed. Look for red dates with "(last sync failed)" to identify ongoing sync issues.
-
User Interface
Main screen rebuild coordination
The main view model now checks for parked rebuilds during background job polling, offers them when the pipeline is idle, and handles the capture/restore workflow. Consent prompts never interrupt active strategy runs or imports.
-
User Interface
Deferral limits prevent silent staleness
You can postpone a data update up to 3 times. After that, it will apply automatically to ensure your pricing stays current.
-
Database
PendingPipelineWork table
Added a new `PendingPipelineWork` table to store rebuild details (steps, strategy, selection, state) across the app restart that applies it. Steps are stored by name rather than enum values to survive build changes. Single-row table by design—newer parked work replaces older.
-
Database
Cleanup policy registration
PendingPipelineWork table added to DatabaseTableCleanupPolicy's protected table list to ensure it is not inadvertently dropped during maintenance operations.
-
Architecture
Added test coverage for DIB EDLP column behavior
Created comprehensive tests to prevent regression of this issue. Tests verify that Level5 is set to zero for Do-It-Best items, that it does not source from the rounding ladder, and that Level3/Level4 continue to use the ladder as intended. This prevents a repeat of the MM-1354 issue where a ladder-calculated value was incorrectly placed in a vendor-specific pricing column.
-
Architecture
Unified active row counting logic
Created ActiveRowCounter helper to centralize the "how many live rows exist for this scope" query used by both the count-validation pass and the reconciliation gate. This ensures both features measure the same thing, preventing silent failures where divergent SQL could cause reconciliation to skip when it should run.
-
Architecture
Rebuild-and-restore runner
A new headless command (`rebuild-and-restore`) applies accepted rebuilds and relaunches the app. Launched by the closing app itself rather than the Windows service, ensuring it runs in the user's session and can restore windows to their desktop even on locked or remote-desktop machines.
-
Infrastructure
Comprehensive test coverage for DIB EDLP column
Added DibEdlpLevel5Tests to verify that the MMVendorData view assigns zero to Level5 and does not source it from the rounding ladder (np.Next3). The tests also verify that Level3 and Level4 continue to legitimately use the ladder, preventing regression of the MM-1354 fix for DIB Aux Retail.
-
Performance & Reliability
Added indexes to speed up sync operations on large catalogs
Syncing large vendor catalogs (especially Orgill and Ace Hardware) will complete noticeably faster.
-
Performance & Reliability
Database indexes added for sync operations
Cloud sync now runs significantly faster, especially for stores with large vendor catalogs.
-
Infrastructure
Added test coverage for out-of-order transaction commits
Added comprehensive sync fidelity tests that reproduce the out-of-order commit race condition using overlapping transactions with different rowversions. Tests verify that rows are deferred rather than skipped when transactions are still in flight, and that all data is eventually synchronized once transactions commit.
-
Infrastructure
Added test coverage for filtered reconciliation
Extended sync fidelity tests to cover reconciliation scenarios where the filter column is also a key column, which is the production configuration for VendorGTIN and DIBCatalogRecords. Tests verify both that reconciliation works under these conditions and that rows outside the filter scope are left untouched.
-
Infrastructure
Added comprehensive sync fidelity test coverage
Added test case RowCommittedOutOfOrder_IsNotSkippedPastAndLost that reproduces the out-of-order commit race condition, verifying that rows committed out of order are deferred and delivered rather than permanently lost. Test fixture now enables READ_COMMITTED_SNAPSHOT to match production RS_CLOUD database settings.
-
Infrastructure
Enhanced cloud sync proxy API
Extended the ICloudSyncProxy interface and ApiCloudSyncProxy implementation to support counting active (non-tombstone) rows in a vendor catalog partition. This enables post-sync validation to verify that the local catalog matches the vendor's published data by comparing active row counts.
-
Infrastructure
Comprehensive sync fidelity test coverage
Added three new test cases covering hard delete scenarios: verification that hard deletes are invisible to standard watermark sync, validation that reconciliation correctly removes orphaned rows, and confirmation that reconciliation refuses to delete all local data when the cloud returns an empty key set.
-
Infrastructure
Parked rebuild storage
Introduces PendingPipelineWork table and service to store rebuild jobs that are waiting for user consent. The table persists the queued post-processing steps by name (not enum ordinal) to survive application version changes across the restart boundary. Includes automatic table creation on first use, matching the pattern used for BackgroundJobStatus and BackgroundJobLock. Steps that no longer parse in the restored version are logged and skipped rather than causing a failure.
-
Infrastructure
Session-aware background runner
Added RebuildAndRestore headless command that applies a parked rebuild and relaunches the interactive application. This runner is spawned by the closing app itself (not by the Windows service) to inherit the user's session context, avoiding impersonation issues on locked workstations, multi-session machines, and remote desktop connections. The runner waits for the interactive presence marker to clear (up to 2 minutes) before touching any tables, ensuring the grid has fully released its handles.
User Interface
-
New Feature
Copy Summary button on Strategy Execution Summary
When viewing the Strategy Execution Summary after a pricing run, you can now click "Copy Summary" to copy the entire report to your clipboard, making it easy to paste the information into an email, support ticket, or notes.
-
New Feature
Title bar data aging warning pill
You'll now see a warning badge in the title bar when your data needs updating. It starts amber when vendor data gets old and turns red with a pulsing effect when your POS data is too old. Hover over it to see details, or click to update your data.
-
New Feature
Title-bar data aging warning pill
Look for a new "Data Aging" badge in the title bar. It appears amber when your data is getting old, and turns red and blinks when your POS data really needs updating. Click it to see details and update your data.
-
New Feature
Related issue linking for follow-up submissions
If you have an open issue but need to report a new but related problem, select "Submit a new issue related to this one" to keep them connected.
-
New Feature
Lock column documentation
Created comprehensive documentation (pricing/lock-column.md) explaining all seven padlock icons, when the column appears, how to interpret blank cells, and common questions. Includes each icon rendered inline, technical details about the data source, and the relationship between icons and pricing rules. Also cross-references SKU-level exceptions and custom groups documentation.
-
Improvement
Settings path changes apply instantly
Changes to default file paths in Settings now take effect immediately. You no longer need to restart Margin Master after updating Import Path, Export Path, or Network Import Root.
-
Improvement
Instant application of default path changes
After changing your default import or export folder in Settings, all file dialogs will immediately use the new location—no restart required.
-
Improvement
Simplified deletion confirmation
When deleting a database, you now type "delete" instead of the full database name to confirm the action.
-
Improvement
Delete button now updates while typing confirmation
The delete button's enabled/disabled state now re-evaluates with each keystroke in the confirmation box, providing immediate visual feedback rather than waiting for focus change.
-
Improvement
Confirmation text box enabled for active database selection
When trying to delete the currently open database, you can now type in the confirmation box to see the full warning message. The Delete button will still be disabled to prevent accidental deletion of the active database.
-
Improvement
Runs with errors always show execution summary
If a strategy run has any problems, you'll always see the Execution Summary screen with the error details, even if you've turned off the after-run summary in settings.
-
Improvement
Summary always appears for runs with errors
Even if you've turned off the Strategy Execution Summary in settings, it will still appear automatically whenever a pricing run encounters errors, so you'll always know when something needs attention.
-
Improvement
Weekday-only aging calculation for Do it Best
If you're a Do it Best store, the system now understands that vendor updates only happen on weekdays, so you won't see false warnings on Mondays after syncing on Friday.
-
Improvement
Updated default POS data aging threshold
The warning for outdated POS data now appears after 5 days instead of 1 day by default, which better matches typical store update schedules.
-
Improvement
Console log visibility based on outcome
The console log now adapts its visibility based on setup outcome: it remains front and center while running and on failure (for troubleshooting), but on success it's hidden by default behind a "View Log" button to emphasize the success confirmation panel.
-
Improvement
Console log visibility refined by outcome
The setup console log now adapts based on outcome: it remains front-and-center during installation and on failure (when troubleshooting is needed), but is demoted to an opt-in "View Log" button on success. This prevents successful installations from feeling uncertain or incomplete due to log text dominating the final screen.
-
Improvement
Friendlier SQL Server version display
When selecting a database server, you'll see clear version names like "SQL Server 2025 Express" instead of confusing numbers.
-
Improvement
Suppressed misleading "0 records / 01/01/01" rows in POS import history
The POS import history grid no longer shows confusing empty rows with "0 records" and placeholder dates from 2001.
-
Improvement
Default POS aging threshold increased to 5 days
The default threshold for POS data age warnings has been increased from 1 day to 5 days to better match typical import schedules.
-
Improvement
Vendor sync now updates freshness timestamp even when no changes found
When vendor sync finds no changes, the system now correctly recognizes your data as up-to-date instead of showing aging warnings.
-
Improvement
Step 1 routing logic refined for different entry points
Plain "Submit New Issue" with open issues now routes to Step 1 for duplicate checking. Direct updates via the issue pill or menu actions ("Update Issue") skip to Step 2 as before. The follow-up flow and startup mode continue to bypass Step 1 since they have explicit intent.
-
Improvement
Support Scripts menu relocated to setup dialogs
Support Scripts is now accessed from within the setup windows instead of the main Tools menu, making it available even when the database isn't yet configured.
-
Improvement
Empty POS tables no longer create misleading fallback rows
The POS table fallback logic now skips tables with zero records, preventing empty tables from masking the "no POS data" condition. Previously, a table with zero rows could suppress both the fallback and the "never imported" warning, making the dialog appear as though data existed when it didn't.
-
Improvement
Do It Best weekday-only vendor aging calculation
For Do It Best stores, the system now understands that vendor data doesn't age over weekends, so you won't see false warnings on Mondays.
-
Improvement
Delete button now updates while typing confirmation
The delete button now responds instantly as you type, making it clearer when you've correctly entered the confirmation text.
-
Improvement
Enhanced SKU exceptions and custom groups documentation
Updated sku-level-exceptions.md and custom-groups.md with details on creating exceptions (via Sku Detail tab, not "Add Selected Sku to Custom Group"), added Ctrl+E shortcut, corrected window sizes and Export to Excel paths, documented save-time warnings, explained duplicate-wins rule and execution order, and added sections on the lock icon. Fixed incorrect references to tables/fields that don't exist. Added documentation for Copy Group from Another Strategy and Find Duplicate SKUs features in custom groups.
-
Bug Fix
Sensitivity score columns now populate in catalog comparisons
When comparing vendor catalogs, the sensitivity score columns will now display values instead of appearing blank.
-
Bug Fix
SKU exception Type column now refreshes after editing future price
When you assign a price level to an SKU exception, the Type column now immediately changes from 'U' (unassigned) to the correct type (R/M/D/etc.) instead of staying stuck on 'U' until you close the dialog.
-
Bug Fix
One Click Statistics self-heals when no tables are selected
One Click Statistics will now always display data, even if your current selection doesn't include any pricing tables.
-
Bug Fix
File dialogs now consistently honor configured default paths
Open and Save dialogs now always start in your configured default paths. Previously, they would remember the last folder you browsed to during your session, which could be confusing if you had configured specific default locations.
-
Bug Fix
Backup directory now updates with import path changes
When you change your default import path, the automatic backup location now updates correctly to match.
-
Bug Fix
Fixed SKU exceptions staying in Unassigned list after being resolved
When you fix an unassigned SKU exception and save, it now disappears from the "Unassigned" list right away instead of staying visible until you close the dialog.
-
Bug Fix
Print button now functional in One Click dialog
The Print button in One Click Statistics now works correctly.
-
Bug Fix
Improved state synchronization in Delete Database dialog
Fixed various property change notifications to ensure all UI elements (confirmation box, delete button, status messages) stay properly synchronized when database selection changes or deletion state updates.
-
Bug Fix
Timestamp now updated on successful no-change syncs
Successful syncs now correctly update your "last synced" timestamp even when there are no catalog changes, so you won't see false warnings about stale data when you're syncing regularly.
-
Bug Fix
Caller prefill preserved when selecting "New Issue" sentinel
Selecting the "New Issue" option in Step 1 now restores any pre-filled Title/Description (from error reports or diagnostics) instead of blanking the form, ensuring automatic diagnostic data isn't lost.
-
Bug Fix
Improved state synchronization in Delete Database dialog
Fixed various property change notifications to ensure all UI elements (confirmation box, delete button, status messages) stay properly synchronized when database selection changes or deletion state updates.
-
User Interface
Copy Summary button added to Strategy Execution Summary
When a strategy finishes, you can now click "Copy Summary" on the Execution Summary screen to copy all the details including any errors, making it easy to paste into an email or support ticket.
-
User Interface
Issue Wizard Step 1 restored with duplicate prevention
Before submitting a new issue, you'll see a list of your open issues first, helping you avoid filing duplicates.
-
User Interface
Enhanced SQL setup success confirmation
When SQL Server setup finishes successfully, you'll see a clear green confirmation screen with the server name you can copy, instead of just a small banner that was easy to miss.
-
User Interface
Success confirmation panel for SQL setup
After SQL Server installs successfully, you'll now see a clear green checkmark and your database connection details, instead of scrolling through technical logs to confirm it worked.
-
User Interface
SQL Instances window layout improved
When viewing SQL Server instances during setup, all buttons and information now fit on screen without needing to scroll sideways.
-
User Interface
Friendly step-by-step progress during SQL Server setup
During SQL Server installation, you'll now see clear progress messages like "Downloading SQL Server 2025 Express" instead of technical console text. The technical log is still available under "Technical details" if needed.
-
User Interface
Friendly step-by-step progress display during SQL installation
When setting up SQL Server or running database scripts, you'll see clear step descriptions like "Installing SQL Server LocalDB" and "Configuring firewall rules" instead of scrolling console text.
-
User Interface
Database connection window now appears in taskbar
If you need to reconnect to your database at startup, the connection window will now appear in your taskbar so you can easily find it.
-
User Interface
Cleaned up duplicate menu entry
The Support Scripts tool can now only be accessed from the SQL Server Setup > Tools menu, removing a duplicate menu entry that previously appeared in the database connection window.
-
User Interface
SQL Server instance dropdowns show product and version
When selecting a SQL Server instance in database utilities, you'll now see which version of SQL Server is running (like "SQL Server 2025 Express") to help you choose the correct server.
-
User Interface
Utilities menu reorganized into functional groups
The Utilities menu is now organized into clear sections: diagnostics and logs at the top, data tools in the middle, and reset options at the bottom, making it easier to find what you need.
-
User Interface
Utilities menu reorganization
The Utilities menu is now better organized with related tools grouped together, making it easier to find the right tool and harder to accidentally click dangerous reset options.
-
User Interface
Color-coded warning banners in Data Aging dialog
When you open the Data Aging screen, you'll now see color-coded warnings: red banners alert you when POS data is old or missing entirely, and amber banners warn when vendor data needs a sync. These match the colored pill in the title bar.
-
User Interface
Prominent warning banners for stale data
When you open the Data Aging screen, you'll now see orange or red warning banners if your vendor or POS data is out of date, making it obvious when you need to sync or import fresh data.
-
User Interface
Clock icon for Data Aging indicator
The Data Aging warning in the title bar now shows a clock icon instead of a warning triangle, making it clearer that the alert is about outdated pricing data.
-
User Interface
Updated Data Aging icon
The Data Aging indicator now displays a clock symbol, making it clearer that it relates to how current your pricing data is.
-
User Interface
Lock column tooltips in main grid
Hover any padlock in the "*" column to see what it means. The column header also has a tooltip explaining the column's purpose.
-
User Interface
Lock column tooltips added
Hover over any padlock in the "*" column to see exactly how that item was priced. The column header tooltip now explains what the column is for.
-
User Interface
Support Scripts relocated to setup window Tools menus
Support Scripts is now found in the Tools menu of the SQL Server Setup and Database Setup windows instead of the main window's File menu.
-
User Interface
Technical log collapsed by default, auto-expands on failure
The technical console log is now hidden by default to keep the screen simple, but automatically appears if something goes wrong so support can troubleshoot.
-
User Interface
Updated confirmation prompt text
The prompt text in the Delete Database window was updated from "Type the database name to confirm deletion" to "Type the word delete to confirm" to reflect the new confirmation method.
-
User Interface
Confirmation box disabled for active database
The confirmation text box in the Delete Database dialog is now disabled when the selected database is the currently active one, making it visually clear that deletion is not possible. Previously, users could type the confirmation text even though the delete button would remain disabled.
-
User Interface
Communications Tester moved to diagnostics section
The Communications Tester utility has been moved from the middle of the menu to the diagnostics section alongside log file tools, since it serves a diagnostic purpose rather than a data management function.
-
User Interface
"No POS data" banner for stores that have never imported
If you've never imported any POS data, the screen now shows a clear message explaining that you need to import your point-of-sale data to see sales and margin information.
-
User Interface
Updated Z column header tooltip
Restored the header tooltip for the "Z" (zone pricing) column, which was being lost when the header was replaced with the bare "Z" symbol. Now reads: "Zone — vendor zone pricing applies to this item."
-
User Interface
Column header tooltips clarified
Hover over the "*" or "Z" column headers to see what those symbols mean.
-
User Interface
Improved path configuration reliability
Enhanced path configuration across multiple screens including Main Window, Cost Break, Custom Groups, Pricing Strategy, Rounding Editor, Rounding Scheme Check, and SKU-Level Exceptions to ensure consistent behavior when working with import/export operations.
-
User Interface
Updated file dialogs across multiple screens
Applied the instant path update behavior to file dialogs in Cost Break, Custom Groups, Pricing Strategy, Rounding Editor, Rounding Scheme Check, and SKU-Level Exceptions screens. All now respect updated default paths immediately without storing previously-selected directories between sessions.
-
User Interface
Toggle command for showing/hiding log details
Added a ToggleLogCommand and ShowLogDetails property to allow users to reveal the full console log on the success screen when needed, supporting power users who want to review what happened without cluttering the default experience.
-
User Interface
SQL Server Setup always accessible from Database Setup window
If you need to install or configure SQL Server during first-time setup, you can now access SQL Server Setup directly from the Database Setup window's Tools menu.
-
User Interface
SQL Server Setup renamed to SQL Server Tools
The "SQL Server Setup" menu option and window are now called "SQL Server Tools" to better reflect all the database management tasks you can do there.
-
User Interface
Updated tooltips and documentation
Updated tooltips on the Miscellaneous options screen and the summary screen's checkbox to clarify that runs with errors always show the summary. Documentation now includes a complete section on the Strategy Execution Summary screen with button descriptions and behavior details.
-
User Interface
SQL Server Setup menu always accessible from Database Setup
The Database Setup window now includes a "SQL Server Setup..." option in its Tools menu, ensuring that users on brand-new machines (with no SQL instance and no database) can always reach the guided SQL installation wizard from the initial setup screen.
-
User Interface
DateTime.MinValue displayed as "—" in import history grid
When enriching POS import history from main tables that lack a LastUpdate column, the CreateDate now displays as "—" instead of "01/01/01 12:00 AM", which was confusing and appeared to be corrupt data.
-
User Interface
Enhanced Options data aging section labels
Updated the Data Aging group box label in Tools > Options > Miscellaneous to clarify that the thresholds control when the title-bar warning appears, making the connection between the setting and the new visual indicator clearer to users configuring their preferences.
-
User Interface
Result screen shows related issue link
After submitting a related issue, you'll see confirmation showing which issue it's connected to.
-
User Interface
Confirmation box disabled for active database
If you select the database you're currently using, the confirmation box is now grayed out to show you can't delete it.
-
User Interface
"SQL Server Setup" renamed to "SQL Server Tools"
The "SQL Server Setup" feature has been renamed to "SQL Server Tools" to better describe what it does.
-
User Interface
Lock icon description converter with tests
Implemented LockIconDescriptionConverter as the single source of truth for tooltip wording, with comprehensive unit tests (LockIconDescriptionConverterTests) that fail if a new icon is added without corresponding tooltip text. The converter returns null for values with no icon (NULL, 'N', 'U'), ensuring blank cells show no tooltip.
-
Architecture
DataAgingIndicatorPlanner extended with VendorIsStale and PosIsStale flags
The DataAgingIndicatorPlanner.Result record now includes VendorIsStale and PosIsStale boolean flags, making it easier for the Data Aging dialog to determine when to show banners without re-evaluating thresholds. Unit tests added to verify the flags match the existing ShowWarning and IsAlarm logic.
-
Architecture
Pure data aging decision logic with comprehensive tests
Extracted a new DataAgingIndicatorPlanner class containing pure, side-effect-free computation of the warning pill's visibility, alarm state, and tooltip text. The planner is fed from application settings and returns a decision record, with 166 lines of unit tests pinning the behavior including threshold comparisons (age >= threshold warns), weekday-only calculations, never-synced cases, and tooltip wording.
-
Architecture
Script output parsing service
A new ScriptOutputParser service uses regular expressions to detect phase headers (>> Step N: ...) and heartbeat lines (still working: label (m:ss elapsed)) from PowerShell script output, enabling the UI to translate technical console streams into structured progress information. The parser scans each appended chunk of output and extracts the last phase and heartbeat label found, which view models then bind to UI elements.
-
Architecture
Extracted data aging decision logic into testable planner
Created DataAgingIndicatorPlanner as a pure, side-effect-free calculation engine for all data aging indicator decisions. The planner is fully covered by 15+ unit tests that pin the exact behavior for threshold comparisons (inclusive), weekday-only vs. calendar aging, never-synced scenarios, tooltip construction, and click-hint display. This separation ensures the title-bar indicator and the Data Aging dialog can share identical logic.
-
Architecture
Data aging stale flags exposed in planner result
The DataAgingIndicatorPlanner.Result record now includes VendorIsStale and PosIsStale boolean flags, allowing the Data Aging dialog to share the exact same staleness logic as the title-bar aging indicator. This ensures both UI elements always agree on whether data is current or needs attention.
-
Infrastructure
Unit tests for summary text generation
Added comprehensive unit tests for BuildSummaryText and HasStepProblems methods, covering successful runs, terminated runs, and various error conditions (load failures, exceptions, no matching data). Tests verify that all error details are included in the copyable summary text.
-
Infrastructure
Test coverage for error summary features
Added comprehensive unit tests that verify the Copy Summary button includes all error details (missing selection values, rounding schemes, step exceptions) and that the HasStepProblems logic correctly identifies when a run must show the summary despite user preferences.
-
Infrastructure
Added notification contract tests for SKU exception derived columns
Added source-level contract tests that verify any code path that reshapes an SKU exception's pricing rule and marks it dirty also notifies the derived "Type" and "Set Future Price to" columns. This prevents future edits from introducing the same display bug.
-
Documentation
New Lock Column reference page
Added comprehensive documentation (docs/marginmaster/pricing/lock-column.md) explaining the lock icon system: what each of the seven padlock symbols means, when they appear, how to interpret blank cells, and how locks relate to SKU-level exceptions and custom groups. Includes a visual key with all seven icons, common questions, and technical details for support.
-
Infrastructure
New ScriptOutputParser for structured progress extraction
Added ScriptOutputParser service that scans PowerShell setup script output for structured markers: ">> Step N: ..." phase headers (from Write-Step) and "still working: label (m:ss elapsed)" heartbeat lines (from Invoke-ChildProcess), converting them into friendly CurrentPhase and PhaseDetail properties for display.
-
Documentation
Enhanced SKU-level exceptions and custom groups guides
Updated sku-level-exceptions.md and custom-groups.md to explain how exceptions and groups interact with the lock icon system, including new sections on "How exceptions run," "The lock icon on the main grid," and expanded troubleshooting for duplicate exceptions and below-cost pricing warnings.
-
Documentation
Updated search index and main window orientation
Added lock icon keywords to the search index (lock icon, padlock, star column, asterisk column, etc.) and updated main-window-orientation.md to include a section explaining the two narrow symbol columns ("*" and "Z") with a reference to the new Lock Column page.
-
Infrastructure
Removal of unused VerifyDataAging method
Removed the legacy VerifyDataAging() method from MainMMViewModel, which had zero callers and implemented an older daily-check pattern. The new title-bar indicator replaces this functionality with continuous passive monitoring.
-
Infrastructure
Removed legacy startup data aging dialog
Retired the VerifyDataAging method that previously showed blocking modal dialogs at startup when data was stale. The new always-visible title-bar indicator provides continuous awareness without interrupting the startup flow, and users can click the pill to access the full Data Aging dialog when needed.
Reporting & Exports
-
Improvement
Smarter detection of genuine update failures
When an update download completes but doesn't take effect on restart (a "swap no-op"), the system now checks whether this is the first attempt for that version or a repeated failure. A first no-op is logged as a warning locally, since the swap usually completes on the next launch. Only when the same target version fails again does the system escalate to an error report on the support dashboard. This change was driven by observing store machines that reported update "failures" on every release cycle yet consistently arrived at each new version within days — their install directories weren't locked, the swaps were simply deferred.
-
Improvement
Added logging for missing UPC codes during export
The export process now logs a warning when SKUs have no UPC code available in either the VendorGTIN or Store tables, showing how many rows were affected. These rows still export with the "XXXXXXXXXXXXXX" placeholder, but the log now provides visibility into data quality issues.
-
Bug Fix
UPC column now exports actual values in text exports
When you export pricing data to NEWRETAILS.txt or other text formats that include UPC codes, the file will now contain the actual UPC numbers instead of showing "XXXXXXXXXXXXXX" for every item.
-
Bug Fix
Excel export blank rows with future price substitution
When printing or exporting to Excel with the "Use Current Price when Future Price = $0.00" option selected, all product information (SKU, description, cost, etc.) now appears correctly instead of showing blank rows.
-
Bug Fix
Excel export blank rows with price substitution
When exporting to Excel with the "Use Current Price when Future Price = $0.00" option checked, items will now show all their data correctly instead of appearing as blank rows.
-
Bug Fix
Sentinel cleanup for synchronous apply failures
When an update apply fails immediately (before the restart), the system now clears the pending-update sentinel and records the failure at the correct location. Previously, a sentinel written before a failed apply would persist and cause the next launch to misclassify the failure as a locked install directory for a swap that was never attempted. This fix applies to all apply paths: the startup version gate, the database setup window's "Download and Install Now" button, and manual update checks from the Help menu.
-
Bug Fix
Reconcile obsolete failures before classifying new outcomes
The system now clears provably outdated failure states before deciding how to classify the current launch's update outcome. When a machine reaches the version it previously failed to install (via repair install, manual installer, or the background service), the old failure counter is reset before the current launch evaluates whether to report a problem. This prevents a machine that has already healed from incorrectly coloring the current launch's verdict.
-
Performance
UPC lookup optimized for large exports
Changed the UPC resolution logic from running two database queries per exported row to a single bulk lookup that processes all SKUs at once in batches of 1,000. This eliminates hundreds or thousands of individual queries during export operations and dramatically improves export speed for files containing UPC columns.
-
Infrastructure
Code cleanup in export logic
Removed obsolete commented-out code from a previous implementation and enabled nullable reference type checking in the PrintViewModel to improve code quality and catch potential null reference issues.
Performance & Reliability
-
Improvement
Automatic connection registry cleanup
When you start Margin Master, it now cleans up your database history by removing entries for databases that have been deleted from the server, but only when it can verify the server is still available.
-
Improvement
Added protective duplicate handling to configuration loading
Enhanced the STORERSC loading logic in the Store Manager to match the same duplicate-handling pattern already used for other configuration entries (existingByOrdinal). This ensures consistent and reliable configuration loading even with imperfect source data.
-
Improvement
Enhanced UPC lookup query filtering
Modified the BuildUpcLookup fallback query to exclude Store rows with NULL or empty UPC values in the WHERE clause. This prevents Entity Framework from attempting to materialize NULL database values into non-nullable string properties, which was the root cause of the exception.
-
Improvement
Local server alias consolidation
If you have multiple connection history entries for the same local database server (due to different naming like "localhost" vs your computer name), these are now automatically combined into a single entry.
-
Improvement
Azure SQL compatibility level detection improved
Compatibility level checks and automatic adjustments now recognize that Azure SQL supports level 160 regardless of its reported 12.0 product version, ensuring optimal query performance for Azure-hosted databases.
-
Improvement
Enhanced splash screen cleanup safety
Both splash screen teardown paths now call SplashScreenManager.CloseAll(force) to guarantee cleanup of any orphaned splash windows, matching the ground-truth force-close approach already used in the async ensure-closed method. The close verification logic was enhanced to check both the service state and the static ActiveSplashScreens registry, ensuring that an orphaned manager (one the service has detached from but is still showing a window) keeps the watchdog timer armed for retry attempts.
-
Improvement
Added orphan-aware splash screen cleanup
Loading screens are now more reliably dismissed when operations complete, even in edge cases.
-
Improvement
Strategy summary now shows sitting margin instantly
The strategy summary dialog now shows your sitting margin and profit impact numbers right away instead of displaying "Calculating..." while you wait.
-
Improvement
Automatic cleanup of legacy and problematic indexes
Existing databases with accumulated performance-draining indexes will be automatically cleaned up when the application starts.
-
Improvement
Mi9 recent price change flag now includes 60-day lookback
Items with recent Mi9 price changes now stay flagged for 60 days after the change takes effect, making it easier to identify recently-changed items in strategies and filters.
-
Improvement
Index rebuilds now skip small indexes where fragmentation is noise
Daily database optimization now focuses on indexes where defragmentation actually improves performance, completing faster.
-
Improvement
Added minimum size threshold for index rebuild candidates
Database maintenance now skips very small indexes that don't benefit from rebuilding, reducing startup time and avoiding unnecessary database locks.
-
Improvement
Automatic repair of incorrect seed index definitions
The index seeding system now detects when a registered index definition has drifted from the current correct version and automatically updates it. This ensures the fleet repairs itself on first startup after update without requiring manual intervention or database scripts. Only affects seed indexes; DMV and SelectionBox-registered indexes are never modified.
-
Improvement
Unrecognized tables are now reported separately from obsolete tables
When optimizing the database, you'll now see two separate messages: one listing obsolete Margin Master tables you can safely remove, and another listing any tables this version doesn't recognize (which won't be touched at all).
-
Improvement
Database cleanup now explains what it will remove
When running database cleanup, you'll now see clear explanations of which tables can be safely removed and which ones the software doesn't recognize, with guidance on what to do.
-
Improvement
New main table selection policy with comprehensive tests
Introduced MainTableSelectionPolicy with 267 lines of tests pinning the exact behavior that prevented store 12180's incident, including how Mi9 single-table mode short-circuits, how grouping fallback resolves, and how leftover Mi9_mainTable tables are ignored in multi-table mode. The policy centralizes logic previously duplicated across DatabaseService1 and StoreDataService with subtle differences.
-
Improvement
Service restart only occurs when service was actually running
Auto-updates will no longer turn on the background service if you had it turned off.
-
Improvement
Removed duplicate migration code from Options screen
Consolidated the schedule migration logic into a single implementation that runs at startup rather than maintaining separate copies in the Options tab. This prevents the two implementations from drifting apart and producing different migration results for the same store.
-
Improvement
Strategy comparison snapshots now captured synchronously
The automatic strategy-comparison snapshot capture (used for before/after analysis) is now awaited during the "Preparing summary..." phase instead of running in the background. This prevents the snapshot from racing with any user actions after the strategy completes, ensuring it captures a consistent view of the pricing results.
-
Improvement
Configurable splash behavior for bulk strategy saves
Added a showSplashOnReload parameter to SaveOrUpdateStrategyToActiveStrategyAsync so callers performing multiple consecutive saves (like Ace Critical Pricing three-step conversion) can suppress intermediate splash displays. Defaults to true (show splash) to preserve existing behavior for single saves.
-
Improvement
Strategy comparison captures now feed execution summary
When viewing the Strategy Execution Summary after a run, sitting margin and profit impact numbers now appear immediately instead of calculating in the background.
-
Improvement
Auto-disable repeatedly failing indexes
Sync and import operations will no longer get stuck repeatedly attempting to build indexes that cannot complete on your system.
-
Improvement
Mi9 effective date now available as a grid column and rule criteria
You can now see the exact date when a Mi9 price change took effect or will take effect by adding the "Mi9 $ Effective Date" column to your pricing grid.
-
Improvement
Maintenance now runs under pipeline gate to prevent deadlocks with sync
Wrapped the OptimizeDatabaseIfNeededAsync call in the heavyPipelineGate semaphore to serialize it with startup sync and strategy runs. The ALTER INDEX REBUILD operations target the same main tables that sync's SyncMainTableCostFields updates, and when the two overlapped SQL Server would pick one as a deadlock victim. Observed cost on 2026-08-20 was 37 seconds lost on a single index rebuild plus retry backoff. The gate already serializes strategy runs against post-processing for this reason; maintenance belongs behind it too.
-
Improvement
New policy class for main table selection
Introduced MainTableSelectionPolicy as a pure-static testable class that centralizes the logic for choosing which main tables to read. All six decision branches are now covered by unit tests pinning the exact customer scenario (Ace store 12180's database state), preventing this class of regression. The policy replaces duplicate code in DatabaseService1 and StoreDataService that had already diverged (StoreDataService was missing the Mi9 single-mainTable guard).
-
Improvement
Show Changed Items grid loads with immediate busy indicator
When viewing changed items after a strategy run, you'll see a "Loading changed items…" message right away instead of a frozen-looking window.
-
Improvement
Optimized strategy comparison snapshot capture
Modified the snapshot capture process to accept pre-computed sitting-margin rows, so callers that need the data for multiple purposes (snapshot storage and summary display) only pay for the expensive scan once. The StrategyComparisonService now provides an overload that accepts already-fetched rows.
-
Improvement
Optimization progress now shows on a fixed 0-100 scale
The startup progress bar now moves smoothly during database optimization instead of jumping around.
-
Improvement
Corruption filter now runs before emptiness check
Table names containing '*' (database corruption) are now filtered out before checking if the list is empty, so a database whose only match is corrupt gets the last-resort fallback instead of an empty list. This ordering is verified by a unit test.
-
Bug Fix
Application crash on startup with duplicate RSC assignments
Margin Master will no longer crash at startup if your store configuration accidentally contains duplicate RSC assignment records. The application will use the first assignment it finds and continue loading normally.
-
Bug Fix
Fixed crash on startup with duplicate STORERSC configuration
The application will no longer crash at startup if your configuration files have duplicate RSC assignment entries for the same store.
-
Bug Fix
SQL Express installer crash on advanced format disk detection
The SQL Express setup wizard will no longer crash on newer computers with NVMe solid-state drives, and will properly detect when special compatibility settings are needed.
-
Bug Fix
SQL Express installer crash with strict PowerShell mode
Fixed a PowerShell array handling issue in the disk sector size detection code that would cause the SQL Express installer and upgrader to crash on systems with strict PowerShell mode enabled. The scripts now properly handle the return value when checking for disks with physical sector sizes larger than 4KB, which is important for SQL Express compatibility.
-
Bug Fix
Fixed label printing crash with NULL UPC values
Fixed a crash that could occur when printing labels for items that don't have UPC codes in your store's database.
-
Bug Fix
Resolved cross-thread crash during price level view changes
Fixed an issue where the price level dropdown could fail to update properly when switching between pricing views, especially during background operations. The list will now refresh correctly in all scenarios.
-
Bug Fix
Cross-thread crash in future pricing panel
Switching between views while working with future pricing will no longer cause the application to crash unexpectedly.
-
Bug Fix
Fixed missing embedded setup scripts causing SQL Server installation failures
If you previously experienced errors when trying to install or upgrade SQL Server Management Studio from the Setup window, this issue is now resolved. The installation scripts are now properly included with the application.
-
Bug Fix
Prevented re-entrant close crash in SQL Server Setup window
Fixed a rare issue where quickly double-clicking the Close button in the SQL Server Setup window could show an error message, even though the window closed properly.
-
Bug Fix
SQL Server Setup window close crash eliminated
The SQL Server Setup window will no longer crash if you accidentally click the close button or X multiple times quickly.
-
Bug Fix
Azure SQL customers no longer nagged about outdated versions
If your store uses Azure SQL Database, you will no longer see daily warnings that your SQL Server is outdated.
-
Bug Fix
Strategy runs now block all user input until completion
When running a pricing strategy, the app will now stay unavailable until the entire process completes and you see the summary, preventing accidental clicks that could interfere with the calculations.
-
Bug Fix
Strategy run now blocks all user interaction until complete
You won't see brief flickers where the app becomes clickable during a strategy run anymore — it will stay locked with the progress screen until all pricing is fully calculated and ready.
-
Bug Fix
Application lockup during Ace Critical Pricing save-as-strategies
After saving Ace Critical Pricing items as pricing strategies, the app will no longer freeze with an unresponsive main window requiring a force-quit.
-
Bug Fix
Eliminated orphaned splash screen during Ace Critical Pricing save
If you saved Ace Critical Pricing settings as pricing strategies, a loading screen could get stuck on your screen and block all mouse and keyboard input, forcing you to close Margin Master from Task Manager. This no longer happens.
-
Bug Fix
Prevent automatic index creation on main pricing tables
Pricing updates and strategy runs will complete much faster, particularly for multi-store groups—one affected store saw zone pricing speed improve from 5 minutes 48 seconds down to 915 milliseconds.
-
Bug Fix
Execution summary now displays rounding and change counts for custom groups
When you run custom groups, the execution summary will now correctly show whether rounding was applied and how many items were changed, making it easier to verify that your pricing updates ran as expected.
-
Bug Fix
Custom group rounding display in execution summary
After running a custom group or SKU exception that applies rounding, the execution summary now correctly shows which rounding scheme was used instead of showing blank.
-
Bug Fix
Execute Strategy confirmation dialog now fires only for phantom runs
When you click Execute Strategy or press Ctrl+X, the pricing run now starts immediately instead of asking you to confirm. The confirmation dialog will only appear if the system detects a suspicious automatic re-run.
-
Bug Fix
Database optimization now shrinks before rebuilding indexes
Startup database maintenance will now complete faster and won't repeat the same work every day.
-
Bug Fix
Corrected database maintenance operation order to prevent self-perpetuating rebuilds
The application will start faster when database maintenance is needed, especially on larger databases. The maintenance process now completes in one pass instead of having to repeat the same work every day.
-
Bug Fix
Store table composite index now correctly created
The RSIX_Store_StoreNumberSKU index, which enables fast lookups by store number and SKU, was never actually created on any database due to a SQL generation bug. The CREATE statement included a guard clause that checked for a column literally named "[StoreNumber],[SKU]" instead of checking for both columns separately, causing the statement to succeed as a no-op while logging "1 created" on every startup. The index is now written longhand and will be automatically created on first startup after update. This index improves performance for store-specific SKU lookups on non-WestLake databases.
-
Bug Fix
Database cleanup can no longer destroy unrecognized tables
If the database cleanup finds tables it doesn't recognize, it will now show you the list and explain that they won't be touched, rather than offering to delete them.
-
Bug Fix
Database cleanup no longer destroys unrecognized tables
If you use "Optimize Database," the cleanup will now only remove tables from old features that are no longer used. Any tables it doesn't recognize will be shown to you in a message but will never be deleted automatically.
-
Bug Fix
Selection boxes empty when store grouping misconfigured
If you turn on "Use Store Grouping" in Options before creating any groups, your selection boxes will still work—the system will use your store's real data and show a warning in the logs.
-
Bug Fix
Empty grid when store grouping enabled without defined groups
If you had store grouping turned on in Settings but never created any groups, the pricing grid would show no items and pricing strategies wouldn't update anything. Now the grid and strategies will work normally using your store's data, and a warning will remind you to either set up groups or turn off grouping.
-
Bug Fix
Selection boxes empty when store grouping enabled without groups
If you accidentally turned on "Use Store Grouping" without setting up groups, your selection boxes will now work correctly instead of appearing empty.
-
Bug Fix
Auto-update now detects and avoids locked install folder scenarios
If an auto-update tries to install while a background import is running, it will now wait and retry on the next launch instead of silently failing to update.
-
Bug Fix
Background schedule migration now runs on every startup
Previously, the migration that converts old separate vendor and POS schedules into the unified Data Update schedule only ran if someone opened the Background Service tab in Options. Since the new Data Update keys default to OFF, stores that upgraded without visiting that screen would silently stop running overnight data updates. The headless service couldn't recover on its own because it only launches when a schedule is active. Now the migration runs on every application launch, both interactive and headless, ensuring all stores migrate successfully.
-
Bug Fix
Schedule migration moved to startup to prevent silent update failures
Your overnight data updates now migrate automatically when Margin Master starts, so vendor catalogs and POS imports continue running on schedule even if you never open the settings screen.
-
Bug Fix
Progress indicators now accurately reflect strategy execution status
The progress bar during strategy runs now correctly shows how much of the entire process is complete, rather than jumping to 100% while steps are still running.
-
Bug Fix
Progress bar stays accurate throughout entire run
The progress bar during strategy runs now shows accurate overall progress instead of jumping to 100% while steps are still processing.
-
Bug Fix
Mi9 recent price change flag now remains active for 60 days after effective date
Items with price changes from Mi9 will now stay flagged as "recently changed" for 60 days after the change takes effect, so your REMOVECHANGE rules will properly protect those prices for the full two-month window.
-
Bug Fix
Resolve socket exhaustion during long sync operations
Long sync operations are now more reliable and won't cause network connection issues on the store computer.
-
Bug Fix
Fixed unnecessary global mainTable clearing on per-store POS rebuilds
After sync completes, dropdown lists (like SKU selection) now populate instantly instead of taking several seconds to reload.
-
Bug Fix
Store number dropdown empty for some stores
The Store dropdown will now populate correctly for all configurations.
-
Bug Fix
Strategy comparison snapshot no longer races with user actions
The automatic strategy-comparison snapshot (when Auto Capture Strategy Results is enabled) now completes fully under the "Preparing summary…" splash instead of running in the background. This prevents the snapshot from reading FuturePrice values that could change if the user started another action immediately after the summary closed.
-
Bug Fix
Database optimization no longer deadlocks with startup cloud sync
Startup will no longer occasionally pause for 30+ seconds when database maintenance and cloud sync run at the same time.
-
Bug Fix
Fixed scheduled sync failures on Ace tables with filtered key columns
Resolved an issue (MM-1398) where scheduled full refreshes were running orphan cleanup on all Ace Hardware tables simultaneously, causing SQL ambiguity errors (SQL 209) on tables where the filter column is also a key column. The sync service no longer force-enables reconciliation during scheduled refreshes since it's now enabled by default with appropriate safeguards.
-
Bug Fix
Selection box cache now validates source tables contain data
Selection boxes that appeared empty due to a temporary configuration issue will now automatically populate correctly after the issue is resolved, without needing manual database cleanup.
-
Bug Fix
Splash screen immediately reappears after strategy summary
After closing the strategy summary, you'll see a "Loading changed items..." message right away instead of a brief moment where the screen appears frozen without explanation.
-
Bug Fix
Empty selection boxes not re-scanned after restart
If selection boxes are empty due to missing data, restarting the application or rebuilding will now correctly re-scan them once data is present.
-
Bug Fix
Store group list no longer includes per-store tables in fallback
Fixed GetGroupList to filter out per-store main tables when store grouping falls back due to missing group tables. Previously would attempt to parse store numbers as group names, creating invalid group entries.
-
Bug Fix
Migration retries on failure instead of skipping permanently
If the migration encounters a transient error (such as database connectivity issues), it deliberately does not mark itself as complete. This allows the migration to retry on the next application launch rather than leaving a store permanently unmigrated and unable to perform background updates.
-
Bug Fix
Store group list showing store numbers instead of group names
GetGroupList now filters to only StoreGroup_{group}_mainTable tables using IsStoreGroupMainTable. Without this filter, the grouping fallback list (which can now include per-store tables like Epicor_12180_mainTable) would have split the table name and invented a store group named "12180".
-
Bug Fix
Leftover Mi9_mainTable could be double-counted
A multi-table Mi9 store caught mid-restructure with a leftover Mi9_mainTable would have double-counted it alongside the real per-store tables (it matches LIKE '%mainTable'). The policy now explicitly excludes the Mi9 single-table name unless the store is actually in single-table mode.
-
Cloud Sync
Extended orphan cleanup to all vendor tables by default
All vendor catalog tables now automatically remove records that vendors have deleted from their systems, preventing issues like printing labels with outdated barcodes.
-
Cloud Sync
Improved connection lifecycle management
Configured the HTTP connection pool with a 10-minute lifetime to balance connection reuse with server-side resource management. Extended the overall request timeout to 5 minutes to accommodate large catalog downloads.
-
User Interface
New Mi9 $ Effective Date column
A new "Mi9 $ Effective Date" column shows exactly when a price change took effect or will take effect, separate from the yes/no flag.
-
User Interface
Updated execution summary default text
Changed the Strategy Execution Summary dialog's sitting margin and profit impact lines from "Calculating..." to "Not calculated" as the default state, accurately reflecting that these metrics are only available when strategy comparison auto-capture is enabled.
-
User Interface
Improved maintenance progress reporting with fixed 0-100 scale
The progress bar during database maintenance now moves smoothly from start to finish instead of jumping around.
-
User Interface
Removed artificial delay in selection box tab creation
Eliminated the 500ms artificial delay that was previously added between each selection box tab during startup, providing a faster and more responsive initial load experience.
-
Database
System diagnostics display corrected for Azure SQL
The System Diagnostics screen now correctly displays Azure SQL edition information when showing database version details.
-
Database
Identified 10 obsolete tables safe for removal
Curated a list of tables from retired features that have been proven to have no remaining readers: legacy Sync Framework artifacts (scope_info, scope_config, schema_info), retired sync-tracking tables (MMVendorData_tracking, VendorGTIN_tracking, Ace_ZonePrice_tracking, Ace_ZonePrice, Ace_Current_tracking), replaced tables (Ace_Levels), and removed features (DIB_Costs). Each entry has been verified to have no creator that still runs and no reader anywhere in the codebase.
-
Architecture
Moved sitting-margin telemetry responsibility
Removed the daily startup sitting-margin telemetry submission (which full-scanned every main table 12 seconds after the splash screen closed) and the post-execution cloud posting. Cloud sitting-margin posting will be moved to the Windows service to run on a schedule without impacting the desktop application's responsiveness.
-
Architecture
Implement connection pooling with DNS refresh
Switched from per-request HTTP clients to a single shared client backed by a SocketsHttpHandler with a 10-minute pooled connection lifetime. This allows DNS changes to be picked up periodically while maintaining connection reuse benefits. Bearer tokens are now set per-request rather than as default headers to safely handle token refreshes during long-running sync operations.
-
Architecture
Simplified MMVendorDataBuilder interface
The BuildMMVendorDataViewAsync method no longer returns a row count that neither caller was reading. The expensive query that produced this unused number has been eliminated, and the method signature changed from Task<int> to Task.
-
Architecture
POS import table protection now derives from the POS system enum
Instead of hand-typing POS prefixes into a static list, the cleanup policy now derives them directly from PointOfSaleSystemTypeEnum, so a newly supported POS system automatically protects its tables—{POS}, {POS}_{store}_mainTable, {POS}_bcp, etc.—the same day it's added. Comprehensive unit tests walk every table name created by SqlTableCreationScripts and every POS in the enum, ensuring no live table can silently fall out of protection if the schema changes.
-
Architecture
Added database table classification policy
Introduced DatabaseTableCleanupPolicy with comprehensive unit test coverage that prevents the allowlist from drifting out of sync with the schema. The policy automatically derives POS table names from PointOfSaleSystemTypeEnum and cross-checks created table names against SqlTableCreationScripts. Two "drift guard" tests ensure newly added tables or POS systems are automatically protected without manual list maintenance.
-
Architecture
Synchronized duplicate table resolution logic
Applied the same fix to both DatabaseService3 and StoreDataService to prevent the two implementations from drifting, ensuring consistent behavior across all consumers of main table resolution.
-
Architecture
Added IndexMaintenancePolicyTests to pin size and fragmentation thresholds
Created a new test suite pinning the 1,000-page minimum and 30% fragmentation threshold. The tests document the regression origin (Aubuchon Mi9, 2026-08-20: 110s rebuilding 54 indexes, 13 of which were too small to benefit) and verify boundary conditions at exactly 999/1000 pages and 30.0/30.1% fragmentation. IndexMaintenancePolicy is a pure static class matching the pattern established by ImportFolderCleanupPolicy.
-
Performance
Removed background sitting-margin scans causing slowness
Margin Master will no longer slow down after running pricing strategies or when first starting up in the morning. Background calculations that were making the app unresponsive have been removed.
-
Performance
Removed deferred sitting-margin background scans
Strategy runs no longer trigger slow background calculations. The Strategy Execution Summary dialog still shows current and future sitting margin plus profit impact, but now displays "Not calculated" when auto-capture of strategy results is disabled in settings.
-
Performance
Batched index seeding during startup
Index seeding now uses a single database connection and pre-reads existing index names before inserting only missing entries, replacing the previous approach that opened a new connection for each index (~276 connection roundtrips on a 23-table store). This eliminates a significant startup bottleneck when all indexes already exist.
-
Performance
Batched index registration during startup
Changed the critical index seeding process to register all indexes in a single database connection instead of opening a new connection for each index. Previously, stores with 23 main tables would make ~276 separate database connections during startup just to check index registration status. The system now builds the full index list first, reads registered indexes once, and inserts any missing registrations in a single batch.
-
Performance
Enable compression negotiation for cloud sync
Cloud sync operations now use less internet bandwidth and may complete faster, especially when syncing large vendor catalogs.
-
Performance
Enable compression for cloud sync requests
Cloud sync operations now transfer less data over the network, making syncs faster and more efficient, especially for large vendor catalogs.
-
Performance
Replaced slow MMVendorData health check with fast targeted queries
Syncs finish several seconds faster—the health check at the end of each vendor sync now completes almost instantly.
-
Performance
Optimized orphan record detection in Cloud Sync
Scheduled vendor catalog syncs now finish much faster. Stores with large Ace Hardware catalogs will notice the most improvement, with sync times reduced by 30+ seconds in many cases.
-
Infrastructure
PowerShell array handling consistency
Applied the comma operator prefix to array returns in disk detection functions, matching the pattern already used in Invoke-SqlQuery. This ensures arrays remain intact across PowerShell versions and strict-mode settings in both Install and Upgrade scripts.
-
Infrastructure
PowerShell array syntax correction
Updated the Get-LargerThan4KSectorDisks function in both install and upgrade scripts to use the comma operator for proper array wrapping, preventing unwinding of single-element arrays that triggered errors in strict mode. This ensures the database installation process completes successfully across all PowerShell configurations.
-
Infrastructure
Added automated tests to prevent setup script deployment failures
Created comprehensive tests that verify all setup scripts referenced by the Guided SQL Server Setup window and Installation Scripts dialog are correctly embedded as resources. These tests check for Install-SQLExpress.ps1, Upgrade-SQLExpress.ps1, Install-SSMS.ps1, Upgrade-SSMS.ps1, Uninstall-SSMS.ps1, Uninstall-SQLServer.ps1, Set-ExecutionPolicy.ps1, Install-DotNetRuntime.ps1, and Install-OleDb12.ps1. The build will now fail immediately if any script is missing, preventing this class of silent deployment failure from recurring.
-
Performance
Removed daily sitting-margin telemetry from startup
The application no longer runs a lengthy background calculation shortly after startup, improving responsiveness when you begin working.
-
Performance
Cached selection box blank-row detection
The "BLANK" option check for each selection box field is now persisted in the SelectionLists cache table during initial build, eliminating the need to scan every main table on warm starts. The cache is automatically cleared when data changes, ensuring accuracy while dramatically reducing repeated database scans during startup.
-
Performance
Cached blank value flags in selection boxes
Selection box lists (Department, Vendor, Category, etc.) now persist their "BLANK" option status in the cache database, eliminating the need to probe every main table for blank values on warm startups. The blank value check (a UNION scan across all main tables) now only runs when the list is freshly rebuilt from actual data, not when loading from cache.
-
Infrastructure
Improved diagnostic tracking for duplicate strategy runs
Added "Unattributed" as an explicit trigger source for strategy runs that reach the execution engine without identifying how they were invoked. This provides the provenance tracking needed to diagnose the intermittent duplicate-execution defect where sessions sometimes produce two pricing runs approximately 52 seconds apart. The CanExecuteStrategy guard already disables the menu item and keyboard shortcut during a run, so any unattributed run is definitively not a UI click and can now be traced accurately.
-
Performance
Reuse HTTP connections during cloud sync
Cloud sync is now more reliable on store machines, especially during long sync sessions, by preventing network connection issues that could interrupt the sync process.
-
Performance
Eliminated redundant database query in table resolution
Hoisted the group table lookup query above the grouping decision branch so the common path reuses the result instead of querying sys.tables twice. This saves a database roundtrip when store grouping is properly configured.
-
Infrastructure
Migration logic consolidated to single implementation
The schedule migration code was moved from BackgroundServiceTabViewModel into MainMMViewModel.BackgroundCoordination.cs and is now called from both interactive startup (MainMMViewModel.InitializeAsync) and headless service runs (HeadlessRunner). This eliminates duplicate code and ensures consistent migration behavior across all launch paths.
-
Infrastructure
Safety backup before cleanup
Before modifying the connection registry, a safety backup is written to DatabaseConnections.json.cleanup.bak, providing a recovery path if manual restoration is needed. The cleanup runs fire-and-forget on a background thread after successful startup validation and swallows all exceptions to ensure it never affects application startup or stability.
-
Infrastructure
Reorganized setup script storage location
Removed duplicate Upgrade-SSMS.ps1 script from the root Scripts folder and consolidated all setup scripts under the `scripts` folder (lowercase) to maintain consistency with the repository structure. This cleanup ensures there's a single source of truth for all PowerShell installation scripts.
-
Infrastructure
SQL Server version detection enhanced with engine edition
Added EngineEdition property to SQL Server version detection queries and telemetry. This allows the application to distinguish Azure SQL from on-premises installations and apply the correct version-support policies to each deployment type.
-
Performance
Optimized main table row count checks
Main table reconciliation now uses a single metadata query against sys.dm_db_partition_stats instead of running individual COUNT(*) queries for each store table (60-120 COUNT(*) operations on multi-million-row tables for large Epicor sites). Falls back to COUNT(*) only when metadata is unavailable.
-
Performance
Optimized main table rebuild checks
Replaced individual COUNT(*) queries for each store's main table with a single metadata query using SQL Server partition statistics. For large multi-store databases (especially Epicor sites), this eliminates 60–120 COUNT(*) operations on multi-million-row tables during startup, reducing the time spent checking which tables need rebuilding.
-
Performance
Eliminated duplicate index rebuild pass during startup
Previously, the managed index rebuild process ran twice in quick succession when both RebuildMainTables and CreateTopPanel steps were queued—once during table rebuild and again a few hundred milliseconds later during selection box build. The first pass is now skipped when CreateTopPanel is also scheduled, since BuildSelectionBoxesAsync performs the same rebuild as part of its comprehensive seed-clean-rebuild sequence. This reduces startup time by eliminating redundant index existence checks and CREATE statements.
-
Infrastructure
Comprehensive test coverage for update service interaction
Added complete test suite verifying the update-service interaction contract, including guards for: both apply paths stopping the service first, failed stops aborting the update, headless imports blocking swaps, restart sentinel being set only when needed, sentinel consumption, and service binary bundling in publish workflow. These source-level tests protect against silent runtime failures that would otherwise be undetectable until machines stop receiving updates.
-
Infrastructure
Added tests to verify migration runs on startup
Created ScheduleMigrationReachabilityTests with four test cases that verify the migration runs in both interactive and headless startup paths, does not remain in the Options tab, and never enables unattended repricing. These tests prevent silent regressions where stores could lose their overnight update schedules.
-
Infrastructure
Added migration reachability tests
New unit tests verify that the migration runs on both interactive and headless startup paths, confirms the Options tab no longer maintains its own copy, and validates that the migration never enables unattended repricing (ExecuteStrategy remains false). These tests prevent regression of the critical migration behavior that keeps stores updating overnight.
-
Infrastructure
Removed unsafe legacy cleanup methods
Removed dead code (SqlServerService.RemoveDeletedDatabasesAsync and SyncDiscoveredInstancesAsync) whose unsafe semantics would have deleted remote server entries and lacked the careful reachability checks implemented in the new cleanup system.
-
Performance
Daily-gated DMV index recommendations during startup
The automatic high-impact index creation from DMV scans is now limited to once per day instead of running during every startup splash screen. Post-strategy-run index recommendations continue to execute normally, ensuring optimal indexes are still created when needed.
-
Performance
Gated connection registry cleanup to weekly execution
The connection registry cleanup process now runs once per week instead of on every application launch. The cleanup probes every SQL Server listed in the connection registry with a 3-second timeout, which caused noticeable delays on machines with stale VPN entries or unreachable servers. Since the registry only changes when connections are modified, weekly cleanup is sufficient.
-
Performance
Optimized Ace Hardware zone pricing query
Modified the Ace zone pricing update script to use an explicit column list instead of SELECT *, allowing SQL Server to use the covering index RSIX_AceZoneRecords_ZoneSku without expensive key lookups. This optimization contributed to the overall 5.7x speedup in zone pricing updates observed in testing.
-
Infrastructure
Corrected Mi9 field mapping documentation
Updated CLAUDE.md and mi9-data-pipeline.md to clarify the positional (not alias-based) mapping of Mi9 user fields, document the UserDatetime1 effective date field, and correct the LastPriceChange field description (populated by Ace enrichment, not available for raw POS data).
-
Infrastructure
Added shared row counting utility for sync operations
Introduced ActiveRowCounter helper class to ensure both the orphan detection gate and existing count-validation logic use identical SQL queries. This prevents drift between the two count methods, which would silently break the optimization's correctness guarantee.
-
Infrastructure
Drop order now follows foreign key dependencies
The cleanup now drops obsolete tables in a curated FK-safe order (children before parents) rather than sorting alphabetically, which previously caused SQL error 3726 by attempting to drop StrategyResultSnapshot before its child StrategyResultSnapshotDetail.
-
Performance
Weekly-gated connection registry cleanup
Connection registry cleanup (which probes every server in the connection list with a 3-second timeout per server) now runs weekly instead of on every launch, using a file-based timestamp gate. Reduces startup overhead for stores with multiple or stale server entries.
-
Performance
Gated high-impact index auto-creation to daily execution
The DMV scan that identifies missing high-impact indexes now runs once per day instead of on every selection panel build (every startup and rebuild). This expensive database scan and potential index creation work is deferred from the splash screen startup window to reduce launch time. Post-strategy index recommendations continue to run immediately after strategy execution.
-
Infrastructure
Added IndexMaintenancePolicy class with unit test coverage
Extracted index rebuild decision logic into a dedicated IndexMaintenancePolicy static class with comprehensive unit tests (IndexMaintenancePolicyTests.cs). Tests pin the 1,000-page minimum and 30% fragmentation threshold, verify boundary conditions, validate the candidate selection and ordering logic, and document the regression origin with real measurements from Aubuchon Mi9. Follows the static-core pattern established by ImportFolderCleanupPolicy.
-
Infrastructure
Double-check guard before every DROP TABLE
DatabaseCleanupService now re-checks the cleanup policy immediately before each DROP TABLE operation, so even if a future refactor passes in the wrong list, no table is destroyed.
-
Performance
Deferred post-startup housekeeping tasks
Heavy background operations like SKU exception description validation and automatic strategy backups now run sequentially in a delayed chain (starting 30 seconds after startup) instead of firing simultaneously during the splash screen. This moves resource-intensive work out of the critical startup path and prevents multiple operations from competing for database resources.
-
Performance
Sequenced post-startup housekeeping tasks
SKU exception description validation and automatic strategy backup now run sequentially 30 seconds after the main window appears, rather than firing simultaneously during startup. This prevents multiple heavy database and cloud storage operations from competing during the busiest part of application launch.
Infrastructure & Internal
-
New Feature
Guided SQL Server Setup Window
A new "Guided SQL Server Setup" button on the Database Setup screen walks you through installing or upgrading SQL Server—you no longer need to run PowerShell scripts manually.
-
New Feature
Guided SQL Server Setup wizard
Use Tools > SQL Server Setup to install or upgrade SQL Server through a step-by-step wizard that automatically detects what's on your computer and recommends the right action. You'll see live progress as the installation runs and be notified if a restart is needed.
-
New Feature
Database Migration Between SQL Server Instances
After installing a new SQL Server instance, you can now use "Migrate Database" (from the Tools menu or the success screen button) to move your Margin Master data onto it. The tool automatically backs up your database, moves it to the new instance, and optionally cleans up the old copy.
-
New Feature
Migrate Database between SQL Server instances
After installing a new SQL Server instance, you can use the "Migrate Database" option to move your Margin Master data from an old instance to the new one. The tool shows only your Margin Master databases, handles the technical details automatically, and keeps a backup file for safety.
-
New Feature
Delete Database utility in SQL Server Setup
You can now safely remove old Margin Master databases from Tools > Delete Database in the SQL Server Setup screen. The tool automatically backs up the database before deleting it and requires you to type the database name to confirm—the active database cannot be deleted from here.
-
New Feature
Delete Database utility in SQL Server Setup
IT staff can now safely remove old Margin Master databases through the SQL Server Setup window. The tool prevents accidental deletion by requiring you to type the database name exactly, won't let you delete the active database, and creates a backup first (enabled by default).
-
New Feature
Service health monitoring and heartbeat
The background service now reports its health to the cloud automatically, making it easier for support to diagnose scheduling issues without needing your log files.
-
New Feature
Service heartbeat to cloud
The background service now checks in with the Manager every hour (adjustable by the server), reporting its version, enabled state, job schedules, and last run results. This solves the "silent failure" problem where a stopped, crashed, or misconfigured service is indistinguishable from one that simply has no work scheduled. On startup, the service checks in immediately so new installs and restarts are visible right away. The heartbeat continues even during long-running imports so the service never appears dead.
-
New Feature
Unified Data Update job replaces separate Vendor and POS schedules
Overnight data updates are now faster because POS and vendor data are imported together in one process instead of two separate runs.
-
New Feature
Remove Empty SQL Server Instances
Once you've moved all databases off an old SQL Server instance, you can remove that empty instance directly from the "SQL Server Instances" list using the "Remove..." button. The system prevents removing any instance that still has databases or wasn't originally installed by Margin Master.
-
New Feature
Remove empty SQL Server instances
After moving all your databases off an old SQL Server instance, you can now remove that empty instance directly from the SQL Server Setup window to free up disk space and simplify your setup.
-
New Feature
Remote log upload command
If support needs to troubleshoot an issue, they can now request your diagnostic logs remotely instead of asking you to find and email files from your computer.
-
New Feature
Remote command channel
Support can now send time-limited commands to a specific store's background service through the Manager. The service polls for commands during each heartbeat, executes them, and reports results back on the next check-in. Commands are an allow-list of known operations the service already implements—anything unrecognized is rejected as unsupported rather than attempted. This channel is designed to never disrupt scheduled operations; all failures are logged and swallowed.
-
New Feature
Optional scheduled pricing strategy execution
You can now schedule your pricing strategy to run automatically after the overnight data update, so future prices are ready each morning without manual intervention.
-
New Feature
Tools menu: SQL Server Instances viewer
You can now view all SQL Server instances on your computer from the Tools menu, including which one Margin Master uses.
-
New Feature
Remote log collection
When you contact support about background service issues, they can now retrieve diagnostic logs remotely without needing to ask you to find and send files.
-
New Feature
Optional automatic strategy execution after data updates
The overnight data update can now automatically run your pricing strategy after importing data, so new prices are ready when you open the store.
-
New Feature
Automated script resolution with version skew protection
Setup scripts are resolved through a three-tier fallback (Azure blob → local cache → embedded resource) with parameter compatibility checking. If a cached or downloaded script is older than the app build and missing required parameters like -LogFile or -NonInteractive, the system automatically falls back to the embedded version to prevent silent parameter-binding failures.
-
New Feature
Tools menu: Re-check, diagnostics, and log folder
The Tools menu now has shortcuts to re-scan your computer, copy diagnostic info for support, and open the setup log folder.
-
New Feature
Tools menu with SQL Server instance inspector
You can now view all SQL Server instances on the computer via Tools > SQL Server Instances to see which ones belong to Margin Master and which belong to other applications.
-
Improvement
Faster SQL Server instance detection
The "Checking this computer" step is now much faster, especially on machines with multiple SQL Server instances or many databases.
-
Improvement
Start stopped SQL Server instances
If a SQL Server instance is stopped, you can now start it directly from the instance list without manually using Windows Services.
-
Improvement
Start stopped SQL Server instances
If you see a stopped SQL Server instance, you can now click "Start Instance" to start it and verify whether it's being used by Margin Master.
-
Improvement
Streamlined removal confirmation flow
When a SQL Server instance is successfully removed, the progress window now closes automatically and displays a clear confirmation message before returning to the instances list. This provides clearer feedback that the operation completed. Failed removals continue to keep the log window open for troubleshooting.
-
Improvement
Instant reconnection after database migration
When migrating a database to another SQL Server, you no longer need to restart Margin Master. The app reconnects to the moved database instantly and continues working.
-
Improvement
Connect after migration now defaults ON
When moving a database, Margin Master will now automatically connect to it when the move completes.
-
Improvement
Same-day installation script logs attached to issues
If you run database installation or SSMS setup scripts and then report a problem the same day, those installation logs are now automatically included with your support ticket to help diagnose setup issues faster.
-
Improvement
Automatic script log attachment to support issues
If you install or upgrade SQL Server or SQL Server Management Studio and then report a problem the same day, the installation logs will automatically be included with your support ticket to help our team diagnose the issue faster.
-
Improvement
Unified data update with single rebuild
Overnight data updates now complete faster because the system rebuilds your pricing data once instead of twice.
-
Improvement
Startup self-heal upgrades legacy service permissions
If you installed the background service before this update, Margin Master will automatically upgrade its permissions the next time the app starts (one-time elevation prompt) so future uninstalls work correctly.
-
Improvement
Startup self-heal upgraded to detect missing delete permission
The startup self-heal that ensures the background service has proper permissions now checks for all three required rights: start (RP), stop (WP), and delete (SD). Services installed before this change had only start/stop and will be upgraded automatically. Added ApplicationSettingKey.BackgroundServiceFullGrantOk to track the upgraded grant; the old BackgroundServiceStartStopGrantOk key is superseded but retained for backward compatibility.
-
Improvement
New Default Instance Name: MARGINMASTER
New SQL Server installations will use the instance name "MARGINMASTER" to avoid conflicts with other applications that may use "SQLEXPRESS."
-
Improvement
Intelligent instance ownership detection
The detection service queries each installed SQL Server instance to determine ownership by checking for Margin Master database signatures. Instances with at least one Margin Master database and no foreign databases are classified as "MarginMaster-owned" and eligible for in-place upgrade. All others are treated as foreign and never modified. Offline instances are safely classified as unknown/foreign to prevent accidental modification.
-
Improvement
Hidden child installer windows in non-interactive mode
The SQL Server installer no longer shows extra console windows popping up during installation.
-
Improvement
Clearer migration completion messages
After migration completes, the message now clearly tells you whether Margin Master will connect to the migrated database when you restart.
-
Improvement
System Diagnostics now shows Azure SQL edition
The System Diagnostics screen now displays "Azure SQL" or "Azure SQL MI" for the database version label when connected to Azure-hosted databases, instead of showing an incorrect SQL Server year version.
-
Improvement
Launch attribution now distinguishes desktop usage from background automation
License check-ins now include LAUNCHSOURCE (Desktop, Service, Manual, or Restore) and LAUNCHJOB (Vendor, Pos, Updates) fields. This allows the server to separate actual store usage from scheduled overnight imports and updates, providing accurate usage metrics in the fleet dashboard. The context is set at startup in App.OnStartup before any API calls can occur.
-
Improvement
Day-of-week scheduling replaces interval-based schedules
You now pick which days of the week scheduled jobs run (Monday, Tuesday, etc.) and what time they run at, making it easier to plan around your store's schedule.
-
Improvement
Added comprehensive test coverage for update-service interaction
Added source-level contract tests that verify the update process correctly stops the background service before swapping files, aborts if the stop fails, only restarts the service if it was actually running, checks for blocking processes, and ensures the service binary is included in published builds. These guards prevent silent update failures that would otherwise be invisible at runtime.
-
Improvement
Intelligent SQL Instance Ownership Detection
The setup wizard now accurately identifies which SQL Server instances belong to Margin Master, ensuring other applications' databases are never touched.
-
Improvement
Smart upgrade vs. fresh install decision logic
The planner automatically decides between in-place upgrade (when a single, older, Margin Master–owned Express instance exists alone on the machine) and side-by-side fresh install (when foreign instances exist, multiple instances exist, or the MM instance is non-Express). This prevents the scripts from attempting upgrades in unsupported scenarios and ensures clean installations when needed.
-
Improvement
SQL Restore Progress and Database Readiness
Enhanced SqlRestoreService to surface SQL Server's "percent processed" InfoMessage events as live progress updates during restore operations, and to explicitly set restored databases to MULTI_USER mode with a readiness wait loop (up to 30 seconds) to ensure the database is immediately usable after restore completes. Fixed a bug in SqlExpressMigrationService where restored databases were incorrectly named after the timestamped backup filename instead of the intended database name due to a missing RenameTo option.
-
Improvement
SQL restore now surfaces live progress and ensures database readiness
Database restore operations now show real-time progress percentages and won't finish until the database is fully ready for use.
-
Improvement
Store identity from legacy GlobalFileConfig is preserved during migration
Enhanced GetStoreSettingsAsync to read ApplicationSettings first as the source of truth, then gap-fill from GlobalFileConfig only when ApplicationSettings values are blank. Previously, the method only read GlobalFileConfig (which it deletes on every startup), causing 109 of 134 surveyed databases to resolve a blank vendor and drop all Ace/Do it Best entities from the data model. Disagreements between the two sources are now logged as warnings, with ApplicationSettings winning and the legacy row removed.
-
Improvement
Day-and-time scheduling replaces interval-based model
Scheduled jobs are now configured by picking days of the week and a time, making it easier to set up overnight automation that matches your store's routine.
-
Improvement
Enhanced PowerShell Scripts with Non-Interactive Mode
Install-SQLExpress.ps1 and Upgrade-SQLExpress.ps1 gain new parameters: -LogFile (starts a transcript for live tailing), -NonInteractive (auto-answers confirmation prompts per safe defaults), -ApplySectorWorkaround (consents to the 4K sector alignment fix), and -ReuseExistingBackups (upgrade only, skips re-backup if backups already exist). Scripts now report results via [MM-RESULT] markers that the app parses to auto-select the newly installed instance. Exit code contract: 0 = success, 3010 = reboot required, 20 = sector workaround consent needed.
-
Improvement
Non-Interactive SQL Uninstall Script
Updated Uninstall-SQLServer.ps1 to support fully automated operation for the guided setup window, adding parameters for -InstanceNames (bypassing the interactive menu), -AllowEmptyRemoval (permitting removal of instances with zero databases), -LogFile (transcript for real-time tailing), and -NonInteractive (suppressing all console prompts). In non-interactive mode, safe prompts auto-answer Yes while risky prompts (continue without backup, continue after failed backup) answer No and exit with code 1. Child processes (setup.exe) now run with hidden windows and emit transcript heartbeat messages every 20 seconds during long silent phases. Exit codes standardized to 0 (success), 3010 (reboot required), or 1 (failure or ownership guard rejection).
-
Improvement
Uninstall script supports non-interactive automation and heartbeat logging
The Uninstall-SQLServer.ps1 PowerShell script now accepts -NonInteractive, -InstanceNames, -AllowEmptyRemoval, and -LogFile parameters for automated removal workflows. In non-interactive mode safe prompts auto-answer Yes while risky prompts (continue without backup, continue after failed backup) answer No and exit with code 1. Long-running child processes (setup.exe uninstaller) now emit heartbeat messages every 20 seconds so transcript readers can distinguish active progress from hangs.
-
Improvement
Post-deletion refresh in SQL Server Setup
After a database deletion completes, the SQL Server Setup window automatically re-scans all instances to update their ownership classifications, such as marking an instance as "Empty" if the last Margin Master database was removed.
-
Improvement
Destination server auto-selected after migration
After moving a database, the server that received it is automatically selected so you can connect right away.
-
Improvement
Adaptive polling interval for responsive command execution
The service normally checks in once per hour, but the server can request faster polling (down to 30 seconds) while commands are outstanding. This makes remote support requests feel immediate without maintaining persistent connections or requiring inbound firewall rules. The minimum interval is enforced client-side to prevent server bugs from creating request loops.
-
Improvement
Background job status now tracks destructive rebuild phases
Added an IsDestructivePhase flag to the BackgroundJobStatus table to distinguish between safe ingest operations (writing vendor/POS tables) and destructive rebuilds (dropping and recreating main tables and selection lists). This allows startup, the background service, and monitoring tools to make safe decisions about when to wait versus when to proceed. The flag is set during main table and selection list rebuilds and cleared during ingest and upon job completion.
-
Improvement
Server Scanner Now Finds Registry-Installed Instances
The server list now automatically finds your SQL Server instance even if it has a custom name like MARGINMASTER.
-
Improvement
Live script output tailing with file watcher
The elevated script runner tails the PowerShell transcript in real time using a FileSystemWatcher, marshaling log updates through the WPF dispatcher so users see progress immediately. Previously, script output was only visible after completion.
-
Improvement
Mutually exclusive detection and execution layouts
Detection, plan review, execution, and result phases are now strictly mutually exclusive via the ShowExecution binding. The execution layout (step list + dark console panel) stays hidden during detection to prevent visual artifacts.
-
Improvement
Leading zeros in store numbers now normalized consistently
Store number comparisons throughout identity validation and renumbering detection now use a single normalization method (StoreIdentityRepairPolicy.Normalize) that preserves leading zeros only when the entire value would otherwise collapse to empty string. This prevents false mismatches when the licensing server returns store numbers with different zero-padding than what's stored locally.
-
Improvement
Contact phone number now migrates from legacy storage
Added migration support for contact phone numbers, which were previously never read from GlobalFileConfig and therefore remained stranded there permanently while email and contact name had migrated to ApplicationSettings. Phone numbers are now reconciled along with other store information on startup.
-
Improvement
New database creation writes identity to ApplicationSettings
InitializeNewMarginMasterDatabaseAsync now writes store number, vendor type, and POS system to ApplicationSettings instead of GlobalFileConfig during database creation. This ensures newly created databases have their identity in the correct location from the start, matching where the running application reads it.
-
Improvement
Settings access for service identity
Extended BackgroundSettingsStore to read application settings by their raw property names (StoreNumber, RetailerSoftVendor, PCGUID) so the service can gather the identity information needed for check-ins, since those values are persisted by the WPF app under non-enum keys.
-
Improvement
Enhanced run attribution and history tracking
The run history now clearly shows when the scheduled data update changed your prices, making it easier to track overnight pricing changes.
-
Improvement
In-window sector workaround consent flow
When a SQL setup script exits with code 20 (sector workaround needed for older installers), the wizard displays an inline decision prompt explaining the issue and allows the user to consent or decline, then re-runs the script with -ApplySectorWorkaround if approved. This replaces the previous Read-Host prompts that couldn't be used in hidden/elevated scripts.
-
Improvement
Database credential merge now updates ApplicationSettings
The credential merge operation in DatabaseSetupViewModel now writes reconciled store identity to ApplicationSettings instead of GlobalFileConfig. Previously it updated About and GlobalFileConfig but never ApplicationSettings, which allowed the two copies to drift apart over time.
-
Improvement
Post-setup instance auto-selection
After a successful SQL installation or upgrade, the Database Setup window automatically refreshes the server list and selects the newly installed/upgraded instance, allowing users to proceed directly to database creation or restore without manual server selection.
-
Improvement
Enhanced Install-SQLExpress.ps1 with new parameters
The install script now supports -LogFile for transcript routing, -NonInteractive to suppress Read-Host prompts (required for hidden execution), -InstanceName override (defaults to MARGINMASTER), and improved sector workaround handling with exit code 20 for consent requests.
-
Improvement
Enhanced Upgrade-SQLExpress.ps1 with backup reuse option
The upgrade script now accepts -ReuseExistingBackups to skip fresh backup creation when acceptable pre-upgrade backups already exist, -LogFile, and -NonInteractive for wizard integration. Result marker lines ([MM-RESULT] Instance=... Server=...) allow the wizard to extract the upgraded instance details programmatically.
-
Bug Fix
Uninstall now removes background Windows service
When you uninstall Margin Master from Windows Apps & features, the background Windows service is now properly removed instead of being left behind on your computer.
-
Bug Fix
Uninstall now removes background service
When you uninstall Margin Master from Windows settings, the background service is now removed automatically. Previously, the service would remain on your computer after uninstall.
-
Bug Fix
SQL installer crash on database-heavy systems
Fixed a PowerShell array-wrapping bug in the SQL Express installer's ownership-check logic that caused crashes on systems with many databases. On instances with 170+ databases, the bug generated "identifier too long" SQL errors by concatenating all database names together. On instances with no databases, it threw PropertyNotFoundStrict exceptions that failed the "Remove Empty Instance" step during discovery. The fix corrects six call sites across Install, Upgrade, and Uninstall scripts. Since failures occurred during the discovery phase, no data was ever modified.
-
Bug Fix
Manual catalog SKU additions now succeed in new databases
Manually adding SKUs to vendor catalogs will now work correctly without silent failures.
-
Bug Fix
Setup scripts now properly embedded in installer
SSMS and .NET Runtime installation will now work reliably even when your computer is offline or the cloud backup is temporarily unavailable.
-
Bug Fix
Azure SQL Database incorrectly flagged as outdated
If your store uses Azure SQL Database or Azure SQL Managed Instance for hosting, you will no longer see warnings about running an unsupported or outdated version of SQL Server.
-
Bug Fix
Store identity now protected from cross-tenant license responses
If your store information ever appeared to change to a different company's store number after a network interruption, this issue is now fixed. Your store identity will remain stable even during connectivity problems.
-
Bug Fix
Store identity now reads from single authoritative source
Fixed a critical issue where store identity (store number, vendor, RSC code, POS system) was stored in both GlobalFileConfig and ApplicationSettings but only partially synchronized between them. A survey of 134 customer databases found all still carrying duplicate POSTYPE entries, 62 carrying duplicate STORENAME, and four stores with actively conflicting identities (including one Ace store incorrectly configured as Do it Best, causing it to use the wrong database tables). ApplicationSettings is now the single authoritative source, with automatic reconciliation on startup that preserves data and logs warnings when conflicts are detected.
-
Bug Fix
License validation now rejects responses for different stores
If the licensing service accidentally returns information for a different store, Margin Master will now reject it and keep your existing license instead of changing your store identity.
-
Bug Fix
Headless background jobs now wait for license check-in before exiting
Previously, scheduled imports that completed in under 30 seconds would exit before their license check-in POST reached the server, causing them to not appear in the fleet dashboard. The headless runner now waits up to 10 seconds for the check-in to complete, ensuring all background runs are properly recorded regardless of how fast they complete. Found when Great Lakes Ace and Breed & Company showed "1 launch today" despite having five scheduled service runs and zero interactive launches.
-
Bug Fix
Silent updates now wait when app is open
Updates will no longer fail silently when you have Margin Master open. The background service now waits until you close the app, and your open session will install updates automatically.
-
Bug Fix
Background service now detects open app sessions before starting updates
The background service's silent self-update would previously attempt to swap application files while a user had Margin Master open. Because Velopack cannot replace folders used by a running process, updates would silently fail and the machine would remain on the old version indefinitely. The service now uses a machine-wide presence marker to detect interactive sessions and defers updates until the app is closed, allowing the app's own hourly update check to handle installations while in use.
-
Bug Fix
Auto-update now waits for headless imports to complete
When the background service launches a headless import (MarginMaster.exe --data-update), that import process holds the installation directory open for its entire duration. Previously, if an update was ready to apply during an import, it would stop the service but proceed with the file swap anyway. Because the headless import child process continued running even after the service stopped, the swap would fail silently—reporting success but actually making no changes—leaving the machine stuck on the old version indefinitely. The update system now detects when another Margin Master process is running from the install folder and defers the update until the next launch after the import completes.
-
Bug Fix
Cleanup of orphaned SQL Server Agent services
SQL Server's uninstaller sometimes leaves the SQL Server Agent service registration behind after removing an instance (observed on SQL 2025 Standard). The removal script now automatically deletes these orphaned Agent service registrations after verifying the engine service has been successfully removed.
-
Bug Fix
Clean up orphaned SQL Server Agent service after instance removal
The uninstall script now detects and removes orphaned SQL Server Agent service registrations that SQL setup sometimes leaves behind after uninstalling an instance (observed with SQL 2025 Standard). The cleanup only runs when the engine service is confirmed removed, ensuring safe deletion.
-
Bug Fix
Database list refreshes after migration or deletion
The list of available databases now updates automatically after moving or deleting a database.
-
Bug Fix
Fixed case-sensitivity issue in scripts folder
Normalized file paths for setup scripts that were tracked under a capital-S `Scripts/` folder while other scripts used lowercase `scripts/`. On Windows these appeared identical but caused the cloud upload process to miss certain files. All scripts are now consolidated under the lowercase `scripts/` directory.
-
Bug Fix
Store renumbering now prevents cross-vendor overwrites
If your store was accidentally configured with the wrong vendor's store number, the automatic repair system will no longer incorrectly overwrite your actual store information across multiple database tables.
-
Bug Fix
Restore missing store identity from legacy configuration
Added fallback logic to recover store identity from GlobalFileConfig when ApplicationSettings is blank, rather than leaving the store permanently unconfigured. Previously, if ApplicationSettings lacked a store number, the application could never recover it and would only display the Store Configuration window. The reconciliation now seeds ApplicationSettings from the legacy row when needed, then removes the duplicate to prevent future conflicts.
-
Bug Fix
Short headless runs now register in fleet dashboard
Fixed an issue where fast scheduled imports (under ~30 seconds) would exit before their license check-in completed, causing these runs to not appear in the fleet dashboard at all. The app now waits up to 10 seconds for the check-in to complete before shutting down. Longer imports were already counted because they naturally took long enough for the background post to finish.
-
Bug Fix
Startup no longer crashes when opening during background rebuild
If you launch Margin Master while a background import is rebuilding data, the app will now wait and show you the rebuild progress instead of opening with blank or incomplete pricing tables.
-
Bug Fix
App startup now waits for destructive rebuild phases to complete
If you open Margin Master while a background update is rebuilding data, you'll see a progress message on the startup screen instead of an empty or partially-loaded grid.
-
Bug Fix
Failed uninstall no longer leaves instance stopped
If removing a SQL Server instance fails, the instance will be automatically restarted so it remains usable and visible in the list.
-
Bug Fix
Service restored after failed instance removal
If removing a SQL Server instance fails, the service will automatically restart so your system is left as it was before the attempt.
-
Bug Fix
Active database deletion now shows immediate feedback
If you try to delete the database Margin Master is currently using, you'll now see a clear message explaining that you need to switch to another database first.
-
Bug Fix
Live database switching disabled during first-run setup
Database migration during initial setup now completes smoothly without freezing.
-
Bug Fix
PC registration now uses persistent computer ID
Fixed GetPCGUID to read the persisted ComputerSettings.PCGUID value instead of generating a fresh random GUID on every license request when the MM_PCGUID machine environment variable was absent (which it always was). This was causing every license validation to register as a new PC against the store's licensed computer count rather than recognizing returning installations.
-
Bug Fix
Service no longer launches pointless update checks every cycle
Stores running automatic background updates will no longer waste resources checking for updates that don't exist. The service now correctly tracks which version is installed.
-
Bug Fix
Installed version now updates from headless runs
The recorded installed version was only written during interactive app startups. On machines where the background service handled all updates and no user opened the app, the recorded version remained frozen at the last manually-opened build. This caused the service's update pre-check to detect a "newer" version every cycle and launch the full app only to be told it was already current. Headless runs now update the installed version marker, eliminating unnecessary update checks.
-
Bug Fix
Service restart sentinel now correctly gated
Refined the logic that records whether the background service should be restarted after an update. The sentinel is now set only when a service that was actively running is stopped for the update, preventing updates from quietly enabling a service the user intentionally left disabled.
-
Bug Fix
SDDL parser now correctly identifies delete permission
The SDDL rights parser now splits the rights string into two-character codes before checking for "SD" (delete), preventing false positives when the substring "SD" spans code boundaries (e.g., "RSDT" is RS + DT, not R + SD + T). Updated unit tests confirm the parser correctly rejects legacy start/stop-only grants and malformed rights strings.
-
Bug Fix
Script log documentation updated
Issue submission documentation now describes the three-bucket auto-attachment system: application logs, strategy execution logs, and same-day installation script logs. Search keywords updated to include "strategy execution logs", "installation script logs", and "script transcript".
-
Bug Fix
Manual catalog insert now explicitly provides CreateDate
Updated the INSERT statement for manual catalog items to explicitly provide GETDATE() for CreateDate as a defensive measure, ensuring the operation succeeds even if the DEFAULT constraint is somehow missing.
-
Bug Fix
Vendor resolution now reads from ApplicationSettings instead of deleted rows
If certain features or data weren't working correctly for Ace Hardware or Do it Best stores, this fix restores proper vendor-specific functionality by ensuring your vendor type is correctly identified.
-
Bug Fix
Store renumbering now requires vendor agreement
The automatic store renumbering feature (MM-1395) now verifies the licensed vendor matches the database's vendor before re-pointing a store to a new number. A renumbering only happens within the same vendor family. This prevents a license response for a different company's store from stamping their identity across StoreManagerInfo, GlobalFileConfig, and About tables, which would destroy all copies of the real store's identity. Ace Hardware and Emery Jensen are treated as one vendor family since EJ stores are carried as Ace in the vendor tables.
-
Bug Fix
SQL Express migration now renames restored databases correctly
Fixed SqlExpressMigrationService to pass RenameTo: dbName in RestoreOptions. Previously the restored database inherited the timestamped backup file's name (e.g., "MyDb_PreMigration_20260816_143022") causing subsequent verification and compatibility-level steps that connected using the original dbName to fail.
-
Bug Fix
Prevented premature job firing on first enable
The IsDue calculation now walks back 0..6 days instead of 0..7, preventing a never-run job from treating "last week's occurrence" as overdue and firing immediately when enabled. A dedicated test pins this behavior, ensuring that enabling a 02:00 schedule at midday does not trigger an import in the middle of a working day.
-
Bug Fix
SQL Server detection now recognizes all named instances
Fixed DatabaseService3.IsSqlServerInstalledAsync and SqlServerScannerService to detect any MSSQL$ service prefix (covering MARGINMASTER, SQLEXPRESS, and custom names) instead of only checking for MSSQLSERVER and MSSQL$SQLEXPRESS. This prevented machines with only a MARGINMASTER instance from being recognized as having SQL Server installed.
-
Bug Fix
RSC code reads and writes corrected across the application
Fixed DatabaseUpdateService.RSCCode property and CleanMMVendorData method to read from ApplicationSettings.RSC instead of the legacy GlobalFileConfig row that GetStoreSettingsAsync deletes on every startup. Previously, reading the deleted row meant setting the RSC here had no effect, and the MMVendorData cleanup was being skipped on migrated databases.
-
Cloud Sync
Azure SQL engine edition reported to fleet telemetry
License validation now reports the SQL Server engine edition (SQL_ENGINEEDITION) to fleet telemetry, allowing Manager to distinguish between Azure SQL Database, Azure SQL Managed Instance, and on-premises editions for support and monitoring purposes.
-
User Interface
Faster instance detection with live progress
The setup window now shows what it's checking in real-time and runs much faster on computers with many databases.
-
User Interface
Heartbeat timer during SQL Server setup
During SQL Server installation or upgrade, the setup window now shows how long each step has been running and reassures you that long silent phases are normal and still progressing.
-
User Interface
Heartbeat status updates during SQL Server installation
When installing or upgrading SQL Server, the setup window now shows how long each step has been running and displays "still working" messages during long quiet periods so you know it hasn't frozen.
-
User Interface
Success confirmation after removing SQL Server instance
After successfully removing a SQL Server instance, you'll now see a confirmation message and return to the instances list automatically, making it clearer that the removal completed.
-
User Interface
Optional automatic connection to migrated database
A new checkbox lets you tell Margin Master to use the migrated database automatically when you restart the application, even if you're currently working with a different database.
-
User Interface
Clearer "cannot upgrade in place" explanation
The setup wizard now clearly explains why a new SQL Server instance is being installed instead of upgrading your existing one.
-
User Interface
Fixed busy indicator display during detection
The setup window shows a proper busy indicator while checking your computer and no longer appears frozen during detection.
-
User Interface
Hidden child installer windows in non-interactive mode
Installer windows no longer flash on screen during SQL Server setup, making the installation process cleaner and less distracting.
-
User Interface
Visible Refresh buttons added
You can now refresh the SQL Server instance list using the Refresh button at the bottom of the window instead of closing and reopening it.
-
User Interface
Refresh buttons added to SQL setup screens
You can now click "Refresh" to update the list of SQL Server instances after making changes to your system.
-
User Interface
Updated migration checkbox label for clarity
The Migrate Database window now clearly indicates that the connection switch happens immediately when the move completes.
-
User Interface
Progress updates during script log collection
Both the full Submit Issue wizard and Quick Issue Submit dialog now display "Collecting installation script logs..." and "Uploading installation script logs..." status messages during the attachment process, providing visibility into this new automatic step.
-
User Interface
Database documentation indexed for search
Added the SQL Express vs. Full License guide to the documentation index with comprehensive search keywords covering common symptom searches like "slow performance," "50 GB limit," "database size cap," and "when to upgrade SQL Server," making it discoverable through the in-app help system.
-
User Interface
Clearer detection summary with labeled sections
The "What we found" section is easier to read, with SQL Server and Management Studio status shown on separate labeled lines.
-
User Interface
Enhanced removal workflow feedback
After a successful instance removal, users now see a confirmation dialog stating "Instance 'X' was successfully removed" and are returned to the refreshed instances list, making the outcome of the operation immediately clear.
-
User Interface
Multi-stage confirmation workflow
The Delete Database dialog implements progressive disclosure with instance selection, database dropdown (showing only verified Margin Master databases), backup checkbox (default on), and a text field requiring exact database name entry. Visual warnings appear if the selected database is currently active. A red header and warning text emphasize the destructive nature of the operation.
-
User Interface
Delete Database dialog with confirmation workflow
The delete tool walks you through choosing a server and database, asks if you want a backup first, and requires typing the database name exactly before the Delete button activates.
-
User Interface
Issue submission progress messages for script logs
Both the full Submit Issue wizard and Quick Issue Submit dialogs now display "Collecting installation script logs..." and "Uploading installation script logs..." status messages when script transcripts are found and attached. This upload occurs after the standard application log attachment and before database backup/additional file uploads.
-
User Interface
Automatic window closure after successful migration
After moving a database, the migration windows close automatically and Margin Master loads your data from the new location right away.
-
User Interface
Redesigned Background Service settings panel
The Background Service settings screen is simpler and shows exactly what your overnight update will do and when it will run next.
-
User Interface
Improved status text clarity
Status messages throughout the setup process are clearer and easier to understand.
-
User Interface
Migrate Database Button on Setup Success Screen
After installing a new SQL Server instance, the success screen now shows a "Migrate a Database..." button to help you immediately move your data onto the new instance.
-
User Interface
Post-installation guidance links migration tool
After the setup finishes installing a new SQL Server instance, a "Migrate a Database" button appears to guide you through moving your data onto the new instance.
-
User Interface
Inline Sector-Workaround Consent Dialog
If your hard drive needs a special compatibility fix during SQL installation, the setup window will ask for your permission before applying it—no hidden prompts.
-
User Interface
Redesigned Background Service settings screen
The overnight automation settings are now simpler to configure, with clear day-of-week checkboxes and plain-English descriptions of when jobs will run.
-
User Interface
Database Setup Window Quick-Launch Buttons
You can launch the guided SQL Server setup from multiple places: the Database Setup screen, the File menu under Utilities, or the Support Scripts window.
-
User Interface
SQL Server Setup menu item and buttons
Added "SQL Server Setup" to the Tools > Support menu in the main window and as a button in the Database Setup window's SQL Server and SSMS sections, providing multiple entry points to the guided setup flow.
-
Database
Schema creator now honors default value constraints
The MigrationBasedSchemaCreator now emits DEFAULT constraints (both SQL expressions and literal values) when creating tables, ensuring NOT NULL columns like CreateDate have working defaults. Includes culture-invariant formatting for bool, string, DateTime, and enum defaults.
-
Database
Startup migration heals missing CreateDate default
Added a startup migration that detects and repairs ManualCatalogItems tables created without the CreateDate DEFAULT constraint, preventing insert failures in databases created prior to this fix.
-
Database
Store identity writes now update correct storage location
Fixed four code paths that were writing store identity to GlobalFileConfig instead of ApplicationSettings: database setup, database creation, RSC code updates, and POS system changes. These writes were being silently discarded on the next startup when the per-startup cleanup removed the GlobalFileConfig entries, causing settings to appear saved but then vanish. All identity writes now go to ApplicationSettings where the running application reads them.
-
Database
Compatibility level correctly set for Azure SQL
Database compatibility level logic now recognizes Azure SQL can use level 160 (SQL 2022 feature set) regardless of its reported product version, ensuring optimal query performance and feature availability.
-
Database
Automatic cleanup of legacy store identity configuration
Added a versioned migration that removes residual store identity entries from GlobalFileConfig once ApplicationSettings contains valid data. The cleanup backs up removed data to GlobalFileConfigBackup first and includes safety checks: it refuses to run when ApplicationSettings has no store number (preventing deletion of the last surviving copy of a store's identity), and only marks itself complete on success so failed deletions retry on next startup rather than leaving orphaned data.
-
Database
Added destructive-phase tracking to background job status
Added `IsDestructivePhase` flag to the `BackgroundJobStatus` table to distinguish between safe ingest phases (which write vendor/POS tables the grid never binds to) and destructive rebuild phases (which drop and recreate main tables and selection lists). The distinction matters because ingest can safely run underneath an open app and can take ten minutes—making users wait through that would be its own bug. The flag is set by actual phase transitions rather than matching phase text, so renaming a step cannot break the data-corruption guard. Includes idempotent ALTER for stores that already have the table.
-
Database
New settings keys for unified schedule and migration flag
Added ApplicationSettingKey entries for the Data Update job configuration (enabled, days, time, last run, include POS, include vendor, execute strategy) and for the day-based schedules for the updates job. Added BackgroundScheduleMigrated flag to track when old per-job schedules have been converted to the new unified model. Vendor and POS keep their enum values so historical run-history rows still render, but nothing schedules them anymore.
-
Architecture
ApplicationSettings is now the single source of truth for store identity
Consolidated store identity management so ApplicationSettings is the authoritative source for store number, vendor type, RSC code, POS system, and store name. License responses no longer overwrite these values—they only confirm them or fail validation. Previously, these values were written to three locations (ApplicationSettings, GlobalFileConfig, and About table) with no reconciliation, causing stores to disagree with themselves. A survey of 134 databases found all carried both copies, with four actively disagreeing (including one with mismatched vendors causing incorrect entity resolution).
-
Architecture
Introduced LaunchContext ambient for process-wide launch metadata
Created LaunchContext static class to hold AppLaunchSource and background job name, set once during startup and readable by license validation. Uses the same ambient pattern as MarginMasterVersionSettings to provide launch attribution without requiring dependency injection in low-level services.
-
Architecture
Single rebuild for combined data sources
The post-processing queue now supports deferred draining, allowing both POS and vendor imports to queue their rebuild steps before draining once. This is the core architectural change that enables the unified Data Update job: both ingests contribute to the same queue, which deduplicates and drains in a fixed order, producing exactly the union of both rebuilds in a single pass. The headless runner suppresses post-processing drains during import steps and explicitly drains once after both sources have contributed.
-
Architecture
Decision-Tree Planner with Unit Test Coverage
Introduces SqlSetupPlanner, a pure-logic component (17 unit tests in SqlSetupPlannerTests) that maps detected SQL environments to ordered script steps. The planner enforces product rules: upgrade only single MM-owned Express instances in place; never touch foreign instances; always install side-by-side when multi-instance or non-Express; SQL steps before SSMS steps. Behavior is pinned by tests to prevent regression.
-
Infrastructure
SQL Server Express edition limits documentation
Created new documentation explaining SQL Server 2025 Express limitations (50 GB database cap, 4 cores, 1.4 GB buffer pool, no SQL Agent) versus full licensed editions. Includes a comparison table, guidance on when stores have outgrown Express based on symptoms like slow performance during peak hours or multi-store deployments, and clarifies that the 2025 edition's increased size cap (up from 10 GB) doesn't change compute restrictions. Indexed for support staff and end users researching database performance issues or upgrade decisions.
-
Infrastructure
DevExpress component update
Updated DevExpress.Wpf and DevExpress.Document.Processor from version 26.1.3 to 26.1.4. This maintenance update includes the latest bug fixes and stability improvements from DevExpress for the UI grid controls, dialogs, and document processing components used throughout Margin Master.
-
Infrastructure
nsoftware component version update
Updated nsoftware.IPWorks to build 9722 and nsoftware.IPWorksSSH to build 9716, with corresponding updates to runtime license stamps in licenses.licx. These components handle FTP and SFTP vendor file downloads.
-
Infrastructure
Launch attribution for scheduled background jobs
Behind-the-scenes improvement that helps RetailerSoft better understand how stores are using Margin Master versus how often automated background jobs are running.
-
Infrastructure
PowerShell strict-mode compatibility
Removed double array-wrapping around Invoke-SqlQuery results that caused incorrect iteration behavior under Windows PowerShell 5.1 strict mode. Plain assignment now correctly binds the inner row array across all zero, single, and multi-row result scenarios.
-
Infrastructure
Database fingerprint safety verification
The delete operation performs dual fingerprint verification—once when populating the database list and again immediately before dropping—to ensure only genuine Margin Master databases can be deleted. The service counts core Margin Master tables (Store, Item, PricingRule, etc.) and requires a minimum match threshold before allowing deletion.
-
Infrastructure
Database fingerprint verification for deletion safety
Implemented database verification logic that checks for the presence of core Margin Master tables (Item, Store, Vendor, etc.) before allowing deletion. Only databases that match the Margin Master signature with a minimum number of core tables can be selected for deletion, preventing accidental deletion of unrelated databases.
-
Infrastructure
Script log collection service added
New ScriptLogCollector service consolidates script transcript discovery across three different app locations (%TEMP%\MarginMaster\InstallationScripts\Logs, %TEMP%\MarginMaster\ScriptLog_*.txt, and C:\ProgramData\RetailerSoft\MarginMaster\DiagnosticTool\Logs\Scripts). Only logs written on the requested date are collected, ensuring relevance to same-day issues. Handles locked files gracefully by reading with FileShare.ReadWrite and deduplicating entry names when multiple sources contain identically-named files.
-
Infrastructure
Automated license drift detection
Added IPWorksLicenseBuildTests to fail the build if nsoftware package versions are bumped beyond what the runtime licenses cover. Previously, this mismatch would only surface as connection failures at runtime; now it's caught during development. The drift check now runs in all configurations, not just DEBUG builds, and reports failures during startup validation before any vendor sync attempts.
-
Infrastructure
Uninstall hook logging
The Velopack OnBeforeUninstallFastCallback hook now logs sc.exe stop and delete exit codes to UninstallHook.log in the ProgramData log folder, which survives uninstall. This provides a forensic trail for diagnosing service-removal failures and replaces silent failures that previously hid orphaned services.
-
Infrastructure
Uninstall hook now logs service removal outcomes
The Velopack uninstall hook now writes detailed outcomes (sc.exe exit codes, access denied errors, success/failure) to UninstallHook.log in the ProgramData log folder. This file survives uninstall and provides a forensic trail for troubleshooting orphaned services, since Serilog is not yet configured inside uninstall hooks.
-
Infrastructure
Invoke-ChildProcess helper for setup scripts
Added a new PowerShell helper function that starts child processes with proper window hiding in non-interactive mode and polls for completion while writing periodic heartbeat messages to the transcript. This ensures long-running silent phases (media extraction, VC++ install, SQL setup) remain visible to both the UI (via transcript) and the user (via status bar timer).
-
Infrastructure
Heartbeat logging in PowerShell scripts
The Install-SQLExpress.ps1 and Upgrade-SQLExpress.ps1 scripts now include an Invoke-ChildProcess function that writes heartbeat lines to the transcript every 20 seconds during long child processes, ensuring the UI transcript reader can distinguish between silent execution and hung processes.
-
Infrastructure
Documentation update for attachment workflow
Support documentation updated to describe the three script log sources, same-day collection logic, shared-access file reading for locked transcripts, and best-effort upload behavior.
-
Infrastructure
Added automated tests to prevent silent script embed failures
Created SetupScriptEmbeddedResourceTests that verify all setup scripts referenced by the installer (Upgrade-SSMS.ps1, Install-SQLExpress.ps1, Install-DotNetRuntime.ps1, etc.) are properly embedded with the exact resource names the resolver expects. This prevents the embed glob from silently breaking in future builds due to path changes or git case-folding issues.
-
Infrastructure
Dependency updates
Updated Entity Framework Core from 10.0.10 to 10.0.11, Microsoft.Extensions.* packages from 10.0.10 to 10.0.11, MySqlConnector from 2.6.1 to 2.6.2, and various other supporting libraries (NuGet.*, Sep CSV parser, ClosedXML, xunit test runner). These updates include security patches and bug fixes from upstream packages.
-
Infrastructure
Added comprehensive tests for launch attribution mapping
LaunchAttributionTests pins the command-line-to-attribution mapping and validates that enum member names match what the server accepts. This prevents silent reclassification if either side changes - job names travel as text so new background jobs require no database migration, but renaming would split history into two separate entries on the dashboard.
-
Infrastructure
Comprehensive test coverage for launch attribution
Added 115 lines of tests to verify that each launch scenario (desktop, scheduled service, manual "Run Now", and silent updates) is correctly identified and reported. This ensures usage metrics remain accurate as new background job types are added and prevents scenarios where automated activity is miscounted as user engagement.
-
Infrastructure
Command execution framework with security boundaries
Implemented a command dispatcher with a fixed allow-list of supported operations. Commands name operations the service already implements and never carry executable payloads. Authentication uses store and vendor numbers rather than sensitive credentials, so the system is designed with limited blast radius. Unrecognized commands are reported as unsupported (not failed) so services running older builds are distinguished from broken ones. Commands expire automatically and all execution happens asynchronously without blocking scheduled jobs.
-
Infrastructure
Automatic pre-delete backup with abort on failure
When backup is enabled (the default), the service creates a timestamped backup file (e.g., MyStore_PreDelete_20260816_143022.bak) before deletion. If the backup fails for any reason, the deletion is aborted and the database remains untouched. The backup file is retained even after successful deletion to allow recovery if needed.
-
Infrastructure
Removed obsolete standalone SSMS upgrade script
Deleted stale root-level Scripts/Upgrade-SSMS.ps1 file. All resolver calls now use the correct version located in the SqlScripts/Powershell subdirectory.
-
Infrastructure
DiagnosticTool cleanup
Removed unused nsoftware package references from MarginMaster.DiagnosticTool. The tool wasn't using these components and was unnecessarily shipping licensed assemblies.
-
Infrastructure
Command dispatcher and token authentication
Created a command routing system that matches incoming command types to their handlers and enforces expiration times. The service authenticates to the Manager using store number and vendor ID to obtain short-lived bearer tokens (cached and auto-refreshed). Uses the same fallback URL list as the main app to handle Azure deployments and network issues gracefully.
-
Infrastructure
Added cross-session presence detection
Introduced a new `InteractiveSessionPresence` marker using a Global mutex that the background service (running in session 0) can see when an interactive user (in session 1) has the app open. The existing single-instance mutex was session-local and invisible across session boundaries. Includes full test coverage (62 new tests) and fail-safe behavior—if the marker cannot be created or checked due to permissions, it reports "nobody is there" and degrades to previous behavior rather than blocking unattended operations.
-
Infrastructure
Settings migration preserves existing schedules
Existing per-job vendor and POS schedules are automatically migrated into the unified data update configuration once on first launch: all seven days are selected (preserving daily behavior), the earlier of the two configured times is used, and the ExecuteStrategy option is set to false unconditionally. The migration ensures no store begins scheduled repricing without explicit consent, even when upgrading from configurations that previously ran separate vendor and POS jobs.
-
Infrastructure
MySql.Data version pin documentation
Added explicit documentation that MySql.Data remains pinned at 6.10.9 as the legacy fallback driver behind the UseMySqlConnector toggle. This clarifies that it is not on the routine update path and will only be removed once migration to MySqlConnector is complete.
-
Infrastructure
Token-based authentication for service API
The service acquires and caches bearer tokens for API authentication using store number and vendor ID, refreshing them before expiration. Includes automatic fallback between primary and backup API endpoints, with preference for whichever worked last time to minimize calls on healthy systems.
-
Infrastructure
Added cross-session presence marker using Global mutex
Introduced InteractiveSessionPresence utility that uses a Global\ mutex to signal when an interactive Margin Master session is open. Unlike the existing single-instance mutex (which is session-local), this marker is visible to the background service running in session 0. The implementation gracefully degrades to local-only scope if SeCreateGlobalPrivilege is unavailable and fails to false (reports "not present") if the marker cannot be read, ensuring permission issues never block legitimate operations.
-
Infrastructure
Shared Script Resolution and Elevated Execution Services
Extracts script resolution (blob download → local cache → embedded fallback) into SetupScriptResolver and elevated PowerShell execution with live log tailing into ElevatedScriptRunner, replacing duplicated logic in DatabaseSetupViewModel and ScriptProgressViewModel. Includes parameter-capability probing: if a cached/blob script predates required parameters like -LogFile, it is replaced by the embedded copy to prevent silent failures.
-
Infrastructure
Legacy GlobalFileConfig store identity rows are cleaned up
Added CleanUpStoreIdentityGlobalFileConfigAsync migration that removes SETTINGS/STOREINFORMATION rows from GlobalFileConfig once ApplicationSettings holds the store's identity. This cleanup runs after GetStoreSettingsAsync reconciles the values, ensuring no data loss. The cleanup version flag is excluded from settings transfer to prevent a transferred "already done" flag from suppressing cleanup on a database that still needs it.
-
Infrastructure
Comprehensive test coverage for schedule logic and planner
Added BackgroundScheduleTests to verify day-of-week schedule evaluation, including edge cases like DST boundaries, never-run jobs, and daily schedules. Added DataUpdatePlannerTests to prove what a scheduled data update does given its configuration, including the critical safety case that a strategy-only configuration (no data sources) is refused to prevent unattended repricing.
-
Infrastructure
Command-line interface supports unified data update
The headless runner now accepts --data-update to run the full configured update in one process. The legacy --import-vendor and --import-pos flags are retained as support escape hatches for diagnostics, but the scheduler only invokes the unified command. Post-processing drain suppression allows both imports to queue steps into a single rebuild operation.
-
Infrastructure
Support Documentation
Adds new guided-setup support doc (marginmaster/support/sql-server-setup-window.md) with screenshots and troubleshooting steps, plus updates to install-sql-express.md and upgrade-sql-express.md documenting the new script parameters and exit codes. Index entries link the new content.
-
Infrastructure
Comprehensive unit test coverage for setup planner
Added SqlSetupPlannerTests with 19 test scenarios covering all decision branches: clean machine, single old instance upgrade, multi-instance side-by-side install, foreign instance handling, offline instance classification, instance name collision fallback (MARGINMASTER → MARGINMASTER2 → MARGINMASTER3), SSMS ordering, and answer handling (ReuseExistingBackups switch).
Other Changes
-
New Feature
Sensitivity Score engine
The system now analyzes which departments are most sensitive to price changes based on your actual sales volume, helping identify where to be careful with price increases versus where you have more flexibility.
-
New Feature
Do it Best Awareness Code E support
Added support for Do it Best Awareness Code "E" (Commodity), mapped to the 25-point bottom rung alongside "D" (Low Awareness). OneClick query now captures "E" separately and the sensitivity engine scores it as low-awareness volume eligible for margin improvement. This aligns with Do it Best's five-tier awareness system.
-
Improvement
One Click auto-recovers from empty table selection
If no pricing tables are selected, One Click will now automatically analyze all available tables instead of showing blank results.
-
Bug Fix
Old version uninstall dialogs now open correctly
When Margin Master detects an old version at startup, the uninstall prompt will now appear properly on your screen instead of being hidden or causing an error.
-
Bug Fix
Fixed sensitivity score calculation SQL error
Corrected a SQL alias mismatch in the sensitivity scoring engine that referenced "x.Code" instead of "codes.Code" for both Ace Hardware and Do-it-Best vendors. This bug could have caused sensitivity scores to be calculated incorrectly or fail to execute during margin analysis.
-
Bug Fix
Statistics display on One Click dialog open
When you open the One Click dialog, you'll now see the correct item counts right away instead of all zeros.
-
Bug Fix
One Click Statistics populate on initial load
When you open One Click Statistics, the numbers now show up right away instead of showing all zeros until you click a checkbox.
-
Bug Fix
OneClick Pricing Sensitivity Mix labels corrected
The Pricing Sensitivity Mix panel on OneClick now shows the correct labels for each sensitivity category—previously "Sensitive" and "Blind" were backwards for Ace stores.
-
Bug Fix
Fixed Print button binding in One Click screen
Corrected a typo in the Print button command binding ("PrintClickComand" to "PrintClickCommand"). This was a latent bug as the button is currently disabled.
-
User Interface
Strategy Comparison sensitivity columns
Strategy Comparison now shows which departments and classes are most price-sensitive, with higher scores meaning customers are more aware of price changes in those categories.
-
User Interface
Improved One Click dialog initialization
The dialog now calls PopulateCurrentStoreAsync during initialization to ensure statistics are visible immediately, since the checkbox toggle handlers only refresh data on change events, not on initial state.
-
Architecture
Sensitivity scoring test coverage
Added comprehensive unit tests locking the sensitivity-score contract: shared 25-100 rung mappings for Ace and Do it Best, units-weighted scoring math, null-when-no-assigned-volume behavior (never zero), additive roll-ups enabling class-to-department aggregation, and Blind/Sensitive share calculations. Tests ensure code changes (like moving DIB "E" to the 25 rung) are intentional and verified.
-
Infrastructure
New thread-safe modal dialog handler
Introduced ShowModalSafeAsync method to safely display modal dialogs from background startup tasks. This ensures the splash screen is verifiably closed and all dialogs are opened on the UI thread, preventing both threading violations and unreachable dialogs blocked by the splash screen.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Pre-flight check warns about incomplete pricing rules before strategy execution; Better error detail sharing; Non-blocking validation allows saving work-in-progress exceptions.
Strategy & Pricing
-
New Feature
Pre-flight check warns about incomplete pricing rules before strategy execution
Before running a strategy, you'll now be warned if any custom groups or SKU exceptions are set up incorrectly and won't price anything, with details about what needs to be fixed.
-
Improvement
Better error detail sharing
Long lists of excluded location codes can now be copied with one click instead of being typed manually from the screen.
-
Improvement
Non-blocking validation allows saving work-in-progress exceptions
When warned about incomplete exceptions, you can choose to save them anyway to finish the work later—the system will check again before actually running your pricing strategy.
- Improvement Enhanced save-time validation message for pricing groups
-
Improvement
Automatic repair offer on screen open
If you open the screen and have groups with margin percentages in their names but no margin settings, the system will offer to fill in the missing margins automatically, making it easier to fix broken groups right away.
-
Improvement
Enhanced reliability for SKU-Level Exceptions screen
Saving and closing the SKU-Level Exceptions screen will work reliably, even if the system encounters internal messaging issues.
-
Improvement
Close-time validation runs after save prompt
Both manager screens now run their validation checks after the save/discard prompt rather than before, ensuring the checks work on what's actually stored in the database. This prevents the confusing scenario where you discard unsaved changes but still get warnings about problems that no longer exist, or miss warnings about problems you just saved.
-
Improvement
Save button now explains when there's nothing to save
If you click Save and nothing happens, you'll now see a message explaining why—either there are no changes, or you need to click out of the box you just typed in.
-
Bug Fix
Restored missing price level comparison options
When creating pricing strategy steps, the standard price levels (Retail, Level1, Level2) now always appear in the "compare to" dropdown, even if you're using a custom column view. Previously, these options could disappear if your view showed certain price columns, which caused pricing steps to stop working.
-
Bug Fix
Custom Group margin percentages now save correctly
When you type a margin percentage into a custom group, it will now save properly instead of disappearing.
-
Bug Fix
SKU exception validation now warns on incomplete pricing rules
If you save a SKU exception without filling in all the pricing details (like choosing "Margin %" but not entering a percentage), you'll now see a warning telling you which SKUs won't be priced. You can still save the incomplete rule to finish later, but you'll know it won't work until completed.
- Bug Fix Automatic margin recovery from group names at save time
-
Bug Fix
Custom Groups manager detects and repairs incomplete rules on close
If you close the Custom Groups screen with groups that have names like "25%Margin" but no actual margin set, Margin Master will now offer to set the margin for you based on the name. This prevents pricing rules from silently failing to apply.
-
Bug Fix
Manage Custom Groups screen crash on open
The Manage Custom Groups screen will no longer crash when opening. If you have groups that need pricing repairs, you'll see the repair prompt after the window appears.
-
Bug Fix
Cancelled pricing runs no longer count as completed runs
If you cancel a pricing run before it starts, the app will no longer ask if you want to run it "again" on your next attempt.
-
Bug Fix
Resolved pricing strategies that compared against missing levels
Existing pricing strategies that compare current price to standard levels like "Level1" now work correctly, even when those levels aren't visible in your current column view.
-
Bug Fix
Price levels no longer dropped when re-saving custom groups or SKU exceptions
Custom groups and SKU exceptions will keep their configured price levels even if you can't see that price level in your current view settings.
-
Bug Fix
SKU Exceptions manager reports incomplete rules on close
If you try to close the SKU Exceptions screen with exceptions that won't actually price (missing margin, markup, or price level), Margin Master now shows you which SKUs have problems and lets you stay on the screen to fix them instead of silently failing later.
-
Bug Fix
Custom groups now preserve their cost basis setting when saved
Custom pricing groups will now keep their cost basis setting (like Average Cost) when you make changes and save the group.
-
Bug Fix
Rounding scheme selection no longer causes save failures
The Save button will work correctly even if a custom group uses a rounding scheme that's not available on your computer.
-
Bug Fix
Error icon updates after changes
Error icons now correctly appear and disappear as you fix or break pricing groups, keeping the display accurate.
-
Bug Fix
Repair prompt timing improved
The prompt offering to fix custom groups with no price level now appears at a better time—after the window is visible but before user interaction begins. The prompt is displayed at application idle priority so the window paints fully first, and is protected against WPF's re-parenting behavior that could cause it to appear multiple times. A failure in the repair offer itself can no longer prevent the screen from opening.
-
Bug Fix
Saved rounding schemes no longer overwritten by global default
Custom groups and SKU exceptions will remember the rounding scheme you chose for them instead of switching to the default rounding scheme.
-
User Interface
Copy button for strategy load errors
When a pricing strategy error appears showing excluded location codes, click the new Copy button to copy all the details to your clipboard instead of manually typing them out.
-
User Interface
Copy button added to Strategy Step Load Error dialog
When you see a Strategy Step Load Error, you can now click the Copy button to copy the entire error message, then paste it into an email or support ticket instead of manually typing it out.
-
User Interface
Repositioned Copy button in load error dialog
When an error occurs during strategy execution, the Copy button now appears at the bottom right, just below the error message box, making it easier to understand that clicking it will copy the error details shown above.
-
User Interface
Copy button repositioned in error dialog
When you see an error dialog during strategy execution, the Copy button now appears at the bottom right, next to the action choices and directly under the error message box, making it easier to understand what text will be copied.
-
User Interface
Immediate error display for broken pricing groups
Broken pricing groups now show a red error icon immediately when you open the screen, with a message explaining what's wrong. You don't need to open each group or wait until closing to find problems.
-
Database
Added validation logic for pricing rule completeness
Created new MissingPriceLevelDetector helper class with 35 unit tests to analyze saved rule text and determine if a rule can produce a price. This logic is pure and reusable, working directly from the stored rule format rather than UI state, making it reliable for both save-time validation and pre-flight checking.
- Architecture New MarginNameParser utility with comprehensive test coverage
Other Changes
-
Improvement
Enhanced update failure state reconciliation timing
Moved obsolete update failure cleanup to run before classifying the current launch's update state, ensuring that machines which have already successfully updated don't carry stale failure markers that would incorrectly influence the current launch's error reporting level.
-
Bug Fix
Eliminated false-positive update failure alerts for self-healing stores
Stores that successfully update but take an extra app restart to complete the process will no longer show up as "update failed" on support dashboards.
-
Bug Fix
Fixed misreported update failures from version gate and database setup
The version gate check during startup and the update-from-database-setup-window path were leaving behind "pending update" markers when the update failed to apply, causing the next launch to incorrectly report a locked install directory for an update that was never attempted. Both paths now clear the pending marker and record the failure at the actual point of failure.
-
Infrastructure
Added comprehensive update health policy test coverage
Added six new tests in UpdateHealthPolicyTests that replay real store occurrence sequences, including Store 12233's self-healing deferred updates and Store 12082's genuinely locked installation scenarios.
Release notes aren't available for this version.
POS data completeness validation; Import completeness verification with user confirmation; Update warning dialogs now show specific version information.
Strategy & Pricing
-
Improvement
Zone assignment logging added to pricing updates
Support staff can now see exactly which pricing zone was used for your store in the application logs, making it easier to troubleshoot pricing questions.
-
Improvement
Unrounded pricing steps now flagged in execution log
The strategy run summary now warns if pricing steps might produce unrounded prices like $12.63, which happens when a step calculates a price but has no rounding rule applied.
-
Improvement
Self-comparison fallback now logs a warning
When a comparison field cannot be resolved, SelectionService.StepQuerySQL still falls back to comparing the column to itself (a safe no-op), but now logs a warning identifying the filter and operator involved. This ensures MM-1367-type failures leave a diagnostic trace instead of silently pricing nothing.
-
Improvement
Enhanced error logging for comparison field failures
Added warning logs in SelectionService when a pricing filter has a comparison operator but no valid comparison value, helping diagnose cases where rules fail to load properly due to missing price levels in the current view.
-
Improvement
Added comprehensive test coverage for column view scenarios
Added six new automated tests covering edge cases including single-column views, mixed price column views, and the exact Ace Hardware customer configuration that triggered the original failure (a view containing only Ace_MapPriceAmt). All tests verify that saved strategy operands correctly resolve regardless of column view configuration.
-
Bug Fix
Custom groups without price levels now warn before saving
When saving a custom group, you'll now get a warning if it's active but has no price level selected. Previously these groups looked complete but never priced anything when the strategy ran.
-
Bug Fix
Custom groups with no price level now reported in strategy run summary
If a custom group can't run, the strategy summary now shows why it was skipped instead of leaving it out.
-
Bug Fix
Strategy rules no longer drop comparison fields silently
If a pricing rule compares to a column that isn't available in your current view (like Level1 or Retail), you'll now see an error message instead of the rule silently pricing nothing.
-
Bug Fix
Strategy rules now preserve comparison fields when loading
If you save a pricing strategy that compares against a specific price level (like Ace Level1 or Zone Retail), then switch to a different view that doesn't show that price level, the strategy will now alert you to the problem instead of silently pricing nothing.
-
Bug Fix
Ace zone pricing now applies automatically during import
If your store uses Ace or Emery Jensen zone pricing, your catalog will now show the correct prices for your assigned zone immediately after import, without needing to open the Store Manager screen first.
-
Bug Fix
Built-in price levels now always available for strategy comparisons
If you have pricing strategies that compare current price to Retail, Level 1, or Level 2, those comparisons will now work correctly even if you've customized your column view to hide those price columns from the grid.
-
Bug Fix
Strategy run summary now reports steps that price without rounding
The strategy run summary now shows which pricing steps calculated prices without rounding them. This helps catch mistakes where unrounded prices overwrite rounded ones.
-
Bug Fix
Warning when saving custom groups without a future price level
When saving a custom group that's missing its price level, you'll now get a warning that it won't price anything when the strategy runs.
-
Bug Fix
Built-in vendor price levels now load correctly from saved rules
Saved pricing rules that compare to vendor levels (like Ace Level1 or Zone Retail) will now load and re-save correctly without losing the comparison field.
-
Bug Fix
Vendor price level entries now correctly match saved rules
Fixed the built-in vendor price level entries (Retail, Level1, Level2, Zone Retail, Zone Level1, Zone Level2) to carry their canonical field names. Previously these entries displayed as "Ace Level1" but had no field name stored, so when a rule saved the canonical "Level1" token, it couldn't match on reload. This mismatch caused the comparison operand to be dropped entirely.
-
Bug Fix
Prevented duplicate price level entries in comparison lists
Enhanced field name matching to prevent the same price column from appearing twice in comparison pickers when both the column view and built-in list offer it. The user's custom display label (from Field Name Mapping) now takes precedence, with the built-in entry filling the gap only if the column view doesn't already supply that field.
-
Bug Fix
Bulk-apply rounding now correctly updates steps that had no rounding
Using "Set Rounding for Active Steps" now actually adds rounding to steps that didn't have it before, instead of silently doing nothing.
-
Bug Fix
Consistent zone selection when multiple store records exist
When multiple Store Manager records resolve to the same POS store number (such as a vendor-matched store plus a locally-discovered store under the same number), the system now uses a deterministic order to select which record's zone to apply: preferring records with an assigned zone, then those with a vendor store number, then the oldest record. Previously, the selection was arbitrary and could result in inconsistent zone assignments.
-
Bug Fix
Apply rounding to all active steps now correctly enables rounding flag
Applying rounding to all steps now works correctly even on steps that previously had no rounding scheme.
-
Data Import
Improved store number matching for zone assignments
Zone assignment now handles store numbers with and without leading zeros correctly (e.g., "017644" and "17644" are recognized as the same store). The system uses numeric matching on both sides and gracefully skips non-numeric store numbers rather than failing the entire assignment process.
-
User Interface
Enhanced strategy execution summary with configuration issue reporting
The Main Table strategy execution summary now includes two new diagnostic sections: one listing custom groups that were skipped due to configuration issues (with reasons), and another identifying pricing steps that wrote unrounded calculated prices. These sections appear only when relevant issues are detected, providing visibility into previously silent failures.
-
Architecture
Added UnroundedPriceStepDetector helper class
Introduced logic to determine whether a strategy step computes a price arithmetically and writes it without rounding, used for flagging potentially problematic configurations while filtering out legitimately rounding-free rules to maintain signal quality.
-
Infrastructure
Added comprehensive tests for comparison field resolution
Added 9 new tests in SelectionBoxDetailTests covering the exact MM-1367 failure condition (level absent from view must report failure), vendor-prefixed label resolution, numeric "Manual" comparisons, and round-trip correctness. Six of these tests fail against the previous code, confirming the bug and the fix.
-
Infrastructure
Automated tests added for zone assignment logic
Added comprehensive test coverage to ensure the zone backfill process only writes vendor-assigned zones (never user overrides), handles deleted records correctly, matches store numbers properly, and performs no-op updates when zones are already correct. These tests prevent regression of the MM-1368 fix.
Imports & POS
-
New Feature
POS data completeness validation
The app now checks that the data it received from your point of sale is complete before updating your prices, preventing situations where a dropped connection would accidentally erase most of your items.
-
New Feature
Import completeness verification with user confirmation
If an import is interrupted or only partially succeeds, Margin Master now asks you to confirm before replacing your data, explaining exactly which stores failed and what will happen if you continue.
-
Improvement
Connection string password redaction in logs
All POS connection strings are now redacted before being written to logs, stripping passwords while preserving server, database, and user ID for support diagnostics. Prevents accidental disclosure of SQL credentials when logs are attached to support issues or emailed.
-
Improvement
Prevent modal dialogs from blocking headless service
Import error notifications now check whether the application is running as a Windows service (headless mode) and skip modal dialogs that would block indefinitely. Headless runs automatically decline incomplete imports rather than waiting for user input.
-
Bug Fix
Fast failure and clear messaging when POS system is unreachable
If you try to import while disconnected from the store network, you now get an answer in about 3 seconds with a clear explanation, instead of waiting 30+ seconds for a confusing error message.
-
Bug Fix
Fast failure when POS server is unreachable
If your computer isn't connected to the store network, imports now tell you within seconds instead of making you wait, and your existing data stays safe.
- Bug Fix Epicor store designation validation in Store Manager
-
Bug Fix
Validation for Epicor store designations in Store Manager
If you try to enter a multi-digit number like "10" or "87" for an Epicor store, Margin Master will now show an orange warning box explaining that Epicor requires a single-character designation, not a store number. This prevents accidentally creating a store mapping that would import zero rows.
-
Bug Fix
Restored POS import functionality for multiple systems
Imports from Spruce, RockSolid MAX, and BisTrack systems that crashed immediately after starting will now work correctly again.
-
Bug Fix
Restored functionality for Spruce, RockSolid MAX, and BisTrack imports
Imports from Spruce, RockSolid MAX, and BisTrack systems now work correctly again after being broken in the previous release.
-
Bug Fix
RockSolid rejected-row errors no longer treated as application crashes
When your RockSolid export file contains rows that can't be imported, you'll still see the error message and error file as before, but these won't be incorrectly reported as application crashes.
-
Bug Fix
Prevent stale data from being re-imported as current
Your pricing data now stays accurate even if the network drops during an import — old prices will never accidentally appear as if they're current.
- Bug Fix Preserved legacy storage format compatibility
-
Bug Fix
MySQL Compass bulk import failures now halt processing instead of continuing silently
If a Compass import fails partway through, the system will now stop and alert you instead of quietly continuing with incomplete data and showing incorrect prices.
-
Bug Fix
Do-It-Best vendor data merge timeout extended from 2 to 10 minutes
Do-It-Best pricing imports will no longer time out on busy systems, ensuring you always get current vendor prices instead of outdated ones.
-
Bug Fix
Accurate import status and row count reporting
The import history now correctly shows whether each import actually worked and how many items were imported, instead of sometimes saying "success" when nothing was actually imported.
-
Bug Fix
Connectivity errors now classified separately from data errors
Network and reachability failures (error numbers 2, 17, 40, 53, 64, 121, 258, 10053, 10054, 10060, 10061, plus SocketException and Win32 host-unreachable errors) are now recognized as "the source is unavailable" rather than genuine data faults. This allows the app to show helpful "are you connected to the store network?" guidance instead of raw provider error messages.
-
Bug Fix
SQL passwords removed from support logs
Connection strings are now redacted before being written to log files, removing the SQL password that was previously logged in clear text. Since logs are routinely attached to support emails, this prevents accidental disclosure of store credentials while preserving all diagnostic information support needs.
-
Bug Fix
Import run history now records actual fetch results
Import processing records now capture per-store row counts and success/failure status from the actual fetch, replacing the previous boolean success flag that couldn't distinguish "read everything" from "read nothing but didn't throw." Prevents situations where stale staging table rows would be re-imported and stamped with today's date.
-
Bug Fix
Network interruption mid-import now exits cleanly
When connectivity is lost partway through a multi-store import, the process now breaks out immediately instead of waiting for a full timeout on every remaining store. Working export files are no longer deleted before confirming the connection is open, preserving the fallback option to reprocess an existing export.
-
Bug Fix
SystemInfoDto POS identity now sent correctly to cloud
Fixed issue where support submissions from clients with unmapped PointOfSaleSystemType values (SpruceWareNet, Versys, TAMS, Unknown) violated the cloud database foreign key constraint and lost the customer's report. The DTO now consistently populates both the legacy PointOfSaleSystemId and the new PointOfSaleSystemType/TypeName fields via SetPointOfSaleSystem().
-
User Interface
Validation message banner in Store Manager
When there's a problem with your store matchup entries, you'll now see a highlighted orange message box above the grid that tells you exactly which store has the problem and how to fix it.
-
User Interface
Stale data notification banner
When an import can't reach your point of sale, a banner now tells you exactly when your on-screen data was last updated, so you know you're looking at older prices.
- User Interface Validation feedback in Store Manager
-
User Interface
Visual banner when viewing data from previous import
A yellow warning banner now appears at the top of the screen when you're looking at older data because the latest import couldn't reach your point of sale, showing exactly when that data is from.
-
Architecture
SQL Server endpoint parsing for TCP probes
Introduced SqlServerEndpointParser to extract host and port from connection strings for network reachability checks. Handles tcp: prefixes, named instances, explicit ports, local aliases, and named pipes. Named instances on dynamic ports return an inconclusive result (since a closed 1433 proves nothing about a SQL Browser-managed instance), allowing the full connection attempt to proceed.
-
Infrastructure
Removed unused service registration code
Deleted the CommonServiceCollectionExtensions.cs file that contained service registrations which were never actually called by the application. This dead code created a maintenance trap where developers could add registrations that appeared correct but had no effect, which was the root cause of this issue.
-
Infrastructure
Added dependency injection validation tests
Implemented automated validation tests that verify all registered services can actually be constructed by the dependency injection container. This prevents issues like MM-1364 from reaching production by catching missing service registrations during development and continuous integration testing, rather than at runtime in front of customers.
-
Infrastructure
Added dependency injection validation testing
Created automated tests that validate the entire dependency injection container at build time, ensuring every registered service can actually be constructed. The test runs without requiring a live database and maintains a baseline of intentionally runtime-constructed ViewModels. This will catch similar registration errors before they reach production.
-
Infrastructure
Removed unused service registration code
Cleaned up an obsolete extension method (AddMarginMasterCommonServices) that was never being called by the application. This dead code previously registered several services including INetworkReachabilityService, but since it was never invoked, those registrations never took effect.
-
Infrastructure
Enhanced issue submission with accurate POS system identification
Issue reports now correctly map POS system types to cloud database foreign keys, fixing a constraint violation that caused some customer reports to be lost entirely. All four submission paths now use a consistent helper that maintains backward compatibility with older servers.
User Interface
-
Improvement
Update warning dialogs now show specific version information
When an update warning appears, it will now clearly show which version is available instead of displaying "(unknown)".
-
Bug Fix
Update deferral tracking now resets after successful updates
Margin Master will no longer incorrectly warn that updates are failing when you're already running the latest version.
-
Architecture
Enhanced update deferral tracking system
Added a new setting (AutoUpdateDeferredVersion) to track which specific version the deferral clock is running against. The deferral date is set once when an update is first seen, while the version is refreshed whenever a newer release supersedes an older one, ensuring accurate reporting throughout the 7-day maximum deferral window.
Reporting & Exports
-
Improvement
Enhanced error reporting fingerprinting
Improved how errors are grouped in the support dashboard by distinguishing wrapper exceptions (AggregateException, TargetInvocationException) from the actual faults they contain. Previously, unrelated errors such as blocked Windows notifications, network timeouts, and resource disposal issues were grouped together under a single fingerprint, making them impossible to diagnose or fix individually. Error grouping now includes the innermost exception type and the first application stack frame for wrapper exceptions, allowing each distinct issue to be tracked separately while maintaining fingerprint stability for all other error types.
-
Bug Fix
Fixed crash after canceling strategy execution
You can now safely import POS data or perform other operations immediately after canceling a pricing strategy—previously this would cause an error.
-
Bug Fix
Improved license validation during service outages
The application will no longer ask you to reconfigure your license when the licensing server is temporarily down—your existing license will remain valid throughout brief service interruptions.
-
Bug Fix
Corrected "Back to Database Selection" logging
Fixed an issue where choosing "Back to Database Selection" during license validation was incorrectly logged as a license validation failure with a null error message. This navigation action is now logged appropriately as an informational event rather than an error.
Other Changes
-
Improvement
License service outages no longer interrupt workflow
You'll no longer see license configuration prompts during temporary outages of our licensing service as long as your existing license is still current.
-
Improvement
Suppressed spurious license revalidation error logs
Eliminated a spurious error log entry ("License revalidation failed: null") that appeared whenever a user chose to return to database selection from the license configuration window instead of completing revalidation. This normal navigation action is now logged as informational rather than an error.
-
Bug Fix
BLANK option now appears in single-value selection boxes
If you have a field like User Code 3 that has one value on some items and is blank on most others, you can now select BLANK to see all the items without that code. Previously, you could only see the items with the code.
-
Bug Fix
BLANK option now appears for single-value columns with blanks
Previously, if a field like User Code 3 had only "M" on some items and was blank on everything else, the filter dropdown would only show "M" with no way to select the blank items. Now the dropdown correctly shows both "M" and "BLANK" so you can filter either group.
-
Bug Fix
Error grouping now distinguishes between different underlying failures
Background error tracking is now more accurate, which helps us identify and fix issues faster.
-
Bug Fix
Strategy execution cancellation no longer breaks subsequent imports
Cancelling a pricing strategy will no longer cause the next data import to fail with an error.
-
Architecture
Removed unused duplicate method
Deleted CreateUniqueFieldListFromMainTableFieldListAsync, a 108-line near-duplicate of the main unique-list builder that had no callers anywhere in the solution but carried the identical one-value bug. Removing it prevents future developers from accidentally reintroducing the defect.
-
Infrastructure
Added automated tests for BLANK option logic
Created a comprehensive test suite (BlankSelectionOptionTests) that pins the exact rule for when BLANK should be offered: blanks must exist in the data AND the field must have at least one real value. Tests cover single-value fields with blanks (the MM-1359 case), multi-value fields, fully populated fields, and entirely-blank fields.
-
Infrastructure
Added test coverage for BLANK option logic
Added comprehensive unit tests that verify when the BLANK option should and shouldn't appear: it appears when the column has blanks in the data and at least one real value, but not when the column is entirely blank (which would create a useless BLANK-only dropdown) or when no blanks exist in the data.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Update alerts now show target version number; Plus-or-Minus spinner now steps by whole dollars in Dollars mode; Plus-or-Minus spinner increment corrected.
Strategy & Pricing
-
Improvement
Update alerts now show target version number
If you see an update warning, it will now tell you which version it's trying to install instead of showing "(unknown)".
-
Bug Fix
False update warning after successful installation
If you successfully update Margin Master, you will no longer see a warning that the update failed.
-
Bug Fix
Update tracking for machines upgrading from pre-August 2026 versions
Resolved a specific issue affecting machines updating from versions older than 2026.804. These older versions stored update status in store-wide settings, while newer versions use machine-specific settings. When the migration logic correctly discarded the old store-wide data (since it couldn't identify which workstation wrote it), the system had no record of a successful update and never cleared the deferral clock. The authoritative "up to date" response from the update server now serves as the definitive signal to clear tracking, regardless of migration path.
Other Changes
-
Bug Fix
Plus-or-Minus spinner now steps by whole dollars in Dollars mode
When using the Plus-or-Minus feature set to Dollars, clicking the up or down arrows now changes the amount by a full dollar ($1.00) instead of just one cent. You can still type fractional dollar amounts if needed, but the spinner buttons work correctly.
-
Bug Fix
Plus-or-Minus spinner increment corrected
When adjusting prices using the plus-or-minus feature in Dollars mode, clicking the up/down arrows now changes the value by $1 instead of 1¢, making it easier to apply dollar-based price adjustments.
-
Bug Fix
Vendor catalog no longer deleted when RSC setting is corrected
If your store's RSC code is corrected in Settings, the next sync will automatically reload the complete vendor catalog for the new RSC instead of leaving you with incomplete data.
-
Bug Fix
Schema migration no longer fails repeatedly on tables converted to views
DatabaseMigrationService now skips ALTER TABLE commands whose target is a view. MMVendorData became a view, so 21 of 47 schema commands failed on every startup — 63 log entries in a single day at store 3936, burying real failures. These commands are now skipped silently since they are unapplicable by definition.
-
Cloud Sync
Multi-RSC stores no longer lose their primary RSC catalog
Stores with multiple RSC codes configured will keep catalog data for all locations, including the main store RSC.
-
Cloud Sync
Dramatic table shrinkage during sync now logged as a warning
Any sync that reduces a table by more than 20% now logs a warning with before/after counts. Store 3936's catalog shrank from 79,661 to 1,167 rows with nothing in the log but "Successfully synced" — the loss left no trace. The warning helps distinguish deliberate scope changes from data corruption.
-
Cloud Sync
Count validation self-heal no longer deletes data before refetching
When count validation detects a local/cloud mismatch and triggers a re-sync, the local partition is no longer deleted first. Re-syncing from RowVersion 0 reaches the same end state via upsert and tombstone cleanup, without a window where a refetch failure would leave the partition empty while the sync still reports success.
-
User Interface
Improved spinner behavior consistency across unit types
The Plus-or-Minus spinner arrows now work the same way for all measurement types—each click increases or decreases by one whole unit of whatever type you've selected.
-
User Interface
Strategy execution summary now shows why steps skipped SKUs
When a pricing strategy step skips products, the summary dialog now explains exactly what's missing — like a product group that no longer exists — so you know what to fix.
Release notes aren't available for this version.
Release notes aren't available for this version.
SQL Server version support policy enforcement; SQL Server version detection and warning system; SQL Server version detection and warning system.
Imports & POS
-
New Feature
SQL Server version support policy enforcement
If your computer is running an old version of SQL Server, Margin Master will now notify you and recommend upgrading to SQL Server 2025 (SQL Server 2022 is the minimum supported version).
-
New Feature
SQL Server version detection and warning system
If your computer is running an old version of SQL Server, Margin Master will now warn you and recommend upgrading to SQL Server 2025 or at least SQL Server 2022.
-
New Feature
SQL Server version detection and warning system
If your computer is running an old version of SQL Server, Margin Master will now warn you at startup and recommend upgrading to SQL Server 2025 (or at least SQL Server 2022). SQL Server Express is free from Microsoft.
-
Improvement
Import file scan results now logged for diagnostics
The Import Manager now writes a detailed log entry after each scan showing how many files were found, how many matched the POS system, how many are backups, and how many are displayed under the current filter. This was added after a store reported an empty import list that required extensive troubleshooting to diagnose. The log entry distinguishes between "no files matched" and "files matched but were filtered out" (for example, when the Backup Files filter is active but all matched files are regular POS exports). This improvement enables faster remote diagnosis of import file visibility issues without requiring database restores or file exchanges.
-
Improvement
Smarter filtering of non-import files
The Import Manager is now better at automatically skipping files that aren't POS exports, even if they have slightly different names or are in folders with unusual names.
-
Improvement
Enhanced file filtering for Margin Master export copies
Copied or renamed versions of export files (like "NEWRETAILS - Copy.TXT") are now automatically ignored during import scanning, just like the originals.
-
Improvement
Import Manager dialog cleanup
Removed unused custom import functionality from the Import Manager, including a non-existent property binding that was generating errors in the log every time the dialog opened, dead code branches, and commented-out blocks.
-
Bug Fix
Import Manager dialog no longer fails silently after finding files
If the Import Manager has trouble reading your import folder, it will now show you an error message explaining what went wrong instead of appearing to freeze with an empty file list.
-
Bug Fix
Import Dialog no longer fails silently when loading files
If the import screen has trouble reading files from your import folder, you'll now see an error message explaining the problem instead of a blank screen.
-
Bug Fix
Import scan no longer hangs on mismatched files
If you have unrelated text or CSV files in your import folder, the Import Manager will now skip them quickly instead of freezing. Your actual POS export files will be detected and displayed normally.
-
Bug Fix
Import scan no longer hangs on incompatible files
If you have extra copies of files or unrelated spreadsheets in your import folder, the Import Manager will now skip them quickly instead of freezing. Your actual import files will appear in the list as expected.
-
Bug Fix
Import no longer hangs on unparseable TransAct records
If your TransAct import file has a record with corrupted or invalid data (like a price that isn't a number), the import will now skip that bad record and continue importing the rest of your data, instead of freezing forever.
-
Bug Fix
Import Dialog no longer fails silently when loading files
If the import screen has trouble reading files from your import folder, you'll now see an error message explaining the problem instead of a blank screen with a stuck loading indicator.
-
Bug Fix
Null dispatcher guard in Import Dialog progress management
Fixed a null reference exception in the Import Dialog's ProgressEnd method that could occur when the DispatcherService was not yet initialized. The method now uses the same DispatchSafe pattern as the rest of the file loading process, preventing crashes during edge-case timing scenarios.
-
User Interface
Improved error handling throughout Import Dialog
All Import Dialog file loading operations are now wrapped in proper exception handling. Previously, unhandled errors in the async WindowLoaded method would be silently swallowed, leaving the UI in an inconsistent state. The busy progress overlay is now guaranteed to clear even when errors occur.
-
User Interface
Clearer status messages during import scan
When the Import Manager skips a file, you'll now see a clearer explanation of why it was ignored.
-
Infrastructure
Comprehensive test coverage for bad record handling
Added automated tests that verify the import engine correctly handles files containing unparseable records in various positions: mid-file, as the last line, and files consisting entirely of bad records. These tests run with a strict 30-second timeout to ensure that any regression causing infinite loops will immediately fail the test suite rather than hanging the build system. Tests were verified against the actual customer database, where all three scenarios hung for the full 30-second cap before the fix and completed in under 500ms after.
-
Infrastructure
Added comprehensive test coverage for import file validation
Added 7 new unit tests covering the field-count sniff logic, including tests for the exact file that caused the customer's scan to hang (2-field file vs. 37-field layout), real BisTrack exports, files with quoted commas in descriptions, truncated rows, header-only files, and the timeout bounds.
-
Infrastructure
Error reporting suppression for unsupported environments
Added the ability to suppress cloud error reporting when running in known-unsupported environments. When SQL Server 2017 or older is detected, all telemetry reporting stops for that session to avoid polluting error data with expected failures from unsupported configurations.
-
Infrastructure
Error reporting suppressed for unsupported SQL Server versions
When SQL Server 2017 or older is detected, cloud error telemetry reporting is automatically suppressed for the entire session. The database schema errors that result from these unsupported versions are expected consequences of running below the minimum functional version, not actionable bugs—reporting them would pollute the error data stream. Users still see warnings in the UI, but errors are only logged locally.
Cloud Sync & Vendor Data
-
Bug Fix
Fixed version reporting to show consistent format
Store version numbers are now consistently reported in the semantic version format shown in the Margin Master title bar (e.g., 2026.803.41581) rather than mixing two different formats side-by-side. The system now combines data from multiple sources and filters out outdated readings from legacy installs on secondary machines that were masking actual current versions. This resolves cases where stores 2928 and 4161 appeared outdated due to old installations on sibling machines, and where Ruidoso #9039 incorrectly appeared as unpatched when it had already updated.
-
Bug Fix
Corrected "last seen" time calculation for store activity
Fixed a timezone defect where "last seen" times were overstated by four hours. The system was mixing UTC timestamps from auto-update check-ins with Eastern timestamps from application activity without conversion, causing the MAX() calculation to always favor the UTC value. All timestamps are now normalized to Eastern time before comparison, providing accurate "days quiet" measurements for store activity monitoring.
Performance & Reliability
-
Improvement
Enhanced startup error handling
Improved the application's resilience to configuration errors by adding a fallback mechanism for unrecognized setting keys. Instead of causing a startup failure, missing configuration keys now log a warning and use a conventional format, ensuring the application can always start even if future updates introduce configuration issues.
-
Bug Fix
Application startup hang resolved
Margin Master will now open normally instead of freezing on the loading screen.
-
Bug Fix
Application startup hang resolved
The application will no longer freeze on the loading screen when it checks for update information at startup.
-
Infrastructure
Safety net for future configuration keys
Added a fallback mechanism that automatically generates configuration keys using a conventional naming pattern when an explicit mapping is missing. This prevents any future missing key mappings from causing application startup failures, logging a warning instead so developers can add proper mappings where needed.
Other Changes
- Improvement Update success now clears failure state on version advancement
-
Bug Fix
SQL Server minimum-version check now uses engine version
If you have an older version of SQL Server installed (2017 or 2019), Margin Master will now correctly recognize it as incompatible and guide you through upgrading or installing the required SQL Server 2022 version. Previously, it would incorrectly attempt to use these older versions.
-
Bug Fix
SQL Server minimum version validation corrected
When connecting to an existing SQL Server instance, the app now correctly identifies whether that server version is compatible with Margin Master. Previously, older incompatible SQL Server versions could be incorrectly accepted.
- Bug Fix Update health state now tracked per machine
- Bug Fix Obsolete failure counters now cleared automatically
- Infrastructure One-time migration from store-wide to machine-specific update tracking
Cost basis selector for Margin % pricing; Show Affected Items for Strategy Steps; Show Affected Items for strategy rules.
Strategy & Pricing
-
New Feature
Cost basis selector for Margin % pricing
Below the Margin % field, you'll see a new "Margin on cost" dropdown. Pick "Store Cost (Default)" to calculate margin the usual way, or choose Replacement Cost, Average Cost, Cost2, or MFG Cost if you want the margin based on a different cost value. Items missing that cost will be skipped.
-
New Feature
Show Affected Items for Strategy Steps
When a pricing rule changes margins or other values it selected on, the normal "Load" button shows nothing because the rule can't find items that now have different values. "Show Affected Items" shows what the rule actually changed on its last run by looking at the history record instead. Double-click any step in the execution summary to see its affected items.
-
New Feature
Show Affected Items for strategy rules
To see which items a strategy rule affected: open the Strategy Execution Summary after running a strategy, select a rule from the list, and click "Show Affected Items" (or double-click the row). The main pricing grid will load showing every item that rule changed, regardless of whether later rules modified them further.
-
Improvement
Enhanced Unpriced SKU Report accuracy
The Unpriced SKU Report after a strategy run now shows a complete count of items without prices, including those that couldn't be priced due to missing cost data.
-
Improvement
Unpriced SKU report now counts all unpriced items
The unpriced items report after running a pricing strategy now accurately counts all items that didn't receive a new price, including those that couldn't be priced due to missing cost information.
-
Improvement
Clearer warning message for unmatched stores
Import warnings now more clearly explain when a store needs to be set up in Store Manager.
-
Improvement
Clearer diagnostic message for unmatched stores
If an item table can't be matched to your store setup, the error message now clearly explains that the table isn't linked to a store record, making it easier to diagnose configuration issues.
-
Improvement
Enhanced protection for POS program directories
RockSolid sites that point DEFAULTIMPORTPATH at the POS installation folder (required because the importer reads RockSolid.RS in place) are now protected by two independent guards: the folder is both outside C:\MarginMaster and under Program Files (x86). Test cases now explicitly verify that C:\Program Files (x86)\Rock and the critical files Rock.exe and RockSolid.RS can never be deleted by future code changes.
-
Improvement
Strategy execution duplicate-run prevention
You can no longer accidentally run the same pricing strategy twice in quick succession—the system now prevents double-clicks and asks for confirmation if you try to re-run within two minutes.
-
Improvement
Store Manager auto-fills RSC from organization majority
When opening Store Manager, any store without an RSC after loading cloud settings is now defaulted to the organization's most common (majority) RSC. This value is marked dirty and pushed to the cloud on save, ensuring Manager learns the derived RSC. The auto-fill is non-destructive—it only fills blank values and never overwrites an explicitly-set RSC.
-
Improvement
Consistent History Recording Across Pricing Methods
Consolidated PSRuleHistory append logic into a single shared function used by both rounding-based pricing and explicit SQL pricing paths. Previously each site built its own de-duplication test, risking divergent behavior where a row's audit trail depended on whether the step happened to use a rounding scheme. Both paths now produce byte-identical history strings.
-
Improvement
Duplicate strategy run prevention with user confirmation
If you accidentally click Execute Strategy twice in a row, the app now asks you to confirm before discarding the current results and running again. The menu item is also grayed out during the entire strategy run to prevent accidental clicks.
-
Improvement
Distinct SKU count logging for strategy runs
Strategy runs now log how many distinct SKUs were actually priced (COUNT(DISTINCT SKU) WHERE FuturePrice <> 0) alongside the per-step total. The TotalSkusAffected metric reported to the cloud is a sum of work across all steps where a SKU touched by five steps counts five times, making it unsuitable for run-to-run comparison; the new distinct count provides the comparable figure.
-
Bug Fix
DIB retail prices now correctly filter by store's assigned RSC
If your Do it Best store has multiple Regional Service Centers, you were seeing prices from the wrong RSC on some items. This is now fixed, and the correct prices for your RSC will display automatically.
-
Bug Fix
Restored RSC filtering for Do-It-Best retail price calculation
Your store will now see the correct retail prices for your region instead of prices from other Do-It-Best regions.
-
Bug Fix
Unified annual impact calculation across all POS systems
Annual impact now correctly shows how much revenue your pricing changes will generate, measured the same way for all stores regardless of which point-of-sale system you use.
-
Bug Fix
Unified annual impact calculation across all POS systems
The annual revenue impact numbers shown after running a strategy are now accurate and consistent regardless of which POS system your store uses. Previously, some systems reported misleading negative impacts even when strategies raised prices.
-
Bug Fix
Catch-all rules now attribute unpriced SKUs
When running a pricing strategy, you'll now see which rule examined each SKU, even if that SKU couldn't be priced due to missing cost information.
-
Bug Fix
Catch-all rules now claim all selected SKUs
When a pricing rule can't calculate a price for an item (usually because cost information is missing), the rule's name will now appear in the pricing analysis so you can see which rule tried to price it.
-
Bug Fix
Catch-all pricing rules now stamp all covered items
When viewing pricing analysis, items with no cost will now correctly show which pricing rule applied to them, even if no actual price could be calculated.
-
Bug Fix
PSRule attribution now works on all items for catch-all rules with rounding
When a pricing rule applies to all items, you'll now see the rule name in the PSRule column for every item, even items that couldn't be priced because they're missing cost information.
-
Bug Fix
Zone pricing now resolves correctly for non-Epicor stores
If you noticed your store's pricing didn't match your assigned zone after a recent update, this fix restores the correct zone-based pricing. Stores were being priced at the national zone even when a specific zone was configured.
-
Bug Fix
Ace Hardware zone pricing now resolves correctly on non-Epicor systems
If your store uses Ace Hardware or Emery Jensen pricing zones with RockSolid, Transact, BisTrack, Catalyst, Falcon, Paladin, or MySQL Compass, your items will now price at your correct assigned zone instead of incorrectly using the national zone.
-
Bug Fix
Import cleanup restricted to application's own folder
If you use a custom import folder outside C:\MarginMaster (like D:\Imports or the POS program folder), old .BAK backup files will accumulate instead of being automatically removed after 7 days. This is intentional—it's safer to let backups build up than risk deleting important POS files.
-
Bug Fix
Store Manager RSC assignments now apply to pricing builds
If you assigned an RSC to a store in Store Manager but pricing still used a different RSC, that will now work correctly. The RSC you see in Store Manager is the RSC that will be used for pricing.
-
Bug Fix
Store Manager RSC mappings now reach the pricing build
If you've assigned RSCs to stores in Store Manager, those stores will now price correctly using their assigned RSC instead of the default application setting.
-
Bug Fix
Restore DIB auxiliary retail pricing
If you price bulk items (like wire, chain, or rope sold by the foot but priced by the roll) using the auxiliary retail, those prices will now appear and your pricing rules will work correctly.
-
Bug Fix
Restored Do-It-Best auxiliary retail pricing in vendor data view
The MMVendorData view now correctly populates the Ace_MSURetail column with Do-It-Best auxiliary retail values from the catalog's SuggAuxRetail field. Previously this column was hardcoded to zero when the view was created, breaking the downstream pricing calculations that depended on it. The view also now includes the PrivateLabel field from the DIB catalog, which is a letter code present on approximately 10% of SKUs.
-
Bug Fix
Mi9 stores now report all twelve months of sales history
Mi9 stores' annual impact figures now include the most recent month, which was previously missing.
-
Bug Fix
Corrected Mi9 monthly sales history to include all twelve months
Annual impact calculations for Mi9/RockSolid stores now include all twelve months of sales history instead of only eleven, making the projections more accurate.
-
Bug Fix
RSC fallback logic now runs on correct code path
Stores that don't have an RSC assigned will now borrow one from other stores in your organization instead of using the wrong default, and new store numbers will price using a reasonable RSC rather than showing no data at all.
-
Bug Fix
RSC fallback ladder now executes for all stores
The RSC fallback logic introduced in MM-1341 (which borrows a workable RSC from other org stores when a store has no explicit mapping) was accidentally implemented in StoreDataService, which is never injected or called. Every pricing operation called DatabaseService instead, so the ladder never ran and stores with missing mappings always fell back to the application-level RSC. The ladder now lives in DatabaseService4.GetSpecificRSCAsync on the actual execution path.
-
Bug Fix
Strategy Step Names with Special Characters
Pricing rule names containing %, _, or [ characters now work correctly and won't lose their history records.
-
Bug Fix
Wildcard characters in rule names now handled correctly
Strategy rules with special characters like "%" or "_" in their names now work correctly and won't accidentally match other rules or skip recording their changes.
-
Bug Fix
Correct Level3 column for DIB stores
The "DIB Aux Retail" column in your pricing grid now shows the correct auxiliary retail prices from the Do it Best catalog instead of internal rounding values.
-
Bug Fix
Corrected Level3 (DIB Aux Retail) column population across all POS import paths
The "DIB Aux Retail" column in the pricing grid now shows the correct auxiliary retail prices instead of being blank or showing rounding values.
-
Bug Fix
Margin calculations respect cost availability
If you select Replacement Cost for margin calculation but a product has no replacement cost entered, that product will be skipped instead of accidentally using a different cost.
-
Bug Fix
Missing STORERSC entries now fall back to application-level RSC
If your store's RSC mapping is not configured, the system will use your main RSC setting and alert support, rather than showing random prices.
-
Bug Fix
Eliminated SKUs with no future price from impact calculations
The Compass/Epicor variant was substituting CurrentPrice when FuturePrice was zero, which incorrectly included every SKU the strategy never touched in the impact totals, inflating them with unrelated price drift. These SKUs are now properly excluded from all calculations.
-
Bug Fix
Cloud sync now preserves locally-derived RSC assignments
RSC assignments that Store Manager fills in automatically (like when it picks the most common RSC in your organization) will now sync to the cloud properly and won't be lost.
-
Bug Fix
Fix auxiliary retail for MySQL Compass stores
If you use MySQL Compass and have pricing rules that check for auxiliary retail prices (like "MSU Retail greater than 0"), those rules will now find and price the correct items.
-
Bug Fix
Fixed MSU Retail updates for MySQL Compass users
Pricing rules that filter on MSU Retail (such as "Ace_MSURetail~GREATER~0.00") now work correctly for Compass POS users.
-
Data Import
Cost basis preserved in saved strategies and SKU exceptions
Your cost basis choice is saved with the strategy and works everywhere—regular pricing rules, custom groups, and individual SKU overrides.
-
Data Import
One-time automatic repair of incorrect DIB retail prices on upgrade
When you first open Margin Master after this update, it will automatically correct any retail prices that were pulled from the wrong Regional Service Center. This happens once in the background and requires no action from you.
-
Data Import
One-time automatic repair for affected Do-It-Best stores
The first time you open Margin Master after this update, it will automatically recalculate all prices to fix any incorrect regional pricing.
-
Data Import
Restore DIB PrivateLabel attribute
The PrivateLabel field from the Do it Best catalog (a letter code present on approximately 10% of SKUs) was being discarded during import. This catalog attribute now imports correctly and populates on applicable items.
-
User Interface
Double-click to show affected items
You can now double-click any rule in the Strategy Execution Summary to quickly see which items it affected.
-
User Interface
Dynamic cost basis options based on column visibility
The cost basis dropdown is populated based on which cost columns are visible in the user's current column view, matching the existing behavior for the "Set To" price level list. Store Cost (Default) is always offered first, followed by any alternate cost columns the store has configured and made visible.
-
User Interface
Store Manager projections preserve manual edits
Store Manager now uses fill-only mode when loading (writes only to stores with no GlobalFileConfig row) and overwrite mode when saving (user-asserted values win). This prevents Store Manager from clobbering RSC or store matchup entries created in the older Store Number Match Up screens while still healing gaps automatically. Test coverage added to pin the projection rules.
-
Database
Improved PSRuleHistory audit trail consistency
Consolidated all PSRuleHistory writing logic to use a single shared method (AppendPsRuleHistorySql) that properly escapes rule names and prevents duplicate entries. This ensures consistent audit trails regardless of whether a rule uses rounding schemes or other pricing logic, and fixes issues where rules containing underscore characters were incorrectly de-duplicated.
-
Database
Added comprehensive test coverage for DIB auxiliary retail pricing
Added 199 lines of automated tests that verify all four SQL scripts correctly source the Level3 column from SuggAuxRetail, prevent regressions that would redirect Level3Zone away from the rounding ladder, and ensure the Compass update path maintains both pricing arms. These tests enforce the invariant that every DIB main table build path must read auxiliary retail pricing, preventing silent data loss.
-
Database
Added comprehensive unit tests for change summary SQL
Created ChangeSummarySqlTests.cs with 11 test cases locking in the contract that all three SQL variants must measure against CurrentPrice, exclude SKUs with FuturePrice = 0, emit exactly H1..H12 (no H0, no H13), and count exactly twelve months. Tests verify that Compass skips its partial current period (in_sales_units_per_1) and starts at per_2, and that Mi9 no longer references RetailLevel1 or emits the dropped H0 column.
-
Architecture
Pricing attribution logic tightened for catch-all rules
The companion stamp statement that attributes unpriced rows now runs as the exact complement of the main pricing statement: the pricing UPDATE's WHERE clause carries the zero-price guard, the stamp's WHERE clause carries the negation of that guard, and together they cover every row in the table. Verified against customer database: catch-all rules now claim all 1,221 unpriced rows (up from 130), with no impact to priced rows (CHECKSUM_AGG unchanged). Renamed StampUnclaimedPsRuleSql to StampUnpricedPsRuleSql to better describe the selection criteria.
-
Architecture
Moved unpriced-item stamping to apply to all catch-all rules
Relocated the PSRule stamping logic for unpriced items from inside the rounding-only path to after both the rounding and no-rounding paths. This ensures that any catch-all rule (one with no WHERE clause) stamps its name on every item it covers, regardless of whether the rule uses rounding or not. The fix ensures consistent attribution behavior across all pricing rule configurations.
-
Architecture
Added test coverage to prevent RSC filtering regression
Introduced DibRscPredicateTests that enforce the RSC predicate must exist in the resolved SQL body (not just comments), be bound to the {RSC} variable, and never revert to the comment-based activation pattern. These tests would have caught the original regression during the MM-1046 refactoring that inadvertently removed the RSC filter marker in commit 592206a.
-
Architecture
Centralized zero-price guard logic
Extracted the zero-price guard expression (which prevents pricing items with no cost basis) into a single shared method to ensure consistency across all three rounding generators and the new attribution statement. This prevents the logic from drifting apart as previously happened between the rounding and no-rounding code paths.
-
Architecture
New StampUnclaimedPsRuleSql method for attribution
Introduced RoundingSql.StampUnclaimedPsRuleSql() to handle attribution of items that pass a step's selection criteria but fail the zero-price guard. This method writes only PSRule and PSRuleHistory columns, never overwrites existing attributions, and uses the same zero-price guard logic (inverted) that the main rounding statements use. The change preserves the invariant that PSRule always names the rule that produced the live FuturePrice.
-
Architecture
Separated store identity from table-naming logic
Introduced StoreManagerSql.MainTableKeyExpr to distinguish between a store's identity (vendor store number preferred) and the key used to name its per-store tables (POS store number preferred for non-Epicor systems). The two expressions now have distinct names, documentation, and test coverage to prevent future confusion. Epicor continues to use vendor store numbers for both purposes.
-
Architecture
Separated store identity key from main table suffix key
Introduced a new MainTableKeyExpr method that generates the correct expression for matching per-store table names, which is distinct from the store's identity key (KeyExpr). For Epicor, both expressions are identical since Epicor names tables by vendor store number. For all other POS systems, the main table key prefers POS store number first (matching how tables are actually named from SELECT DISTINCT StoreNumber), while the identity key prefers vendor store number first (a configured store's true identity). This architectural separation prevents future confusion between these two related but distinct concepts.
-
Infrastructure
Renamed and clarified PSRule stamping method
Renamed RoundingSql.StampUnclaimedPsRuleSql to StampUnpricedPsRuleSql and removed the WHERE clause that prevented stamping items already claimed by earlier rules. This reflects the method's actual purpose: it's the complement to the pricing statement, covering exactly the rows that the pricing statement excluded (items with zero-priced basis). Together, they ensure every row in a catch-all selection is attributed.
-
Infrastructure
Added automated tests to prevent RSC predicate regression
Created DibRscPredicateTests suite with assertions that verify the RSC variable is consumed in the SQL body (not just declared in comments), the resolved script filters MMVendorData by the supplied RSC, no unsubstituted placeholders remain after resolution, and the RSC predicate is never reintroduced as a comment marker that C# uncomments. These tests would have caught the original regression from commit 592206a.
-
Infrastructure
Removed stray temp_build directory from repository
Deleted 200+ files of committed build output (DevExpress DLLs, import layouts, SQL scripts) that were mistakenly tracked in the temp_build folder. This directory contained a pre-regression copy of the vendor data SQL script that made the broken RSC mechanism appear functional when searching the codebase. Updated .gitignore to prevent future build output commits.
-
Infrastructure
Enhanced strategy execution telemetry
Strategy execution reports now show more accurate counts of how many products were actually repriced.
-
Infrastructure
Added unit tests for mapping-write logic
Added ShouldWriteMappingTests.cs with six test cases pinning the rule that decides whether Store Manager should write a mapping to GlobalFileConfig, covering scenarios like no existing row (always writes), blank new value (never writes), load vs. save behavior (fill-only vs. overwrite), and unchanged values (skipped to avoid churning rows). This rule is critical to MM-1351's fix because it must never clobber a mapping the user set elsewhere and must never invent one from a blank.
-
Infrastructure
Removed committed build output and updated .gitignore
Deleted the temp_build/ directory containing stale build artifacts (300 files, 28K deletions). The stale copy of UpdatemainTableFromMMVendorData.sql still contained the commented RSC marker, making repository searches incorrectly suggest the mechanism was still wired up. Added temp_build/ to .gitignore to prevent future commits of build output.
-
Infrastructure
Add regression tests for DIB auxiliary retail
Added comprehensive test coverage (DibAuxRetailLevel3Tests) to prevent future regressions in DIB auxiliary retail handling. The tests enforce that all main table build paths correctly source Level3 from the auxiliary retail field rather than reverting to rounding ladder values.
-
Infrastructure
Strategy execution telemetry enhancements
Added SummaryFormatVersion field (defaulting to 2) to StrategyExecutionTrackingRequest to prevent the cloud from mixing incompatible calculation methods across schema versions. Added TriggerSource ("Menu", "AiReviewPrompt", or "Headless") and SecondsSinceLastRun fields to identify the source of duplicate same-session executions. Enhanced logging to capture full stack traces when a strategy re-runs within 300 seconds of the previous one.
Imports & POS
-
Improvement
Import unconfigured stores automatically
When your POS system exports data for a store you haven't set up yet in Margin Master, that store's products now show up automatically. You'll see a notice at the end of the import telling you which stores to finish configuring in Store Manager.
-
Improvement
Reduced telemetry noise for configuration states
Unmapped stores no longer generate error-level telemetry events or leave behind orphaned temp tables during each import run, reducing log clutter and making genuine import errors easier to identify.
-
Improvement
Automatic RSC fallback for stores without mappings
Stores without a price code (RSC) assigned will automatically use the same price code as your other stores, so you'll see pricing data immediately instead of zero items.
-
Improvement
Automatic zone fallback for stores without zone assignments
Stores without a pricing zone will now use the national zone automatically, giving you correct vendor pricing until you assign a specific zone in Store Manager.
-
Improvement
Re-enable previously auto-excluded stores
Stores that were hidden because they had no vendor number will automatically reappear in your next import.
-
Improvement
Added policy and tests for StoreNumber normalization eligibility
Created StoreRoutingFilterPolicy.ShouldNormalizeStoreNumber and Mi9TableConstants.IsStoreGroupMainTable to centralize and test the decision logic. The policy now explicitly rejects store-group tables, all-stores tables (mainTable, Mi9_mainTable), and tables with unusable derived tokens (empty strings or "mainTable" itself). Added 20 new unit tests covering group table recognition, normalization policy for all table types, and regression guards for the reported bug.
-
Improvement
Smarter RSC fallback when store mapping is missing
Stores without their own pricing RSC now use the same RSC as your other stores, giving more consistent pricing until you assign the correct RSC in Store Manager.
-
Bug Fix
Graceful handling of unmapped BisTrack stores during import
If your BisTrack export includes a new store that hasn't been assigned a vendor yet, the import will skip that store cleanly with a warning instead of showing errors. Once you map the store to a vendor in Store Manager, future imports will process it normally.
-
Bug Fix
Graceful handling of unmapped stores during import
If a new store location appears in your POS data before it's been set up in Margin Master, the import will skip it with a clear message instead of showing an error, and you'll still be able to find and configure it in Store Manager afterward.
-
Bug Fix
Unconfigured stores now import instead of being silently excluded
New stores from your POS system will now show up in Margin Master right away, even before you've assigned them a vendor store number in Store Manager.
-
Bug Fix
Prevented StoreNumber normalization from running on store-group tables
Fixed incorrect data updates that caused the application to hang during startup when using store groups.
-
Bug Fix
Import folder cleanup deleting RockSolid installation files
The app will no longer accidentally delete RockSolid program files during its daily maintenance routine. If you experienced "RockSolid database file not found" errors after July 2nd, this fix resolves the root cause.
-
Bug Fix
Import folder cleanup now protected against deleting POS installation files
If your import folder is set to your RockSolid installation directory, the daily cleanup will no longer touch any of your POS files—only the old import backups Margin Master created.
-
Bug Fix
Fixed StoreNumber normalization tracking to be per-table instead of session-wide
Fixed an issue where some store-specific pricing tables wouldn't update correctly after the first data operation in a session.
-
Bug Fix
Simplified store/group name extraction logic
Collapsed redundant if/else branches in GetStoreOrGroupNameFromTableName — both StoreGroup_{group}_mainTable and {POS}_{store}_mainTable carry the identity in the second underscore-delimited token, so the conditional was returning the same value regardless of branch.
-
Bug Fix
Epicor store char validation allows POS-keyed imports
Epicor record validation now distinguishes between "store char never seen before" (dropped so discovery can register it) and "known store with no vendor number" (passed through keyed by POS store number). Previously, both cases were rejected at parse time, making unmapped stores permanently invisible even after they were discovered.
-
Cloud Sync
Zone sync includes defaulted zones and reconciles by effective key
Zone sync for grouped Epicor stores now gathers zone overrides using the effective-key eligibility predicate, ensuring stores with POS-only keys are included. The excluded-store reconciliation prompt (PromptAndDropExcludedStoreMainTablesAsync) matches tables by EffectiveStoreKey instead of VendorStoreNumber so POS-derived table names resolve to their store rows for friendly labeling.
-
Data Import
Store discovery unchanged for unmapped stores
The skip logic deliberately runs after the Store table insert, ensuring that new POS stores are still discovered by the system after import. This allows them to appear in Store Manager for vendor mapping, which would be impossible if they were skipped earlier in the process.
-
Data Import
Epicor stores import under POS-derived keys when unmapped
Epicor store discovery and INDecoded import no longer auto-exclude stores missing a Vendor Store Number. EpicorINRecord.IsValid now passes rows from known store chars even when unmapped (the conversion list keys off EffectiveStoreKey), EpicorFTPFileExtractorService registers new stores without excluding them, and the RSC resolution borrows a working RSC instead of skipping the main-table build. Unmapped stores are reported to the configuration notice, not shown in per-loop MessageBoxes.
-
Data Import
MySQL/Compass import includes stores with POS numbers only
MySQL and Compass import paths now include stores that have a POS store number but no vendor number in their eligible store lists, using EffectiveStoreKey for table naming and eligibility. Previously these stores were filtered out by the "LEN(ISNULL(VendorStoreNumber,'')) > 0" predicate, causing their data to be ignored despite being present in the POS export.
-
Data Import
BisTrack/DIB imports build against borrowed RSCs
The three BisTrack/DIB import paths (1040, 6828, and generic InsertIntoMainTable) no longer skip the main-table build when GetSpecificRSCAsync returns no store-specific RSC. The RSC ladder resolves a fallback, the table builds against that RSC, and the store is reported to the configuration notice. Closes an MM-1341-shaped hole where a blank RSC left the MMVendorData join unfiltered, silently pricing the store off an arbitrary RSC.
-
User Interface
End-of-import notice for incomplete store configuration
After importing, if any stores need setup, you'll see one notice listing them all and offering to open Store Manager for you.
-
User Interface
Single configuration notice replaces multiple import warnings
After import, you'll see one summary showing all stores that need attention, with an option to open Store Manager immediately to fix them.
-
Database
One-time repair re-enables previously auto-excluded stores
Stores that were previously hidden because they had no vendor number assigned will automatically reappear after this update.
-
Database
Store effective key calculation in SQL and C#
Added StoreManagerSql helper class and StoreManagerInfo.EffectiveStoreKey property, both implementing the same logic: VendorStoreNumber when assigned, otherwise the POS-derived fallback (PosStoreNumber for most systems, PosStoreCharOrdinal for Epicor extended chars). All eligibility filters, table-name generation, and store lookups now use this consistent expression instead of testing VendorStoreNumber presence.
-
Architecture
Effective store key resolves vendor number or POS fallback
Introduced StoreManagerInfo.EffectiveStoreKey and its SQL twin StoreManagerSql, which resolve to VendorStoreNumber when assigned or fall back to PosStoreNumber (or PosStoreCharOrdinal for Epicor non-alphanumeric chars). All eligibility filters, table-naming logic, and reconciliation queries now use the effective key, ensuring configured stores behave identically while unconfigured stores gain a working fallback. Added 28 new unit tests covering the key resolution, RSC ladder, and issue collector.
-
Infrastructure
Import folder cleanup policy with unit tests
Created ImportFolderCleanupPolicy as a standalone, testable component with two independent safety rules: IsProtectedFolder blocks cleanup in system/program directories, and IsRemovableBackup only allows deletion of Margin Master's own backup files. Comprehensive unit tests replay the exact 72 filenames from the customer incident to ensure none can ever be deleted again. If the import path is misconfigured to point at a protected directory, the app now logs a warning instead of silently skipping cleanup.
-
Infrastructure
Import cleanup policy with comprehensive test coverage
Added ImportFolderCleanupPolicy class with IsProtectedFolder and IsRemovableBackup methods to enforce the two safety rules, plus ImportFolderCleanupPolicyTests with 31 test cases covering the exact files that were deleted in the customer incident. The rules are now directly unit-testable and cannot drift apart from the actual cleanup logic.
-
Infrastructure
Store configuration issue collector service
Added IStoreConfigurationIssueCollector singleton to gather "this store isn't configured correctly" observations across an import run. Import subsystems report issues as they discover them; MainMMViewModel drains and displays them once at the end. Deduplicates store/issue pairs automatically so per-store loops don't create duplicate notices.
-
Documentation
Updated Store Manager and Epicor troubleshooting docs
Corrected docs/marginmaster/getting-started/store-manager.md and docs/marginmaster/pos-systems/troubleshooting-epicor-zero-skus.md to reflect that a blank Vendor Store Number is no longer a cause of missing SKUs or store exclusion. Stores now import under their POS-derived key until a vendor number is assigned.
Cloud Sync & Vendor Data
-
Improvement
Statistics tracking failures now degrade gracefully
Sync statistics are diagnostic data and no longer have the authority to fail a data synchronization. If the statistics table cannot be accessed or updated (before, during, or after sync), the system will log a warning and continue syncing data without statistics for that table. Previously, a statistics recording failure at the end of a successful sync could turn the completed sync into a reported failure.
-
Bug Fix
Local database contention no longer aborts cloud sync
Previously, when the local SyncStatistics table experienced lock waits (due to multiple sync operations or database activity), the 30-second timeout would abort the entire table sync and report it as a "Cloud sync timeout" error with misleading suggestions to reduce batch size or optimize server indexes. The statistics tracking commands now use a 120-second timeout to wait out contention, and statistics failures are gracefully degraded rather than aborting the sync. Resolves issue affecting store 18788 where four Ace Hardware tables reported false timeout errors within five minutes.
-
Bug Fix
Data Aging view now displays after vendor reset
If you reset vendor data and choose to sync immediately, you'll now see the Data Aging screen as expected, and the sync will complete normally instead of appearing to freeze.
-
Bug Fix
Data Aging view now displays after vendor reset
After you reset vendor data and choose to sync immediately, you'll now see the Data Aging screen when the rebuild finishes, just like when you sync from the toolbar button.
-
Bug Fix
Do-It-Best mailbox downloads now process successfully
If you use Do-It-Best and noticed order confirmations or catalog updates weren't appearing in Margin Master, this fix restores that functionality. Purchased items will now appear in your pricing grid as expected.
-
Bug Fix
Do-It-Best mailbox files now processed after download
Order confirmations, POS reload files, and inventory updates from Do-It-Best that were downloaded from your mailbox will now be imported and visible in Margin Master instead of being silently skipped.
-
Bug Fix
Fixed DIB mailbox downloads being marked as incomplete transfers
Do-It-Best order confirmations now arrive correctly in your pricing grid. Previously, all mailbox files appeared as incomplete downloads and were never processed.
-
Bug Fix
Fixed mailbox file download path handling
Downloaded mailbox files are now correctly recognized and processed instead of being marked as incomplete transfers.
-
Bug Fix
FTP download helper now returns actual filename written to disk
Modified FTPHelperSync2.DownloadFile to return the actual path written (instead of just success/failure) so the caller and helper stay synchronized about the filename. When a remote timestamp is supplied, it's appended to prevent two same-named remote files from overwriting each other in the download folder. Also stopped flattening underscores to hyphens, which was breaking DIB's TYPE_MEMBER_yyyyMMdd-HHmmss naming convention.
-
Bug Fix
Mailbox files now filed correctly into permanent storage
Processed Do-It-Best mailbox files now appear correctly in the Local Files section, organized by member number and file type.
-
Bug Fix
Fixed mailbox files not filing into member-specific folders
Downloaded Do-It-Best files now organize properly into store-specific folders instead of failing to save.
-
Bug Fix
Fixed mailbox file storage folder creation
Mailbox files now move into the correct storage folders (MailBoxFiles\[member]\[ORDCNFM|POSLOAD|RTL_INV]) instead of failing silently.
-
Bug Fix
Mailbox file archiving now uses correct folder structure
Previously downloaded Do-It-Best files now appear properly in the "Local Files" view, organized by member and file type.
-
Bug Fix
Filename timestamps now preserve DIB naming convention
Corrected the timestamp format applied to downloaded files to maintain DIB's underscore-based naming convention (TYPE_MEMBER_yyyyMMdd-HHmmss) instead of converting all underscores to hyphens, which was breaking the expected file structure.
-
Bug Fix
Preserved underscore separators in DIB filenames
Fixed a character replacement that was converting underscores to hyphens in downloaded filenames, breaking the DIB naming convention (TYPE_MEMBER_yyyyMMdd-HHmmss) that other parts of the system parse. Filenames now maintain their original format.
-
Bug Fix
Removed misleading "FTPS firewall" error for mailbox failures
The recent change that surfaced "TransferIncomplete" dialogs blamed FTPS firewall issues when mailbox downloads failed, but this was incorrect—the failure occurred 1.1 seconds into the transfer (a blocked passive channel would have burned the full 45-second timeout), and directory listings using the same channel succeeded. The real cause was the filename mismatch, now resolved.
-
Infrastructure
Added mailbox file-path contract tests
Introduced comprehensive unit tests to verify download path construction and filing path logic, preventing future silent regressions. Tests cover timestamped downloads, member folder preservation, file-type subfolder organization, and rooted-path edge cases.
-
Infrastructure
Added comprehensive test coverage for DIB mailbox file paths
Created 10 new automated tests that verify the two path computations used in DIB mailbox processing, preventing future silent regressions. Tests confirm that timestamped downloads produce distinct filenames, member folders are preserved, and file type subfolders are created correctly.
User Interface
-
Improvement
Simplified Create Support Issue button behavior
The green "Create Support Issue" button now creates a new issue right away instead of showing a menu first, making it faster to start logging issues.
-
Improvement
Simplified Create Support Issue button
Click the Create Support Issue button to go straight to the new issue form — no more dropdown menu to navigate.
-
Improvement
Update tracking protected against database timeouts
Added a 5-second timeout cap to the update sentinel write operation to prevent blocking when the database connection string is valid but the server is unreachable. The operation runs asynchronously off the UI thread and continues with the update even if the sentinel write fails or times out, ensuring diagnostic tracking never prevents a user-requested update from proceeding.
-
Improvement
Update sentinel write is fault-tolerant on database setup screen
The update sentinel write from the database setup screen is designed to gracefully handle scenarios where no database connection exists yet (such as initial setup). The write runs off the UI thread with a 5-second timeout and swallows any failures, ensuring that database connection issues never prevent a user-requested update from proceeding. Timeouts and failures are logged for diagnostic purposes but do not interrupt the update process.
-
Bug Fix
Update sentinel now tracked from database setup screen
If you apply an update from the database setup screen and it fails multiple times, the app will now correctly offer to run a repair install to fix the problem.
-
Bug Fix
Update failure tracking now works from database setup screen
When applying updates from the database setup screen, the app now attempts to write the update sentinel to the database before restarting. This write is done on a best-effort basis with a 5-second timeout, since this screen can run before a database connection exists. The sentinel write enables tracking of consecutive update failures, which can trigger a repair install option if updates repeatedly fail. Previously, updates applied from this screen were never tracked, so existing customers updating from the "Manage Database Connections" screen would not benefit from the automatic repair install safety net.
-
User Interface
Added menu bar to Support Issues window
You can now access Quick Submit from the Actions menu at the top of the Support Issues window.
-
User Interface
Added Actions menu bar to Support Issues screen
Look for the new Actions menu at the top of the Support Issues screen to access Quick Submit for faster issue reporting.
-
User Interface
Per-section empty-state text in Support Issues list
When you have closed all your open issues, you'll now see a "No open issues" message under the Open section header instead of just blank space.
-
User Interface
Added empty state messages to Support Issues sections
You'll now see a clear message telling you when there are no issues in a section, instead of just seeing blank space.
Reporting & Exports
-
Improvement
Network latency warning threshold adjusted
Network connection tests no longer show warnings for connections that are working normally but happen to be a bit slower due to distance from the server.
-
Improvement
Standardized version reporting in diagnostics
Connection diagnostic reports for MySQL and FTP connections now use the standardized semantic version format (e.g., "3.2.1") instead of the assembly version, providing clearer and more consistent version information when troubleshooting with support.
-
Bug Fix
Update health tracking now scoped per workstation
If you work at a store with multiple workstations, you should no longer see incorrect "Margin Master could not install an update" messages caused by another computer's update activity.
-
Bug Fix
Failure counter now clears after successful updates from any source
If the "Margin Master Update Problem" dialog previously suggested a repair install, that repair will now properly clear the error state and stop the daily notifications.
-
Bug Fix
Stale update sentinel no longer leaves failure counter stuck
Update status tracking is now properly reset when Margin Master updates through alternate installation methods.
-
User Interface
Connection report text wrapping enabled
Connection test results now display in an easier-to-read format that doesn't require scrolling left and right.
Performance & Reliability
-
Improvement
Improved connection timeout handling consistency
Changed exception handling for connection timeouts from TaskCanceledException to the more general OperationCanceledException, and reduced timeout logging from Error to Warning level since timeouts are expected behavior when servers are unreachable rather than exceptional conditions.
-
Improvement
Faster follow-up update checks preserved
Fixed the 10-minute quick-check timer being overridden on startup. After applying an update, the app deliberately checks for follow-up fixes more frequently (every 10 minutes instead of hourly) to quickly pick up any hotfixes. This accelerated check now persists correctly instead of being reset to the standard one-hour interval.
-
Bug Fix
Support Issues screen crash resolved
The Support Issues screen will now open correctly without crashing when accessed from Support Tools.
-
Bug Fix
Support Issues Actions menu crash resolved
The Actions menu in Support Tools now opens correctly without causing the application to crash.
-
Bug Fix
Eliminated unobserved exception crash during database connection testing
When the app tests a connection to a database server that is offline or unreachable, you will no longer see delayed error messages or crashes appearing 15-20 seconds after the connection attempt.
-
Bug Fix
Database connection timeout handling improved
When the application tests a database connection that times out (such as when the server is unreachable), it now handles the timeout cleanly without causing the application to crash several seconds later.
-
Bug Fix
Auto-update retry loop prevention
If Margin Master can't install an update after trying twice, it will stop restarting on its own. You can still update anytime using the Help menu.
-
Bug Fix
Auto-update retry prevention for failed versions
If an update fails to install on your computer, Margin Master will stop trying to install that specific version automatically. You can still install it manually using the "Update Ready" button or Help menu, and when a newer version is released, it will try that one automatically.
-
Bug Fix
Update problem dialog now properly notifies users
If there's an update problem, you'll now see a dialog offering to repair the installation instead of the app restarting before you can respond.
-
Bug Fix
Update problem dialog timing correction
The update problem dialog will now reappear on the next launch if it was closed automatically due to a restart, ensuring you always have a chance to see it and choose a repair option.
-
Bug Fix
Auto-update check timer preservation
Corrected timer initialization logic to preserve the accelerated 10-minute check interval that is set after a successful update. Previously, the startup routine unconditionally set a 1-hour interval, overriding the shorter interval meant to help machines quickly pick up follow-up fixes after an update.
-
Bug Fix
Blocked automatic updates for specific failed versions
The automatic update system now consults the failure counter (AutoUpdateConsecutiveFailures) before attempting installation. Previously this counter was recorded but never checked, causing the hourly timer and 7-day forced-update override to repeatedly attempt the same version that had already failed. The block is version-specific—new releases always get attempted since locks are often transient.
-
Infrastructure
Exception handling refinement
Changed connection timeout exception handling from catching TaskCanceledException to the more appropriate OperationCanceledException, and downgraded timeout logging from Error to Warning level since timeouts are expected failure scenarios rather than exceptional errors.
Other Changes
-
Improvement
Changed behavior for recurring support issues
If an issue you previously marked as resolved happens again, the system will now help you file a new follow-up ticket that references the original one, making it easier for support to see the full history.
-
Improvement
Changed 'Not Resolved' action to create follow-up issue
If you previously marked a support issue as resolved but the problem comes back, clicking "Alert support that this issue is NOT resolved" will now create a new follow-up issue instead of reopening the old one.
-
Improvement
Streamlined follow-up issue creation
When you create a follow-up from a closed issue, you'll now skip the contact selection screen and go straight to describing the problem, saving time since it automatically uses the same contact as before.
-
Improvement
Follow-up issues automatically reuse original contact
When you create a follow-up issue, the same contact person from your original issue is automatically selected.
-
Improvement
Automatic RSC defaulting for unmatched stores
When Store Manager can't determine a store's RSC from your POS system or existing settings, it will now automatically use the RSC that most of your other stores use, saving you from having to fill in missing RSCs manually.
-
Improvement
Auto-populate blank RSC codes with organization majority
If a store is missing its RSC code, Store Manager will automatically fill it with the RSC used by most of your other stores, saving you from entering it manually.
-
Improvement
Live Support link includes store context
Your store information now transfers automatically when you open Live Support chat, so support staff can see your store details right away.
-
Improvement
Streamlined backup metadata reading
The Restore Database screen now loads backup file information faster, especially when working with large database backups.
-
Bug Fix
Eliminated IPWorks Zip license validation failures
Fixes an issue where the application would sometimes fail to read or create ZIP files due to license validation errors, especially on terminal server environments.
-
Bug Fix
StoreNumber normalization no longer corrupts store-group tables
Fixed a bug that caused Margin Master to freeze for several minutes during startup when using store groups. Store selection and historical pricing data now work correctly for grouped stores.
-
Bug Fix
Corrected button availability for follow-up creation
Fixed the condition for enabling the "Create a new issue from this one" button to check IsResolved instead of IsClosedFinal, allowing follow-up creation from any resolved issue, not just those fully closed by support.
-
Bug Fix
Live Support errors now logged
Failures when opening the Live Support URL are now logged instead of silently swallowed, making it easier to diagnose issues when the browser fails to launch or the URL is malformed.
-
Bug Fix
Fixed license loading timing issue in Restore Database window
The Restore Database window now works correctly when opened during initial application startup.
-
Bug Fix
ZIP read failures now surface in Restore Database file list
If a ZIP backup file is corrupt or unreadable, the Restore Database screen now shows what went wrong instead of hiding the file from the list.
-
Data Import
Do it Best mailbox uploads use built-in ZIP compression
DIB mailbox batch file uploads now compress inventory files using System.IO.Compression. The archive layout (files stored under bare file names with no directory component) matches what IPWorks Zip produced, so Do it Best receives the same format.
-
Data Import
Do it Best mailbox archive format preserved
ZIP archives created for Do it Best mailbox uploads continue to store files under their bare file names (no directory structure), matching the exact layout that Do it Best expects. This maintains compatibility with the vendor's systems despite the underlying compression library change.
-
User Interface
Simplified resolve/reopen logic on Support Issues screen
The resolve button on support issues now only marks issues as resolved—it won't reopen them. To report a recurring problem, use the "NOT resolved" or "Create a new issue from this one" option instead.
-
User Interface
Simplified issue resolution workflow
Removed the reopen functionality from the MarkResolved command. The action now only supports marking issues as resolved (one-way), simplifying the workflow and preventing confusion between reopening and filing follow-ups.
-
User Interface
Submit Issue wizard now supports direct navigation to submission step
Added StartOnSubmitStep flag to the Submit Issue wizard, allowing certain workflows (like follow-ups) to bypass earlier wizard steps when all required information is already known. The wizard validates that a contact is selected before allowing direct navigation to step 3.
-
User Interface
Follow-up wizard opens directly on submission step
The follow-up form now skips contact selection and opens ready for you to describe the problem and submit.
-
User Interface
Store Manager RSC display improvements
The Store Manager screen now applies the majority RSC default during initialization, right after loading cloud store settings. The defaulted RSC is persisted to the database using the existing `UpdateDatabaseFromCloud` path, ensuring the value is saved and remains consistent. The process is logged with details about how many stores were defaulted and which RSC was used.
-
User Interface
Submit Issue wizard supports pre-selected contacts
Added PreSelectContactId and StartOnSubmitStep properties to SubmitIssueViewModel to support the follow-up flow. The pre-selected contact is resolved against the freshly loaded store and support contacts list, ensuring the prior contact is still valid and available before auto-selecting it.
-
User Interface
Restore Database dialog now uses built-in ZIP extraction
Database restore from ZIP files works the same way, but is now more reliable when opening archives created by earlier versions of the software.
-
User Interface
Updated startup license report
Removed IPWorks Zip from the component license validation report shown during application startup. The report now shows only IPWorks FTP and IPWorks SFTP, which remain as licensed components. The NSoftwareLicenses:IPWorksZip configuration key is now ignored.
-
Database
Per-table tracking of StoreNumber normalization
Changed the normalization tracking from a single session flag to a per-table HashSet. Previously, the first table lookup would mark the work as complete for the entire session, causing any tables that appeared later to silently skip normalization for the remainder of the session. Each table is now tracked individually and normalized exactly once per session, even if it's discovered after other tables have already been processed.
-
Database
Scoped to Store Manager display only
This change affects only the Store Manager's RSC display and persistence (`StoreManagerInfo.RSCCode` table). The legacy pricing-join RSC source (`GlobalFileConfig.STORERSC` setting) remains unchanged, ensuring backward compatibility with existing pricing workflows.
-
Architecture
Store context URL builder consolidated
Created a shared StoreContextUrlBuilder service that both the What's New page and Live Support link use to build URLs with store context parameters. This eliminates duplicate URL-building logic and ensures consistent store identification across all external web pages the application opens.
-
Architecture
New table classification helpers for main table types
Added IsStoreGroupMainTable() and ShouldNormalizeStoreNumber() helper methods to distinguish between per-store tables (Epicor_1316_mainTable), store-group tables (StoreGroup_Core_mainTable), and all-stores tables (mainTable). These helpers enforce that StoreNumber normalization only applies to per-store tables where it's semantically correct, preventing data corruption in tables with different grain structures.
-
Infrastructure
Removed nsoftware IPWorks Zip dependency
Eliminated the nsoftware IPWorks Zip component after recurring machine-specific node-check failures ("Could not find a valid license on this system") that persisted across multiple key rotations and affected backup restore operations on customer machines. All ZIP operations now use System.IO.Compression, which is part of the .NET framework and requires no licensing.
-
Infrastructure
RSC majority calculation with unit tests
Added StoreManagerRscHelper.ComputeMajorityRsc, a pure function that identifies the most frequent non-blank RSC value. Includes comprehensive unit tests covering edge cases (all blanks, ties, whitespace handling, case-insensitivity) to ensure the majority is computed correctly and reproducibly.
-
Infrastructure
Consolidated ZIP operations into single helper class
ZIP file operations for database backups are now faster and more reliable.
-
Infrastructure
New ZipFileHelper utility class
Created ZipFileHelper to wrap System.IO.Compression with async support, progress reporting, and compatibility with archives previously created by IPWorks Zip. Includes comprehensive test coverage, including verification that backup metadata stored in ZIP comments by the old component can still be read.
-
Infrastructure
Unit test coverage for RSC majority calculation
Added comprehensive unit tests that verify the majority RSC calculation against real-world data distributions (e.g., Great Lakes Ace: H=71, I=8, N=1, blank=18 → H). Tests cover edge cases including empty inputs, all-blank values, clear majorities, deterministic tie-breaking, and whitespace/case handling.
-
Infrastructure
Removed IPWorks Zip runtime license configuration
Removed IPWorksZip license key from appsettings.json, Azure Key Vault retrieval in the publish workflow, startup validation, and the IPWorksLicenseService. The three ApplicationSettingKey enum entries (IPWorksLicenseFTP, IPWorksLicenseSSH, IPWorksLicenseZip) are now marked as legacy/unread to preserve existing database rows and enum ordinals.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
BisTrack network import root with automatic branch file ingest; BisTrack network import root with automatic per-branch file collection; Purchase order number tagging for BisTrack items.
Strategy & Pricing
-
New Feature
AI-powered rounding scheme analysis
The AI assistant examines your rounding scheme's annual profit impact, shows which price-ending transitions (like .79→.99) generate the most revenue, identifies high-impact SKUs, and calculates charm pricing percentages. Results appear in an easy-to-read dialog that helps you understand whether a scheme is worth activating.
-
New Feature
AI-powered rounding scheme analysis
In the Rounding Scheme editor, click the new "Analyze with AI" button to get a detailed analysis of how the selected scheme will affect your pricing. The AI examines your actual sales data to show total profit impact, which price endings change most, and which individual products drive the biggest gains or losses. This helps you understand the real-world effect before applying a scheme.
-
New Feature
Deterministic strategy review scoring engine
Strategy reviews now show consistent, reproducible scores every time you review the same strategy—the math is stable and auditable.
-
New Feature
AI pricing strategy review and scoring
When you ask the AI to review a pricing strategy, it will score how well the strategy is working across multiple factors like how many items it prices, how consistently it uses rounding rules, and how many exceptions are needed—all on a simple 0-100 scale.
-
New Feature
AI strategy review and scoring system
When you ask the AI assistant to review your pricing strategy, it now provides a detailed 0-100 score showing exactly where your strategy is strong or weak, with specific recommendations for improvement prioritized by volume impact.
-
New Feature
Strategy execution summary screen
After running a pricing strategy, you'll see a summary showing how long it took, how many steps ran, and how many items were affected. Each step shows its status so you can quickly see if anything failed or was skipped.
-
New Feature
AI Review button in Pricing Strategy Manager
When you click "AI Review" in the strategy manager, the system will check if your strategy has been run recently. If not, it will offer to run it first so the AI can review your actual pricing results and give you accurate feedback.
-
New Feature
Strategy execution summary dialog
After running a pricing strategy, you'll now see a summary showing how long it took, how many products were affected, and what happened in each step. If AI is enabled, you can click "AI Review" to get feedback on your strategy.
-
New Feature
Profit impact display on Strategy Execution Summary
When you finish running a pricing strategy, the summary window now shows exactly how many profit dollars you'll gain or lose and what your margin will change from and to (for example, "30.0% -> 35.0%" and "+$2,500 gained").
-
New Feature
Cloud upload checkbox in Strategy Backup dialog
When backing up your strategy, check "Upload to Cloud" to save a copy to the Margin Master cloud in addition to the local file.
-
New Feature
Strategy execution performance tracking
Reviews now identify which pricing steps waste time updating products that later steps re-price, helping you eliminate slow, unnecessary work from your strategy.
-
New Feature
Strategy review snapshot persistence
Strategy reviews now show up-to-date scores immediately after running a strategy, without waiting for the AI to recalculate.
-
New Feature
AI-powered strategy review from summary
If AI is turned on, you'll see an "AI Review" button on the summary screen. Click it to get an AI-powered analysis of your pricing strategy's effectiveness, including a scorecard and recommendations based on the items that were just repriced.
-
New Feature
AI Review button in Manage Pricing Strategies
The strategy manager now has an "AI Review" button that analyzes your active pricing strategy and provides recommendations. The system will ask you to run the strategy first if it hasn't been executed recently.
-
New Feature
Unified local/cloud restore source picker
When restoring, you now pick your backup source (Local or Cloud) in one dialog, then choose what to restore from that backup.
-
New Feature
Tabbed Local/Cloud restore picker
Restoring a strategy now shows a single dialog with Local and Cloud tabs, so you can pick from either source without opening multiple windows.
-
New Feature
AI strategy analysis tools
You can now ask the AI questions like "Which products aren't being priced by my strategy?" or "Show me which strategy steps are being overridden by later steps" and get detailed answers.
-
New Feature
AI strategy analysis tools
You can now ask the AI assistant questions like "What's my strategy score?", "Which items aren't being priced?", or "Show me my strategy steps" and get detailed answers.
-
New Feature
Manager-initiated strategy review with run requirement
Before running an AI review of a strategy that hasn't been executed recently, you'll be asked if you want to run it first so the AI can analyze real data instead of just the rules.
-
Improvement
Strategy backup cloud upload now uses Azure blob storage
Strategy backups now upload to the cloud more reliably and can handle larger files without timing out.
-
Improvement
Strategy cloud backup uses blob storage
Strategy backups to the cloud are now more reliable and have no file size limits.
-
Improvement
Rounding dimension now compares to vendor-default scheme
The AI now scores your rounding schemes by comparing them to your vendor's standard scheme. Tighter schemes (fewer price points) score higher because they capture more margin.
-
Improvement
SKU-level exceptions performance optimization
The "SKU Level Exceptions" step in strategy execution now runs about 4 times faster.
-
Improvement
SKU exceptions deduplication and conflict resolution
If you have multiple exceptions for the same SKU, the newest one now automatically wins, and the summary will tell you how many conflicts were resolved.
-
Improvement
Exact organization-level margin calculations
Margin calculations for multi-store strategies are now more accurate, especially when stores have different sales volumes.
-
Improvement
Strategy steps wait for in-progress rebuilds instead of failing
Strategy steps now wait up to 10 minutes for panel rebuilds to finish, ensuring they read the correct field configuration instead of randomly failing with false "field missing" errors.
-
Improvement
Startup splash screen ownership tracking
Implemented an ownership tracking mechanism for the freshness check splash screen, matching the pattern already used by other startup operations like LoadColumnUsingViewManagerAsync. The `ownsSplash` flag ensures that only the code path that displayed the splash is responsible for hiding it, preventing scenarios where one operation accidentally closes a splash screen that another operation is still using.
-
Improvement
Improved delete confirmation message
When deleting a custom group, the confirmation message now tells you exactly how many items will be removed.
-
Improvement
Enhanced delete confirmation message
When deleting a Custom Group, the confirmation message now tells you how many SKUs will be removed.
-
Improvement
Enhanced backup selection with DevExpress tree control and cloud upload checkbox
When backing up, you'll see an improved checklist tree showing what's available to back up, and you can choose to upload to the cloud at the same time.
-
Improvement
Strategy cloud backup remembers upload preference
When backing up your strategy, the "Upload to Cloud" option will remember your last choice.
-
Improvement
Non-vendor SKU pricing coverage (dimension 3)
The AI now checks that items without vendor pricing (like custom or special-order items) have proper cost-based pricing rules set up.
-
Improvement
Conflicting exception detection and logging
The strategy summary now shows how many duplicate SKU exceptions were skipped, with the most recent exception being applied when conflicts occur.
-
Improvement
Accurate error messages distinguish rebuild timing from missing fields
If a strategy step fails to load, the error message will now tell you whether the selection panel was being rebuilt (a timing issue you can fix by re-running) versus a field actually being missing from your view layout.
-
Improvement
Smart de-duplication prevents redundant cloud uploads
If your strategy hasn't changed since the last cloud upload, the system won't waste time uploading an identical copy.
-
Improvement
Strategy cloud restore reads from blob storage
When restoring a strategy from the cloud, you'll see backup file names and sizes more clearly in the restore dialog.
-
Improvement
Strategy-scoped exception and step counting
Exception counts in strategy reviews now show only the exceptions that actually belong to that strategy, not unrelated exceptions from other strategies in the database.
-
Improvement
PricingStrategy-code reliance penalty
The AI now warns when your strategy relies on vendor pricing codes (A/B/C/D) because items next to each other on the shelf can have different codes, making rules unpredictable.
-
Improvement
Strategy execution workflow enhancement
Strategy execution now captures comprehensive summary data including per-step results, processing duration, and termination status. This data is immediately available to the new summary dialog and persisted for AI review operations, ensuring the review process has access to the most recent execution metrics.
-
Improvement
Hardened validity gate for profit analysis
Incorrectly entered future prices (like accidentally typing $0 or an unrealistic amount) will no longer throw off your profit and margin calculations.
-
Improvement
Enhanced backup tree view with DevExpress TreeViewControl
The backup selection tree is easier to read and automatically focuses on your pricing strategies when opened.
-
Improvement
Refined rubric definitions for accuracy
The AI now gives more accurate guidance about rounding improvements, correctly identifies when non-vendor items need special pricing rules, and warns about risky pricing patterns that could make shelf neighbors inconsistently priced.
-
Improvement
Catch-all and cross-hierarchy hygiene refinements
The AI now only flags "ALL" catch-all rules when they're not at the end of your strategy, where they belong.
-
Improvement
Exclude built-in views from backup and restore selection
The backup and restore dialogs now only show views you created, not the built-in default views.
-
Improvement
Strategy cloud backup retention policy
The cloud will keep your 3 most recent strategy backups automatically.
-
Improvement
Enhanced hygiene detection
The AI can now tell you exactly which strategy steps are using unstable name fields instead of reliable codes, and warn you when a catch-all rule is positioned incorrectly.
-
Improvement
Exclude built-in views from backup selection
The backup tree now shows only your custom views, not the built-in system defaults.
-
Improvement
Strategy completion workflow optimization
The strategy execution summary now appears immediately after completion instead of waiting for the price changes grid to load.
-
Bug Fix
Backup and restore now preserve inactive SKU exceptions
All pricing exceptions on a strategy are now safely preserved when backing up and restoring, even if they're temporarily turned off.
-
Bug Fix
Store-specific SKU exceptions now preserved during backup and restore
When you back up and restore a pricing strategy, SKU exceptions that were set for specific stores will now stay assigned to those stores instead of incorrectly applying to all stores.
-
Bug Fix
Strategy steps no longer skip during selection panel rebuilds
If a pricing strategy previously gave you different SKU counts across runs (like swinging between 588 and 600+ items), or showed confusing "field not in the current view" errors for fields that were definitely present, those issues are now fixed. All strategy steps will apply consistently every time.
-
Bug Fix
Splash screen cleanup after freshness check
When Margin Master starts up and checks your pricing data, the "Verifying pricing data..." message will now disappear as soon as the check finishes, rather than staying visible until a later step closes it.
-
Bug Fix
Splash screen leak during freshness verification
The loading screen will no longer appear to freeze on the "Verifying pricing data..." message during application startup.
-
Bug Fix
Store Number column sorting corrected
When you sort by Store Number in the pricing grid, stores now appear in the correct order (1, 2, 3... 10, 11) instead of the confusing alphabetical order (1, 10, 11... 2, 20).
-
Bug Fix
Eliminated false FAILED warning for Sitting Margin History sync
You will no longer see incorrect "FAILED" warnings when saving Sitting Margin History — the system now properly recognizes when the save completed successfully.
-
Bug Fix
Store-specific pricing exceptions now restore correctly
Store-specific pricing exceptions now remember which store they apply to when restoring from a backup.
-
Bug Fix
Inactive SKU exceptions no longer lost during backup
Inactive (turned off) SKU pricing exceptions are now included in backups so they can be recovered if needed.
-
Bug Fix
Follow-up to MM-1321
This change addresses a remaining issue from ticket MM-1321 where store 4229 reported being stuck on the "Verifying pricing data..." message. The freshness check now tracks whether it owns the splash screen and only hides it if it was the one that displayed it, preventing conflicts with other startup operations.
-
Bug Fix
Prevented strategy manager from opening during execution
You can no longer accidentally open the strategy manager while a strategy is running.
-
Bug Fix
Custom group SKU descriptions preserved when copying strategies
When copying a pricing strategy, custom group SKU descriptions now copy over instead of appearing blank.
-
Bug Fix
Custom group SKU descriptions preserved when copying strategies
When copying a pricing strategy, custom group SKU descriptions now carry over correctly instead of appearing blank.
-
Bug Fix
Improved group deletion behavior
After deleting a group, the list now automatically selects the next available group.
-
Bug Fix
Strategy execution timing accuracy
Fixed a timing bug where custom groups containing zero SKUs would leave their processing end time null, causing the next phase (SKU exceptions) to incorrectly absorb that step's elapsed time in reports. All steps now properly record their completion time regardless of the number of items processed.
-
Bug Fix
Custom group SKUs attach to correct groups when copying strategies with duplicate group names
If a strategy has multiple custom groups with the same name, copying the strategy now keeps each group's SKUs separate instead of merging them incorrectly.
-
Bug Fix
SKU Level Exceptions dialog no longer shows stuck loading indicator
The "Please Wait..." loading message in the SKU Level Exceptions screen no longer gets stuck after the data has finished loading.
-
Bug Fix
Early returns from BuildSelectionBoxesAsync no longer wipe the panel
When BuildSelectionBoxesAsync returned early (no current view, or a view with no tabs), it left MainTabs cleared but never refilled it, permanently wiping the selection panel until the next successful rebuild. The panel is now only modified on successful completion.
-
Bug Fix
Fixed cloud upload failure due to timestamp changing mid-backup
The backup filename includes a timestamp (now HHmmss format), but BackupFileName was re-evaluating DateTime.Now on every read. During a single backup operation, the write/zip/cloud-read steps targeted different files, causing "could not find file" errors during cloud upload. The filename is now stamped once at the start of each backup (BeginNewBackupFile) and reused throughout. Same-day backups no longer overwrite each other thanks to the time component.
-
Bug Fix
Duplicate cloud strategy backups avoided
If your strategy hasn't changed since the last cloud backup, the system won't upload a duplicate copy to the cloud.
-
Bug Fix
Fixed duration calculation for empty custom groups
Corrected the processing time calculation for custom groups that matched zero SKUs. Previously these groups would show inflated durations in the summary because the timer wasn't properly stopped, absorbing time from subsequent processing phases.
-
Bug Fix
SKU Level Exceptions screen now shows wait indicator during load
The SKU Level Exceptions screen now shows a "Please Wait" indicator while loading large exception lists instead of appearing frozen.
-
Bug Fix
Strategy backup filename stability for cloud uploads
Cloud uploads now work reliably, and multiple backups on the same day no longer overwrite each other.
-
Bug Fix
Internal tombstone records no longer copied to new strategies
The CopySkuExceptionsAsync method lacked the DUPLICATE filter present in all other queries against the SKU exceptions table, carrying retired tombstone records into each new strategy. These internal markers are now excluded from copy operations.
-
Cloud Sync
Automatic strategy review snapshots
Your strategy scores update automatically each time you run a pricing strategy, so the AI always shows you the latest analysis without any delay.
-
Cloud Sync
Enhanced telemetry for organization-level profit reporting
The system now persists the underlying sales and gross profit dollar totals (both current and future price scenarios) when posting sitting margin data to the cloud. This enables Margin Master Manager to compute exact organization-level profit metrics by simple summation across stores and groups, replacing the previous inventory-weighted approximation. The profit gained or lost is calculated as the difference between future and current gross profit totals (ΣGrossProfitFP − ΣGrossProfitCP).
-
Cloud Sync
AI instruction fetching and message proxying through Manager
Extends ApiClientService with GetAiInstructionsAsync (fetches the editable system prompt markdown from api/v2/ai/instructions) and SendAiMessagesAsync (proxies Claude requests through api/v2/ai/messages with Bearer token, X-AI-Feature/Session-Id/Sequence metering headers, and a 120-second timeout for tool-heavy turns). The server relays requests to Anthropic using RetailerSoft's key, so no API key configuration is required on the client.
-
Cloud Sync
Enhanced strategy execution telemetry
Sitting margin telemetry posted to the cloud now includes dollar totals (sales and gross profit at both current and future prices) in addition to margin percentages, allowing the cloud to aggregate profit metrics exactly across any organization structure. Store and group-level summaries persist these values for accurate regional and enterprise-level reporting.
-
Data Import
Improved data quality filtering for profit analysis
Strategy profit projections are now more reliable and won't be thrown off by pricing errors in your data.
-
User Interface
Per-row delete button added to custom groups grid
Each custom group row now shows a small delete icon on the right side. Click it to remove that group after confirming.
-
User Interface
Per-row delete buttons in Manage Custom Groups
Each Custom Group now has a delete button (trash icon) next to it for quick removal.
-
User Interface
Simplified strategy backup/restore menu structure
The Utilities menu now has just two strategy options: "Backup" and "Restore" instead of four separate buttons.
-
User Interface
Simplified Strategy menu with two unified commands
The Strategy menu now shows just "Backup" and "Restore" instead of four separate options.
-
User Interface
"Upload to Cloud" checkbox now remembers your preference
The "Upload to Cloud" option on the strategy backup screen will now remember whether you had it checked or unchecked the last time you used it.
-
User Interface
"Analyze with AI" action on Rounding Scheme screen
Right-click any rounding scheme and choose "Analyze with AI" to get instant insights on profit impact, price changes, and recommendations. A progress indicator shows you what the assistant is doing while it works.
-
User Interface
AI analysis result dialog in Rounding Scheme editor
The "Analyze with AI" option appears in the Rounding Scheme editor's action menu when AI features are enabled. After a brief analysis period (with status updates), a window displays the results in plain text, explaining the scheme's profit impact and strategic considerations.
-
User Interface
Execute-first workflow for AI strategy reviews
The AI will only review strategies that have been recently run, so you always get feedback based on your latest pricing calculations, not outdated numbers.
-
User Interface
Improved consistency between grid and dropdown
The main pricing grid's Store Number sorting now uses the same NumericStringComparer that the store number selection box uses, ensuring consistent behavior throughout the application.
-
User Interface
Strategy Execution Summary displays profit metrics
After executing a strategy, you can now see at a glance how much your margin will change and the estimated profit impact in dollars.
-
User Interface
Improved strategy execution progress and completion flow
After running a strategy, the summary screen now appears immediately without delays, and the window no longer flickers between busy and ready states.
-
User Interface
Strategy restore dialog now lists cloud backups from blob storage
When restoring a strategy from the cloud, you'll now see a cleaner list showing file names, dates, versions, and file sizes for all available backups.
-
User Interface
New dialog services for strategy analysis
Registered two new dialog services in the main window: StrategyAiResultView for displaying AI analysis scorecards, and StrategyExecutionSummaryView for the post-run summary. Both use the standard 750×750 resizable dialog style and are center-aligned over the parent window. Added StrategyExecutionSummaryViewModel to the dependency injection container.
-
User Interface
New dialog services for AI results and execution summary
Registered two new dialog services in the main application window: StrategyExecutionSummaryView (750×750 resizable) for displaying execution results, and StrategyAiResultView (750×750 resizable) for showing AI-generated strategy analysis reports.
-
User Interface
Strategy execution window control improvements
The screen now stays properly locked during the entire strategy execution process, preventing accidental clicks that could interfere with the operation.
-
User Interface
Visible upload progress during cloud backup
You'll now see progress messages while your strategy backup uploads to the cloud instead of the app appearing frozen.
-
User Interface
AI Review workflow improvement
Clicking "AI Review" in the strategy summary now closes the summary first, then shows the AI analysis separately instead of stacking windows.
-
User Interface
Enhanced execution summary dialog
The summary screen now has clearer buttons with icons, and clicking "AI Review" smoothly transitions to the analysis without overlapping windows.
-
Database
DUPLICATE tombstone records protected from accidental deletion
Added safeguards across backup, restore, and copy operations to prevent deletion of internal DUPLICATE tombstone records. These records are now consistently excluded from operations that could make them unrecoverable, ensuring database integrity.
-
Database
Read-only rounding analysis toolset
AiRoundingToolset provides six read-only SQL tools reusing the analyze-rounding-scheme JOIN logic (RoundingSchemeDetail + Last12 volume weighting): list main tables, list schemes, get active scheme, score a scheme (items changed, up/down split, annual impact, charm %), show top ending transitions by profit, and list top SKUs by absolute impact. Table names are validated against sys.tables; scheme IDs are int parameters. Results are returned as JSON arrays (up to 50 rows for table queries, top 12/20 for aggregates).
-
Architecture
Client-side agentic loop service
Implements AiAssistantService, which orchestrates the full tool loop: fetch instructions, send a user prompt, parse tool_use blocks in the assistant's response, execute each tool via AiRoundingToolset, return tool results as a new user message, and repeat up to 12 iterations until the model returns a stop_reason other than "tool_use". All tool execution is logged and exception-safe; errors are returned to the model as tool_result blocks with is_error=true.
-
Architecture
Unit tests for scoring rubric
Added StrategyReviewScorerTests with hand-computed baseline verification, determinism checks (byte-identical JSON on repeated scoring), hygiene penalty coverage, and volume-blind fallback scenarios, ensuring the rubric math remains stable across code changes.
-
Architecture
AI toolset integration and dependency injection
Integrated the new AiStrategyToolset and StrategyReviewService into the application's dependency injection container and merged the strategy tools with existing rounding tools in AiAssistantService. The strategy toolset is co-authored with Claude Opus 4.8 (1M context) and follows the same architectural pattern as the existing AiRoundingToolset, ensuring consistent tool definition, error handling, and JSON response formatting.
-
Architecture
Sitting margin computation refactoring
The sitting margin calculation has been refactored to return a comprehensive result object (SittingMarginResult) containing both the margin ratios and the underlying dollar totals (sales and gross profit for both current and future prices). This enables exact aggregation at any level and provides the profit delta calculation in one place. New unit tests lock down the aggregation math, margin calculations, profit delta logic, and formatted output for both gains and losses.
-
Architecture
Five-test validation suite
Added comprehensive test coverage: rubric math verification against hand-computed values, determinism (byte-identical scores for the same strategy), hygiene flag generation, non-vendor edge cases (zero non-vendor items = full marks), and volume-blind detection (zero sales history).
-
Architecture
Sitting margin calculation testing
Added comprehensive unit tests covering sitting margin aggregation logic, including dollar totals summation, margin computation, profit delta calculation, edge cases (zero sales, negative profit), and UI formatting. Tests lock the deterministic calculation behavior that feeds cloud telemetry, local execution summaries, and organization profit charts.
-
Infrastructure
Client-side AI assistant service with tool loop
Implements IAiAssistantService (AiAssistantService class) to orchestrate the full tool-calling loop: fetches system instructions via GET /api/v2/ai/instructions, builds tool definitions from AiRoundingToolset, sends each turn to POST /api/v2/ai/messages with metering headers (X-AI-Feature="AnalyzeRoundingScheme", X-AI-Session-Id, X-AI-Sequence), processes tool_use blocks by executing local tools, and loops until the model returns stop_reason != "tool_use" (max 12 iterations). Uses Claude Opus 4-8 model with 4000 max tokens and a 120-second HTTP timeout for tool-heavy turns.
-
Infrastructure
Read-only rounding analysis toolset
Adds AiRoundingToolset with six SQL-based tools validated against sys.tables (table names) and parameterized scheme IDs to prevent injection. Tools mirror the existing RoundingSchemeDetail/Last12 JOIN logic used by the analyze-rounding-scheme skill: list_main_tables, list_rounding_schemes, get_active_rounding_scheme, score_rounding_scheme (items, changed count, impact dollars, up/down split, charm %, pushed-over-whole-dollar count, above-lowest-comp count), ending_transitions (top 12 FromEnding→ToEnding by impact with item/unit counts), and top_skus_by_impact (top 20 SKUs by absolute impact with description, current/rounded price, units). Results are JSON arrays (max 50 rows) or error objects.
-
Infrastructure
AI API client methods for instruction fetch and message relay
Extends ApiClientService with GetAiInstructionsAsync (fetches markdown system prompt from GET /api/v2/ai/instructions, returns AiInstructionsDto.Instructions) and SendAiMessagesAsync (proxies raw Claude JSON request to POST /api/v2/ai/messages with X-AI-Feature/Session-Id/Sequence headers, returns HTTP status and response body for caller-driven tool loop). Both methods use bearer token authentication and the RetailerSoft server base URL. SendAiMessagesAsync uses a 120-second timeout to accommodate multi-tool turns.
-
Infrastructure
Headless execution support
Added detection for headless/service mode execution to skip showing the modal summary dialog when running without a UI, ensuring future Windows service-based strategy execution won't block waiting for user interaction.
Imports & POS
-
New Feature
BisTrack network import root with automatic branch file ingest
If your store exports BisTrack data to a network share with separate folders per branch, you can now enter that share path in Settings → Miscellaneous → Network Import Root. Margin Master will automatically find and copy the right files before each import—you no longer need to manually copy files from the network to your local import folder.
-
New Feature
BisTrack network import root with automatic per-branch file collection
In Settings > Miscellaneous, BisTrack users will see a new "Network Import Root" field. Enter a network share path (like \\server\MM\Export) that contains per-branch subfolders (Branch01, Branch15, etc.). Each time you run an import, Margin Master will automatically copy the latest files from these branch folders into your local import folder—eliminating the manual copy step.
-
New Feature
Purchase order number tagging for BisTrack items
Items from purchase orders now show their PO number in a custom field (which you can display as "PO Number" in your field settings), making it easy to filter and price items by purchase order.
-
New Feature
Purchase order file processing for BisTrack
Items from your purchase orders will now show their PO number in the "PO Number" field, making it easy to filter and analyze pricing for specific purchase orders.
-
New Feature
POS export date shown in Data Aging view
The "Last Update" date in Data Aging now shows when your POS system created the export file, giving you a more accurate view of how fresh your data really is.
-
New Feature
Automatic import of new items from purchase orders
New items that appear on purchase orders but not yet in your catalog are automatically added so you can price them right away instead of waiting for the next catalog update.
-
New Feature
Automatic addition of new purchase order items
New items on your purchase orders that haven't appeared in your POS export yet will be automatically added to Margin Master so you can price them right away.
- Improvement Network import deduplication now based on local folder contents
-
Improvement
Network import speed optimization for multi-branch stores
Network imports for stores with multiple branches now start processing much faster instead of appearing to hang on "Begin POS Data Import."
-
Improvement
Faster network branch import scanning
Importing from network folders is now much faster, especially when bringing in data from multiple stores at once.
-
Improvement
Simplified reprocessing workflow for network imports
To import a branch file again, just delete its .BAK backup file or rename it back to .csv—no need to hunt for hidden tracking files.
-
Improvement
Data Aging screen now shows actual POS export date
The "Last Update" column in Data Aging now shows when your POS created the export, giving you a more accurate picture of how fresh your data is.
-
Improvement
Enhanced splash screen cleanup reliability
All splash screen teardown operations now include a ground-truth forced closure that closes every active splash window unconditionally. This runs before modal dialogs open and during all cleanup operations, ensuring orphaned splash screens cannot hide behind dialogs and re-surface later. The operation is safe to call repeatedly and has no effect when no splash windows are active.
-
Improvement
Import history tracking enhanced
Import processing history now records the source file's export timestamp and file name per store, providing better audit trail and data aging visibility. Previous import records for each store are automatically replaced with the latest import information.
-
Improvement
Optimized drift detection SQL query
The drift count calculation was refactored to use a derived table with a SUM aggregate instead of a simple EXISTS check, allowing accurate counting of drifted rows for threshold comparison while maintaining query performance.
-
Bug Fix
Eliminate duplicate POS store numbers in Store Manager
When viewing the Store Manager, you'll now see only one entry per store number instead of duplicate rows, making it easier to manage store assignments.
-
Bug Fix
BisTrack description update failure after import
After importing BisTrack data, product descriptions and custom group names now update properly instead of showing outdated information.
-
Bug Fix
BisTrack import processing table resolution failure
When importing BisTrack catalog files, the system will no longer fail with a database error. SKU exceptions and custom groups will update correctly after each import completes.
-
Bug Fix
Eliminated stranded splash screen deadlock after vendor imports
After importing vendor catalogs, the "Finalizing…" message will now properly disappear instead of getting stuck on screen and preventing you from using the application.
-
Bug Fix
Prevent false-positive drift detection from single divergent cost rows
Stores with a few discontinued or special-priced items will no longer trigger an unnecessary pricing rebuild on every launch.
-
Bug Fix
Prevent importing partially-written BisTrack export files
Margin Master will no longer import BisTrack files that are still being written to the network. If an export is in progress when you start an import, the app will skip incomplete files and import them on the next run once they're fully written.
-
Bug Fix
File stability check prevents importing incomplete exports
Margin Master now waits for files to finish being written before importing them, preventing the issue where partial data was silently imported from files that were still being created on the network.
-
Bug Fix
Store normalization for multi-branch comparison
Store numbers are now normalized before comparison during the orphan detection process, ensuring that "01" and "1" are treated as the same store. This prevents accidental removal of stores whose numbers differ only in leading zeros between the import files and Store Manager records.
-
Bug Fix
Stop repeated self-heal attempts when drift cannot be resolved
Startup time improved from 37 seconds to 19 seconds for affected BisTrack stores by eliminating repeated rebuilds and selection list rescans.
- Bug Fix Changed exports are now reliably reprocessed
-
Bug Fix
Network import no longer overwrites active files in import folder
The ingest now skips copying a network file if an active local file with that name already exists in the import folder, preventing the system from clobbering files that are awaiting processing or have been manually renamed back from backup for reprocessing.
-
Bug Fix
Prevented branch catalog loss from PO file processing
Fixed a serious issue where importing a purchase order file could accidentally delete most of your branch catalog, leaving only the items from that one PO.
-
Bug Fix
Purchase order files excluded from branch catalog rebuild
Processing purchase order files will no longer accidentally wipe out your branch catalog—only the items on the PO will be tagged, and your full inventory stays safe.
-
Data Import
Network ingest now uses local folder state for deduplication instead of manifest
The import process now checks your local import folder to see what's already been imported, rather than maintaining a separate hidden tracking file.
-
Data Import
Automatic purge of orphaned BisTrack store data
If your store stops exporting data for a particular branch location, that branch will automatically disappear from your store selection lists after the next import, instead of remaining as an unusable "phantom" option.
-
Data Import
Orphaned store purge for BisTrack multi-branch imports
When a store location is removed from your BisTrack system and stops being exported, its data will now be automatically cleaned up after the next import instead of remaining visible in store selection dropdowns.
-
Data Import
Store number normalization for orphan detection
Store number matching now uses the same normalization logic as the import process itself: leading zeros are stripped and whitespace is trimmed, so store "01" and "1" are treated as identical. This ensures accurate detection of which stores are still active versus orphaned, preventing false positives that could incorrectly preserve dead data or incorrectly delete active stores.
-
Data Import
Network branch ingest now copies purchase order files
Purchase order files from your network folders will now be automatically copied and processed without affecting your regular catalog imports.
-
Data Import
Automatic network branch folder filtering by store number
Margin Master will only copy files from network branch folders that match your store numbers—any extra folders on the share (like backups or other stores' data) are automatically ignored.
-
Data Import
Network ingest runs automatically before each BisTrack import
Each time you run an import, Margin Master will first check the network share for new branch files and copy them automatically. If the network isn't available, the import continues with files already on your local computer.
-
Data Import
Purchase order file parsing and validation
Added RSImportFileHelperService.ReadPurchaseOrderFile to parse PO number from the filename (stripping "PO" prefix and extension), extract the branch from the file's Store column, and collect distinct SKUs. The method validates that the file uses the expected DIB1040 layout and contains usable data before processing. Pure filename parsing logic is separately unit-tested.
-
User Interface
Improved Store Manager data integrity
The Store Manager load query now uses a ranking system to prioritize rows with complete data over blank entries. This ensures that store mappings display the most complete and recent information available when the database contains multiple records for the same POS store number.
-
User Interface
Import and export path fields now use folder picker controls
The Import Path, Export Path, and Network Import Root fields in Settings now have a "..." browse button to pick folders, and you can still type or paste network paths directly.
-
User Interface
Network Import Root folder picker added to Miscellaneous settings
When configuring the network import root, you can click the folder icon to browse for the network share instead of typing the path manually. A warning appears if the folder can't be reached right now, but you can still save the setting.
-
User Interface
Purchase order processing integrated into import workflow
ProcessBisTrackPurchaseOrdersAsync now runs after branch builds and orphan purging but before the post-processing queue in the main import flow (MainMMViewModel.ImportData1.cs). The splash screen displays progress for each PO being processed, and detailed logging tracks PO counts, items tagged, and new items added. Errors are reported via the standard import error notification without blocking the main import.
- Infrastructure Network share remains strictly read-only
Cloud Sync & Vendor Data
- Improvement Diagnosed and resolved sync failures at Hills Flat Lumber Co (store 5645)
-
Improvement
Prioritized error messaging in sync dialog
The sync failure dialog now checks for damaged runtime conditions first before falling back to connectivity or generic error messages, ensuring the most specific and actionable error information is always shown to the user.
-
Bug Fix
Orphaned splash screen cleanup
The "Finalizing..." screen that appears during sync will no longer get stuck on your screen, blocking you from using Margin Master.
- Bug Fix Cloud sync failure dialog now surfaces .NET runtime repair instructions
-
Bug Fix
.NET runtime damage detection in sync failures
If sync fails because your .NET installation needs repair, you'll now see a clear message telling you to repair or reinstall .NET Desktop Runtime, instead of being told to check a log file.
-
Cloud Sync
Improved splash screen lifecycle management
Added fallback logic in the Main Table view model to unconditionally close all active splash screens during teardown operations. This ensures that even if the splash service's state tracking becomes inconsistent, no visual elements will remain orphaned on screen.
User Interface
-
New Feature
AI Services settings tab
A new AI settings section has been added to the Options screen where AI features can be turned on or off for this computer.
-
New Feature
AI Options tab with master enable switch
You'll see a new "AI (Artificial Intelligence)" tab in Settings. It starts as OFF and requires the support password to enable. Once enabled, future AI-powered pricing tools will become available.
-
Improvement
Dramatically faster exception list loading
The Sku Level Exceptions window now loads much faster, and the progress bar updates smoothly instead of appearing frozen.
-
Improvement
Dramatically faster loading for SKU Level Exceptions
Large lists of SKU exceptions now load much faster, and you'll see smooth progress updates instead of the window appearing frozen.
-
Improvement
Enhanced duplicate row selection logic
When multiple database records exist for the same POS store number, the system now intelligently selects the best record by prioritizing rows with populated vendor store numbers and RSC codes, then falling back to the most recently updated record. This ensures users always see the most complete and current store information.
-
Improvement
Numeric-aware store number sorting
Store numbers in dropdown lists now sort in natural numeric order (1, 2, 10 instead of 1, 10, 2).
-
Improvement
Numeric store number sorting across exception and custom group dialogs
Store numbers now appear in numeric order (1, 2, 10) instead of alphabetical order (1, 10, 2) throughout the exception and custom group screens.
-
Bug Fix
Removed duplicate store entries in Store Manager
If you previously saw the same store listed multiple times in Store Manager, you'll now see just one row per store with the most complete information displayed.
-
Bug Fix
Restore dialog now uses actual database names by default
When you select a backup to restore, the suggested restore name will now be the original database name (like "MM_1372_ImportTest") instead of a newly generated name that might have dashes or underscores from your store name. This prevents database name errors and makes it easier to identify which backup you're restoring.
-
Bug Fix
Store Number column now sorts numerically in Main Table
When you click the Store Number column header to sort your pricing data, stores now appear in the correct numerical order. For example, Store 2 will now appear before Store 10 instead of after it.
-
User Interface
Resizable Exceptions window with improved grid layout
You can now resize the Sku Level Exceptions window to see more data at once. The delete button stays visible even with long store lists, and you can scroll horizontally to see all columns.
-
User Interface
Resizable SKU Level Exceptions window
You can now resize the SKU Level Exceptions window to see more rows and columns at once.
-
User Interface
Password-protected feature activation
Enabling AI services requires entering the support password ("Sunshine", case-insensitive) in a modal dialog, mirroring the security model used by the Background Service tab. Disabling the feature does not require a password. This ensures AI capabilities are only activated on machines where pre-release testing is intended.
-
User Interface
Grid sorting and filtering enabled
Click any column header to sort the list, or use the filter dropdown to find specific exceptions quickly.
-
User Interface
Password-protected AI enablement
Turning on AI services requires entering a support password; turning it off does not require a password.
-
User Interface
Token usage placeholder panel
The AI tab includes a "Token Usage & Allowance" section that currently displays placeholder text. This panel is prepared to show token consumption and monthly allowance information once the server-side metering and billing APIs are implemented in future phases.
-
User Interface
Enhanced grid column behavior
Added minimum and maximum widths to key columns, enabled sorting and filtering on all data columns, and improved text wrapping and tooltip display for store lists that exceed the column width.
-
Database
New application setting for AI feature flag
Added AIServicesEnabled to the ApplicationSettingKey enumeration. This boolean setting (default false) controls whether AI services are enabled machine-wide and will gate the visibility of all AI-related actions and panels throughout the application.
-
Infrastructure
Machine-level AI visibility gate
Introduced ApplicationSettingKey.AIServicesEnabled, a new machine-local setting that defaults to FALSE. This serves as the single master switch for all AI functionality across the application. When disabled, no AI actions, panels, or features are visible anywhere in the app — Margin Master behaves exactly as it did before. This allows the AI feature to ship in a completely dark state and be revealed only on machines where it is deliberately enabled during the pre-release phase.
Reporting & Exports
-
New Feature
Export AI results to browser for printing and PDF
You can now click "Open in Browser (Print / PDF)" to open the AI analysis in your web browser, where you can print it or save it as a PDF file.
-
New Feature
Browser export for print and PDF
Click "Open in Browser (Print / PDF)" to open the review in your web browser, where you can print it or save it as a PDF using your browser's File menu.
-
Improvement
Friendlier progress messages during AI analysis
The progress window during AI analysis now shows clearer status messages like "Scoring the strategy" instead of technical tool names.
-
Improvement
Friendlier AI progress messages
The progress splash during AI analysis now shows clearer messages like "Finding coverage gaps" instead of technical tool names.
-
Improvement
Standardized version numbers in diagnostic reports
Diagnostic reports now display the canonical application version format (e.g., 2026.726.32673) instead of the raw assembly version (e.g., 20.26.726.32673), matching the version shown in the title bar. This applies to both FTP and MySQL/Compass connection diagnostics.
-
Bug Fix
Fixed false "slow/unstable connection" warnings
Connection tests no longer show false warnings about slow speeds on normal internet connections.
-
User Interface
AI results display as formatted HTML
When you view AI analysis results, tables and headings now display properly formatted instead of as raw text with pipe symbols.
-
User Interface
HTML rendering for AI review output
AI reviews now show formatted tables, headings, and styled text instead of plain text with markdown symbols.
-
User Interface
Connection report window now wraps text
Connection test reports are now easier to read without needing to scroll sideways.
-
User Interface
AI result dialog now fills available space
The AI result dialog no longer uses a fixed-size text box. The browser control and its border now expand to fill the dialog, and the dialog itself has minimum dimensions (640×480) but can be resized for better readability of large reports.
-
User Interface
Resizable AI result dialog
You can now resize the AI review window to see more content at once.
Performance & Reliability
-
Bug Fix
Application crash during column drag operations
Dragging column headers to rearrange columns or set up grouping now works reliably without causing the application to crash.
-
User Interface
Updated grid header styling across all screens
Modified nine grid header styles across multiple screens including the Main Table, Excel Import dialogs, Cost Break analysis, SKU-Level Exceptions, and Store Manager views. The styling changes are internal only—all headers maintain their current visual appearance (left/right/center alignment, bold formatting) while now properly supporting column drag operations.
Other Changes
-
New Feature
Time-limited secure download links for cloud backups
Download links for cloud backups now expire after 7 days for security.
-
New Feature
Create follow-up issue from closed support tickets
When viewing a closed issue, click "Create a new issue from this one" to report a related problem. The form will automatically include a reference to the original issue.
-
Improvement
Database restore naming behavior updated
When you restore a database backup, the suggested database name will now match the original backup's name instead of creating a new name, making it clearer which database you're restoring.
-
Improvement
New workflow for following up on fully-closed support issues
If a problem comes back after support has fully closed your issue, you'll now click "Create a new issue from this one" instead of "Reopen". This automatically fills in a new issue form that references your original issue, so support can see the history while keeping proper records.
-
Improvement
Support issue state now distinguishes user-resolved from staff-closed
If you mark an issue resolved, you can still reopen it if the problem persists. If support closes an issue, you'll create a new follow-up issue instead of reopening the old one.
-
Improvement
Support ticket pre-filling now more accurate
You won't accidentally report update problems to support when everything is actually working fine.
-
Improvement
Cancel option for unusually long startup operations
If startup is taking longer than expected, you'll now see an explanation and a Cancel button that lets you choose whether to wait or return to the app.
-
Improvement
Enhanced elapsed time display during long operations
The progress window now shows elapsed time in a clearer format and explains that work will continue in the background if you choose to cancel.
-
Improvement
Folder browse dialogs open at current path
When browsing for import/export folders in Settings, the dialog now starts at your current folder instead of the desktop, making it easier to adjust existing paths.
-
Improvement
Improved SQL connection timeout messaging
When SQL connection diagnostics time out after 5 seconds, users now see a clearer message: "Cannot connect to port {port} within the timeout. The server may be unreachable or the port blocked." This provides better guidance when troubleshooting unreachable SQL servers in the Settings screen.
-
Improvement
Folder picker starts at current backup location
The backup folder browse dialog in the Restore Database window now opens at the current backup path (matching the Options window behavior) instead of the system default location.
-
Improvement
Backup filenames include timestamps for uniqueness
Multiple backups created on the same day now create separate files instead of overwriting each other.
-
Improvement
Backup completion now generates secure links
After completing a backup, the "Copy Link" button now gives you a secure link that expires after 7 days.
-
Bug Fix
Update-health warning incorrectly triggered after successful update
If Margin Master successfully updated itself when you launched it, you will no longer see a confusing warning message about update problems on that same launch.
-
Bug Fix
Update deferral warning no longer shows after successful update
Fixed MM-1336 where the "you've been behind on updates for N days" prompt could appear immediately after the application successfully updated itself. When an update completes successfully, the deferral tracking is now properly reset, preventing the stale anchor from incorrectly triggering the overdue update dialog on the same launch that just updated.
-
Bug Fix
Splash screen no longer disappears during legitimate long-running operations
On slower computers or with large catalogs, the startup screen will no longer disappear while work is still happening, preventing the app from appearing frozen.
-
Bug Fix
Splash screen escalation replaces force-close for long operations
If the startup progress window stays on one step for more than 2 minutes, you'll now see a "Still working" message with how long it's been running and a Cancel button. You can click Cancel if you believe it's stuck, or wait if you know the operation is still working (like downloading large updates).
-
Bug Fix
Database switching now works on first click
Switching between databases in the database menu now works immediately on the first click.
-
Bug Fix
Database switch now responds to first click
Switching databases from the database menu now works immediately on the first click.
-
Bug Fix
Restore link copy confirmation now appears in strategy picker
After copying a database restore link from the strategy picker, you'll now see a confirmation message letting you know the link was copied successfully and how long it remains valid.
-
Bug Fix
Eliminated unobserved task exceptions in SQL diagnostics
Fixed a diagnostic routine that left background socket connection attempts unobserved when testing SQL connections to dual-stack or multi-address servers that were unreachable. This caused delayed SocketExceptions to surface on the finalizer thread (fingerprint a6c90c8e, 16 occurrences across 6 stores). The connection test now uses a bounded 5-second timeout with proper cancellation, matching the pattern already used throughout the fleet for network probing, ensuring all pending attempts are properly observed and canceled.
-
Bug Fix
Folder pickers now open at current location
When browsing for Import, Export, or Network Import folders in Settings, the folder picker now opens at your currently configured location instead of the desktop.
-
Cloud Sync
Cloud backup retention increased to 3 backups
The system now keeps your 3 most recent cloud backups, so you have more restore points available if needed.
-
Cloud Sync
Cloud backup retention increased to 3 backups
Your last 3 cloud backups are now saved instead of just 1, giving you more restore points if you need to recover data.
-
Cloud Sync
Private storage containers with SAS authentication
Your cloud backups are now stored privately and can only be accessed with secure download links.
-
Cloud Sync
Private blob storage containers with SAS authentication
Cloud backup files are now stored securely and cannot be accessed without a special download link.
-
Cloud Sync
Time-limited download links for cloud backups
Download links for cloud backups now expire after 7 days for added security.
-
User Interface
Clipboard confirmation for backup download links
When you click the copy icon next to a cloud backup, you'll now see a message confirming the download link was copied to your clipboard and explaining it works for 7 days.
-
User Interface
Backup Complete summary reorganized with tabs
After a backup, local and cloud details are now on separate tabs for easier reading, and you can quickly copy the cloud download link with one click.
-
User Interface
Backup Complete summary redesigned with tabs
After a backup, the summary window now shows local and cloud details on separate tabs for easier reading, and you can copy the cloud download link with one click.
-
User Interface
Restore dialog default name logic improved
The restore screen now makes better decisions about what to name your restored database based on where the backup came from.
-
User Interface
Updated Take Action menu in Support Tools
The right-click menu on support issues now shows different options depending on whether you marked it resolved or support fully closed it.
-
User Interface
Enhanced elapsed time display on splash screen
The splash screen's "still working" elapsed timer now shows hours when operations exceed 60 minutes (format changes from "m:ss" to "h:mm:ss"), providing better visibility for exceptionally long operations.
-
User Interface
Confirmation dialog before canceling long-running operations
If you click Cancel during a long operation, you'll be asked to confirm whether you want to return to Margin Master, with a reminder that work will continue behind the scenes.
-
User Interface
Restore Database window reorganized with lazy cloud scanning
Restoring a backup is now clearer with Local and Cloud backups on separate tabs. Cloud backups are only scanned when you open that tab, making the window faster to load.
-
User Interface
Restore Database dialog reorganized with Local/Cloud tabs
When restoring a database, local and cloud backups now appear on separate tabs for easier navigation.
-
User Interface
Copy link buttons in Restore Database screen
Click the new copy link icon next to any cloud backup to get a secure download link that you can share with support or use on another computer.
-
User Interface
Copy link buttons added to restore backup grids
You can now click a copy button next to any cloud backup to get a secure download link.
-
User Interface
Support Issues screen button visibility updated for issue states
The Support Issues detail view now shows different action buttons based on whether an issue is user-resolved (Resolved status) or staff-closed (Closed/ClosedResolved statuses). The "Reopen Issue" button only appears for user-resolved issues, while "Create a new issue from this one" appears for staff-closed issues.
-
User Interface
Copy link buttons in Strategy Restore picker
Strategy backup downloads now use secure, expiring links that you can copy with one click.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Reset Point of Sale Data command; Restore Backup button added to startup Database Setup window; Restore Backup option during startup.
Strategy & Pricing
-
New Feature
CPP Reason column added to Ace Critical Pricing results
The pricing grid now shows exactly why each item appears in your Ace Critical Pricing report, making it easier to understand which pricing rules each item violated without needing to manually compare prices.
-
New Feature
Set PowerShell Execution Policy script
When running PowerShell installation scripts manually (outside the app), Windows will no longer block them with "scripts cannot be loaded" errors.
-
New Feature
View toggle system for upcoming screen redesigns
Two screens now have "Use New View" and "Use Legacy View" buttons that let you switch between the current version and an upcoming redesigned version.
-
New Feature
Complete V2 Strategy Manager implementation
You can now use the new Strategy Manager to create and edit pricing strategies, reorder steps using toolbar buttons or keyboard shortcuts (Ctrl+click to move by 5, Alt+click to jump to top/bottom), manage custom product groups, configure SKU-level exceptions, and export strategies to Excel.
-
New Feature
V2 Strategy Manager interface
The Strategy Manager now responds immediately when you click on different pricing steps, making it much faster to review and edit your pricing strategy.
-
New Feature
Inline condition value editor in V2 Strategy Manager
Click the small pencil icon next to any condition (like "Department equals:" or "Vendor equals:") to open a list of all values. Click the red × button next to any value to remove it from the condition. If you remove all values, the entire condition is removed. Changes are tracked and can be saved or discarded normally.
-
New Feature
Reset button in condition editor popup
When editing pricing strategy conditions, you can now click the "Reset" button at the bottom of the popup to undo your changes and restore the original condition values. This is helpful if you've made changes and want to start over without closing the editor.
-
New Feature
Reset button in condition editor popup
When editing conditions in a pricing strategy step, you can now click the "Reset" button (located next to the "Close" button) to undo any changes you've made and restore the original values. This is helpful when experimenting with different settings and wanting to start over.
-
New Feature
List Price column for MSRP data
A new "List Price" column is now available to view manufacturer suggested retail prices. To see this column, open the Column View editor and add "List Price" to your visible columns. This is especially useful for tracking MSRP on products like Stihl where distributor pricing may not be visible.
-
New Feature
List Price (MSRP) column added to Main Table
You can now add a "List Price" column to your pricing views to see the manufacturer's suggested retail price for each item, which is especially helpful for analyzing pricing on products like Stihl equipment.
-
New Feature
List Price added to pricing strategy targets
When the List Price column is visible, you can now choose it as a target when setting up automatic pricing rules. The system will remember this choice when you reload your saved strategies.
-
New Feature
Add/subtract price modifiers for SKU exceptions
When creating SKU-level pricing exceptions, you can now adjust prices up or down by specific amounts or percentages, giving more flexibility than just setting fixed prices.
-
New Feature
Cloud-based Strategy Backup
A new "Backup Strategy to Cloud" option saves your pricing strategy settings to cloud storage, and "Restore Strategy from Cloud" retrieves them. These options appear in the Strategy menu below the local backup options.
-
New Feature
Fixed retail price toggle for cost break levels
In the cost break editor, you can now check "Fixed Price" for any cost range and enter a specific retail price. For example, items costing $5.00-$10.00 could all be priced at $12.99 instead of using a margin percentage.
-
New Feature
Fixed retail price toggle for cost break levels
In the cost break screen, each pricing level now has a "Fixed Price" checkbox and "Fixed $" field. Check the box to set an exact retail price for items in that cost range, or leave it unchecked to use margin-based pricing like before.
-
New Feature
Charm pricing offset for increment rounding
In the Rounding Editor's increment rounding section, a new "Subtract" field lets you automatically adjust rounded prices. Enter -$0.01 to create .99-ending prices, or use other values for different pricing patterns like .95 or .97 endings.
-
New Feature
Charm pricing offset for increment rounding
Added a "Subtract" field to the Increment Rounding configuration in the Rounding Editor. After rounding to the nearest increment (e.g., $10.00), the system now subtracts the specified offset amount, enabling charm pricing strategies. For example, with a $1.00 increment and $0.01 offset, prices round to $9.99, $19.99, etc. instead of $10.00, $20.00. The offset is stored as the second value in the rounding level's Points array and applied in the SQL pricing calculation.
-
New Feature
Margin Master Diagnostic Tool standalone application
The Diagnostics tool helps identify and fix common setup problems like missing SQL Server, network issues blocking cloud sync, incorrect POS file formats, and database connection errors.
-
New Feature
SQL Server upgrade and installation tools
The AI assistant can now walk you through upgrading your SQL Server to the latest version (2025 Express), installing or updating SQL Server Management Studio, and updating Margin Master itself. Just ask the AI for help and it will guide you through each step, including showing you any error messages if something goes wrong.
-
New Feature
DIB-2 psychological rounding scheme added
When using DIB-2 pricing, items will round to different price endings based on Do it Best's latest recommendations—for example, items between $10-$19.99 will only end in .49 or .99, and items between $20-$49.99 will only end in .99.
-
New Feature
DIB-2 rounding scheme
When calculating retail prices using the DIB-2 scheme, prices will round to psychological price points (like $4.99 or $19.49) based on December 2025 Do it Best guidelines.
-
New Feature
MFG Cost field available in pricing strategy rules
When building pricing rules or setting future prices, you'll now see "MFG Cost" as an option in the field dropdown, right below List Price. Use it the same way you would any other cost or price field.
-
New Feature
MFG Cost field added to pricing grid
A new "MFG Cost" column is now available in your pricing grid. You can show or hide it like any other column, and it will display manufacturer cost information when available.
-
New Feature
Update failure detection and escalation
When an update fails twice or Margin Master has sat on an old version for 3 days, you'll see a "Could Not Update" dialog explaining what went wrong. It only asks once a day, and stops appearing once an update goes through.
-
New Feature
Added MAPP pricing display for Ace Hardware
When looking up Ace Hardware items, you can now see MAP and iMAP pricing directly in the Catalog Lookup window.
-
New Feature
Cloud strategy restore re-enabled
From the Backup menu, you can now select "Restore Strategy from Cloud" to automatically download and apply your most recent cloud-saved pricing strategy. The app will restart with your restored settings.
-
New Feature
AI-powered log analysis with Claude integration
The tool can now automatically read your Margin Master logs and use AI to suggest what might be causing errors or sync problems.
-
New Feature
Automated SQL Server 2025 upgrade workflow
The AI will now automatically detect whether your SQL Server can be upgraded in-place or if a new instance is needed, and will explain what it's doing and why at each step.
-
New Feature
Added MAPP pricing display for Ace Hardware items
Ace Hardware products now show MAP and iMAP pricing restrictions when you look up catalog items.
-
New Feature
Cloud restore for pricing strategies
You can now restore your pricing strategy from your most recent cloud backup, similar to how database restore works.
-
New Feature
Automatic strategy backups on key operations
Strategy backups now happen automatically whenever you save changes to strategies, rounding rules, or exceptions—no need to manually back up after every change.
-
New Feature
SQL Server installation detection and automated setup
The tool automatically detects if SQL Server is installed and can install SQL Server 2022 Express for you if needed.
-
New Feature
PowerShell execution policy script
A new script in the Support Tools menu helps fix issues where Windows blocks PowerShell scripts from running.
-
New Feature
Post-dialog actions and saved selection handling
When you load a saved selection or custom group from the Strategy Manager and close the dialog, the main pricing grid automatically updates to show those items.
-
New Feature
POS file format validation module
You can now validate a POS export file before importing to see if it matches the expected format for your POS system — this helps catch file format issues early.
-
New Feature
Network and cloud connectivity diagnostics
The tool tests your network connection to the cloud sync server, POS systems, and checks if firewalls are blocking required ports.
-
New Feature
PowerShell execution engine for advanced diagnostics
Added PowerShellEngine service and PowerShellRunnerModule to execute ad-hoc PowerShell commands with real-time output capture. Used internally by other modules for Windows Firewall checks, service management, and WMI queries. Also available as a standalone module for support staff to run custom diagnostic scripts.
-
Improvement
Background SKU reconciliation for MySQL Compass
MySQL Compass imports now complete much faster because cleanup tasks run quietly in the background once per week instead of during every import.
- Improvement Critical Pricing Protection reason display
-
Improvement
Expanded character support for strategy names
When creating or editing a strategy name, you can now type < and > characters. For example, you could name a strategy "Spring <2026> Promotion" or "Items >$100".
-
Improvement
Optimized strategy reset query performance
The "Reset Strategy" step before applying new pricing rules now completes much faster, especially for stores with large product catalogs.
-
Improvement
Strategy backups upgraded to V2 format
Strategy backups now save more of your settings and preferences, giving you better protection for your pricing configuration.
-
Improvement
Automatic full strategy backup
When you back up your pricing strategy, everything is now included automatically—no need to choose what to back up.
-
Improvement
One-click strategy backup
When you backup your strategy, it now happens immediately without asking what to include — just click and it's done.
-
Improvement
Optimized IsDirty flag calculation in strategy grid
Changed the IsDirty flag to be cached with a backing field instead of being recalculated on every access through service calls. This reduces over 834 redundant service calls down to a single cached value that updates only when the underlying data changes, dramatically improving grid rendering performance.
-
Improvement
Cached dirty state tracking for strategy steps
The grid now caches each step's "dirty" (unsaved changes) state instead of recalculating it every time the grid refreshes. The dirty indicator is only recalculated when a property actually changes, dramatically reducing unnecessary computation during scrolling and editing.
-
Improvement
Optimized strategy grid rendering performance
The strategy list grid now loads and displays much faster when you open the Manage Pricing Strategies dialog.
-
Improvement
Faster dialog load time
The Manage Pricing Strategies dialog now opens noticeably faster, especially for strategies with many steps.
-
Improvement
High-performance step reordering in Pricing Strategy editor
When you move pricing strategy steps up or down using the toolbar buttons or right-click menu, the movement now happens instantly without lag, even in strategies with hundreds of steps.
-
Improvement
Instant step reordering in pricing strategies
When you reorder pricing strategy steps using drag-and-drop or arrow keys, the moves now happen instantly without delays. Your changes are saved to the database when you click the Save button.
-
Improvement
Simplified step editor data binding
Clicking between strategy steps in the editor now happens instantly without any delay.
-
Improvement
Automatic strategy continuation after view switch
When you're running a strategy and the app suggests switching to a different view that has the fields you need, clicking "Yes" will now switch the view and continue running your strategy immediately — you no longer need to click the Run button again.
-
Improvement
List Price added to price comparison dropdowns
When viewing List Price in the pricing grid, you can now select it from the price comparison dropdowns to compare it against other pricing levels.
-
Improvement
Batch processing for SKU-level exceptions
When running pricing strategies with many SKU exceptions, the process now completes much faster — what previously took 10-15 minutes now finishes in under a minute.
-
Improvement
Single-click inline editing for Future Price column
Click once on any Future Price cell to start typing a new price directly in the grid—no need to open the full product details window.
-
Improvement
Simplified rounding logic for pricing calculations
Streamlined the rounding algorithms used in margin and markup calculations to ensure consistent results across all pricing screens and reports. This reduces edge cases where rounding differences could cause slight discrepancies in displayed values.
-
Improvement
Alphabetical sorting for custom groups
When viewing custom groups, they now appear in A-Z order by name, making it easier to quickly find a specific group using the browser's search feature.
-
Improvement
Smart throttling for automatic cloud strategy backups
The automatic backup system now compares the current pricing strategy content against the last uploaded version using a hash comparison. If the strategy content is identical and was uploaded within the past 4 hours, the cloud upload is skipped. Any genuine change to pricing strategies triggers an immediate upload regardless of timing. This reduces redundant cloud uploads while ensuring all meaningful changes are backed up promptly.
-
Improvement
Smart throttling for automatic cloud strategy uploads
The system now skips uploading your pricing strategy backup to the cloud if nothing has changed since the last upload within 4 hours, making the backup process more efficient.
-
Improvement
Partial execution of strategy steps with missing category values
When running a pricing strategy, if a step looks for categories that don't exist in your store (like a Department or Vendor Category that was removed or never imported), the step will now apply to the categories that do exist rather than stopping. You'll see a message showing which categories will be used and which are missing.
-
Improvement
Abort now opens strategy editor for failed steps
After aborting a failed strategy step, the strategy editor now opens automatically showing the problem step, so you can fix it immediately.
- Improvement Strategy failure now loads selection for review without data refresh
-
Improvement
Optimized future price reset query performance
The "Reset Future Prices" operation in the pricing grid now runs significantly faster, especially noticeable in stores with tens of thousands of products.
-
Improvement
Optimized SKU exception description updates using batch queries
The SKU Level Exceptions screen now loads significantly faster, especially at stores with many SKU exceptions.
- Improvement Optimized description cleanup for SKU exceptions
-
Improvement
Cancellation support for background reconciliation
The background SKU reconciliation process now properly supports cancellation when the application is closed, preventing potential database connection issues during shutdown. A dedicated cancellation token source ensures the background task terminates cleanly.
-
Improvement
Added diagnostic logging for strategy switching
Added detailed timing logs throughout the strategy switching process to measure performance at each step (event firing, saving dirty changes, cache hits vs database loads). This will help diagnose any future performance issues and provides visibility into how long each phase of the switch takes.
-
Improvement
Enhanced strategy step count display
The loading screen now shows how many items are in each pricing step as it loads (for example, "Loaded SKU exceptions (1,234 items)").
-
Improvement
Faster strategy step parsing
Strategy step parsing now executes entirely on a background thread between progress updates, rather than switching back to the UI thread for each of the 118 steps. This significantly improves load times while maintaining accurate progress reporting at 5% intervals.
-
Improvement
Progress bar updates remain smooth during strategy loading
The progress bar now updates smoothly when loading strategy steps, so you can see continuous progress instead of it appearing to hang.
-
Improvement
Enhanced Critical Pricing transparency
You can now instantly see whether an item was flagged for being priced below cost, above MAP, or violating IMAP rules, along with whether it was based on Current Price (CP) or Future Price (FP).
-
Improvement
Simplified Do-It-Best pricing display to match web app
Do-It-Best product pricing now shows a simpler view with just Suggested Retail, Level 1, and Level 2 prices, matching what you see in the web app.
-
Improvement
Faster update checks after applying an update
If the application updates itself, it will check for additional updates after 10 minutes instead of waiting a full hour, helping you get important follow-up fixes faster.
-
Improvement
Faster update check after automatic updates
After Margin Master updates itself, it will check for additional updates sooner (10 minutes instead of 1 hour), helping you get fixes faster.
-
Improvement
Strategy deletion now removes all related data
Deleting a pricing strategy now removes all associated configuration data, ensuring a cleaner removal.
-
Improvement
Automatic execution policy checks in all installation scripts
Installation scripts now configure themselves to run when launched manually, reducing setup friction for support staff.
-
Improvement
Strategy Manager loading performance optimized
The Strategy Manager dialog now opens noticeably faster, particularly for stores with complex pricing strategies.
-
Improvement
Simplified strategy grid cell styling
Reduced complexity in the XAML styling rules for strategy step rows by consolidating multiple conditional styles. Inactive rows show with gray background, unsaved changes show italic/bold text, and inactive steps with unsaved changes show purple background. The styling logic is now more efficient with fewer conditional checks.
-
Improvement
Instant step selection with ViewModel hot-swapping
Clicking between strategy steps in the grid now updates the detail panel instantly, with no loading spinner or delay.
-
Improvement
Instant step reordering operations
Moving pricing strategy steps up or down is now instant with no delay or screen flicker, even in strategies with many steps.
-
Improvement
Optimized pricing strategy editor responsiveness
The pricing strategy editor now feels more responsive when making changes to step order.
-
Improvement
Optimized step dirty-checking logic
Improved the performance of detecting unsaved changes in strategy steps by short-circuiting the expensive rule text comparison when step name or sequence has already changed. This reduces unnecessary text parsing operations during step manipulation.
-
Improvement
Keyboard shortcuts for bulk step movement
You can now quickly reorganize pricing steps using Alt+Arrow to jump to top/bottom or Ctrl+Arrow to move 5 positions at once.
-
Improvement
Performance optimization for dirty state tracking
Introduced a lightweight MarkDirty() method that sets the dirty flag and updates the UI without invoking the full instruction comparison logic. This improves responsiveness when moving multiple strategy steps, as the system no longer needs to regenerate and compare instruction text just to show the yellow highlight.
-
Improvement
Added lightweight dirty marking for better performance
Introduced a direct MarkDirty() method that sets the dirty flag without recalculating the entire instruction text, improving responsiveness when moving multiple steps in quick succession.
-
Improvement
Pre-load first strategy step to eliminate click delay
Clicking on the first pricing strategy step now responds instantly with no delay.
-
Improvement
Saved selection loading moved to dialog
If you have items selected when opening Pricing Strategy, the selection now loads inside the dialog with a progress message.
-
Improvement
Faster deletion of pricing strategy steps
Deleting a pricing strategy step now happens instantly and automatically selects the next step for editing.
-
Improvement
Optimized change detection for pricing strategies
The change tracking system now monitors specific user actions (move/delete operations, step property changes) and sets a dirty flag immediately, rather than recalculating the entire strategy state on every check. The flag is cleared after successful save operations or when switching between strategies.
-
Improvement
Optimized change tracking for strategy steps
Refactored the IsDirty property to use a backing field and only raise property change notifications when the value actually transitions from clean to dirty or vice versa, preventing redundant UI updates and evaluations.
-
Improvement
Enhanced save operation logging
Added PRE-SAVE and POST-SAVE log entries during the save-and-close operation to help diagnose any future issues with the save workflow timing and sequence.
-
Improvement
Enhanced save diagnostics for close-after-save workflow
Added diagnostic logging before and after save operations when closing the pricing strategy editor, making it easier to troubleshoot any issues with the save-and-close workflow.
-
Improvement
Optimized cost break name loading performance
The SKU-level exceptions screen will now load much faster, especially when viewing many exceptions at once.
-
Improvement
Strategy manager now defaults to V2 view each session
Each time you open Margin Master, the pricing strategy manager will open in the new view. If you switch to the legacy view, that choice will only last until you close the application.
-
Improvement
Faster and more reliable scheme copying and deletion
The Edit Rounding Scheme window no longer reloads the entire scheme cache after copy or delete operations, making these actions significantly faster. Copy operations now automatically select the newly created scheme and display a confirmation message. Delete operations navigate back through your selection history (similar to a browser's back button) rather than jumping to an arbitrary scheme.
-
Improvement
Enhanced rounding scheme copy workflow
Streamlined the copy scheme operation to update the in-memory cache automatically without requiring a full refresh of all schemes from the database, improving performance when duplicating rounding schemes.
-
Improvement
Optimized single-row updates in Main Table grid
Streamlined the grid update logic to refresh only the affected row rather than recreating the entire product collection. The existing PropertyChanged notification and RefreshRow mechanisms already handle the visual update correctly, making the collection recreation redundant.
-
Improvement
Formula system enhanced for List Price support
The pricing formula generation and parsing logic now handles List Price as a target level, ensuring strategies can be saved with List Price targets and correctly reloaded from stored formulas. This maintains consistency with existing price level options like Comp1-Comp5 and vendor-specific pricing fields.
-
Improvement
List Price available in Set Future Price dialog
Ace Hardware stores can now choose List Price as the target when setting future prices, making it easier to align pricing with vendor list prices.
-
Improvement
Clearer countdown behavior in error dialogs
Updated the countdown logic to be more explicit: the timer only runs for the IgnoreAndContinue action, which is the only safe option to auto-execute. This prevents potentially destructive actions (Abort) from running automatically without explicit user confirmation.
-
Improvement
Added method to force rounding scheme list refresh
Introduced a ReloadRoundingSchemes method in the Future Price panel that clears the cached rounding scheme data and triggers a UI refresh. This ensures the dropdown always displays current data after operations that modify or reload the scheme configuration.
-
Improvement
Simplified detection logic for marker steps
Streamlined the code that identifies special marker steps by removing an unreliable action-based check and relying solely on step name pattern matching, making the detection more robust and easier to maintain.
-
Improvement
Enhanced batch logging for SKU exceptions
Added detailed logging for each formula combination processed during SKU exception batching, recording the ActionType, RoundingScheme, and number of SKUs affected per combo. This improves troubleshooting capabilities when investigating performance or accuracy issues with SKU-level pricing exceptions.
-
Improvement
Future Price column updates immediately when toggling edit mode
When you enable or disable Future Price editing in Settings, the Main Table updates immediately to show or hide the editing capability.
- Improvement Enhanced batch grouping for SKU exceptions
-
Improvement
Enhanced batch grouping for SKU exceptions
The batch execution engine now groups SKU exceptions by action type, rounding scheme, AND plus/minus modifier together. This ensures that exceptions with different adjustment formulas are processed separately with the correct SQL calculation logic, while still batching SKUs with identical settings for performance.
-
Improvement
Enhanced batch processing for SKU exceptions
SKU exceptions are now grouped by action type, rounding scheme, AND the add/subtract modifier, ensuring that all three factors are considered when optimizing batch updates. This prevents exceptions with different adjustment rules from being incorrectly grouped together while maintaining fast batch performance.
-
Improvement
Added POS-specific import script support
Import processing now checks for POS-specific InsertIntoMainTable.sql scripts (e.g., BisTrackInsertIntoMainTable.sql) before falling back to the generic import routine. When a POS-specific script exists, it bypasses the intermediate _Store table and reads directly from the _current table, allowing for optimized queries tailored to each POS system's data structure. The duplicate removal step is automatically skipped when using these optimized scripts since they guarantee no duplicates.
-
Improvement
Better SQL timeout and connection error logging
SQL timeouts and closed-connection errors are now logged as warnings instead of errors, reducing noise in logs during large data operations. These conditions are expected during intensive operations like syncing large catalogs and don't represent actual system failures.
-
Improvement
Enhanced SKU resolution for custom group management
Added a new SKU resolution method that searches across all main tables (by primary SKU first, then by AltSku) to ensure items are always stored using their canonical SKU identifier, regardless of which identifier format the user enters.
-
Improvement
Enhanced SKU resolution logic in Custom Groups
Improved the logic that checks whether a SKU already exists in a Custom Group by comparing resolved primary SKUs rather than the entered value, and added cleanup of stale database entries to maintain data consistency.
-
Improvement
Preserved DIB-1 scheme for legacy support
If you're already using DIB-1 pricing, nothing changes—your current price rounding will continue to work exactly as before.
-
Improvement
Rounding scheme selection
You can select either the older DIB-1 or newer DIB-2 rounding scheme when analyzing margins and calculating retail prices.
-
Improvement
Enhanced strategy error messages for missing filter values
Error messages during strategy execution are now clearer about whether a step will run with partial data or must be skipped entirely.
-
Improvement
Ignore option consistently skips failed steps
The "Ignore" option now always skips problem steps completely, making the behavior more predictable.
-
Improvement
Better error logging for failed pricing strategies
Strategy execution failures that occur before any steps complete will now properly write summary logs, making it easier to diagnose issues like database mapping problems or configuration errors that prevent strategy execution from starting.
-
Improvement
Automatic cleanup of old strategy execution logs
Strategy execution logs older than 30 days are now automatically purged when a new strategy execution begins. This prevents the logs directory from growing indefinitely while retaining recent history for troubleshooting.
-
Improvement
Automatic log cleanup for strategy execution
Strategy execution logs older than 30 days are now automatically purged when a new strategy run begins. This prevents log files from accumulating indefinitely and consuming disk space while retaining recent execution history for troubleshooting.
-
Improvement
Unified numeric field handling for Falcon imports
Created a shared helper function that consistently processes numeric fields (prices, costs, quantities, and sales history) across both Falcon CSV and Excel import paths. This ensures both import methods handle edge cases identically and prevents similar issues in the future.
-
Improvement
Rounding scheme editor now shows saved rollback settings
When you edit a custom rounding scheme that uses rollback rules, the rollback settings section will now appear automatically instead of staying hidden.
-
Improvement
MFG Cost available in pricing strategies
When creating pricing rules or strategies, you can now select "MFG Cost" as a price level to base your calculations on, giving you another option for automated pricing decisions.
-
Improvement
Elevated logging for empty custom groups from Debug to Warning
You'll now see a clear warning message if a custom group is set up but won't actually change any prices, helping you identify configuration mistakes.
-
Improvement
Enhanced logging for empty custom groups
Store managers will now see a clearer warning message when a custom pricing group is set up incorrectly and won't apply any changes.
-
Improvement
User notification when updates are deferred
If you trigger an update check manually while exporting prices or running a strategy, you'll see a friendly message explaining that the update will install automatically once you're done.
-
Improvement
Active database targeting for maintenance dialog
The Database Maintenance dialog now scopes operations to the currently active Margin Master database by name, rather than applying maintenance across all databases on the server. Combined with the ownership filter, this ensures maintenance operations are both targeted and safe.
-
Improvement
Skip legacy data migration during strategy execution
The system now skips old-format migration and deduplication processes during strategy execution. These one-time data cleanup operations are deferred to when the SKU Level Exceptions screen is opened directly, preventing them from blocking pricing operations.
-
Improvement
Strategy definition filtering enhancement
Strategy step loading now explicitly excludes 'PLACEHOLDER' entries from the GlobalFileConfig table, in addition to 'Custom Groups' and 'Sku Level Exceptions', ensuring only valid strategy steps are processed during execution.
-
Improvement
Simplified Do-It-Best pricing display
Do-It-Best pricing in Catalog Lookup now shows the three most important price points (Suggested Retail, Level 1, Level 2) without extra clutter.
-
Improvement
Removed rarely-used restore options
The restore dialog now shows only the most commonly needed options, making it simpler to choose what to restore.
-
Improvement
Strategy Manager rendering optimized
Strategy Manager opens faster when working with large pricing strategies.
-
Improvement
Cached rounding scheme collections
Rounding scheme dropdown lists are now cached instead of allocating new collections on every access, reducing memory allocations and improving responsiveness when editing strategy steps.
-
Improvement
Cached rounding scheme collections
Rounding scheme dropdown lists are now cached in the ViewModel instead of being recreated on every access, reducing memory allocations and improving UI responsiveness when interacting with the rounding settings.
-
Improvement
Enhanced startup contention handling
Increased database lock retry logic from 3 to 5 attempts with longer timeouts (10s instead of 3s) for GlobalFileConfigService operations during application startup. This prevents initialization failures when multiple services read configuration data concurrently, particularly when loading the Strategy Manager alongside other screens.
-
Improvement
Added MarkClean method to strategy step display model
Implemented a new MarkClean() method that directly clears the dirty flag on strategy steps without the expensive recalculation path, improving performance during save operations while ensuring accurate dirty state tracking.
-
Improvement
Dramatically improve SKU Exceptions loading performance
The SKU Level Exceptions screen now loads much faster, especially when you have many exceptions configured.
-
Improvement
Enabled lazy loading for cost break values in Future Price panel
Changed cost break values to load only when needed rather than immediately when the panel initializes. This reduces unnecessary database queries and improves overall responsiveness.
-
Improvement
Strategy backups no longer include database connection data
New strategy backups created going forward will not include the DatabaseConnections.json data, reducing backup file size and eliminating the possibility of accidentally restoring incorrect connection settings. This aligns strategy backups with the existing blob-backup behavior, which already excluded this machine-specific infrastructure data.
-
Improvement
Enhanced backup restore verification
Tested with a customer backup file containing 431 strategy steps across 5 strategies (DEFAULTSTRATEGY with 140 steps, JWN ACE 2021 with 147 steps, SKUCOUNTS with 137 steps, and others), verifying all strategies appear correctly in the UI with accurate step counts.
-
Improvement
Future Price Panel rounding scheme validation improved
Saved pricing selections will load correctly even if the rounding scheme name's capitalization has changed.
-
Improvement
Extended timeout for variance recalculation
Increased timeout protection for price variance recalculation and related maintenance operations to ensure these operations complete successfully on large datasets.
-
Improvement
Backup file size reduced
Removed 627 lines of dead code that attempted to serialize rounding schemes as entity objects. Rounding schemes now flow through the existing GlobalFileConfig backup mechanism, eliminating duplicate storage paths and reducing backup file complexity.
-
Improvement
Enhanced SKU Level Exceptions execution logging
The strategy execution log now shows detailed information about SKU-level exceptions processing, including how many exceptions were found and applied, making it easier to verify your pricing overrides are working.
-
Improvement
Dynamic Future Price editing toggle
Turning Future Price editing on or off in Options now takes effect immediately without restarting Margin Master.
-
Improvement
Click-to-set Future Price feature now respects inline editing mode
The existing click-to-set Future Price feature (which copies values from other columns) now properly defers to inline editing when that mode is enabled, preventing conflicts between the two editing methods.
-
Improvement
Added support for additional pricing source columns in batch exceptions
Enhanced the batch exception SQL generator to support additional pricing source columns including RETAILZONE, FUTUREPRICE, STORECOST, LISTPRICE, and Ace Hardware-specific fields (MSURetail, MapPriceAmt, ImapPriceAmt). This ensures that SKU-level exceptions can reference these columns when calculating exception prices.
-
Improvement
Manual and automatic backups use consistent vendor identification
Both user-initiated manual backups and automatic scheduled backups now consistently use the numeric vendor ID, ensuring all backups are properly categorized in the cloud storage system regardless of how they were triggered.
-
Improvement
Enhanced cost break SQL generation
The pricing calculation engine now checks if a cost break level uses fixed pricing before applying margin-based calculations. When a level has fixed pricing enabled with a valid price, the SQL generator creates a CASE statement that returns the fixed price directly. Warning messages for excluded levels now indicate whether the exclusion is due to zero margin or disabled fixed pricing.
-
Improvement
Better handling of SQL timeout error logging
Modified DatabaseService2 to log SQL timeout errors (error -2) and subsequent "connection is closed" errors as Warnings instead of Errors. These conditions are expected during large-table operations and do not represent actual failures, reducing false alarm noise in diagnostic logs while still recording the events for troubleshooting.
-
Improvement
Enhanced SQL Server instance detection and recommendations
The get_sql_instances_detail tool scans all local SQL instances, checks versions against the SQL 2025 target (version 17.x+), identifies MarginMaster-only vs. mixed-database instances, and provides a RecommendedAction field (run_sql_express_upgrade, run_sql_express_install, or none) with upgrade block reasons (e.g., "Contains non-MarginMaster databases"). The AI uses this data to guide users through the correct upgrade path.
-
Improvement
Added safety net for rounding scheme misconfiguration
While the underlying rounding schemes should be updated to cover the full price range of items they're applied to, this guard prevents catastrophic pricing errors when schemes are misconfigured or applied too broadly. A comment in the code notes that fixing the rounding scheme definition is the correct long-term solution.
-
Improvement
Added safety documentation for rounding scheme configuration
Added inline documentation noting that while the UpperLimit guard prevents incorrect prices, the underlying rounding scheme should be properly configured to cover the store's actual price ranges. The guard is a safety net, not a substitute for correct rounding scheme setup. Stores using custom schemes should verify their schemes cover all relevant price points.
-
Improvement
Strategy detection query added for fresh installs
Added a new database query that retrieves all existing strategy names from GlobalFileConfig during application startup. This query enables the auto-detection logic and runs only when no active strategy has been previously set, minimizing performance impact.
-
Improvement
Enhanced support issue diagnostics
When submitting a support issue (both quick submit and full issue forms), the system now automatically attaches the most recent strategy execution logs if available. The attachment collects all log files from the same execution run (within 60 seconds) and zips them together. If this attachment fails for any reason, the issue submission continues normally without interruption.
-
Improvement
Strategy execution logs included in support submissions
When you submit a support request, strategy run details are now automatically included to help the support team diagnose issues faster.
-
Improvement
Auto-show exception column when relevant
After running a pricing strategy that creates special item-level rules, the "*" column will automatically appear so you can immediately see which items were flagged—unless you've already customized where that column appears.
-
Improvement
Enhanced diagnostic logging for strategy finalization
Added logging at the start of each finalization sub-step (saving counts, resetting unchanged prices, configuring vendor SKU types, loading price changes) to improve troubleshooting when issues occur during strategy execution.
-
Improvement
Standardized zone pricing table column widths
Zone pricing columns (Retail, Level 1, Level 2, MSU Retail) now use consistent 80-pixel widths instead of proportional sizing for better readability and alignment.
-
Improvement
Disabled automatic column width calculation
Turned off BestFit column sizing which was measuring all rows on every render, contributing to slow grid display times without providing significant benefit.
-
Improvement
Exposed ConvertConditions method in StrategyStepService
Made the ConvertConditions method public and added it to the IStrategyStepService interface to support rebuilding display conditions after inline edits, enabling the ViewModel to refresh condition display after removing values.
-
Improvement
Better user feedback for delete operations
Delete operations now provide clear success or failure messages to the user. The system logs detailed information about the deletion process, including whether database records were found and whether the deleted scheme was the default.
-
Improvement
Countdown stops when switching to Wait mode
Changing your error handling choice to "Wait" immediately stops any countdown timer.
-
Improvement
Enhanced SQL error handling to skip retries for permanent errors
Modified database service to immediately stop retrying when encountering SQL errors 207 (Invalid column name) or 208 (Invalid object name), which indicate structural database problems that won't resolve with retries. This reduces unnecessary delays and log noise when database schema issues occur.
-
Improvement
More accurate logging for SKU exception processing
The "X SKUs applied" log message previously counted exception rows parsed rather than actual database rows updated, making it appear that exceptions were working when they were silently failing. The underlying count still reflects parsed rows, but the fix ensures those rows now translate to actual SQL updates.
-
Improvement
Enhanced cost break level management
Insert and delete operations for cost break levels now preserve the fixed price settings, copying UseFixedPrice and FixedPrice values when creating new levels above or below existing ones.
-
Improvement
Enhanced pricing calculation SQL
Updated the SQL-based rounding calculation engine to apply the offset amount after increment rounding is performed, ensuring the adjustment occurs at the correct stage of the pricing workflow.
-
Improvement
PowerShell execution engine now prefers PowerShell 7
The PowerShell engine now detects and uses PowerShell 7 (pwsh.exe) when available, falling back to Windows PowerShell 5.1 if not found. This eliminates CLIXML-serialized progress records that pollute stderr output in Windows PowerShell 5, resulting in cleaner captured output for AI analysis and user display.
-
Improvement
Rounding preview now matches actual pricing run results
The rounding scheme editor's "Check" preview now applies increment rounding using the same formula as the pricing run, ensuring the previewed price exactly matches what will be calculated during actual pricing operations.
-
Improvement
Legacy pricing strategy rule migration
Margin Master now starts faster when connecting to databases that have already had their pricing rules updated.
-
Improvement
Execution policy handling in all scripts
Updated all installation scripts (Install-SQLExpress.ps1, Install-SSMS.ps1, Install-OleDb12.ps1, Uninstall-SQLServer.ps1, Uninstall-SSMS.ps1, Upgrade-SQLExpress.ps1) to automatically check and set the execution policy to RemoteSigned if needed when run manually outside the app. This ensures scripts can run even if launched from Windows Explorer without requiring the user to manually bypass execution policy.
-
Improvement
Extracted click-to-set price column mapping to dedicated method
Refactored the 23-case switch statement that maps clicked column types to their source price values into a new TryGetClickToSetFuturePriceSource method, improving code readability and maintainability in the main click handler.
-
Improvement
Downgraded strategy execution log levels for user-initiated stops
Changed log severity from Error to Warning when users intentionally stop strategy execution due to load failures. This reduces alarm fatigue in logs since these are expected user decisions rather than system errors.
-
Improvement
Support form pre-fill for update failures
When you click "Contact Support" from the update dialog, the support form already has all the technical details filled in—you just add anything else you want to say and send it.
-
Improvement
License verification now retrieves full license details
When you verify your store number, you'll now see your license expiration date and the number of stores on your license.
-
Improvement
User-driven update failures now surface immediately
If you click "Update Now" and it fails, Margin Master shows you the "Could Not Update" dialog right away instead of just a notification you might miss.
-
Improvement
Log analyzer now detects warnings in addition to errors
The LogAnalyzerModule now parses [WRN]/[WARN] entries in addition to [ERR]/[ERROR], grouping and reporting warnings with appropriate severity. Serilog's optional source context prefix is stripped to improve deduplication and readability.
-
Improvement
Database schema checks updated for current table names
MarginMasterHealthModule now expects AceCatalogRecords instead of the obsolete Ace_Current table, and reads ApplicationSettings using current column names (Setting/Value instead of SettingKey/SettingValue). SQL version recommendations updated: SQL 2022 (v16) shows an Info-level message suggesting upgrade to SQL 2025; pre-2022 versions show a Warning-level message.
-
Improvement
POS connectivity module classifies POS modes
The POS connectivity diagnostic now understands which type of connection your POS system uses and only tests the relevant connections (FTP, direct database, or file share).
-
Improvement
POS file format module reads configuration from database
The POS file format checker now knows which POS system you use and opens the file picker to the right folder with the correct file type already selected.
-
Bug Fix
Strategy finalization now shows progress updates
When running a strategy, you'll now see progress messages during the final cleanup phase instead of the screen appearing stuck on the last step.
-
Bug Fix
Eliminated strategy execution hang caused by SKU exception loading
Pricing strategies now execute immediately without freezing, even at stores with thousands of SKU-level pricing exceptions.
- Bug Fix Fixed multi-minute hang when processing SKU-level exceptions during strategy execution
-
Bug Fix
Fixed reversed logic in no-decreases price guard
When you enable "No Decreases" on a pricing strategy step, prices will now stay at or above their current price as intended. Previously, a bug was causing prices to decrease even when this option was checked.
-
Bug Fix
Custom group minus rounding point actions now parse correctly
When you create a custom pricing group and choose to subtract rounding points (e.g., "minus 2 points"), the pricing calculation will now correctly subtract those points instead of incorrectly adding them.
-
Bug Fix
Settings migration duplicate key errors resolved
Fixed errors that could occur during migration from the legacy GlobalFileConfig system to ApplicationSettings when duplicate configuration keys existed. The migration process now tracks keys added in the current batch and skips duplicates, preventing database constraint violations while still properly cleaning up old configuration entries.
-
Bug Fix
Strategy switching no longer freezes application
You can now switch between pricing strategies or rename them without the application freezing.
-
Bug Fix
Strategy switching no longer freezes application
Switching between pricing strategies now works smoothly without causing the application to freeze.
-
Bug Fix
Eliminated UI deadlock during strategy switching
The app will no longer freeze when you switch between pricing strategies, even when working with large datasets or multiple open screens.
-
Bug Fix
Wait indicator now shows during strategy switching
When you switch between pricing strategies, you'll now see the wait indicator showing that Margin Master is working, instead of the screen appearing frozen or unresponsive.
-
Bug Fix
Splash screen progress now updates through SKU exceptions step
The loading screen now shows "Updating display" after loading SKU exceptions, so you can see progress is still happening instead of appearing frozen.
-
Bug Fix
UI responsiveness during strategy loading
The application will no longer freeze or appear unresponsive when loading your pricing strategy at startup. The loading screen will remain animated and show smooth progress updates.
-
Bug Fix
Eliminated UI freeze during pricing strategy display
When you open a pricing strategy with many steps, the grid now appears instantly instead of freezing the application for several seconds.
-
Bug Fix
Strategy switch now uses splash screen instead of busy overlay
When you switch pricing strategies, you'll now see a full splash screen showing the progress instead of a dimmed overlay, making it clearer that the system is working.
-
Bug Fix
Strategy switch splash screen not hiding
When you switch between pricing strategies, the "Loading..." screen now disappears correctly every time, even when switching to a strategy you've used before.
-
Bug Fix
Zone pricing icon displays correctly
Products with Ace Hardware zone pricing now show the Ace icon in the "Z" column as expected.
-
Bug Fix
Restore zone pricing Ace icon display
The Ace Hardware icon now shows up correctly in the grid when items have zone pricing.
- Bug Fix Plus/minus values now load correctly when opening saved strategy steps
-
Bug Fix
Save confirmation dialog no longer loops when closing Pricing Strategies
When you save changes to a pricing strategy and then close the window, you'll no longer see the save confirmation dialog pop up multiple times.
-
Bug Fix
Fixed infinite save prompt loop in Pricing Strategy editor
After saving changes to Custom Groups or SKU exceptions in the Pricing Strategies window, you can now close the window without being repeatedly prompted to save changes.
-
Bug Fix
DIB Aux Retail strategy now uses correct catalog pricing
When creating custom pricing groups with the "DIB Aux Retail" strategy, future prices will now match Do-It-Best's actual auxiliary retail prices instead of showing inflated amounts. For example, items that should be priced at $0.49 will no longer show future prices over $100.
-
Bug Fix
DIB Aux Retail field now populated with correct catalog data
When creating custom pricing groups that use "DIB Aux Retail" as the pricing strategy, the system will now use the correct auxiliary retail price from your Do-It-Best catalog instead of an incorrect inflated value.
-
Bug Fix
Report scripts error blocking label printing
If you were unable to print bin tags or price stickers and saw an error about "Report Scripts," this issue is now resolved. All label printing should work normally.
-
Bug Fix
Application crash during cost break deletion
You can now safely delete multiple cost break pricing models in sequence without the application crashing. After deleting a model, the next available model will load automatically.
-
Bug Fix
Fixed grid display errors in Catalog Lookup
The Catalog Lookup screen now displays properly without layout errors, and columns size appropriately for better readability.
-
Bug Fix
Fixed grid column sizing errors in Catalog Lookup
Resolved AutoWidth errors in the search results grid and zone pricing table that could cause display issues. Column widths are now set to fixed values or proportional sizing for more reliable display.
-
Bug Fix
Excluded wildcard filters now generate correct SQL
When you exclude items by wildcard pattern in a pricing strategy (e.g., "exclude all UPCs starting with 12345"), the filter now works correctly instead of failing silently.
-
Bug Fix
Do-It-Best Level1-5 pricing missing on manually added catalog items
When you add Do-It-Best items from the catalog, all five pricing levels now appear correctly in the pricing grid instead of showing blank or zero values.
-
Bug Fix
SQL validation now allows hyphen character in WHERE clauses
Fixed an issue where strategy filters containing hyphen characters (e.g., part numbers like "ABC-123") were incorrectly rejected as unsafe SQL, preventing strategies from executing. The SQL safety validator now properly allows hyphens in WHERE clause expressions.
-
Bug Fix
Deleted pricing strategies no longer recreate themselves
When you delete a pricing strategy, it will now stay deleted. Previously, the strategy could reappear if any SKU exceptions or custom groups were still referencing it.
-
Bug Fix
Strategy Backup dialog now appears correctly
Clicking "Backup Strategy" from the database menu now opens the backup dialog as expected instead of doing nothing.
-
Bug Fix
Strategy Backup dialog now displays correctly
When you click "Backup Strategy" in the File menu, you'll now see the backup options dialog where you can choose what to include in your backup.
-
Bug Fix
Strategy Manager save performance
Saving changes in Strategy Manager is now instant instead of freezing the screen for several minutes.
-
Bug Fix
Strategy save operation freeze resolved
Saving changes to your pricing strategies now takes just a few seconds instead of freezing the program for several minutes.
-
Bug Fix
Strategy Manager save freeze resolved
The Strategy Manager will no longer appear frozen when saving your pricing strategies, especially when working with strategies that have many steps.
-
Bug Fix
Eliminated redundant processing during step reordering
When reordering steps in your pricing strategies, the app no longer freezes or lags, especially in large strategies with many steps.
-
Bug Fix
Fast step movement in pricing strategy V2 editor
The pricing strategy editor no longer freezes when moving steps up or down, making it much faster to reorganize your pricing rules.
-
Bug Fix
Dirty indicator now appears after moving strategy steps
When you drag pricing strategy steps up or down to reorder them, the affected rows now turn yellow right away to show you have unsaved changes.
-
Bug Fix
Dirty indicator now appears after moving pricing strategy steps
When you drag a pricing rule up or down in the strategy list, the affected rows now turn yellow to remind you to click Save.
-
Bug Fix
Close button now prompts to save unsaved pricing strategy changes
When you click the X button to close the Manage Pricing Strategy window with unsaved changes, you'll now see a prompt asking if you want to save. Click "Yes" to save your changes or "No" to discard them.
-
Bug Fix
Close button now prompts to save changes
When you close the Pricing Strategy window with the X button, you'll now be asked if you want to save your changes instead of losing them.
-
Bug Fix
Dialog now opens instantly with visible progress
When you open Manage Pricing Strategies, the window appears right away and shows you what's loading, so you know the program is working instead of appearing frozen.
-
Bug Fix
Pricing Strategy dialog opens immediately
When you click to open the Pricing Strategy dialog, it now opens right away and shows a loading message instead of freezing the screen.
-
Bug Fix
Restore pre-load initialization for pricing strategy dialog
When opening the Manage Pricing Strategy dialog, you'll see the loading message on the main window before the dialog appears, rather than seeing a busy indicator inside the dialog itself.
-
Bug Fix
Restore pre-load initialization for Pricing Strategy dialog
When opening the Pricing Strategy manager, the app now loads all strategy information before the dialog appears, showing progress messages on the main screen.
-
Bug Fix
Right panel displays correct step details when switching between steps
When editing pricing strategies, selecting a different step in the left list now immediately shows the correct settings for that step in the right panel, including rounding options and min/max rules.
-
Bug Fix
Strategy step right panel visibility restored
When editing pricing strategies, the details panel on the right side of the screen now appears correctly instead of staying empty.
-
Bug Fix
Restore visibility of strategy step details panel
When you click on a pricing strategy step, the details panel on the right side of the screen now appears as expected, showing all step information and settings.
-
Bug Fix
Step deletion now occurs instantly without database delay
Deleting a pricing strategy step is now instant, and the selection automatically moves to the next step.
-
Bug Fix
Eliminated UI deadlock when discarding pricing strategy changes
When you close the pricing strategy window with unsaved changes and click "No" to discard them, you'll now see a brief "Discarding changes..." message and the window will close properly instead of freezing.
-
Bug Fix
Fixed UI freeze on discard changes
The pricing strategy window no longer freezes when you click "No" to discard your changes and close the window.
-
Bug Fix
Improved condition value display in pricing strategies
When setting up pricing rules with multiple category, vendor, or other condition values, they now display as "Hardware or Plumbing or Electrical" instead of in separate boxes, making it easier to understand which products the rule will affect.
-
Bug Fix
Eliminated freeze when closing Pricing Strategy screen
When you open and close the Pricing Strategy screen without making changes, it now responds instantly instead of freezing for several seconds, especially with large pricing strategies.
-
Bug Fix
Fixed slow load/close performance in Pricing Strategy editor
The Pricing Strategy screen now opens and closes immediately when you haven't made any edits, eliminating the previous delay.
-
Bug Fix
Fixed infinite loop when closing with unsaved changes
The "Save changes?" dialog now only appears once when closing the pricing strategy editor, and the window closes immediately after clicking Save or Discard.
-
Bug Fix
Pricing Strategy editor infinite loop on close
When closing the Pricing Strategy window with unsaved changes, you'll now see the save prompt only once, and the window will close properly after you choose to save or discard your changes.
-
Bug Fix
Restored unsaved changes prompt in Pricing Strategy editor
You'll now see a "Save changes?" prompt when trying to close the Pricing Strategy editor with unsaved work, preventing accidental data loss.
-
Bug Fix
Fixed change tracking in Pricing Strategy editor
The editor will now correctly enable or disable the Save button based on whether you've actually made changes, and won't incorrectly warn you about unsaved changes when there are none.
-
Bug Fix
Condition editor popup binding crash resolved
When editing conditions in a pricing strategy, the editor popup now opens and closes smoothly without errors.
-
Bug Fix
Condition editor popup binding crash resolved
The condition editor popup in pricing strategies will no longer cause crashes when it closes automatically.
-
Bug Fix
Pricing strategy condition editor remove button now functional
When editing pricing strategy conditions, the × button next to each value now properly removes that value from the list. Previously, clicking this button would do nothing.
-
Bug Fix
Fixed non-functional buttons in Condition Editor popup
When editing pricing strategy conditions, clicking the × button to remove individual values or the Close button to dismiss the editor now works as expected instead of being unresponsive.
-
Bug Fix
Fixed crash when deleting pricing strategy conditions
The strategy editor no longer crashes when you delete a condition from a pricing rule.
-
Bug Fix
Resolved window closing infinite loop
The Pricing Strategy window will now close properly when you choose to save or discard changes, instead of sometimes freezing or becoming unresponsive.
-
Bug Fix
Closing flag now set before async operations
When closing the Pricing Strategy dialog, the system now correctly ignores background updates that could previously cause the "unsaved changes" prompt to reappear.
-
Bug Fix
Busy indicator now displays during save operations
When you click Save or close the pricing strategy window with unsaved changes, you'll now see the busy indicator appear right away instead of the window appearing frozen.
-
Bug Fix
Busy indicator now displays during pricing strategy saves
When you save a pricing strategy, you'll now see the "Saving Strategy..." message appear immediately, confirming that your changes are being saved.
-
Bug Fix
Loading indicator now displays before save operations
When you click Save or close the pricing strategy window with unsaved changes, you'll now see the "Saving..." loading message immediately instead of the window appearing to freeze during the save.
-
Bug Fix
Loading indicator now displays during pricing strategy saves
When you save a pricing strategy, you'll now see the loading spinner right away instead of the screen appearing to freeze while the save completes.
-
Bug Fix
Busy indicator clears prematurely during pricing strategy save
When saving a pricing strategy, the loading spinner will now remain visible until the save is completely finished, instead of disappearing early while the save is still happening.
-
Bug Fix
Busy indicator now stays visible during pricing strategy save
When you save a pricing strategy, the busy spinner will now stay on screen until the save is completely finished, so you'll always know when it's safe to continue working.
-
Bug Fix
Busy indicator now reliably displays during save operations
The "Saving changes..." message will now always appear when you save a pricing strategy, so you'll know the system is working.
-
Bug Fix
Busy indicator now displays correctly during save operations
When you save a pricing strategy, you'll now reliably see the "Saving changes..." indicator appear on screen.
-
Bug Fix
Fixed missing loading indicator in Pricing Strategy Manager
The "Please wait..." loading spinner now displays properly when you're saving pricing strategies or performing other operations that take time to complete.
-
Bug Fix
Improved loading indicator behavior in Pricing Strategy editor
The "Please wait..." loading spinner now transitions smoothly when loading pricing strategies, without flickering or visual glitches.
-
Bug Fix
Fix crash when opening Custom Groups screen
Custom Groups screen no longer crashes when you try to open it.
-
Bug Fix
Fixed Custom Groups crash due to missing style resource
Custom Groups will now open without crashing.
-
Bug Fix
Corrected rule numbering in Load Saved Selection dialog
When loading saved pricing rules, the rule numbers shown in the dialog now match the correct order.
-
Bug Fix
Corrected rule numbering in pricing strategy display
When viewing your pricing strategy rules, they will now always be numbered in the correct order (1, 2, 3...) instead of appearing scrambled.
-
Bug Fix
Variance column filters in strategies now work correctly
If you created pricing strategies with rules like "select items where cost variance is greater than 125%", those rules will now correctly filter items instead of selecting almost everything.
-
Bug Fix
Deleted rounding schemes now persist after restart
When you delete a custom rounding scheme, it will now stay deleted even after closing and reopening Margin Master.
-
Bug Fix
Rounding scheme deletion now persists to database
When you delete a custom rounding scheme, it now stays deleted even after closing and reopening Margin Master.
-
Bug Fix
Eliminated UI freeze during click-to-set Future Price operations
When you click on a price column (like Current Price or Retail) to copy that value into Future Price, the app now responds immediately instead of freezing.
-
Bug Fix
Removed unnecessary grid refresh when setting Future Price via click
When you click on a price to set Future Price, the app now responds instantly instead of freezing with a progress bar.
-
Bug Fix
Fixed store selection error in SKU exceptions for single-store customers
Editing margin percentages for SKU exceptions now works correctly without error popups, even if your store only has one location.
-
Bug Fix
StoreNumber missing from database queries in single-store mode
The SKU detail screen now correctly identifies which store each item belongs to, even when the store column is hidden from the main pricing grid.
-
Bug Fix
StoreNumber field now loaded even when hidden from grid
Pricing changes and exceptions now save correctly even if your store doesn't display the Store Number column.
-
Bug Fix
MAP and IMAP price levels now preserved in custom groups
If you created a custom group using Ace MAP Price or Ace IMAP Price, it will now remember your selection when you reopen the group instead of resetting to "Not Set."
-
Bug Fix
Eliminated splash screen race condition in click-to-set Future Price
The loading splash will no longer appear when clicking price columns to set Future Price, making the feature feel more responsive and eliminating the freeze that occurred on the second click.
-
Bug Fix
Eliminated splash screen lockup on rapid click-to-set future price
You can now click on different SKUs quickly to set future prices without the app locking up. The splash screen no longer appears for this fast operation.
-
Bug Fix
Remove orphaned store data on CounterWorks import
If your store previously had multiple locations or migrated from another system, old pricing data from those setups will no longer interfere with your current prices. The Main Table pricing grid will now show accurate prices based only on your active store data.
-
Bug Fix
Strategy restore no longer overwrites database connections
If you restore an old strategy backup, your database connection will remain intact and you can continue working immediately. Previously, this could break your connection and show confusing error messages.
-
Bug Fix
Strategy restore no longer overwrites database connections
If you restore an old strategy backup, your database connection will remain intact and you won't see "Store Configuration Required" errors or need Brad to recreate your database.
-
Bug Fix
ListPrice now populated in per-store imports for MySQL Compass
List prices from your MySQL Compass POS system will now appear correctly in the pricing grid for all stores, even when store grouping is turned off.
-
Bug Fix
List Price now imports from MySQL Compass
When importing POS data from MySQL Compass, list prices will now correctly appear in your pricing grid. Previously, these prices were being skipped during the import process.
-
Bug Fix
Restored pricing strategies now visible in UI
Pricing strategies from backup files now appear in the Pricing Strategy screen immediately after restore, instead of being invisible even though they were restored.
-
Bug Fix
Rounding scheme name lookups now case-insensitive
If your rounding schemes were saved with different capitalization than how they appear in pricing strategies, those strategies will now work correctly instead of failing.
-
Bug Fix
FuturePrice changes in SKU Detail dialog now persist
When you open a SKU's detail window and change the future price for any store, that change will now be saved when you click "Save & Close" instead of being lost.
-
Bug Fix
Future Price edits now persist correctly
Previously, when you changed a Future Price for an item and clicked Save, your change would be lost. This now works correctly and your Future Price edits will be saved.
-
Bug Fix
Case-insensitive rounding scheme lookup
All rounding scheme name comparisons now use case-insensitive matching (StringComparison.OrdinalIgnoreCase). Previously, if a pricing strategy referenced a rounding scheme with different capitalization than how it was stored (e.g., "standard" vs "Standard"), the application would fail to find the scheme and display errors or apply incorrect pricing rules.
-
Bug Fix
Strategy restore now preserves all pricing rules
When you restore pricing strategies from a backup, all the strategy rules are now properly restored and the strategies work correctly.
-
Bug Fix
ListPrice option now available for all Epicor POS users
If your store uses Epicor POS, you'll now see the ListPrice option when setting future prices, regardless of whether you're affiliated with Ace Hardware, Do-It-Best, or another vendor.
-
Bug Fix
List Price option missing from Future Pricing strategy processing
Previously, if you selected "List Price" in Future Pricing settings and clicked Apply, nothing would happen. Now it works correctly and your strategies will save and reload properly.
-
Bug Fix
List Price target level now works in Future Pricing
When creating a Future Pricing rule and selecting "List Price" as your target price level, the rule will now calculate and apply prices correctly based on the List Price field from your vendor catalog.
-
Bug Fix
Future Price panel now applies List Price selection
When you select "List Price" as the target pricing level in the Future Price panel and click Apply, your selected items will now update correctly instead of being skipped.
-
Bug Fix
ListPrice option now works in Future Price Panel
When setting future prices, the ListPrice option now works correctly as a source for your pricing calculations.
-
Bug Fix
Rounding schemes now included in V3 backups
Your custom rounding schemes (like round to nearest nickel or dime) are now included when creating strategy backups.
-
Bug Fix
Strategy backup restore now preserves rounding schemes
When you restore a strategy backup with the "Rounding Schemes" option checked, your custom rounding rules will now be restored correctly. Previously, these settings were being lost during the restore process.
-
Bug Fix
List Price option now saves correctly in custom groups
When you edit a custom group and choose "List Price" as the future pricing method, that choice now appears correctly when you reopen the group for editing.
-
Bug Fix
List Price selection now saves in custom groups
When you select "List Price" as your pricing level in a custom group, it will now save properly instead of reverting to a default value.
-
Bug Fix
Dialog now defaults to waiting for user input
Error dialogs will now wait for you to make a decision instead of automatically closing after a countdown.
-
Bug Fix
Dialog now defaults to waiting for user decision
The error dialog will now stay open until you click Accept, giving you time to read the error and choose how to proceed.
-
Bug Fix
Countdown timer removed from Abort action
If you select "Abort" when a strategy load error appears, you must now click the Accept button to proceed — the dialog will not automatically close and abort your import.
-
Bug Fix
Abort action no longer auto-executes with countdown
If you previously saved "Abort" as your preference for handling data load errors, the dialog will no longer automatically close and abort — you'll need to click the Accept button to confirm the abort action.
-
Bug Fix
Fixed layout clipping in strategy error dialog
Radio button options in the strategy error dialog are no longer cut off and display their full text.
-
Bug Fix
Strategy log column order corrected
When viewing strategy execution logs, the "Skus" and "Changes" columns now appear in the correct order.
-
Bug Fix
Fixed zone pricing sync timeouts on large store groups
Corrected a programming error where database timeout values were not being passed correctly to SQL update commands. Commands that update Level1/Level2 pricing from Ace zone records, apply zone-specific retail pricing, recalculate price variances, and set vendor ownership flags were defaulting to a 30-second timeout instead of the intended 300-600 seconds. On large store groups (300,000+ rows), this caused these updates to fail silently, leaving pricing fields blank or set to zero after sync completed.
-
Bug Fix
Rounding scheme dropdown now refreshes after database restore
When you restore a backup, the rounding scheme dropdown in the pricing panel will now show all your saved rounding schemes correctly instead of appearing blank.
-
Bug Fix
Rounding scheme dropdown not refreshing after strategy restore
When you restore a saved pricing strategy or switch to a different store database, the rounding scheme dropdown will now show all available schemes instead of appearing blank.
-
Bug Fix
Rounding scheme dropdown empty after backup restore
If you restore a backup containing custom rounding schemes, those schemes will now appear in the future price panel dropdown and work correctly. Previously, they would be missing even though the restore completed successfully.
-
Bug Fix
Rounding scheme headers now created during backup restore
If you restore a backup that contains custom rounding schemes, those schemes will now appear correctly in Margin Master and be available for use in pricing strategies.
-
Bug Fix
Extended timeout for cost field synchronization
Fixed an issue where cost updates would fail for stores with large inventories.
-
Bug Fix
Zone pricing timeout errors on large databases
If you have a large Ace Hardware catalog, zone pricing updates will no longer fail partway through, ensuring all your pricing levels update correctly.
-
Bug Fix
Restored Ctrl+F keyboard search in custom groups manager
When managing custom groups, you can now press Ctrl+F on your keyboard to open a search box and quickly find groups by typing part of their name. Press Escape to close the search box.
-
Bug Fix
Custom groups now display in correct order
When viewing your custom groups, they now appear in the correct numerical order instead of randomly shuffled.
-
Bug Fix
Rounding scheme backup and restore now functional
When you back up your settings, rounding schemes are now included. When you restore from a backup, rounding schemes will be properly restored. Previously, rounding scheme settings were silently dropped.
-
Bug Fix
Rounding scheme backup restored to correct format
Removed incorrect code that attempted to backup rounding schemes as separate database entities. Rounding schemes are stored in the GlobalFileConfig table with Section='ROUNDING' and are now properly included in backups through that mechanism. The backup process was excluding ROUNDING entries from GlobalFileConfig while also failing to properly backup the entity format, causing rounding schemes to be lost during backup/restore operations.
-
Bug Fix
Do-It-Best import table creation now runs on every startup
If you restored Margin Master from a backup, Do-It-Best catalog imports would fail. This is now fixed—imports will work correctly after database restores.
-
Bug Fix
DIBMailBox_ItemPricing table creation now runs unconditionally
Importing Do-it-Best pricing data will now work correctly even if you've recently restored your database from a backup.
-
Bug Fix
Corrected detection of legacy SKU Level Exceptions steps
SKU-level price overrides in strategies imported from older systems will now apply correctly instead of causing errors.
-
Bug Fix
Strategy execution no longer fails on legacy SKU exception steps
If you imported pricing strategies from an older system and saw errors about "Not Future Price Setting to Load," those strategies will now run without errors. SKU-level exceptions will continue to work as expected.
-
Bug Fix
Legacy SKU Level Exceptions step detection improved
Pricing strategies with custom-named exception steps (often imported from older systems) will now run without errors. These exception steps are already processed separately, so the system now correctly skips them during the main strategy run.
-
Bug Fix
Per-formula progress updates for SKU exception batches
When Margin Master is applying SKU-level exceptions, the progress window now shows which formula is being processed (e.g., "SKU Exceptions: formula 2 of 7") and updates continuously, so you can see that the application is still working rather than appearing frozen.
-
Bug Fix
Future Price column arrow key navigation restored
You can now use arrow keys to move between rows when in the Future Price column, just like in other columns. Previously, arrow keys would change the price value instead of moving to the next item.
-
Bug Fix
Future Price inline editing navigation restored
You can now use arrow keys to move between cells while editing Future Prices directly in the pricing grid.
-
Bug Fix
Rounding scheme deletion crash resolved
Deleting or clearing a rounding scheme in the Rounding Editor now works smoothly without generating errors.
-
Bug Fix
Null reference protection in Rounding Editor
The Rounding Editor will no longer crash in certain edge cases when opening or switching between rounding schemes.
-
Bug Fix
Corrected store number filtering in Ace zone pricing sync
Ace Hardware zone pricing data will now sync correctly without database errors. Previously, sync may have failed when downloading zone pricing for specific stores.
-
Bug Fix
Single-click editing now works for Future Price cells
When Future Price editing is enabled, you can now click once on a Future Price cell to start editing instead of having to click twice.
-
Bug Fix
Future Price inline editing now activates on single click
When Future Price inline editing is turned on in settings, you can now click once on a Future Price cell to edit it immediately, just like other spreadsheet applications.
-
Bug Fix
Single-click Future Price editing with custom templates
When single-click Future Price editing is enabled in settings, clicking on Future Price cells now reliably opens the editor, even when the cells have special display formatting.
-
Bug Fix
Single-click Future Price editing now works with custom cell template
When you click once on a Future Price cell to edit it, the editor now opens immediately every time, instead of requiring a second click.
-
Bug Fix
Future Price inline editor now visible when editing enabled
When you enable Future Price editing in Settings and click to edit a Future Price in the Main Table, you can now see the editor box and the value you're typing. Previously, the editor was hidden behind the display template.
-
Bug Fix
Future Price editor now visible when editing is enabled
You can now see the Future Price values you're typing when editing prices directly in the grid. Previously, the editor was hidden behind other display elements.
-
Bug Fix
Base prices now update during incremental Ace sync
Previously, if Ace or Emery Jensen changed their catalog prices between full rebuilds, your base pricing columns wouldn't reflect the updates until you performed a complete data refresh. Now those prices stay current with every sync.
-
Bug Fix
Base retail pricing now updates from Ace zone 99999
If your store uses Ace zone 99999, base retail prices will now update correctly when you sync, ensuring your pricing analysis uses the most current data.
-
Bug Fix
SQL backup crash with apostrophes in store name
Database backups will no longer fail for stores with apostrophes in their name.
- Bug Fix Missing database tables for PricingStrategy feature in existing installations
-
Bug Fix
Backup dialog no longer crashes with missing pricing strategy tables
The backup and restore dialogs will now open without errors, even if your database was restored from an older backup or experienced update issues in the past.
-
Bug Fix
Backup failure when pricing strategy tables are missing
Backups will now complete successfully even if your database doesn't have the pricing strategy feature tables, which could happen with older store databases.
-
Bug Fix
SKU exceptions with LEVEL and ZONE action types now apply correctly
If you previously created SKU exceptions that targeted Level 1-5 pricing or zone pricing columns, those exceptions will now work as expected when you run pricing strategies. Previously these exceptions appeared to load but had no effect on your prices.
- Bug Fix Batch SKU exceptions now apply plus/minus adjustments
-
Bug Fix
Plus/minus adjustments now apply in batch SKU exception mode
If you set a SKU exception to use a margin or retail level plus an additional dollar amount or percentage (e.g., "Margin 30% + $2.00"), that adjustment will now be applied correctly when running the pricing strategy.
-
Bug Fix
Excel import now works when file is open
You can now import Excel spreadsheets without closing them first. Previously, if the file was still open in Excel, the import would fail silently and skip those products.
-
Bug Fix
Strategy execution crash with malformed SKU exceptions
Pricing strategies will no longer fail when encountering SKU exceptions with duplicate rule settings. The system now uses the first value and continues processing.
-
Bug Fix
Prevent exception when parsing malformed pricing rule parameters
Pricing rules with duplicate action settings will no longer cause the application to crash when applied to products.
-
Bug Fix
Fixed OrderMultiple field to support decimal values
Changed the OrderMultiple field from integer to decimal type to accommodate stores that use decimal order multiple values instead of whole numbers. This resolves data import errors and crashes when loading product data from POS systems that store fractional order multiples.
-
Bug Fix
Ace catalog lookup crashes resolved
Ace Hardware catalog lookups will no longer crash when viewing product details.
-
Bug Fix
SKU exceptions for "Remain Current Price" now apply correctly
When you set a SKU exception to "Remain Current Price," the pricing strategy will now correctly keep that item at its current price instead of calculating a new one.
-
Bug Fix
SKU exceptions with CURRENTPRICE action now apply correctly
If you set a SKU exception to "Keep Current Price," the pricing strategy will now correctly preserve the current price instead of calculating a new one.
-
Bug Fix
Pricing strategy backup now reads from live data tables
If you created new pricing strategies or edited existing ones after the initial software setup, those changes were not being saved in your backup files. This is now fixed — all strategies and any changes you make will be included in backups.
-
Bug Fix
Strategy backup now captures current data instead of stale migration records
Pricing strategy backups will now include all your current strategy changes. Previously, if you edited a strategy after initial setup, those edits weren't being saved in backups.
-
Bug Fix
REMOVECHANGE exception now correctly preserves current price
When you apply a REMOVECHANGE exception in a pricing strategy, the item's future price will now stay at its current price instead of being set to zero. This prevents accidentally marking items for a price change to $0.00.
-
Bug Fix
REMOVECHANGE strategy now preserves current price
When a pricing strategy uses the REMOVECHANGE action, items will now keep their current price instead of being incorrectly changed to $0.00.
-
Bug Fix
Fixed crash when importing Epicor store information with missing dates
Epicor store imports will no longer crash when date information is missing from the database.
-
Bug Fix
Fixed DateTime overflow error during Epicor MySQL store import
Fixed an error that could prevent the Epicor MySQL import from completing successfully.
-
Bug Fix
Pricing strategy step deletion now persists correctly
If you delete the last step in a pricing strategy, it will now stay deleted when you close and reopen Margin Master. Previously, the last step would come back after restarting the application.
-
Bug Fix
Strategy deletion not triggering save state
When you delete a step from your pricing strategy, the Save button will now activate correctly so you don't lose your work.
-
Bug Fix
Strategy step deletion now persists correctly
When you delete a step from a pricing strategy, that change now saves to the database correctly. Previously, deleted steps would come back the next time you opened the strategy.
-
Bug Fix
Strategy step deletion now persists correctly
When you delete a step from a pricing strategy and save, the change will now be properly saved to the database and remain deleted when you reopen the strategy.
-
Bug Fix
ADDPOIN/SUBPOIN operations now processed correctly in batch mode
When applying pricing exceptions that shift rounding levels (like SUBPOIN3 to drop 3 bracket levels or ADDPOIN2 to raise 2 levels), the batch processor now correctly adjusts prices instead of skipping them.
-
Bug Fix
ADDPOIN/SUBPOIN rounding point shifts now work in batch mode
When you create a SKU exception that adds or subtracts rounding points (like "shift up 3 points" or "shift down 6 points"), those point adjustments will now be applied correctly to your pricing. Previously, these were being ignored and all items were treated the same way.
-
Bug Fix
Fixed store selection error for Epicor SKU exceptions
When adding or editing special pricing for individual SKUs, Epicor users will no longer see an error message saying no stores are selected. The system now correctly identifies your store locations.
-
Bug Fix
Empty strategy backup notification
When you restore a backup file with no pricing rules, you'll see a warning icon and a message telling you "No pricing strategy rules were found in this backup file. Your existing strategy rules were not modified." This makes it clear your current pricing rules haven't been changed.
-
Bug Fix
Added notification for empty pricing strategies during backup restore
If you restore a backup file that doesn't have any pricing strategy rules saved in it, you'll now see a warning icon and a message explaining that your current pricing strategies weren't changed. This helps you understand exactly what was restored from the backup.
-
Bug Fix
CPFPDif filter now handles price increases and decreases symmetrically
When creating strategy rules that filter by dollar price change (CPFPDif), conditions like "less than $1" or "greater than $5" now correctly include both price increases and decreases that meet the criteria. Previously, these rules were incorrectly excluding all price decreases.
-
Bug Fix
Backup now includes all pricing strategies from migrated databases
If your store was migrated from an older system, your pricing strategies will now be properly included when creating backups, preventing potential data loss during restore operations.
-
Bug Fix
Backup dialog now displays pricing strategies correctly
When you open the backup options dialog, you'll now see your pricing strategies listed with accurate information about steps, custom groups, and SKU exceptions, rather than seeing "N/A" or missing data.
-
Bug Fix
SqlDateTime overflow on strategy restore
Backup files containing pricing strategies with missing creation dates can now be restored successfully without errors.
-
Bug Fix
Eliminated row explosion during BisTrack mainTable import
BisTrack pricing imports that previously processed tens of thousands of extra rows now only process the actual number of products, significantly reducing import time.
-
Bug Fix
Strategy backup vendor identification restored
If your store works with multiple vendors under the same store number, strategy backups to the cloud will now save to the correct vendor account without errors.
-
Bug Fix
Strategy backup now includes vendor type
Strategy backups sent to the cloud were missing the VendorType field in the request payload. This field has been restored to ensure backups are properly categorized by vendor (Ace Hardware, Do-It-Best, Emery Jensen, Orgill, or United Hardware) on the server. Both manual and automatic strategy backups now correctly include this information.
-
Bug Fix
Strategy backup now uses correct vendor identification
The cloud strategy backup system was incorrectly using vendor short names (like "ACE" or "DIB") instead of the numeric vendor ID when saving and retrieving pricing strategy backups. All backup operations now properly use the vendor ID, ensuring backups are correctly associated with the right vendor and can be reliably retrieved later.
-
Bug Fix
Zero-price items now skip rounding calculations
Items showing $0.00 in their pricing level (usually items that exist in your POS but not in the vendor catalog) will now keep their existing Future Price during rounding instead of being reset to $0.00.
-
Bug Fix
Skip rounding for zero-price items
Items with zero prices will now correctly skip the rounding process, ensuring only valid prices are rounded according to your rounding scheme settings.
-
Bug Fix
Increment rounding now respects strategy step filters
When using pricing strategies with dollar increment rounding (like YETI 2020 with $3 increments), prices set by earlier strategy steps will no longer be accidentally changed.
-
Bug Fix
Strategy backup download timeout increased
If you previously saw errors when trying to download strategy backups, especially larger ones, those downloads should now complete successfully.
-
Bug Fix
Delayed busy spinner during cost break save
The loading spinner now only appears during the actual save, not while you're entering or confirming the cost break name.
-
Bug Fix
Increment rounding offset now persists correctly
If you use increment rounding with a custom offset, that offset value will now be remembered after closing and reopening Margin Master.
-
Bug Fix
Increment rounding offset now saves correctly
When you set up increment rounding with an offset (e.g., round to nearest 99¢), that offset will now save correctly and reload when you reopen Margin Master.
-
Bug Fix
Increment rounding offset now applies consistently
When your pricing scheme uses increment rounding with offsets (like making prices end in .99), those offsets will now be applied correctly even if the price started at a whole dollar amount.
-
Bug Fix
Strategy backup timestamps now display in local time
When viewing available strategy backups to restore, the dates and times now show correctly for your time zone instead of being off by several hours.
-
Bug Fix
Strategy backup dates now display in local time
When restoring a pricing strategy from a backup, the dates now show in your local time instead of UTC, making it easier to find the right backup.
-
Bug Fix
Fixed duplicate SKU entries in Custom Groups
SKUs in Custom Groups now appear only once with the correct description, instead of showing duplicate entries.
-
Bug Fix
Eliminated duplicate SKU entries in Custom Groups
Each product now appears only once in Custom Groups instead of showing up multiple times.
-
Bug Fix
Cost break summary now respects fixed price vs. margin mode
When reviewing pricing strategy details, cost breaks now show the correct pricing values—either a dollar amount or a percentage—matching how each level is actually configured.
-
Bug Fix
Cost break summary now respects fixed price setting
When you set up cost breaks with fixed retail prices, the pricing summary will now show those dollar amounts instead of incorrectly showing margin percentages.
-
Bug Fix
Rounding scheme sentinel values no longer applied as future prices
If you have items over $200 using rounding schemes designed for lower-priced items, they will now show realistic future prices instead of jumping to $99,999.98.
-
Bug Fix
Guard against rounding scheme UpperLimit sentinel in strategy execution
If you use a pricing strategy with a custom rounding scheme that doesn't cover all price ranges, high-priced items will now show the correct calculated price instead of an overflow value like 99999.98.
-
Bug Fix
Cost break dropdown now refreshes when loading strategy steps
If you create a new cost break and then edit a saved pricing strategy that uses it, the cost break will now load correctly instead of appearing empty.
-
Bug Fix
Custom group dialog now resolves alternate SKU formats
Previously, typing your store's SKU number into the custom group dialog wouldn't find the item unless you used the exact vendor SKU. Now you can use either your store number or the vendor number, and the system will find the right item.
-
Bug Fix
Cost break cache now refreshes when loading strategy steps
If you create a new cost break and then try to use it in a pricing strategy step, it will now work immediately instead of showing an error message.
-
Bug Fix
Custom group item lookup now supports alternate SKU formats
When adding items to a custom group, you can now type either the regular SKU or the MI9 store number — both will work and find the correct item.
-
Bug Fix
Remove stale custom group entries when adding resolved SKUs
If you previously added an Ace store number to a custom group before that item was in your system, you can now re-add it after importing that product without creating duplicate entries. The old "Not in Database" entry will be automatically removed.
-
Bug Fix
Stale alternate SKU entries cleaned up automatically
If you add a SKU to a Custom Group before the catalog is loaded, then add it again later, you'll no longer see two entries for the same item.
-
Bug Fix
License validation state now excluded from strategy backup restore
If you restore a strategy backup that was created on a different computer, your license will continue to work correctly without triggering security errors.
-
Bug Fix
License validation state excluded from strategy backups
License validation state is now excluded from strategy backup restoration to prevent licensing conflicts when importing strategy files across different Margin Master installations. This ensures that each installation maintains its own license validation status independent of imported pricing strategies.
-
Bug Fix
Strategy execution no longer skips steps with partially missing data
If a pricing strategy references Department 30, 46, and 78, but Department 78 doesn't exist in your current data, the strategy will now apply to Departments 30 and 46 instead of skipping the step completely. A warning message shows which categories exist and which are missing before you continue.
-
Bug Fix
Strategy execution now handles legacy Custom Groups step naming
If you previously imported a pricing strategy from an older system and saw errors when running it, those strategies will now execute successfully. The Custom Groups pricing rules will apply correctly.
-
Bug Fix
Migrate legacy Custom Groups step naming on strategy load
If you imported a pricing strategy from an older system, Custom Groups steps will now be automatically corrected and work as expected without manual intervention.
-
Bug Fix
Cloud backup failure notification added
Previously, when the cloud strategy backup failed, the error was only written to the log file with no visible notification to the user. This meant users had no way to know their backup didn't reach the cloud. Now a warning dialog appears showing the specific error message and instructing users to check their internet connection or contact support if the problem persists. The strategy is still saved locally as a fallback.
-
Bug Fix
Cloud backup failure feedback
If your cloud backup doesn't work, you'll see a message explaining the problem and what to do next. Your work is still saved on your computer.
-
Bug Fix
Strategy step names with apostrophes no longer cause database errors
You can now name your pricing strategy steps with apostrophes (like "Update DIB SKU's" or "Frank's Pricing Rule") without encountering errors when applying prices.
-
Bug Fix
SQL syntax error in pricing strategy step names
You can now create and apply pricing strategy steps with apostrophes in their names without encountering database errors.
-
Bug Fix
Corrected strategy rule tracking for MI9 member pricing
For MI9 stores, items using member pricing now correctly show their actual pricing source instead of incorrectly displaying a strategy rule name.
-
Bug Fix
Invisible characters now display in grid cells
If your POS system data contains special invisible characters (like soft hyphens), they will now show up as numbers in the grid instead of appearing blank, so you know the cell has data in it.
-
Bug Fix
Block strategy execution when all filter values are missing
If a pricing strategy step tries to filter by categories or groups that don't exist in your current data, the system will now skip that step and show you a warning instead of accidentally applying prices to the wrong items.
-
Bug Fix
Block strategy step when all filter values are missing
When running a pricing strategy, if a step tries to filter by categories that don't exist in your current data (for example, departments that have been removed), the step will now be safely skipped instead of accidentally applying to items it shouldn't. You'll see a warning explaining that the step was skipped and should be re-run after importing updated data.
-
Bug Fix
MI9 pricing rule labels now update correctly after strategy reruns
If items were showing the wrong pricing rule name after a previous strategy update, re-running the pricing strategy will now correctly update the rule name shown in the pricing grid.
-
Bug Fix
Corrected pricing rule tracking for MI9 systems
The "governing rule" column in the pricing grid now shows the correct, most recent pricing strategy that was applied to each item, instead of sometimes showing an old or incorrect rule name.
-
Bug Fix
Backup process memory optimization
Creating backups will now work reliably even for stores with very large numbers of pricing strategies, and won't cause the application to run out of memory and crash.
-
Bug Fix
Catalog data import now updates product information correctly
Product information from Ace Hardware — including departments, pricing levels, vendor details, and velocity codes — now imports correctly for all Propello stores.
-
Bug Fix
Strategy error abort action now opens editor
When a pricing strategy step has an error and you click "Abort," the strategy editor will now open automatically so you can see and fix what went wrong.
-
Bug Fix
Strategy abort now loads selection for review
When a pricing strategy stops before completing, the affected items now appear in the main pricing grid for you to review, rather than opening the strategy editor right away.
-
Bug Fix
Strategy backup memory usage reduced for large catalogs
Strategy backups for large vendor catalogs will now complete successfully without causing the application to slow down or crash.
-
Bug Fix
Bootstrapper closes Margin Master before installing updates
If Margin Master is running when an update downloads, it will now close automatically before installing the update, so you don't need to remember to close it yourself.
-
Bug Fix
Removed erroneous Do-It-Best price scaling logic
Items from Do-It-Best that previously showed incorrect prices in the pricing grid will now display the correct retail and cost values from the vendor catalog.
-
Bug Fix
Removed incorrect Do-It-Best UOM price scaling
Previously, the system tried to automatically adjust vendor prices when it detected unit-of-measure differences (like per-foot vs. per-roll). This sometimes changed prices incorrectly. Now vendor prices display exactly as they appear in the vendor's catalog.
-
Bug Fix
Prevent crash when strategy execution has no results
Fixed an OverflowException that occurred when attempting to log strategy execution summary after a complete failure (such as when the CHAR() mapping bug causes group table build to fail). The system was attempting to calculate average duration per step by dividing by zero when no steps completed. The summary now displays "N/A" for average duration instead of crashing.
-
Bug Fix
Prevent crash on empty strategy execution results
Fixed a crash that could happen when running certain pricing strategies. The application now handles these cases gracefully.
-
Bug Fix
Default to national pricing zone when store zone data is missing
If your Ace store's department zone assignments haven't loaded yet, pricing will automatically use national pricing (zone 99999) instead of showing an error.
-
Bug Fix
Selection tabs now reload after database restore
Custom pricing fields now work correctly in strategies after restoring a backup.
-
Bug Fix
View switching now properly updates cached view definition
If you switched from one saved view to another and then tried to apply a pricing strategy that uses columns like Vendor, Comp5, Level2, or AverageCost, you would get an error saying the field wasn't available. This now works correctly.
-
Bug Fix
Auto-select existing pricing strategy on new installation
If you install Margin Master on a new computer and restore your database, your existing pricing strategy will now be automatically selected instead of requiring you to manually choose it from settings.
-
Bug Fix
Auto-select existing pricing strategy on new installation
If you restore a database backup or open Margin Master for the first time, the app will now automatically find and use your existing pricing strategies instead of creating a new blank one.
-
Bug Fix
Ace Hardware rounding scheme compatibility
If you're an Ace Hardware store using pricing strategies, rounding steps that were previously being skipped due to load failures will now work correctly.
-
Bug Fix
Ace rounding scheme migration
If your pricing strategies were not loading or applying correctly due to rounding configuration issues, they will now work as expected after this update.
-
Bug Fix
Strategy execution tracking authentication restored
Strategy execution data was not being posted to the cloud due to a missing authentication token in the API call. This has been fixed to properly include the Bearer token when sending execution tracking information.
-
Bug Fix
Strategy execution tracking authentication retry
Fixed an issue where strategy execution tracking could fail to upload when authentication tokens expired. The system now automatically retries with fresh authentication credentials, ensuring tracking data is reliably captured even during long-running operations.
-
Bug Fix
BisTrack import now correctly loads vendor catalog data
Previously, BisTrack imports would complete without error messages but leave the pricing grid empty with no vendor data or dropdown selections available. This is now fixed and all vendor catalog information imports correctly.
-
Bug Fix
Strategy backup upload timeout increased
If you previously saw error messages about strategy backups failing to upload to the cloud, these should now succeed even on slower internet connections.
-
Bug Fix
Extended cloud upload timeout for large strategy backups
If you previously experienced failed backup uploads with timeout errors, especially on slower internet connections, these uploads should now complete successfully with the extended 10-minute timeout window.
-
Bug Fix
Corrected increment rounding for nearest and round-up methods
If you use rounding schemes that round prices to the nearest dollar or other increment, the system will now calculate the correct rounded price every time, without skipping valid price points.
-
Bug Fix
Check button now previews the correct rounding scheme
When editing a rounding scheme, clicking Check now shows you how pricing will look with that specific scheme, not with whichever scheme happens to be active in your store.
-
Bug Fix
Automatic correction of invalid increment rounding rules
If a rounding scheme had an incorrect increment setting that prevented higher-priced items from rounding, it has been automatically fixed so all items in the price range now round properly.
-
Bug Fix
Epicor store mapping setting now preserved across sessions
If you use Epicor and have pricing strategies saved, your store selections will now work correctly after application restarts and updates, instead of mysteriously losing their settings.
-
Bug Fix
Restore SKU-level exception icon rendering
The "*" column now shows icons indicating which items have special pricing rules applied, making it easier to identify locked margins, plug retail prices, and custom group assignments at a glance.
-
Bug Fix
Pre-Rounded column now updates for all MI9 pricing strategies
When you apply pricing rules that don't use rounding on MySQL Compass stores, the Pre-Rounded column now shows the correct calculated price instead of an old value from a previous step.
-
Bug Fix
Pre-Rounded column now updates for non-rounding MI9 pricing rules
When you apply pricing rules that don't use rounding (such as setting prices to a specific level or margin), the Pre-Rounded column will now show the correct current price instead of an old value.
-
Bug Fix
Falcon import now handles blank prices and costs
When importing Falcon data, service items and products with missing prices or costs will now import successfully with zero values instead of causing the entire import to fail.
-
Bug Fix
Duplicate SKU prevention in custom groups
When you add the same item to a custom group twice, the system now handles it gracefully instead of failing silently in the background.
-
Bug Fix
Prevented duplicate key errors in custom group SKU operations
You can now add SKUs to custom groups without getting errors if the SKU is already in the group. The operation will succeed and skip any duplicates automatically.
-
Bug Fix
Rollback rounding no longer orphans .98/.99 prices
Items priced at amounts ending in .98 or .99 will now stay in the correct price group when your store uses round-down pricing rules, instead of unexpectedly jumping up by $10.
-
Bug Fix
Rollback rounding now correctly handles gap cents (.98/.99)
When using rounding schemes with rollback rules, items priced at amounts like $259.99 will now correctly round to $259.97 instead of incorrectly jumping up to $269.97.
-
Bug Fix
Main table now rebuilds after startup vendor sync
If you're prompted to download vendor data when opening Margin Master, the pricing grid will now show the correct current prices immediately after the download completes, instead of displaying old prices until you manually refresh.
-
Bug Fix
Force rounding table regeneration after engine math changes
Items with rollback rounding now price correctly after updates to the pricing engine, fixing cases where prices were still wrong even after the engine was fixed.
-
Bug Fix
Automatic rounding table regeneration after engine fix
When you open Margin Master after this update, all rounding schemes will automatically rebuild their internal tables to fix the band calculation issue, ensuring prices round correctly across all ranges.
-
Bug Fix
SKU exception lock icon now displays after Execute
When you run Execute with SKU-level exceptions, the grid now immediately shows the lock icon in the '*' column for affected products. Previously this icon was missing until you viewed the product's detail screen.
-
Bug Fix
Restored lock icon display for SKU exceptions
The batch SKU exception processing path introduced in May 2026 (MM-1193) carried forward pricing calculations and rule history but inadvertently omitted the [Lock] field update that drives the "*" column icon in the Main Table grid. This meant SKU exceptions processed during Execute Strategy would calculate correctly but show no visual indicator unless the user manually opened and closed SKU Detail for each item. The fix adds proper lock icon mapping (M for margin, R for set price, C for cost break, D for price levels) matching the original per-block behavior, restoring the audit trail that helps stores identify which items have active exceptions.
-
Bug Fix
Blank Fixed Retail price no longer breaks custom pricing groups
If you create a custom pricing group using Fixed Retail and forget to enter a price, the group will now save without errors instead of silently failing to update any items. Note: any existing groups that were saved with blank prices will need to be edited or deleted to work properly.
-
Bug Fix
Blank Fixed Retail price no longer breaks custom group batch updates
If you leave the Fixed Retail price blank when updating a custom group in the pricing panel, the system will now skip that action instead of failing the entire update for all items in the group.
-
Bug Fix
Custom group skip guard now properly detects empty pricing actions
If you configure a custom group with a pricing strategy like Fixed Retail but forget to enter a price, the system will now skip that group with a clear warning message instead of showing repeated error messages during processing.
-
Bug Fix
Fixed custom group skip guard that could never trigger
If you set up a custom group with an incomplete pricing strategy (such as choosing "Fixed Retail" but leaving the price blank), the system will now skip that group silently instead of logging error messages for each batch of items.
-
Bug Fix
Auto-update restart now defers during active operations
If an update is ready while you're running a strategy or exporting prices, you'll see a message explaining that the update will be applied automatically once your current operation finishes. Your work will no longer be interrupted.
-
Bug Fix
Database Maintenance restricted to Margin Master databases
Previously, when Margin Master connected to a shared SQL Express instance as sysadmin, the Database Maintenance dialog would enumerate and potentially operate on every user database on the server, including co-hosted POS system databases. The dialog now uses a fingerprint-based ownership check (matching the same signature tables used during install/upgrade/uninstall) to identify only Margin Master-owned databases. All maintenance operations—including Shrink Log Files, Rebuild Indexes, Update Statistics, Remove Unused Indexes, Remove Duplicate Indexes, Identify Missing Indexes, and Create Missing Indexes—are now restricted to the active Margin Master database.
-
Bug Fix
Database maintenance scope restricted to owned databases
When you run database maintenance on a shared server, the tool now automatically skips databases that belong to other software like your POS system.
-
Bug Fix
SQL errors during strategy execution now display to user
If something goes wrong during strategy execution, you'll now see an error message explaining the problem instead of the app appearing to freeze.
-
Bug Fix
Corrected basic rounding no-decreases comparison
Fixed the Rounding_Basic guard to compare the rounded price against CurrentPrice instead of FuturePrice, and to prevent decreases rather than cap increases. This now matches the correct pattern already used in the Rounding_PlusMinus and Rounding_Increment methods.
-
Bug Fix
Custom pricing group subtract action parsing corrected
Custom pricing groups that subtract an amount from prices will now work correctly when reopened or applied.
-
Bug Fix
Export progress dialog now closes properly for Falcon, Mi9, Westlake, and Propello
The progress dialog now closes automatically after exporting price changes to Falcon, Mi9, Westlake, or Propello systems instead of appearing stuck.
-
Bug Fix
Export progress dialog now closes properly
The "Exporting..." progress window now closes automatically when your export is complete.
-
Bug Fix
Busy indicator now shows when switching strategies from any control
The loading spinner now appears reliably every time you switch between pricing strategies, regardless of where you click.
-
Bug Fix
Price lock status icons restored
The lock column now shows the correct icon for each type of pricing rule applied to a product, making it easier to see at a glance which pricing method is in use.
-
Bug Fix
Restore lock indicator icons
Lock icons now display correctly in the grid showing which items have pricing locked and what type of lock is applied.
-
Bug Fix
Automatic model reload after deletion
After deleting a cost break model, the next model loads automatically so you can continue reviewing or deleting additional models without extra steps.
-
Bug Fix
Added fallback wildcard conversion
Added a defensive fallback that converts asterisk (*) wildcards to SQL percent (%) wildcards even when the "Like:" prefix is missing. This prevents wildcard filters from being treated as literal values if they bypass the normal conversion path.
-
Bug Fix
Prevent infinite rebuild loop during concurrent sync and import
Background sync operations will no longer cause the pricing grid to rebuild multiple times in a row, which previously made the application unresponsive during sync.
-
Bug Fix
Wildcard filters now properly use SQL execution path
Filters using wildcards (like "ABC*" to match all items starting with ABC) now work correctly in pricing strategies.
-
Bug Fix
Corrected backup and restore menu item labels and commands
The database menu now shows the correct labels for backup and restore options, making it clear which action each menu item performs.
-
Bug Fix
Strategy Manager window close error
Strategy Manager window now closes properly after saving changes without showing an error.
-
Bug Fix
Fixed dirty tracking after moving strategy steps
When you reorder strategy steps by moving them up or down, the dialog now correctly shows that changes need to be saved.
-
Bug Fix
Renaming a strategy step now marks the strategy as dirty
When you rename a pricing strategy step, the Save button will now activate and you'll be prompted to save changes if you try to close.
-
Bug Fix
Strategy no longer marked as modified on open
Opening a pricing strategy no longer triggers the "unsaved changes" warning when you close it without making any edits.
-
Bug Fix
Fixed condition display not refreshing after edits
When you edit or remove values from a pricing condition, the changes now appear immediately in the editor without needing to reopen the strategy.
-
Bug Fix
Property change handler ignores events during close
Added early return checks in the `OnPricingStrategyServicePropertyChanged` and `OnStepsChanged` event handlers to prevent processing property changes when the dialog is in the closing state. This prevents race conditions where events triggered by async save/reload operations could re-mark the dialog as dirty during shutdown.
-
Bug Fix
Strategy rows no longer show as unsaved after successful save
After you save changes to a pricing strategy, the rows will no longer appear highlighted as if they still have unsaved changes.
-
Bug Fix
Dirty state properly cleared after successful save
After saving changes to a pricing strategy, the editor will no longer incorrectly warn you about unsaved changes when you try to close the window.
-
Bug Fix
Single-store fallback missing in SKU exceptions dialog
Store selection dropdowns in the SKU exceptions screen now populate correctly for single-store locations instead of appearing empty.
-
Bug Fix
Store selection fallback for SKU exceptions dialog
The store selection dropdown in SKU Exceptions now populates correctly for all account types.
-
Bug Fix
Added re-entrancy protection to click-to-set Future Price handler
Rapid clicking on multiple items will now be handled safely—the second click is ignored until the first completes, preventing the application from becoming unresponsive.
-
Bug Fix
Click-to-set now prevents unintended row selection
Clicking a price column to set future price now only sets the price—it won't accidentally switch to a different product row.
-
Bug Fix
Completed ListPrice import fix for all MySQL Compass configurations
An earlier fix (MM-1169) added ListPrice mapping to the grouped-store import path, but multi-store setups without grouping use a different code path with separate MERGE scripts that were not updated. This change completes the fix by updating both SqlMergeMySqlStoreToStoreMainTable.sql scripts to include ListPrice in the SOURCE SELECT, UPDATE SET, INSERT columns, and VALUES clauses.
-
Bug Fix
Ace Direct list prices now properly updated
List prices will now import correctly whether you're using standard MySQL Compass or Ace Direct configurations.
-
Bug Fix
Strategy step ordering corrected during restore
Pricing strategy steps now appear in the correct order after restoring a backup, instead of appearing scrambled.
-
Bug Fix
Strategy execution no longer terminates on scheme name mismatch
Pricing strategies will run successfully even if rounding scheme names don't match exactly in capitalization.
-
Bug Fix
Strategy step sequence numbering corrected during backup migration
Pricing strategy steps are now restored in the correct order from older backup files.
-
Bug Fix
Legacy V1 backup rounding schemes now migrate correctly
Rounding schemes from older backups now restore correctly when upgrading from previous versions.
-
Bug Fix
Legacy backup compatibility for rounding schemes maintained
Rounding schemes from older backup files are now restored correctly, ensuring settings are preserved when upgrading or restoring from historical backups.
-
Bug Fix
SKU exceptions now preserve List Price selection after save
After saving a SKU exception with "List Price" selected, the form now correctly shows the saved state without incorrectly prompting you to save again.
-
Bug Fix
SKU exception settings reload correctly after save
After saving a SKU-level exception, the pricing settings will now display the correct saved values instead of showing outdated information.
-
Bug Fix
Auto-apply setting no longer bypasses Wait preference
If you've chosen to review errors manually, the dialog will always appear even when auto-apply is enabled.
-
Bug Fix
Auto-apply preference now respects "Wait for User Input" setting
Fixed an issue where the "auto-apply saved preference" setting would bypass the dialog even when the saved preference was set to "Wait for User Input". Now the dialog always appears when this preference is selected, honoring the user's explicit request to review each error.
-
Bug Fix
Resolved dialog sizing conflicts
Fixed conflicting size constraints where the dialog window specified Width=500 but the internal UserControl required MinWidth=580. The dialog now uses Width=560 with SizeToContent=Height and a MinHeight/MaxHeight range of 380-620 pixels, eliminating size conflicts and ensuring consistent display.
-
Bug Fix
Strategy log time format simplified
Strategy execution times are now easier to read, showing whole seconds for quick operations instead of detailed milliseconds.
-
Bug Fix
Rounding scheme list correctly initializes on panel load
Also fixed the initialization sequence during panel startup to ensure the rounding schemes list is properly cleared before being rebuilt, preventing similar issues when the panel first loads.
-
Bug Fix
Rounding scheme restore fixed for all backup versions
Applied the fix to both backup restore code paths: the newer V3 backup format (RestoreBackupDataModelV3Settings) and the legacy V1/blob restore path (RestoreBackupDataModelSettings). Both now seed RoundingScheme headers after restoring GlobalFileConfig ROUNDING entries, ensuring consistent behavior regardless of backup version.
-
Bug Fix
Extended timeout for Ace Hardware MAP pricing updates
Fixed an issue where Ace MAP pricing updates would fail to complete for stores with many products.
-
Bug Fix
Settings Transfer now includes rounding schemes
When transferring settings from another store's database, rounding schemes are now properly copied over.
-
Bug Fix
Rounding scheme restore detection corrected
The restore dialog now correctly shows which rounding schemes are available in a backup file.
-
Bug Fix
SKU Detail changes now refresh Main Table grid immediately
When you make pricing changes in the SKU Detail window, they now appear immediately in the main pricing grid as soon as you close the window. You no longer need to click "Refresh Data" to see your changes.
-
Bug Fix
Main Table grid auto-refresh after SKU Detail edits
When you make pricing changes or set exceptions in the SKU Detail window, those changes now show up immediately in the main pricing grid.
-
Bug Fix
Future Price editing setting now applies immediately after changing Settings
Changes to the Future Price editing option in Settings now take effect right away without needing to restart Margin Master.
-
Bug Fix
Prevented accidental editing of non-Future Price columns
Other pricing columns remain protected and cannot be accidentally edited, even when Future Price editing is enabled.
-
Bug Fix
Improved editor activation logic for Future Price column
Enhanced the ShowingEditor event handler to properly detect the Future Price column even when the Column property is null (which occurs with custom templates). The code now falls back to checking the TableView's FocusedColumn to determine if editing should be allowed.
-
Bug Fix
Crash when saving new SKU-level exceptions
The SKU Exceptions screen will no longer crash when saving changes in certain timing scenarios.
-
Bug Fix
Reduce error logging severity for open issues retrieval
Changed failed open issues retrieval from error-level to warning-level logging to reduce noise in logs when this non-critical operation fails.
-
Bug Fix
Pricing strategy summary queries protected against missing tables
The inventory backup service now ensures pricing strategy tables exist before generating summaries, preventing errors during the backup summary generation process.
-
Bug Fix
Fixed crash when switching pricing strategies
Fixed an error that could occur when quickly switching between pricing strategies on the SKU exceptions screen.
-
Bug Fix
Prevented crashes in One-Click filters with null inventory values
The One-Click screen will no longer crash when filtering by items with inventory or sales history when some products have missing data.
-
Bug Fix
Pricing strategy filters now work with store groups
Pricing strategies that use formula filters will now work correctly when applied to store groups instead of crashing.
-
Bug Fix
SKU exceptions for "Ignore" action now clear price changes
When you set a SKU exception to "Ignore," the strategy will now correctly clear any price change for that item.
-
Bug Fix
SKU exceptions with REMOVECHANGE action now apply correctly
If you set a SKU exception to "Ignore," the pricing strategy will now correctly remove any pending price changes for that item.
-
Bug Fix
Pricing strategy restore now writes back to live data tables
When restoring a backup, your pricing strategies' custom groups and SKU exceptions now properly appear in the application immediately after restore, instead of being invisible until manually recreated.
-
Bug Fix
Fixed crash when exporting custom pricing groups after SKU import
Exporting custom pricing groups to Excel will no longer crash after you've imported SKUs into those groups.
-
Bug Fix
Fixed mixed-type data error in custom pricing groups Excel export
Fixed an error that could occur when exporting custom pricing group strategies to Excel reports.
-
Bug Fix
Corrected grouping logic for different POIN shift amounts
Different rounding shift amounts are now kept separate during processing, ensuring each SKU exception gets the correct shift value applied.
-
Bug Fix
Code quality improvements to prevent null reference issues
Enabled nullable reference checking and resolved four pre-existing nullable warnings in the selection service to improve code safety and prevent potential runtime errors.
-
Bug Fix
Backup now falls back to database when strategy steps are missing from configuration
Pricing strategies with missing configuration data will now be backed up completely with all their pricing rules intact.
-
Bug Fix
Corrected regression introduced by MM-1094 fix
The March 2026 MM-1094 fix corrected the "no decreases" guard to compare against Current Price instead of Future Price. This exposed a latent bug where zero-price items were being incorrectly processed by rounding schemes. Items previously accidentally preserved by the old comparison logic are now explicitly and correctly skipped using the zero-price guard.
-
Bug Fix
Increment-only rounding schemes now calculate prices correctly
Pricing strategies that use only dollar increments (without specific price points) will now calculate prices correctly instead of showing $0.00.
-
Bug Fix
Fixed database cleanup query column reference
Corrected a SQL query in DatabaseUpdateService that attempted to delete obsolete "HasMultipleRSCs" setting using wrong column name [Key] instead of [Setting]. This cleanup operation was failing silently during database updates. The query now references the correct column and executes successfully.
-
Bug Fix
Fixed persistent "Not in Database" errors
SKUs that were stuck showing "Not in Database" errors will now be automatically corrected the next time you open the Custom Group.
-
Bug Fix
Corrected "Not in Database" status for valid SKUs
Products that exist in your system are no longer incorrectly shown with "Not in Database" errors in Custom Groups.
-
Bug Fix
SKU exception pricing also protected from sentinel values
Individual SKU exceptions will also show correct prices for high-value items instead of unrealistic sentinel amounts.
-
Bug Fix
Rounding scheme overflow protection in SKU exceptions and column rules
SKU exceptions and column-based pricing rules now handle prices outside the rounding scheme's range correctly, preventing unexpected overflow values in the pricing grid.
-
Bug Fix
Runtime safeguard for unrecognized Custom Groups steps
If a strategy contains a legacy Custom Groups step that wasn't migrated yet, it will be safely skipped during execution to prevent errors, and the system log will recommend reloading the strategy to fix it permanently.
-
Bug Fix
Strategy history tracking with special characters
The PSRuleHistory field, which tracks which pricing rules have been applied to each item, now correctly records step names containing apostrophes. This ensures accurate audit trails for pricing changes even when step names include special characters.
-
Bug Fix
Prevented null prices when using competitor pricing levels
Pricing strategies using competitor prices (Comp1-Comp5) now treat empty competitor prices as zero instead of producing blank future prices.
-
Bug Fix
Correct property name in logging statement
Fixed reference to ImportProcessing.ID property in logging (was incorrectly referencing .Id).
-
Bug Fix
Zone-specific pricing now applies store-level overrides
Stores with zone-specific pricing from Ace Hardware now receive their correct retail prices based on their assigned pricing zone.
-
Bug Fix
Strategy error ignore action simplified
When a pricing strategy step has an error and you click "Ignore," the step will be skipped completely and the strategy will continue with the next step.
-
Bug Fix
Ace Hardware zone pricing import SQL error resolved
Ace Hardware zone pricing will now import correctly without database errors.
-
Bug Fix
Prevent overflow error in strategy execution timing
Added bounds checking to the average-duration-per-step calculation in strategy execution logs. The value is now clamped before creating a TimeSpan to prevent OverflowException in edge cases where timing values could exceed maximum limits.
-
Bug Fix
Guard against duration calculation overflow in strategy execution logs
Fixed a rare crash in the Strategy Execution Logger when calculating average step duration. The system now validates that the calculated average is a finite number and clamps it to valid TimeSpan limits before formatting, preventing overflow exceptions in edge cases with unusual timing data.
-
Bug Fix
Restore zone pricing marker icon
The "Z" column now correctly shows which items have different prices for different store zones.
-
Bug Fix
Custom group restore reliability
Restoring custom groups from backup files now works correctly even if the backup contains duplicate items.
-
Bug Fix
Improved custom group restoration from backup
Restoring custom groups from backup files now works even if the backup contains duplicate SKU entries.
-
Bug Fix
Rounding editor now displays rollback settings when reopening saved schemes
When editing a saved rounding scheme that uses rollback rules, the rollback options now display correctly in the editor.
-
Bug Fix
Resolved incorrect cost and retail display for DIB customers
Items in the main pricing grid now display the correct current vendor costs and retail prices after a catalog sync, instead of showing prices from a previous version.
-
Bug Fix
Corrected Shrink Log Files scope parameter
The Shrink Log Files maintenance script was inadvertently receiving the server name instead of the database name, which caused it to run unscoped across all databases. The script now correctly receives the active database name and respects the ownership filter, ensuring it only shrinks log files for the connected Margin Master database.
-
Bug Fix
Increased timeout for filter list database operations
Added a 120-second command timeout to the UPDATE operation that resets negative or null future prices when applying filter lists. This prevents the operation from failing prematurely on large datasets or slower database connections.
-
Bug Fix
Fixed post-rounding decrease removal WHERE clause
Changed the decrease removal SQL from "WHERE FuturePrice > CurrentPrice" (which removes increases) to "WHERE FuturePrice < CurrentPrice AND FuturePrice > 0" (which correctly removes decreases). This cleanup step now properly enforces the no-decreases rule after all rounding has been applied.
-
Bug Fix
Misleading MySQL import log message corrected
Corrected a log message that appeared at the start of MySQL Compass POS imports. The message previously contained confusing text about stores not processing, when it should have simply indicated the import was beginning.
-
Bug Fix
Help button repositioned on Pricing Strategy screen
The help button on the Pricing Strategy screen is now positioned correctly next to the Export to Excel button.
-
Bug Fix
Settings update no longer blocks progress reporting
Changed the ApplicationSettings database write operation from asynchronous fire-and-forget to synchronous execution. Since the atomic MERGE completes in approximately 10ms, this preserves the UI thread context needed for progress updates while avoiding thread-switching issues that previously prevented progress from rendering.
-
Bug Fix
PLACEHOLDER keys excluded from strategy step loading
Strategy execution now excludes entries with the key 'PLACEHOLDER' when loading strategy steps from the database, preventing empty or invalid steps from being processed during strategy execution.
-
Bug Fix
Automatic migration of pricing rules from old field to new field
All existing pricing rules that used Auxiliary Retail continue to work automatically without needing to recreate them.
-
Bug Fix
Automatic migration of existing pricing strategies
Your existing pricing strategies that used Aux Retail will continue working automatically—no changes needed on your part.
-
Bug Fix
Safer cost break level range validation
Replaced unsafe index-based access in the cost break level property change handler with bounds-checked array access. This prevents crashes when background threads attempt to validate level ranges while the collection is being modified on the UI thread.
-
Bug Fix
Allowed asterisk character in SQL validation
Updated the SQL safety validation regex to permit the asterisk (*) character in WHERE clause expressions, preventing false-positive validation errors when wildcard patterns are used in strategy filters.
-
Bug Fix
Managed indexes with missing columns now auto-disable gracefully
Enhanced the managed index creation process to automatically disable indexes that reference columns no longer present in the database (such as Formula2/Formula3 after table rebuilds). Previously, these orphaned index definitions would cause recurring errors during diagnostics or optimization tasks. The system now detects SQL errors 207 and 1911 (invalid/missing column) and disables the affected index definitions automatically.
-
Bug Fix
Removed non-functional restore option
Removed the "Sort Options" checkbox from the restore dialog as it had no backing property and was never functional.
-
Bug Fix
Manage Pricing Strategy save operation freeze
Saving changes to a pricing strategy now completes instantly instead of freezing the window for several minutes.
-
Bug Fix
Improved save and close sequence
Refined the save-and-close process to properly synchronize step order changes and close the window only after saving completes, preventing potential data loss or incomplete saves when closing with pending changes.
-
Bug Fix
Fixed discard changes behavior in strategy editor
Clicking "No" when closing a pricing strategy now properly discards all your changes and shows the last saved version.
-
Bug Fix
Fixed visual styling for inactive steps with unsaved changes
Inactive pricing steps now display more clearly with gray text and background, while steps with unsaved changes show with yellow highlighting.
-
Bug Fix
Null-safe string comparisons in SKU detail save
Replaced instance .Equals() calls with static string.Equals() for SKU and StoreNumber property comparisons throughout the SKU detail save path. This prevents null reference exceptions when comparing potentially null values during record matching and filtering operations.
-
Bug Fix
Improved string comparison reliability
Replaced direct string equality checks with string.Equals() throughout SKU detail save operations to prevent potential null reference errors when comparing SKU and StoreNumber values.
-
Bug Fix
Prevented unintended row selection during click-to-set Future Price
Clicking a price column to set Future Price will no longer also select that row, preventing unexpected navigation while the update is in progress.
-
Bug Fix
Hardened click-to-set against SQL errors from special characters
Added apostrophe escaping to the SKU parameter in the UPDATE query to prevent SQL injection errors when processing SKUs that contain single-quote characters.
-
Bug Fix
Rounding schemes now restore from GlobalFileConfig format
Restoring a strategy backup now correctly brings back all your rounding scheme settings.
-
Bug Fix
Fixed dialog appearing behind other windows
Error dialogs will no longer appear hidden behind other windows on your screen.
-
Bug Fix
Error dialog button caption now reflects selected action
When a strategy loading error occurs, the action button now shows the correct label based on your selection (Ignore, Abort, or Accept) instead of always saying "Accept and Continue."
-
Bug Fix
Strategy error dialog button caption corrected
When a strategy encounters a load error, the action button now clearly shows what will happen when you click it ("Ignore and Continue" or "Abort Execution").
-
Bug Fix
Settings transfer now includes rounding schemes
Transferring settings between databases now correctly includes your custom rounding schemes.
-
Bug Fix
False error logs when clearing cost break selection
Eliminated spurious "NOT FOUND" error logs that appeared when clearing a cost break selection in the Future Price panel. Clearing the selection is valid behavior and no longer generates error telemetry.
-
Bug Fix
Added validation for empty margin values in future pricing
Future pricing rules will no longer create invalid margin settings if you leave the margin value blank.
-
Bug Fix
Eight additional SKU exception actions now supported in batch mode
Added missing SQL generation cases for RETAILZONE, FUTUREPRICE, STORECOST, LISTPRICE, ACE_MSURETAIL, ACE_MAPPRICEAMT, and ACE_IMAPPRICEAMT action types. These actions were previously ignored in batch mode but worked correctly in the per-block fallback path, creating inconsistent behavior. Batch mode now has full parity with the per-block execution logic.
-
Bug Fix
Corrected obsolete settings cleanup query
Fixed a SQL query in DatabaseUpdateService that referenced the wrong column name ('Key' instead of 'Setting') when removing the deprecated 'HasMultipleRSCs' setting.
-
Bug Fix
Corrected property name and logging errors
Fixed two build errors: corrected ImportProcessing.Id to .ID (property name typo) and added explicit string casts for dynamic MySQL connection identity fields in logging statements to resolve compiler warnings.
-
Bug Fix
Bulk add-to-custom-group robustness
Adding multiple items to a custom group from the main grid now correctly handles items that are already in the group.
-
Bug Fix
Strategy steps list auto-selects first item after switch
After switching strategies, the first step will now be automatically selected so you can immediately see its details instead of seeing a blank panel.
-
Bug Fix
Better error handling for backup failures
Added error message display when strategy backup fails, showing the specific error to the user and logging details for troubleshooting.
-
Bug Fix
Window close error after saving strategy
Clicking "Save and Close" in the strategy manager no longer shows an error message after saving.
-
Bug Fix
Strategy step name changes now properly trigger save prompt
The system now correctly prompts you to save when you've renamed a pricing strategy step.
-
Bug Fix
Discard Changes now fully resets the pricing strategy
Clicking "Discard Changes" when closing the pricing strategy editor now correctly cancels all your edits and reloads the original strategy.
-
Bug Fix
Eliminated false "unsaved changes" prompts during scheme loading
You'll no longer see incorrect "unsaved changes" warnings when switching between rounding schemes without making edits.
-
Bug Fix
Fixed SQL injection vulnerability in Future Price update
Escaped apostrophes in SKU values before interpolating them into the SQL UPDATE statement. SKUs containing apostrophes would previously cause the query to fail or behave unpredictably.
-
Bug Fix
Click-to-set Future Price respects column editing mode
Fixed MM-1174 by ensuring click-to-set Future Price functionality properly handles the Future Price column regardless of the inline editing setting. The hit-test logic now runs before checking the SetFuturePriceOnClick guard, preventing conflicts between the two modes.
-
Bug Fix
Downgrade failures now detectable
If you downgrade to an older version and it doesn't take, Margin Master now knows and tells you instead of pretending it worked.
-
Bug Fix
Added early return for non-price column clicks
The handler now returns immediately when clicking non-price columns (such as SKU, Department, etc.) rather than processing through the full switch statement and doing nothing. This prevents unnecessary work and potential edge-case errors.
-
Bug Fix
Diagnostic logs cleared on startup to prevent confusion
DiagnosticTool now deletes previous session log files on startup (DiagnosticTool-*.log), ensuring the log directory only contains the current session's logs. This prevents old error messages from being analyzed by the AI when troubleshooting current issues.
-
Cloud Sync
SQL-based strategy backup system
Strategy backups now POST to the Manager API and store JSON in a SQL database (RS_Data table) instead of Azure Blob Storage. The API tracks backup date, version (V1/V2/V3), trigger source, and file size. A migration utility (MarginMaster.BlobMigration) is available to import existing blob backups into the new system.
-
Cloud Sync
Organization-scoped strategy backups
Modified strategy backup API calls to support organization-level scope instead of vendor-specific scope. The system no longer sends vendor type when creating backups, allowing backups to be managed at the organization level across multiple stores.
-
Cloud Sync
Optimized zone pricing update logic
Enhanced the change-detection logic in the zone pricing update script to include base price columns in the WHERE clause, ensuring the UPDATE statement only executes when Retail, Level1, or Level2 values actually differ for zone 99999 records. This prevents unnecessary database writes while maintaining data accuracy.
-
Cloud Sync
Improved sync detection for base pricing changes
Enhanced the WHERE clause logic to detect when base pricing columns need updating from zone 99999, ensuring the sync process captures all relevant price changes and keeps the local database fully up to date.
-
Cloud Sync
Strategy cloud backup commands connected
Connected the existing STRATEGY_BACKUP_CLOUD and STRATEGY_RESTORE_CLOUD backend commands to the new menu items, allowing users to save their pricing strategy configuration to the cloud and retrieve it later. This complements the existing local backup/restore functionality.
-
Cloud Sync
Simplified backup submission API
Removed VendorType parameter from strategy backup submission since the server now automatically resolves the vendor from the store configuration. This simplifies the backup process and ensures consistency with the organization-scoped backup strategy.
-
Cloud Sync
Improved server-side store resolution
Updated both automatic and manual strategy backup workflows to pass the vendor type (VendorNameShort) alongside the store number. This allows the server to use the combination of store number and vendor name to resolve the unique Store record and correctly determine VendorId and OrganizationId for backup storage.
-
Cloud Sync
API client method signature updated
The SubmitStrategyBackupAsync method now requires the vendor type parameter to be passed explicitly, ensuring all backup submissions include complete metadata about the store's primary vendor configuration.
-
Cloud Sync
Backup list retrieval now filters by vendor ID
When viewing available strategy backups to restore from the cloud, the system now sends the vendor ID to properly filter the list. Previously, this could have resulted in seeing backups from the wrong vendor or missing valid backups.
-
Cloud Sync
MFG Cost propagates to group tables during import
MFG Cost values propagate from store main tables to group main tables during MySQL imports using MIN aggregation. The field is deliberately excluded from the SqlMergeMySqlStoreToGroupMainTable sync path to match List Price's existing behavior pattern.
-
Data Import
Relocate DIB Aux Retail to Level3 field
The Auxiliary Retail price from Do-It-Best now appears in the Level3 column instead of Level5Zone in the pricing grid.
-
Data Import
DIB Aux Retail now imports to Level3 field
Do-It-Best Aux Retail prices now appear in the Level3 column alongside your other pricing levels.
-
Data Import
Improved auxiliary retail handling for multi-unit items
Multi-unit display items (like boxes of screws) will now show correct per-unit auxiliary retail prices instead of the full box price.
-
Data Import
Improved store number detection for single-store configurations
Enhanced the database query logic to fall back to the main inventory table when the SelectionLists table doesn't contain store number entries. This situation occurs naturally for single-store customers since the system doesn't build selection dropdowns for fields with only one unique value.
-
Data Import
Add single-store POS system detection
Added logic to identify POS systems that don't support multi-store exports (currently CounterWorks). These systems hardcode all imported data to store number '0', so any other store numbers in the database represent stale legacy data that should be automatically removed during import to prevent data contamination.
-
Data Import
Compass MySQL imports now capture List Price
When you import data from Epicor Eagle, the system will now automatically capture and display List Price information if it's available in your POS system.
-
Data Import
Extended timeout for price variance calculations
Increased the timeout for the CurrentPriceVariances calculation from default (30 seconds) to 600 seconds (10 minutes) to accommodate the scalar UDF performance limitations on large datasets. This ensures variance calculations complete even when SQL Server cannot parallelize the query.
-
Data Import
Added automatic migration for legacy SKU Level Exceptions steps
Pricing strategies from older systems are automatically updated to work correctly when you load them, removing duplicate or incorrectly named exception steps.
-
Data Import
Strategy restore process aligned with live data sources
Restoring pricing strategies from backup will now properly restore all your strategy settings and custom groups.
-
Data Import
Automatic migration of prefixed Custom Groups steps
You no longer need to manually fix or recreate Custom Groups steps after importing pricing strategies from older systems.
-
Data Import
Fixed vendor cost and retail price import accuracy
Vendor pricing information in the main pricing grid now matches the actual values from Do-It-Best catalogs.
-
Data Import
Simplified vendor data update process
Streamlined the SQL update procedure by removing the PriceAdj common table expression and associated ratio calculations. All vendor pricing fields (Retail, Level1-5, DIB costs, and Cost2) now transfer directly from vendor data without intermediate calculations, improving import performance and data accuracy.
-
Data Import
Automatic database migration at startup
Added a one-time migration routine that runs during application startup to update strategy configuration data. The migration only runs for Ace Hardware stores and safely updates strategy rules without requiring manual intervention.
-
Data Import
MFG Cost imported from MySQL Compass vendor catalogs
MFG Cost values automatically import from your vendor catalog files during regular POS imports.
-
Data Import
Strategy backups no longer capture database connection settings
New strategy backups created after this fix will not include DatabaseConnections.json, consistent with the blob-backup feature which already excluded this file for the same reason. Legacy V1/V2 backups that contain this section will deserialize without error but the connection data will be ignored during restore.
-
Data Import
Epicor Compass import now populates List Price
Modified the Compass MySQL import process to extract the in_list_price value from the EAGLEDW.IN table and populate the new ListPrice column during data imports. The field is carried through all data transformation steps including table merges and group table operations.
-
Data Import
MFG Cost imported from POS systems
If your POS system tracks manufacturer cost, this information will now automatically appear in Margin Master after each data import.
-
User Interface
Improved progress feedback for strategy step loading
When switching pricing strategies, you'll now see the progress window update smoothly with item counts for each custom step, instead of appearing frozen near the end of the loading process.
-
User Interface
Expanded rounding schemes documentation
The rounding schemes help page is now easier to navigate and includes examples showing how to set up nickel rounding (5 cent), dime rounding (10 cent), and other common pricing patterns used by hardware stores.
-
User Interface
Strategy execution progress shown in title bar
You can now see which step is running in the window title when executing a strategy.
-
User Interface
Strategy execution progress display in title bar
When running a pricing strategy, you'll now see which step is currently processing in the window title bar, making it easier to track progress through long-running strategies.
-
User Interface
Expanded allowed characters for strategy names
When creating or renaming a pricing strategy, you can now include < and > symbols in the name (for example, "Clearance <50%" or "Premium > $100").
-
User Interface
Help button alignment on strategy window
The help button now appears in the correct position alongside the Export to Excel button.
-
User Interface
Splash screen appears immediately when executing strategies
When you click Execute Strategy, the progress window now appears right away instead of after a short pause, making the application feel more responsive.
-
User Interface
Splash screen displays immediately on Execute Strategy
When you click Execute Strategy, you'll now see the splash screen and status messages right away instead of waiting. This helps you know the system is processing your request.
-
User Interface
Busy indicator for step reordering operations
When you drag steps up or down in your pricing strategy, you'll now see a "Moving step..." message appear briefly while the change is being processed.
-
User Interface
View toggle system for Strategy Manager and Options
A "Use New View" button now appears on the Strategy Manager and Options screens, letting you switch to the updated interface. If you prefer the classic version, click "Use Legacy View" to switch back. Your choice is saved automatically.
-
User Interface
Enhanced visual styling for inactive strategy steps
Inactive pricing strategy steps are now easier to spot with a gray background color.
-
User Interface
Clearer condition value formatting in pricing strategy detail panel
Multi-value conditions in pricing strategies now show as readable text like "Vendor is ACE or DIB or Orgill" instead of separate boxes, making it clearer how the rule works.
-
User Interface
Relocated legacy view toggle to hamburger menu
The "Use Legacy View" button is now located in the hamburger menu (three lines icon) at the bottom, instead of on the main toolbar.
-
User Interface
Disable all controls during busy operations
All buttons and fields are now grayed out while pricing strategies are being saved, loaded, or calculated, preventing you from accidentally clicking anything until the operation finishes.
-
User Interface
Disable all controls during busy operations
The pricing strategy screen will now gray out and prevent edits while saving or loading, ensuring your changes aren't accidentally overwritten.
-
User Interface
ListPrice added to price comparison dropdowns
When choosing which prices to compare in the pricing grid, ListPrice now appears as an option in the dropdown menu.
-
User Interface
Improved dialog layout
Error messages and action choices in the Strategy Load Error dialog are now arranged vertically for easier reading.
-
User Interface
Strategy log time format simplified
Strategy execution logs now show simpler time formats like "5s" or "2m 15s" instead of including milliseconds.
-
User Interface
Live progress updates during SKU exception batch processing
When you apply pricing exceptions to thousands of SKUs, the splash screen will now show you which pricing formula is currently being applied and how many SKUs are being processed, giving you confidence that the operation is working and hasn't stalled.
-
User Interface
Single-click Future Price editor activation
You can now start editing Future Price values with a single click when the inline editing option is turned on.
-
User Interface
Cloud strategy backup/restore menu items added
Added two new menu items under the Strategy submenu: "Backup Strategy to Cloud" and "Restore Strategy from Cloud". These options appear below the existing local backup/restore options and use cloud upload/download icons to distinguish them from local operations. The underlying functionality was already implemented but previously inaccessible to users.
-
User Interface
Store column added to restore strategy dialog
The restore dialog now shows which store created each backup, making it easier to identify the right backup when multiple stores share access.
-
User Interface
Documentation updated for fixed price mode in Cost Break Analysis
The help documentation now explains how to use the fixed price option in Cost Break Analysis, which lets you set one price for all items in a cost range instead of using a margin percentage.
-
User Interface
Busy spinner now appears after confirmation dialog
The loading spinner will no longer cover up the "Update this Cost Break?" confirmation message, making it easier to read and respond to the prompt.
-
User Interface
Pricing Strategy dropdown now shows code descriptions for Ace Hardware
When you click to filter the Pricing Strategy column, the dropdown now shows descriptions like "S - Sensitive" and "C - Competitive" so you can see what each code means without memorizing them.
-
User Interface
Improved Pricing Strategy grid performance
The Pricing Strategy screen now responds immediately when switching between strategies, even those with hundreds of pricing rules.
-
User Interface
Improved strategy step focus after switching
After switching strategies, the first pricing step is automatically selected so you can immediately see its details in the right panel.
- User Interface Plus/minus spinner now displays units directly
-
User Interface
Added increment rounding feature clarification
If you need prices rounded to the nearest nickel (5 cents) or dime (10 cents), use the Increment Rounding option in the rounding editor rather than trying to configure it with the penny rounding grid.
-
User Interface
Window height reductions for smaller displays
Configuration and database windows are now smaller and fit better on laptop screens.
-
User Interface
Dialog window size optimization
Several settings and configuration windows have been resized to fit better on your screen without excessive scrolling or extending off-screen.
-
User Interface
Update DIB field labels for standard level columns
Do-It-Best stores will see clearer column names that match the price types from Do-It-Best catalogs.
-
User Interface
Updated DIB pricing field labels
The pricing grid now shows clearer labels for Do-It-Best pricing columns (Aux Retail, Sug Retail, and EDLP).
-
User Interface
Corrected menu labels for backup and restore operations
The File menu now shows the correct labels: "Backup Database", "Restore Database", "Backup Strategy", and "Restore Strategy" each do what their names say.
-
User Interface
Simplified restore dialog
The restore screen now shows fewer, more useful options in a simpler layout, making it easier to restore your pricing strategy and settings.
-
User Interface
Simplified restore dialog layout
The restore dialog is now more compact and easier to read, with all options in a single list instead of split across two columns.
-
User Interface
Simplified strategy grid cell styling
Streamlined the visual styling logic for inactive and modified strategy steps by removing expensive FindAncestor data bindings and consolidating three multi-data triggers into two simpler data triggers plus one multi-trigger. Also removed a hidden IsDirty column that was triggering unnecessary style recalculations.
-
User Interface
Strategy Manager V2 placeholder screen
The new Strategy Manager screen is now accessible with a simplified toolbar layout. Full functionality including the optimized strategy grid will be available in the next update.
-
User Interface
Pricing Strategy Manager V2 placeholder view
The new Pricing Strategy Manager preview shows a placeholder screen with "coming soon" messaging — the current version remains fully functional.
-
User Interface
Simplified step movement commands
Step movement buttons and menu options now respond immediately when clicked, with no delay or loading indicator.
-
User Interface
Added loading indicator during Manage Pricing Strategy window startup
You'll now see a "Loading strategy steps..." message with a spinner while the Manage Pricing Strategy window opens, so you know the window is loading properly.
-
User Interface
Loading indicator during startup
You'll see a "Loading strategy steps..." message when opening the Pricing Strategy editor while it loads.
-
User Interface
Remove in-dialog loading indicator
You'll no longer see a "Please wait" message inside the Pricing Strategy dialog — all loading happens before the dialog opens.
-
User Interface
Streamlined rounding scheme selector
Replaced the custom rounding scheme selection control with a standard combo box that binds directly to the available rounding scheme names. The control is automatically enabled/disabled based on the "Use Rounding" checkbox state.
-
User Interface
Improved performance when selecting pricing strategy steps
Switching between pricing strategy steps is now faster and more responsive with no loading delays.
-
User Interface
Strategy editor right panel
Resolved issue MM-1145 where strategy step details were completely hidden in the right panel due to missing view model binding property.
-
User Interface
Improved feedback during discard operation
You'll now see a "Discarding changes..." message when you choose not to save your pricing strategy changes, so you know the app is working.
-
User Interface
Condition editor button layout updated
The condition editor popup now shows two buttons at the bottom: "Reset" to undo changes and "Close" to exit the editor.
-
User Interface
Improved condition editor button layout
The condition editor popup now shows Reset and Close buttons next to each other at the bottom, making it easier to find and use both options.
-
User Interface
Improved event handler shutdown logic
Added _isClosing guards to OnStepsChanged and OnPricingStrategyServicePropertyChanged event handlers to prevent them from updating UI state during the window close sequence, ensuring clean shutdown behavior.
-
User Interface
Applied fix to both save actions
Whether you click the Save button or close the window and choose "Yes" to save changes, the loading indicator will display correctly in both cases.
-
User Interface
Remove development test button
Removed an orange "Test Busy" button that was used during development to verify the busy indicator functionality. This was a temporary testing control not intended for production use.
-
User Interface
Remove test button from toolbar
Removed a development test button that was inadvertently left in the production interface.
-
User Interface
Enable full row selection in SKU Level Exceptions grid
In SKU Level Exceptions, the entire row now highlights when selected, making it easier to see which SKU you're working with.
-
User Interface
V2 strategy manager now defaults at each startup
Each time you start Margin Master, you'll see the modern pricing strategy manager by default. If you switch to the legacy view, that choice only lasts until you close the program.
-
User Interface
Updated view switch dialog text
The message when switching views now says "continue with the strategy" instead of "re-run" to match what actually happens.
-
User Interface
Removed "Database Connections" option from restore dialog
The restore options tree no longer shows a "Database Connections" checkbox. This option was misleading because restoring database connections from a backup always caused problems rather than helping users. Legacy backups that contain this data will still restore successfully—the connection settings are simply ignored.
-
User Interface
Removed Database Connections option from restore dialog
When you restore a strategy backup, you'll no longer see a "Database Connections" checkbox that could accidentally disconnect your database.
-
User Interface
Improved error handling in pricing screens
When editing pricing strategies or custom groups, the rounding scheme dropdown now correctly selects your saved scheme even if the capitalization has changed.
-
User Interface
ListPrice added to Set Future Price options
When setting future prices, you can now choose to set them to the vendor's ListPrice value automatically.
-
User Interface
Improved dialog behavior for safer default actions
The countdown auto-execute feature is now limited to the only safe action (Ignore and Continue). This prevents accidental data loss or import interruptions from auto-firing destructive actions like Abort when users have pre-saved their error handling preferences.
-
User Interface
Enhanced dialog sizing behavior
The Strategy Load Error dialog now automatically adjusts its size to fit the error message without unnecessary extra space.
-
User Interface
Strategy log column order adjusted
In strategy logs, the total number of SKUs now appears before the number of changes.
-
User Interface
Search panel restored in Manage Custom Groups screen
You can now press Ctrl+F to search for specific custom groups by name or other details in the Manage Custom Groups screen.
-
User Interface
Double-click behavior refined for Future Price editing
Double-clicking a Future Price cell while editing keeps the editor open instead of opening the item details window.
-
User Interface
Improved Future Price column cursor feedback
The mouse cursor now clearly shows whether Future Price cells can be edited or not.
-
User Interface
Improved click-through behavior for Future Price template
Made the Future Price cell template grid transparent to mouse clicks so that clicks pass through to the underlying grid cell element, improving the reliability of single-click editing activation.
-
User Interface
Future Price column display updated
The Future Price column now uses two different display modes: when editing is disabled, it uses the up/down arrow template for visual indication; when editing is enabled, it uses standard currency formatting (C2) to ensure the editor remains visible during data entry.
-
User Interface
Menu Organization Enhancement
The Strategy menu now clearly separates local file backups from cloud backups with a divider line, making it easier to choose the right option.
-
User Interface
Cloud restore dialog with backup history
When restoring from the cloud, you can now see a list of all your saved backups with dates and choose which one to restore.
-
User Interface
Store number column added to restore dialog
When you open the restore strategy dialog, you'll now see which store each backup came from in a new "Store" column.
-
User Interface
Cost break grid columns for fixed pricing
The cost break grid now displays two new columns: "Fixed Price" (checkbox) and "Fixed $" (dollar amount). The dollar amount field is only enabled when the Fixed Price checkbox is checked, preventing accidental entry when using margin-based pricing.
-
User Interface
New columns in cost break grid
The cost break pricing grid now displays two new columns: "Fixed Price" (a checkbox to toggle the pricing mode) and "Fixed $" (a currency input field that is only enabled when the checkbox is checked). These columns appear alongside the existing "Target Margin" column, allowing users to choose their preferred pricing method per level.
-
User Interface
New subtract field in Rounding Editor
The Rounding Editor's increment rounding panel now displays a "Subtract" input field below the "Above" field. This currency-formatted field accepts positive or negative decimal values and defaults to $0.00 when empty.
-
User Interface
New offset input field in Rounding Editor
Added a currency-formatted text field labeled "Subtract" to the Increment Rounding section of the Rounding Editor screen. The field accepts dollar amounts, defaults to $0.00, and displays with standard currency formatting (C2 mask).
-
User Interface
Simplified fixed price and margin field visibility
Cost break pricing rows now show only the pricing field you're actually using—you'll see either "Fixed Price" or "Target Margin" based on your selection, making it clearer which pricing method is active.
-
User Interface
Fixed pricing column visibility in cost break grid
The pricing grid now shows only the relevant column (Fixed Price or Target Margin) based on which pricing method you've selected, making it clearer which values are active.
-
User Interface
Improved error messages for strategy steps with missing data
Warning messages now clearly show which category values will be used and which are being skipped when running a pricing strategy.
-
User Interface
Enhanced error messaging for strategy step validation
When a strategy step has missing categories, you'll now see a clearer message explaining which categories will be used and which are missing, with options to continue or stop.
-
User Interface
Improved error messaging for cloud operations
The error dialog displays the specific failure reason from the cloud service and provides clear next steps: verify internet connectivity and try again, or contact support if issues persist. This replaces the previous silent failure behavior where users had to check log files to diagnose problems.
-
User Interface
Improved error messaging
The new error dialog displays the specific error reason when available, helping users and support staff diagnose cloud connectivity or authentication issues more quickly.
-
User Interface
Reduced splash screen flicker during auto-continued strategy errors
The screen no longer flickers when automatically skipping problem steps in a pricing strategy.
-
User Interface
One-time notification for corrected in-use schemes
If you use a rounding scheme that was corrected, you'll see a one-time message explaining the fix and asking you to verify the results using the Check button in the rounding editor.
-
User Interface
Updated Epicor import options help text
Removed the word "always" from the store mapping description on the Epicor settings screen to accurately reflect that store mapping is configurable rather than mandatory.
-
User Interface
Update Problem dialog with repair install option
The "Could Not Update" dialog shows you what version you're on, what version it tried to install, and why it failed. You can install it directly (Margin Master downloads the installer and runs it for you), send the problem to support with everything filled in, or wait 24 hours.
-
User Interface
Prevented duplicate strategy switch triggers
Added suppression logic to the pricing strategy combo box to prevent it from triggering redundant strategy switches when the selection is updated programmatically (as opposed to user clicks). This eliminates unnecessary processing and potential race conditions when the UI updates itself in response to strategy changes.
-
User Interface
Improved scheme management instructions
The help now explains how to make a copy of a built-in scheme like "Ace-1" so you can customize it for your store without starting from scratch.
-
User Interface
Improved cloud restore feedback
When restoring from the cloud, you'll see clear progress messages showing what's happening at each step.
-
User Interface
Added busy indicators for move operations
You'll now see a "Moving step..." message briefly appear when reordering strategy steps, confirming the action is in progress.
-
User Interface
Consolidated Options menu item
The Tools menu now shows only one "Options" entry instead of two separate menu items.
-
User Interface
Toggle buttons added to legacy screens
Adds "Use New View" buttons to both the legacy Pricing Strategy Manager (ManagePricingStrategyView) and legacy Options window (frmOptions) that switch the user to the new version and persist the preference via ApplicationSettingsService. When toggled, the current dialog closes and reopens with the alternate view.
-
User Interface
Strategy grid with visual status indicators
Strategy steps now display with visual cues: inactive strategies appear grayed out, and strategies with unsaved changes are clearly marked so you know when to save.
-
User Interface
Lazy-loaded step detail panel
The strategy step detail panel (right side of dialog) is now created only when the user first selects a step, rather than being created during dialog initialization. This optimization reduces memory usage and startup time.
-
User Interface
Removed main window splash screen for strategy dialog
The main window no longer shows a "Loading Pricing Strategies..." splash screen before opening the dialog. All loading feedback now appears within the dialog itself using its built-in busy indicator, providing a cleaner and more responsive user experience.
-
User Interface
Improved condition value display
Simplified the display of condition values in strategy steps to show values in a wrapped panel layout without unnecessary selection or delete controls for read-only items.
-
User Interface
Simplified condition display in step details
Updated the conditions section to use a cleaner ItemsControl with simple Border elements instead of a complex ListBoxEdit with selection and delete capabilities. Condition values are now displayed as read-only chips, matching their actual behavior in the interface.
-
User Interface
Condition editor popup with value management
Added a centered popup dialog displaying the condition name, operator (e.g., "equals", "contains"), and scrollable list of values. Each value has a remove button. The popup closes automatically when the last value is removed or when the user clicks the Close button.
-
User Interface
Improved scheme selection and dirty tracking
Decoupled the UI's selected scheme from the global service state using a local backing field. The active scheme in the service is now only updated when the window closes, preventing circular event cascades that previously caused unexpected behavior. Added an isLoadingScheme flag to suppress false dirty-state detection when switching between schemes programmatically during copy/delete operations.
-
User Interface
Improved delete and navigation behavior in Rounding Editor
After deleting a rounding scheme, the editor now automatically returns to the scheme you were viewing before, making it easier to manage multiple schemes.
-
User Interface
List Price available in Selection Boxes for Ace stores
When creating selection boxes for Ace stores, you can now include "List Price" as one of the displayed or filtered fields.
-
User Interface
Improved dialog window focus behavior
The error dialog will now reliably appear on top of other windows so you don't miss it.
-
User Interface
Updated progress messaging
When watching pricing strategies run, you'll see "batch mode" in the progress display for SKU exceptions.
-
User Interface
Main Table screen interaction improvements
The pricing grid is now easier to navigate and updates faster when you make changes through the SKU Detail window.
-
User Interface
Improved Custom Groups screen reliability
The Custom Groups screen now shows accurate SKU information without confusing duplicates or error messages.
-
User Interface
Editor validation prevents saving unusable increment amounts
The rounding editor now prevents you from saving an increment amount higher than $1,000, which would stop items from rounding correctly.
-
User Interface
Improved Catalog Lookup grid column sizing
Updated column width behavior throughout Catalog Lookup: search results grid changed from AutoWidth=True to fixed widths, SKU column uses MinWidth with auto-sizing, and zone pricing columns use consistent 80-pixel widths for Retail, Level 1, Level 2, and MSU Retail.
-
User Interface
Improved loading status messages
Loading messages now show more helpful information like "Loading 47 strategy steps..." instead of generic status text.
-
User Interface
Removed unused styling rules
Cleaned up obsolete strikethrough text decorations and a hidden "IsDirty" column that were no longer needed, further simplifying the grid rendering pipeline.
-
User Interface
Integrated saved selection workflow
You can now choose to load a saved selection or custom group directly after closing the Strategy Manager, saving navigation steps.
-
User Interface
Improved SKU Exceptions grid navigation
You can now use arrow keys to move between exception rows more easily in the SKU-level exceptions screen.
-
User Interface
List Price available in Column View and Selection Box editors
To see List Price in your pricing grid, open the Column View editor and add the "List Price" field. You can also use it as a filter criterion in your Selection Boxes.
-
User Interface
Restore dialog now shows available rounding schemes
In the Restore Backup dialog, the "Rounding Schemes" section will now show as available (not grayed out) when your backup file contains rounding scheme data.
-
User Interface
MFG Cost appears in Main Table grid and selection tools
MFG Cost is now available as a grid column in the Main Table view with currency formatting (c2), default column width matching other cost fields, and display text "MFG Cost" (short: "MC"). The field also appears in selection boxes, future price panels, and custom group configuration dialogs.
-
User Interface
Simplified Options menu
Removes the separate "Options (New)" menu item from the Edit menu, consolidating to a single "Options" entry that respects the user's view preference setting.
-
User Interface
Direct step reordering with collection move
Implemented a fast direct move operation (MoveStepDirect) that reorders steps by moving items within the ObservableCollection without triggering full grid rebinds or dirty-checking loops. This makes drag-and-drop reordering feel instantaneous.
-
User Interface
Strategy grid rendering optimization
Opening the Manage Pricing Strategy window now shows a "Rendering strategy grid..." message while loading, giving clearer feedback about what the app is doing.
-
User Interface
Enhanced strategy management dialogs
Added integrated dialog services for Strategy Name input, Custom Groups management, Rounding Scheme selection, and SKU Level Exceptions, all accessible from within the V2 Strategy Manager with consistent sizing and positioning.
-
User Interface
Launch Diagnostics from Database Setup window
You can now click "Launch Diagnostics" from the database setup screen if you're having trouble connecting.
-
User Interface
AI tab auto-activates on selection and supports Enter key
Pressing Enter in the AI chat box now sends your message—no need to click the Ask button.
-
User Interface
Check for Updates in Database Setup window
You can now check for and install Margin Master updates from the database connection screen before logging in.
-
User Interface
Check for Updates in Database Setup
You can now check for Margin Master updates from the startup screen before connecting to a database.
-
Database
Add PricingStrategy table creation to database update routine
Your database will automatically be updated to support advanced pricing strategies when you start the application. No manual action is required.
-
Database
Automatic column migration for existing databases
Implemented automatic database migration that adds the ListPrice column to all existing main tables on application startup. Uses a one-time flag (ListPriceColumnAdded) to ensure the column is added only once, following the same pattern as previous Ace MAP column additions.
-
Database
Covering index for Ace Hardware zone pricing queries
Zone pricing updates for Ace Hardware will now run significantly faster, especially the first table updated after opening Margin Master or after a catalog refresh.
- Database Added table creation scripts for complete PricingStrategy schema
-
Database
Added defensive table creation to backup operations
Both BackupInventoryService and BackupService now call CreatePricingStrategyTables (which is idempotent using IF NOT EXISTS) at the start of any pricing strategy query operations, ensuring database consistency across all backup/restore workflows.
-
Database
Track last cloud upload timestamp and content signature
Two new application settings store the timestamp and SHA256 hash of the most recent successful strategy upload to the cloud. These values are used to determine whether a new upload is necessary based on content changes and elapsed time.
-
Database
Improved PSRule and PSRuleHistory field handling
Both the PSRule tracking field and PSRuleHistory audit trail now correctly handle special characters in strategy step names, ensuring accurate price change history even when step names contain quotes or apostrophes.
-
Database
Added filtered index for future price operations
Created a new filtered index (RSIX_*_FuturePrice) on the FuturePrice column that only indexes rows where a future price is actually set (not NULL and not 0). This targeted index dramatically reduces the number of rows the database must examine when resetting future prices.
-
Database
Optimized DIBMailBox pricing integration for BisTrack
The new BisTrack import script includes logic to detect whether the DIBMailBox_ItemPricing table exists and contains data, then performs a 3-table JOIN using a pre-aggregated subquery that returns only one row per item/store combination. This prevents the pricing mailbox from creating multiple rows for the same SKU when multiple price records exist, which was the root cause of the duplicate row problem.
-
Database
Strategy backup metadata updated
Added StoreNumber field to strategy backup list items to support displaying store information in the restore interface and enable organization-level backup management.
-
Database
Backward-compatible cost break storage
The new UseFixedPrice and FixedPrice fields are stored in the existing JSON configuration. Existing cost break configurations are unaffected as the new fields default to false and 0, maintaining current margin-based pricing behavior.
-
Database
Extended increment rounding storage
The increment rounding offset is stored in the second position of the Points array in RoundingLevel records. Existing records without this value automatically default to $0.00, maintaining full backward compatibility with previously configured rounding schemes.
-
Database
Extended rounding level data model for offset storage
Extended the IncrementRoundingModel and RoundingLevel classes to store and retrieve the offset amount. The offset is persisted as the second element in the Points array (Points[1]), while the rounding method index remains in Points[0]. The SQL rounding calculation now adds the offset to the final rounded price.
-
Database
One-time migration regenerates existing increment scheme tables
Added automatic per-database migration that regenerates the detail tables for all custom increment rounding schemes, removing the incorrectly baked increment values while preserving the increment rules themselves. This migration runs once when the application starts after this update, ensuring existing schemes produce correct results immediately.
-
Database
MFG Cost column added to main tables
Added MfgCost decimal(18,2) column to all mainTable variants via one-time startup migration. The migration runs once per database, tracked via the MfgCostColumnAdded application setting flag, and adds the column to all store and group main tables if not already present.
-
Database
New application settings for view preferences
Added UseLegacyStrategyManager and UseLegacyOptions boolean settings to ApplicationSettingKey enum, both defaulting to false (new views). These settings are persisted in the application settings table and checked when opening either the Strategy Manager or Options dialogs to determine which view to display.
-
Database
Clear cost break cache when saving or deleting cost breaks
Added cache invalidation to ensure the cost break names cache is properly cleared when cost breaks are saved, deleted, or cleaned up, preventing stale data from being displayed.
-
Database
Automatic schema upgrade for existing databases
The first time you start Margin Master after this update, the database will automatically update to support the new List Price column—no manual steps required.
-
Database
Detection logic for identifying affected schemes
Added logic to identify rounding schemes containing increment rules with the $99,999.99 sentinel value and determine whether each scheme is actively used by checking references in pricing strategies, custom groups, and SKU exceptions. Real increment values ($1, $3, $10, 5¢, etc.) used by other stores are correctly identified and left untouched by the correction process.
-
Database
Automatic database migration for MFG Cost
The application automatically adds the MfgCost column to all main tables (mainTable and store-specific tables) on first launch after upgrade. A new ApplicationSettingKey.MfgCostColumnAdded flag prevents duplicate migrations. The field is also included in all SQL scripts for creating new tables and merging data.
-
Database
New StrategyBackupListItemDto model
Added StrategyBackupListItemDto with Id, BackupDate, BackupType, TriggerSource, BackupVersion, and FileSizeBytes properties. Includes FormattedSize helper to display human-readable file sizes (KB/MB) in the restore dialog.
-
Database
Legacy strategy rule migration
Old pricing strategy rules are automatically updated to the new format when you open the app for the first time after this update.
-
Database
Added LegacyStrategyRulesMigrated application setting
Added `LegacyStrategyRulesMigrated` to the `ApplicationSettingKey` enum to track whether the one-time pricing strategy rule migration has been completed for a given database. This prevents redundant migration attempts on subsequent application starts.
-
Database
Demo database settings
Added two new application settings to track demo database state: IsDemoDatabase (bool) and DemoDatabaseVendor (string). These are stamped after restoring a demo database and allow the application to identify demo environments and provide vendor-specific demo data.
-
Architecture
Modernized report event handling for security compliance
Replaced 104 lines of deprecated embedded report scripts with 134 lines of compiled C# event handlers across all label report classes. The barcode hiding logic (which suppresses barcodes when no product code exists) now executes through BeforePrint event handlers wired up in each report's constructor, eliminating the security vulnerability associated with dynamic script execution while maintaining identical behavior.
-
Architecture
Deferred step sequence persistence
Added ReplaceStepOrder method to PricingStrategyService that accepts a reordered list of steps and synchronizes it to the internal model collection. The ManagePricingStrategyV2ViewModel now tracks pending move changes with a local flag and calls SyncStepOrderToService before saving, ensuring the correct step order is persisted without triggering expensive recalculations during the move operation itself.
-
Architecture
Simplify viewmodel initialization sequence
Removed deferred initialization logic (`InitializeOnLoadAsync`) from the pricing strategy dialog viewmodel and restored immediate initialization in the constructor. The "instant open with deferred load" pattern proved problematic for ensuring all services were ready before user interaction, so initialization now completes fully before the dialog is shown.
-
Architecture
InstructionSet-based condition editing
Implements safe condition editing by working through the InstructionSet architecture: parse Instructions to InstructionSet, call StrategyCondition.DeleteCondition(value) to remove the value, rebuild rule text via GetRuleText(), update model.Instructions, and rebuild display conditions. This approach ensures dirty detection and save/discard flows work automatically without modification.
-
Architecture
Enhanced view model extensibility
Made the IsBusy and BusyMessage properties virtual in ManagePricingStrategyV2ViewModel, allowing derived classes to override busy state behavior if needed for specialized pricing strategy implementations.
-
Architecture
Parsing and grouping optimization
SKU exceptions are now parsed once upfront into typed batch rows (action type, numeric value, rounding scheme) and grouped by their settings before database execution. This eliminates redundant parsing and allows the database to handle all SKUs with identical pricing rules in a single batch operation.
-
Architecture
Per-combo SQL execution for SKU exception batches
Split the single monolithic SQL batch operation into separate calls for each unique (ActionType, RoundingScheme) combination. Each call creates its own temporary table, processes only that combination's SKUs, and reports completion before moving to the next. This architectural change enables the UI progress updates while maintaining the performance benefits of batch processing (still ~1,665 individual SQL calls reduced to 7 combo calls, completing in under a minute for large exception sets).
-
Architecture
Improved SKU exception batch grouping logic
Modified the batch processing grouping key to use the raw ACTIONADDSUBTRACT value instead of the computed SQL modifier. This ensures that different POIN operations (like ADDPOIN3 vs ADDPOIN5 or SUBPOIN3 vs SUBPOIN6) are processed in separate batches with their distinct point shift values intact, while still allowing other modifiers like ADDDOLL or ADDPERC to batch efficiently.
-
Architecture
Separated increment calculation from rounding table generation
Moved increment rounding from the precomputed RoundingSchemeDetail table into a separate calculation step (RoundingEngine.ApplyIncrement). The table now stores only right/left/rollback/range rounding data, while increment rounding is applied via formula both in the pricing run (SQL) and the editor "Check" preview (C#). This prevents the 10,000-row table limit from being exceeded when using fine-grained increments.
-
Architecture
Improved rounding scheme validation logic
The startup validation now uses both configuration hash AND generation version to determine whether a scheme needs regeneration, instead of checking configuration alone. This ensures that when a build changes the rounding math without changing the rules, existing schemes automatically detect they're stale and regenerate. Schemes that are already correct after a version bump get their checksum re-stamped to avoid unnecessary validation on subsequent startups.
-
Architecture
Template implementation refactored
Migrated icon column templates from static XAML DataTemplates to dynamically-generated ControlTemplates with proper binding context. This change restores the legacy implementation approach that correctly binds to grid cell values, removing non-functional XAML template definitions.
-
Architecture
Restore synchronous initialization pattern
Removed the `InitializeOnLoadAsync()` method and `InitialSavedSelectionName` property that supported deferred initialization. The constructor now performs all necessary setup synchronously, with the view model fully initialized before the dialog is shown to the user.
-
Architecture
Code cleanup for grid update logic
Simplified the SKU Detail save logic by working directly with MainTableViewModel instances instead of converting to/from the underlying mainTable entity model, reducing complexity and improving maintainability.
-
Architecture
Refactored SKU exception SQL generation
The BuildColumnExprSql method now properly brackets table names and incorporates the adjustedExpr fix from main, ensuring SQL is correctly generated when combining column references with add/subtract modifiers. This merge resolves conflicts between two concurrent improvements to the pricing strategy execution engine.
-
Architecture
Organization-scoped backup data model updated
The StrategyBackupListItemDto model now includes StoreNumber to support displaying backups across an organization rather than just for a single store. This enables multi-store organizations to view and restore backups from any location with appropriate permissions.
-
Architecture
View routing logic in MainMMViewModel
Modifies `ManagePricingStrategy()` and `OptionsEditAsync()` methods to check ApplicationSettingKey values and route to either legacy or V2 implementations. Adds cross-navigation support so toggling views within a dialog closes the current one and reopens the alternate version seamlessly.
-
Architecture
Eliminated StrategyStepViewModel from V2 editor
Removed the StrategyStepViewModel layer entirely from the V2 pricing strategy editor. Reference data (rounding schemes, min/max strategies, SKU types) is now loaded once and shared across all steps, while computed properties (step name editability, rounding label text, min/max instructions) are refreshed only when the focused step changes. This reduces memory usage and eliminates the need for model swapping logic.
-
Architecture
View model infrastructure for V2 Strategy Manager
Implemented ManagePricingStrategyV2ViewModel with DI registration, dialog service configuration, and SwitchToLegacy property to support seamless toggling between views. The legacy ManagePricingStrategyViewModel received a corresponding SwitchToNewView property and UseNewView command for bidirectional navigation.
-
Architecture
Diagnostic results support skip state
DiagnosticResult now includes Skipped and SkipReason properties, allowing modules to gracefully exit when prerequisites are missing (e.g., no file selected, no POS type configured) without reporting failures. A new DiagnosticResult.Skip factory method simplifies creating skip results.
-
Performance
Strategy step reordering now instant
Moving pricing strategy steps up or down in the list now happens instantly.
-
Documentation
Added detailed issue investigation notes
Created comprehensive documentation of the investigation process, including code flow analysis, root cause identification, and testing procedures for the Future Price click-to-set hang issue (MM-1157).
-
Infrastructure
Completed abandoned FuturePrice save feature
Implemented the logic that was previously started but left incomplete (evidenced by the commented-out line at 847). The feature now properly iterates through all dirty SKU view models and persists FuturePrice changes to the database.
-
Infrastructure
Support documentation for timeout issue investigation
Added internal documentation (MM-1183) analyzing a complex sync timeout issue at a large Ace Hardware customer where Level 1 and Level 2 pricing failed to update after sync due to incorrect timeout parameter usage in database queries affecting 324,000+ SKU tables.
-
Infrastructure
Enhanced diagnostic logging for pricing operations
Added detailed logging for pricing calculations to help identify and resolve pricing discrepancies more quickly. This diagnostic information will aid in troubleshooting when users report unexpected margin or markup values.
-
Infrastructure
Strategy backup upload tracking
Added two new application settings to track the timestamp and content hash of the last successful cloud strategy upload. These values enable the throttling logic to determine whether a new upload is necessary.
-
Infrastructure
Documentation index updated with fixed price keywords
Updated search keywords and content excerpts in the documentation index to include "fixed retail price," "flat retail price," and "fixed price" terms, making it easier to discover this pricing option through search.
-
Infrastructure
Improved backup performance for large datasets
Changed BackupService to use JsonTextWriter with FileStream instead of JsonConvert.SerializeObject, keeping memory usage proportional to a single write buffer rather than the full backup file size. This particularly benefits stores with extensive pricing strategy data.
-
Infrastructure
Rounding table integrity verification
Added a one-time database verification step that regenerates every custom rounding scheme's pricing table and compares it against the stored version, logging whether each scheme is identical or has differences. This regression check confirms that recent rounding engine improvements (which moved increment rounding from precomputed tables to runtime calculation) did not inadvertently alter any existing non-increment pricing schemes. The verification runs once per database and logs results for diagnostics.
-
Infrastructure
Fast-path validation now respects generation version
Updated the rounding scheme integrity check to bypass the "fast path" (skipping validation when configuration is unchanged) if the generation version is outdated. This ensures schemes regenerate after a math fix even when their rules are identical, then get re-stamped with the current version so future startups can safely use the fast path again.
-
Infrastructure
Added test coverage for lock icon mapping
Added 14 new tests that verify each exception type produces the correct lock character, ensuring the batch path matches the behavior of the original per-SKU processing. Tests specifically prevent the system from accidentally using markers reserved for other features like Custom Groups.
-
Infrastructure
Added lock icon mapping tests
Created comprehensive test coverage pinning the correct lock character for each exception action type (MARGIN→M, SETPRICE→R, COSTBREAK→C, RETAIL/LEVEL→D). These tests guard against silent mislabeling that would stamp thousands of SKUs with plausible-but-wrong markers, and verify case-insensitivity and proper precedence rules (e.g., COSTBREAK must not fall through to the generic 'D' default).
-
Infrastructure
Improved application settings database updates
Replaced the UPDATE/INSERT pattern with a single MERGE statement for updating application settings in the database. This eliminates race conditions and ensures settings are always saved correctly whether they already exist or need to be created.
-
Infrastructure
POS system import documentation
Added comprehensive documentation for 22 POS systems covering import file formats, field mappings, pipeline details, and troubleshooting tips. Documentation includes detailed guides for RockSolid, RockSolid Max, Transact, Bistrack (5 variants), Catalyst, Epicor FTP, Epicor MySQL Compass, Falcon, Spruce, Paladin, MI9, ECS, Prosperity, and 10 additional systems. Each guide includes file format specifications, field-to-column mappings, import workflow explanations, and common questions.
- Infrastructure Improved diagnostic logging for strategy loading
-
Performance
Strategy Manager grid rendering optimized
The Pricing Strategy Manager window now opens much faster and shows a progress message while loading your strategy steps.
-
Infrastructure
Performance diagnostics added
Added stopwatch timing and detailed logging throughout the strategy loading pipeline to measure database query times, model building, caching, and UI updates. This instrumentation will help identify bottlenecks in future performance investigations.
-
Infrastructure
Enhanced save verification logging
Added diagnostic logging that captures pricing step order at three key points: initial load, before save, and after save completion. Each log entry includes step sequence, name, rounding setting, and active status, enabling developers to verify that step ordering is preserved correctly through the save operation.
-
Infrastructure
Improve MySQL connection logging type safety
Added explicit string casting to MySQL server identity logging to improve type safety in diagnostic output.
-
Infrastructure
Strategy backup upload now returns server timestamp
The cloud backup upload now returns and stores the server-assigned backup timestamp instead of using the local system time, ensuring consistent backup history tracking across different time zones and system clock variations.
-
Infrastructure
Comprehensive regression tests for rollback rounding
Added thorough test coverage for the NEW WILMES rounding scheme including verification that .98/.99 prices stay in their proper groups, round-trip invariant validation between the table generator and direct rounding engine, and parser flag tests. Updated the legacy reference engine to mirror the fix so fleet validation continues to isolate only intentional increment-scheme differences. All 43 rounding tests pass.
-
Infrastructure
Added comprehensive test coverage for rollback rounding
Added test cases covering the "NEW WILMES" rounding scheme scenario and validating that rollback schemes generate correct pricing bands and maintain round-trip consistency between generated tables and direct price calculations.
-
Infrastructure
Added regeneration gate tests
New RoundingSchemeRegenerationGateTests lock in the version-gate behavior to prevent future math fixes from silently leaving customers on stale pricing bands. Tests verify that freshly stamped checksums skip regeneration, stale generation versions force regeneration even with unchanged config, and the gate properly handles missing checksums or changed configurations.
-
Infrastructure
Test coverage for regeneration gating
Added comprehensive unit tests that verify the generation-version gate works correctly: fresh schemes skip regeneration, schemes from prior builds with unchanged config are forced to regenerate, and the gate properly handles missing checksums or changed configurations. These tests lock in the behavior to prevent future math fixes from silently leaving customers with stale calculations.
-
Infrastructure
Safety checks at multiple update stages
The deferral logic now guards three distinct phases: the initial hourly auto-update check (skips the entire tick), the pre-download phase (for interactive updates), and post-download as a safety net if an operation started during the download. This multi-layered approach ensures no restart path can interrupt user work, and flags are cleared on application startup to prevent stale state from blocking legitimate updates.
-
Infrastructure
UpdateRepairService for last-resort installer download
When you choose "Download and Install Now," Margin Master downloads the installer, closes the background service that might be locking the folder, and lets you confirm before shutting down and running the installer.
-
Infrastructure
SimpleMapper optimization
Removed unused delegate creation code in SimpleMapper that was creating unnecessary overhead during property mapping operations.
-
Infrastructure
Performance monitoring added
Added detailed timing logs throughout the strategy loading pipeline to track database queries, model building, and UI updates. This enables faster diagnosis of any future performance issues.
-
Infrastructure
Removed diagnostic timing logs
Cleaned up temporary diagnostic logging and stopwatch timing code that was added during the performance investigation. This includes removal of timing logs from PricingStrategyService initialization, strategy loading, and dialog opening sequences.
-
Infrastructure
Removed 600+ lines of dead rounding scheme code
Eliminated obsolete code that attempted to backup and restore rounding schemes as full entity objects with separate rule tables. This code was never functional as rounding schemes have always been stored in GlobalFileConfig format in Margin Master.
-
Infrastructure
Remove Azure Blob Storage dependencies for strategy backups
Removed AzureBlobService calls from BackupService.SendStrategyToCloudAsync. BackupDataToCloudResult.URL field replaced with BackupDate. Cloud backup now returns server-assigned backup timestamp instead of blob URL. Local file backups continue to work as before.
-
Infrastructure
Proper ViewModel lifecycle and resource cleanup
Implemented IDocumentContent for dialog lifecycle management and IDisposable for proper event cleanup. The ViewModel now subscribes to service events (ActiveStrategyChanging, ActiveStrategyChanged, StrategyListChanged, StepsChanged, RefreshDisplayNeeded) during initialization and unsubscribes on disposal. The StrategyStepViewModel now also unsubscribes from model PropertyChanged events in its Dispose method and when swapping models, preventing memory leaks from abandoned event handlers.
-
Infrastructure
Four PowerShell scripts bundled with DiagnosticTool
Install-SQLExpress.ps1, Upgrade-SQLExpress.ps1, Install-SSMS.ps1, and the new Upgrade-SSMS.ps1 are now copied to the DiagnosticTool output directory at build time, allowing the AI tools to execute them without requiring the Scripts folder to be present on the target machine.
-
Code Quality
Removed unused rounding definition property
Removed the dead IncrementRounding_SelectedIndex property from RoundingDefinition, which was never read or used by the application.
-
Infrastructure
SQL Developer upgrade script removed
Removed the Upgrade-SQLDeveloper.ps1 script and its documentation. This script was designed for upgrading SQL Server Developer edition instances to SQL Server 2025, but Developer edition is rarely used in production hardware store environments. The equivalent Upgrade-SQLExpress.ps1 script remains available for the more common Express edition deployments.
-
Infrastructure
Removed obsolete SQL Developer upgrade script
Removed the "Upgrade SQL Developer" script from the Installation Scripts catalog, embedded resources, blob storage references, and documentation. This script was redundant as most Margin Master deployments use SQL Express, and the SQL Developer upgrade workflow is rarely needed in retail hardware store environments.
-
Infrastructure
Diagnostic session logging and cloud reporting
Implemented DiagnosticSessionLogger and DiagnosticApiClient to track diagnostic sessions, log module execution results, and optionally upload session data to marginmaster.com for support analysis. Each session is assigned a unique ID and includes machine identity, store number, vendor, and per-module issue/resolution tracking.
-
Infrastructure
Store identity verification and token management
Added StoreIdentityService to prompt for and verify store number/vendor against the cloud licensing API before running cloud-dependent modules. Implements token budget tracking for Claude API usage and displays remaining tokens in the status bar.
-
Infrastructure
Code signing for MarginMasterDiagnostics.exe
Extended the GitHub Actions publish workflow to sign MarginMasterDiagnostics.exe with the same certificate and metadata as MarginMaster.exe. The diagnostic tool is published into the same output directory and bundled in the Velopack installer package.
Imports & POS
-
New Feature
Reset Point of Sale Data command
If you need to start fresh with your POS data, you can now use Support Tools > Reset POS Data to completely clear your current POS information. After resetting, you'll need to re-import your POS data to see products in the main table again.
-
New Feature
Falcon POS Excel import support
Falcon stores can now import inventory directly from Excel spreadsheets. Place your Falcon export file (.xlsx) in the import folder and click Import Data — the system will read the file, show progress, and load all inventory into Margin Master.
-
New Feature
Bulk SKU import from files
Use Tools → Import File to select an Excel or text file containing SKUs. The system will automatically find matching catalog items and add them to your list.
-
New Feature
Bulk SKU import from files
Click Tools > Import File to upload an Excel or text file containing SKUs. The system will automatically find and add all matching catalog items to your list.
-
New Feature
Bulk import from Excel and CSV files
Use Tools > Import File to select an Excel or CSV file with SKUs. The system will automatically look up each SKU in your vendor's catalog and add matches to your list.
-
New Feature
Bulk spreadsheet import for new products
Place Excel files containing new product SKU numbers in C:\MarginMaster\NewProductImport and select "Import New Product Spreadsheets" from the Data menu. The system will validate each SKU, import the valid products, and create a log file showing what was imported and what couldn't be found.
-
New Feature
Import New Product Spreadsheets menu option
A new "Import New Product Spreadsheets" option appears in the Data menu. Place Excel files containing SKU lists in C:\MarginMaster\NewProductImport, click the menu option, and the system will automatically validate and import the products.
-
New Feature
Ace zone display in Store Matchup
The Store Matchup screen now shows which Ace pricing zone is assigned to each store.
-
New Feature
BisTrack DIB6828 CSV format support
Stores using the BisTrack DIB6828 export format can now import pricing data directly—the Import Manager automatically recognizes the format and processes it correctly.
- New Feature INDecoded store character scanner
-
New Feature
INDecoded store character scanner
In the Settings > Connections tab, click "Scan INDecoded File" to automatically find all POS store codes in your Epicor file. A grid will appear showing each store code; enter the matching vendor store number for each one, then click "Save Store Mappings" to apply.
-
New Feature
Automatic store reconciliation after MySQL Compass sync
When you sync with Epicor/MySQL Compass, Margin Master will now tell you if new stores have been added or if existing stores are no longer found, helping you keep your store list up to date automatically.
-
New Feature
Automatic Compass store discovery and reconciliation
When you import data, the system now automatically adds any new stores it finds and alerts you about stores that are no longer in your POS system. New stores show "Needs Setup" and need a Vendor Store Number assigned before they'll be included in imports.
-
New Feature
Scripts menu with Epicor store diagnostics
You can now run diagnostic queries from the Scripts menu to troubleshoot store character issues in Epicor databases without writing SQL.
-
New Feature
Shift-click store picker for selective POS imports
When you need to refresh data for just a few stores instead of all of them, hold Shift when you click "Update Point of Sale Data." A window will appear where you can check the stores you want to update, then click Import.
-
New Feature
Reset POS Data command
You can now reset your Point of Sale data from the Tools menu if you need to clear everything and re-import from scratch. The system will ask you to confirm before deleting anything, and you'll need to re-import your POS data afterward.
-
New Feature
Bulk SKU entry via paste
Use Tools → Enter Bulk List to paste a comma-separated list of SKUs from your clipboard. The system will look them up and add any matches to your catalog item list.
-
New Feature
Bulk SKU entry via paste
Click Tools > Enter Bulk List to paste a list of SKUs from your clipboard or type them separated by commas or line breaks.
-
New Feature
Bulk import from pasted SKU list
Use Tools > Enter Bulk List to paste SKUs from emails, spreadsheets, or other sources. Separate SKUs with commas, spaces, or place one per line.
-
New Feature
Re-import Epicor files without Eagle server connection
When importing Epicor data, you'll now be asked if you want to re-import the last downloaded file instead of downloading fresh data from the Eagle server. This lets you refresh your pricing grid even when the Eagle server is offline.
-
New Feature
Zone override capability
You can now override the pricing zone for any Ace store by entering a different zone number in the "Zone Override" column.
-
New Feature
BisTrack DIB6828 format support
Stores using the DIB6828 export format from BisTrack can now import their data directly without manual conversion.
-
New Feature
Streaming import mode for Epicor
Turn on "Use Streaming Import" in Settings > Connections to reduce memory usage during Epicor imports, especially helpful for very large inventory files.
-
New Feature
POS store number reassignment handling
If you're removing a store because its POS number was reassigned to a different location, select "POS number reassigned" — this allows the new store with that number to import correctly without conflicts.
-
New Feature
Vendor data freshness check before import
Before importing store files, you'll now see a reminder to sync vendor data if it's more than a day old. Fresh vendor data ensures your pricing analysis and margins are calculated accurately.
-
New Feature
Vendor data freshness prompt before import
If your vendor catalog hasn't been updated recently, you'll see a prompt asking whether you want to sync it before importing store files. Syncing first ensures your pricing analysis uses the latest vendor cost and catalog information.
-
New Feature
Unmapped Store Character Detection and Exclusion
If the Epicor import finds store characters that aren't assigned to vendor store numbers, you'll get a notification listing them and can choose to automatically exclude them from future imports.
-
New Feature
Unmapped store character detection and exclusion prompt
If the INDecoded file contains stores you haven't mapped yet, you'll get a notification after import with the option to automatically exclude those unmapped stores from future imports, or you can assign store numbers to them in Options > Connections.
-
Improvement
Fallback data source for import history display
You can now see how many records exist for each store location even if the system hasn't tracked recent imports.
-
Improvement
Data Aging displays per-store record counts from main tables
You'll now see how many records each store has and when they were last updated, even if import history isn't tracked.
-
Improvement
Session-based MySQL connection availability caching
If your MySQL Compass server is unavailable, import operations will now complete much faster by skipping repeated connection attempts. To restore MySQL functionality, go to Tools > Options and use the Save & Test button.
-
Improvement
BisTrack mainTable insert optimization
BisTrack store imports now process inventory data more efficiently, reducing import time for large catalogs.
-
Improvement
BisTrack bulk import with Sep library
When importing multiple BisTrack store files, all files are now loaded together in one operation, making the import process much faster.
-
Improvement
BisTrack bulk import performance optimization
When importing multiple BisTrack CSV files, the system now uses Sep-based batch loading to combine all store files into a single staging table, performs data cleanup once instead of per-file, and creates a compound index on Store and SKU before processing. This significantly reduces import time when loading data for multiple store locations.
-
Improvement
Simplified BisTrack batch import workflow
Importing multiple BisTrack CSV files at once is now faster and more reliable.
-
Improvement
BisTrack batch import engine rewrite
Multi-store BisTrack imports are now much faster and more reliable.
-
Improvement
Cross-file batching for faster BisTrack imports
BisTrack data imports now complete much faster, especially when importing multiple files at once.
-
Improvement
Optimized BisTrack preloaded import pipeline
BisTrack imports for Do-It-Best stores now complete faster with less database overhead.
-
Improvement
Automatic detection of store-specific New Product Form format
When importing a New Product Form with a Yard # column, products will be added only to the store listed in the spreadsheet, not to all stores in your system.
-
Improvement
Store-specific New Product Form detection
The import process now recognizes when a New Product Form includes store identification (store number and name in the header). When detected, the system reads the store information and automatically assigns all imported products to that specific store location. This handles the updated BisTrack form format where store-specific forms include a "Yard #" column and shift the SKU column position.
-
Improvement
SKU count column added to Epicor store scanner results
When you scan an Epicor inventory file, you'll now see how many items each store code has. The stores with the most items appear first, which helps you match the codes to your actual store locations.
-
Improvement
SKU count column added to store scanner grid
The store mapping screen now shows how many products were found for each store code, making it easier to match codes to your actual store locations.
-
Improvement
Epicor store mapping enabled by default
When importing from Epicor, store numbers from your POS system will automatically be converted to match the store numbers used in vendor catalogs like Ace Hardware, making pricing comparisons more accurate without additional setup.
-
Improvement
Epicor store mapping default changed to enabled
Store number mapping for Epicor systems is now on by default. If your store doesn't use different store numbers between Epicor and Margin Master, you can turn this off in the Options settings.
-
Improvement
File Transfer Progress Display
File download progress now shows "Transferred 45.3 MB..." instead of large byte numbers.
-
Improvement
Enhanced progress display during Epicor file download and processing
During Epicor sync, you'll now see clearer progress messages showing file sizes in MB/GB and which store is being processed out of how many total stores.
-
Improvement
Enhanced Epicor store character display
When setting up Epicor store characters, you'll now see the actual symbol for extended characters alongside the numeric code, making it easier to identify which character you're working with.
-
Improvement
Auto-create Store Manager Info entries for new Epicor stores
When new stores are found during an Epicor import, they're automatically added to your Store Manager Info. You'll see a message listing the new stores and asking you to assign vendor store numbers in Options > Connections.
-
Improvement
Automatic store detection and registration for Epicor imports
When new store locations appear in your Epicor data, Margin Master will now add them to your store list automatically and remind you to assign vendor store numbers in the Connections settings.
-
Improvement
Context-aware INDecoded file selection
When you rescan Epicor stores, the system will now show you the date of your last downloaded file and ask whether you want to use it or get a fresh copy from the server. If the server isn't available, you can still use the existing file.
-
Improvement
Automatic Epicor store ordinal migration at startup
If you use Epicor and have binary store data, the app now automatically converts it to the correct format when it starts, preventing potential store mapping issues during imports.
-
Improvement
Store deletion reason dialog for Epicor Eagle stores
When you try to remove an Epicor store that still appears in your POS system, you'll see a dialog asking why you're removing it. Choose the option that best describes your situation before confirming the deletion.
-
Improvement
Enhanced store number display for Epicor systems
Extended the POS-to-Vendor store number mapping display to work with all Epicor store configurations. Previously, this feature only worked for stores using MySQL/Compass imports, but now applies to all Epicor stores since they all use the Store Manager for store number mapping.
-
Improvement
Automatic retry for transient network errors during POS connection tests
When testing your POS connection in Settings, brief network interruptions will no longer cause the test to fail immediately. The system will now automatically retry a few times before showing an error, making connection testing more reliable.
-
Improvement
Automatic retry for transient connection failures
When testing your POS connection in Settings, the test will now automatically retry if it hits a temporary network issue, making the test more reliable.
-
Improvement
Chunked queries for large datasets
The reconciliation process fetches remote SKUs in batches of 10,000 records to handle stores with large inventories efficiently, with progress logged for each batch. Orphaned records are deleted in batches of 1,000 to maintain database performance.
-
Improvement
Added timeout protection for all POS bulk imports
Import operations that would previously freeze the application will now time out after 30 minutes with a clear error message.
-
Improvement
Better logging for bulk import diagnostics
Added detailed logging throughout the bulk import process, including batch progress, FileHelpers parsing errors, timing information, and completion status. This will help identify and diagnose import issues more quickly in the future.
-
Improvement
MySQL SKU reconciliation moved to background with weekly throttle
MySQL Compass imports now complete much faster because SKU cleanup runs in the background instead of during the import process.
-
Improvement
POS table fallback for stores without import history
Stores that imported POS data before import tracking was added will now see when their POS data was last updated, instead of seeing no information.
-
Improvement
POS data fallback when import history unavailable
The Data Aging screen now shows POS data information even if detailed import history is missing.
-
Improvement
Enhanced RockSolid import error handling
Improved error messages for common RockSolid import failures including missing OLEDB drivers, file not found, locked files, and import timeouts. Each error now provides specific guidance on resolution.
-
Improvement
Import record count now calculated for RockSolid
The Data Aging View now shows exactly how many items were imported from RockSolid each time.
-
Improvement
Faster pricing strategy grid loading
The pricing strategy grid now loads noticeably faster when switching between strategies or opening the pricing screen.
-
Improvement
Faster Excel file processing with progress tracking
Excel imports now show detailed progress (rows imported, percentage complete) and run faster, especially for large files with tens of thousands of items.
-
Improvement
Special POS system documentation
Advanced import features like Bistrack DirectConnect (live database queries) and Epicor incremental sync are now fully documented with setup instructions.
-
Improvement
Chunked bulk import with automatic retry for Excel files
Large Excel imports are now more reliable and will continue even if temporary database issues occur.
-
Improvement
Reduced MySQL connection timeout
When MySQL Compass is unavailable, the system will now detect this within 10 seconds instead of waiting up to 5 minutes.
-
Improvement
Automatic settings loading for newly visible tabs
When POS tabs become visible after a POS type change, their settings are automatically loaded in the background, ensuring the tabs are ready to use immediately without requiring manual navigation or refresh.
-
Improvement
Automatic settings cleanup on POS system change
If you're viewing a tab that becomes hidden when you switch POS systems, the screen automatically moves you to a visible tab.
-
Improvement
Switched to asynchronous database connection for Spruce imports
The program will no longer freeze while connecting to the Spruce server—you can still interact with the application during the connection process.
-
Improvement
Added detection and warnings for incomplete MySQL imports
If an import doesn't bring in all your products, the system now alerts support staff with specific details about what went wrong and how to fix it.
-
Improvement
Reduced unnecessary error logging for schema variations
Changed error handling to log a single warning instead of repeated errors when the stext_ext_1 column is unavailable, reducing telemetry noise and making genuine errors easier to identify.
-
Improvement
Reduced error logging severity for auto-update checks
Auto-update check failures (due to SQL connection issues or network problems) are now logged as warnings instead of errors. Since the application continues working normally when update checks fail, these should not be reported as critical errors in telemetry, especially for stores with Named Pipes or other network configuration issues.
-
Improvement
Skip redundant mainTable rebuild for BisTrack
The import process now detects when BisTrack's InsertIntoMainTable.sql has already built the mainTable with pre-aggregated vendor data during import, and skips the redundant DROP+rebuild step in Process Store Data. This eliminates duplicate work and further speeds up the BisTrack import workflow.
-
Improvement
Skip redundant mainTable rebuild for BisTrack
For BisTrack systems using the DIB1040 layout, the import process now detects when the vendor catalog has already been merged into the mainTable during the SQL insert phase and skips the redundant Store-to-mainTable rebuild step, eliminating duplicate processing and improving import speed.
-
Improvement
Manual catalog entries now expire after 7 days
Manual catalog entries that don't appear in your import files within 7 days are automatically cleaned up to keep your data current.
-
Improvement
Manual catalog items now expire after 7 days instead of immediately
Manual catalog items will remain in the system for 7 days, giving you more time before they're automatically removed if they don't appear in your official store data.
-
Improvement
Bulk insert operations replace row-by-row processing
CSV data loading now uses Z.BulkOperations library with pre-compiled column setters instead of building DataTable objects with per-row dictionary lookups. Column mappings are computed once at the start of each file rather than looking up each cell individually, reducing CPU overhead during large imports.
-
Improvement
Single-pass cleanup for BisTrack data
Moved data normalization (quote stripping, store number formatting, deduplication) from per-file processing to a single cleanup operation after all files are loaded. This reduces the number of database operations from N operations (one per file) to a single batch operation, improving performance and consistency.
-
Improvement
Optimized batch parameters for large BisTrack datasets
Set batch flush threshold to 50,000 rows with 10,000-row bulk insert batches and extended timeout to 1 hour, specifically tuned for handling large multi-store BisTrack imports efficiently while maintaining responsive progress feedback.
-
Improvement
Reduced import delays and improved UI responsiveness
The application will remain more responsive during BisTrack imports, and imports will complete several seconds faster.
-
Improvement
Reduced import thread delay
Reduced the post-bulk-upload thread delay from 500ms to 50ms, providing a minor additional performance improvement during the import process without affecting stability.
-
Improvement
Added format validation for BisTrack imports
The system now warns you immediately if a BisTrack file is in an unexpected format, instead of appearing to complete successfully while importing no data.
-
Improvement
Enhanced BisTrack import progress messages
The import progress window now shows more detailed messages about what stage each store is in during import, making it easier to track progress.
-
Improvement
Enhanced BisTrack store build status messages
Progress messages during BisTrack imports now clearly show which step is running and how many rows are being processed for each store.
-
Improvement
Enhanced import logging for store assignments
Import logs now display the store number and name when processing store-specific spreadsheets, making it easier to verify which location's inventory is being updated during the import process.
-
Improvement
Optimized duplicate removal during BisTrack cleanup
Updated the deduplication logic to work directly with cleaned store and SKU fields rather than re-trimming them during duplicate detection, allowing the database to use indexes for faster processing.
-
Improvement
Extended command timeouts as safety margin
Increased command timeout limits during critical import operations: store rebuild timeout raised from 120 to 600 seconds, and the main table insert during RockSolid import raised from 30 to 300 seconds. These provide additional headroom for large datasets or constrained hardware environments, though the optimized vendor data join should keep actual execution times well below these limits.
- Improvement Streaming import option for Epicor
-
Improvement
Epicor import now works with existing files when FTP is unavailable
You can now re-run Epicor imports using previously downloaded data files without needing to configure FTP settings.
-
Improvement
FTP credentials no longer required for same-day Epicor reimports
You can now reimport today's Epicor data without needing FTP credentials configured, as long as the file was already downloaded once today.
-
Improvement
Store characters sorted by size for easier identification
Stores are now listed with the largest ones first, so your main locations appear at the top of the list.
-
Improvement
Enhanced MySQL connection diagnostics
Connection testing now logs MySQL server identity information (hostname, version, current database) and attempts to list available databases when permission allows. This additional logging helps diagnose cases where the configured MySQL server IP routes to an unexpected Eagle instance or database.
-
Improvement
Enhanced MySQL connection diagnostics
Added diagnostic logging during MySQL connection testing to capture hostname, server version, current database name, and available databases. This information helps troubleshoot connection issues and verify the correct database is being accessed.
-
Improvement
Epicor Import Progress Messages
During Epicor import, you'll see exactly how much of the file has been processed with megabyte counts and percentages.
-
Improvement
Reset logic now prevents duplicate processing of dropped tables
The reset process now drops per-store tables first, then queries the database again to truncate remaining POS-specific tables. This ensures already-removed tables aren't processed twice and improves the efficiency of the reset operation.
-
Improvement
Enhanced table cleanup logic
The reset operation now uses a two-phase approach: first dropping per-store main tables, then truncating remaining POS-specific tables. This ensures dropped tables aren't visited twice and provides cleaner database state for fresh imports.
-
Improvement
Dynamic human-readable descriptions for excluded stores
When you enter store exclusions, the software now shows you exactly which stores you're excluding with their names and codes instead of just showing raw symbols.
-
Improvement
Real-time display of excluded stores with readable labels
When you enter stores to exclude, you'll now see a description below showing exactly which stores are being excluded in plain language.
-
Improvement
Progress updates now visible during Epicor data processing
The import progress screen now shows real-time status updates instead of appearing stuck.
-
Improvement
POS reset logging now shows table cleanup count
When using the POS data reset tool, you'll now see confirmation of how many tables were removed, helping you verify the cleanup worked correctly.
-
Improvement
POS data reset now logs table counts
When resetting POS data through Support Tools, the system now counts and logs how many per-store tables are being dropped. This diagnostic information helps troubleshoot data reset operations and confirm the expected tables were removed.
-
Improvement
Enhanced progress feedback during MySQL Compass import
The import progress window now displays which specific store's extended fields are being updated during post-import processing, making it easier to track progress and identify if a particular store is experiencing delays.
-
Improvement
Enhanced import progress feedback for MySQL Compass
The import screen now shows more detailed progress information, including which store is being processed during extended field updates.
-
Improvement
Added offline and error handling for Epicor downloads
Added three new service methods: FindMostRecentINDecodedFilePath (locates the latest cached file), CanConnectToFtpAsync (tests server connectivity), and DownloadAndDecodeINFileAsync (downloads and decodes the IN file without importing). These enable the Store Manager to make intelligent decisions about file availability and server connectivity before prompting the user.
-
Improvement
Added FTP connectivity check before download attempts
The Epicor FTP extractor service now tests server connectivity before attempting downloads. This allows the Store Manager to provide helpful messages when the server is unreachable and offer appropriate alternatives (use cached file or wait until connected).
-
Improvement
Store Manager auto-heals unassigned store rows
When you open the Store Manager and scan for Epicor stores, any previously unassigned stores will now be automatically mapped to the correct vendor store numbers.
-
Improvement
Enhanced store discovery with automatic mapping
When you scan for stores in the Store Manager, any new store numbers that match previously mapped stores will be assigned automatically.
-
Improvement
Ongoing supplemental migration on startup
The Store Manager will now automatically detect and add any missing store configurations each time you open Margin Master.
-
Improvement
Store Manager initialization includes format migration
The Store Manager screen now shows only active, correctly-formatted store mappings.
-
Improvement
Enhanced store mapping supplement process
Improved the GlobalFileConfig supplement routine to match stores by their position in the POS system (ordinal) rather than only by vendor store number. When a store row exists without a vendor store number assigned, the supplement process now updates that row with mapping data instead of creating a duplicate entry. This ensures RSC codes and Ace zone overrides are properly applied to discovered stores.
-
Improvement
Store Manager now auto-saves on close
Your store configuration changes will now save automatically when you close the Store Manager window, so you won't lose any edits.
-
Improvement
Epicor Eagle stores protected from premature deletion
If you try to delete an Epicor Eagle store that still exists in your POS system, Margin Master will mark it as Excluded instead and explain that the store would just come back on the next import.
-
Improvement
Clearer messaging for Epicor store deletion attempts
Warning messages when managing Epicor stores now clearly tell you which part of your Epicor system the store comes from.
-
Improvement
Debugger mode protection for MySQL imports
Added a safety check that prevents MySQL imports from running while the application is attached to a debugger, avoiding potential connection conflicts during development troubleshooting.
-
Improvement
Smart handling based on deletion reason
If you say a store number was reassigned to a different location, Margin Master will disconnect the old store from that POS number so the correct store can use it.
-
Improvement
Added automatic single-store mapping for Epicor MySQL
Single-store Epicor MySQL setups now configure themselves automatically without needing manual store matching.
-
Improvement
Single-store automatic mapping and self-healing
Single-store locations now require no manual store setup — the system automatically connects your Margin Master store to the correct Epicor MySQL store.
-
Improvement
Enhanced CSV parsing for quoted fields with special characters
The new CSV import logic uses RFC-4180 compliant parsing to correctly handle product descriptions containing commas, quotes, and other special characters (e.g., descriptions like "1,751" or "5/8" BANDING"). This prevents data corruption and ensures fields are parsed accurately even when they contain delimiter characters within quoted values.
-
Improvement
Copy to Clipboard for query results
Click "Copy to Clipboard" to copy query results as tab-separated text that can be pasted into Excel or emails.
-
Improvement
Store number display/sort options now accessible to Compass users
Compass users can now see and adjust how store numbers are displayed and sorted in store selection lists—these settings were previously hidden.
-
Improvement
Enforce POS-to-vendor store number mapping for all Epicor stores
Store number mapping is now always on—every POS store must have a Vendor Store # assigned in Store Manager for data import to work.
-
Improvement
Store number display options now always visible for Epicor
Store number display and sorting preferences are now always available in Epicor settings, making it easier to configure how store numbers appear in selection lists.
-
Improvement
Store number display settings now always visible for Epicor users
Settings for how store numbers are displayed and sorted are now always visible when using Epicor.
-
Improvement
Enhanced yard detection in import spreadsheets
The new-product import now looks for an explicit "Yard" or "Store #" column header anywhere in the spreadsheet, reading the yard value from either the metadata row or data rows. This is more robust than the previous fixed-cell layout and adapts if the SKU column position changes.
-
Improvement
Malformed rows now logged as warnings with line numbers
When rows are skipped during import, you'll see warning messages showing exactly which line numbers had problems and why.
-
Improvement
Better error handling for import file validation
The ImportFileIsValid method in RSImportFileHelperService now distinguishes between files that should be ignored (wrong format for the configured POS system) versus genuine fatal errors (locked files, I/O errors, type load failures). A sticky exception is no longer set when encountering files with mismatched columns or headers, preventing one bad file from poisoning the entire import pipeline.
-
Improvement
Clearer status messages when non-POS files are skipped
When a file is skipped because it doesn't match the expected POS format, the import status log now displays "No valid records found in file — ignoring (wrong format for this POS)" to clarify why the file was not processed.
-
Improvement
Enhanced bulk import performance and diagnostics
Replaced List-based duplicate checking with HashSet for O(1) lookups instead of O(n), significantly improving performance on large files. Added comprehensive progress logging including batch write counts, error summaries, and elapsed time tracking. Compiled type definitions are now preferred over Roslyn-compiled .map types to ensure field converters work correctly.
-
Improvement
Expanded vendor data reset coverage
The "Reset Vendor Data" command now clears all modern cloud sync tables for Ace Hardware (AceCatalogRecords, AceZoneRecords, AcePlanogramRecords, AceMappPricingRecords, etc.) and Do-It-Best (DIBCatalogRecords, DIBPriceLevelRoundingDetails, etc.) in addition to legacy tables. This ensures a complete reset of all vendor data and forces a full re-sync on the next cloud update.
-
Improvement
Enhanced vendor data reset with modern sync tables
The existing "Reset Vendor Data" feature has been expanded to include all modern cloud sync tables for Ace Hardware, Emery Jensen, and Do-It-Best, including catalog records, zone records, planogram records, taxonomy records, and pricing records. The feature now clears both legacy and modern sync metadata tables, ensuring a complete reset that forces a full re-sync on the next vendor data update.
-
Improvement
Simplified demo database backup directory handling
Streamlined the demo mode cloud database update process to use the configured backup directory directly instead of querying the SQL Server for its backup path, improving reliability and consistency with application settings.
-
Improvement
Field mapping reference tables
Each POS guide includes complete field mapping tables showing which POS fields map to which Margin Master columns, including max field lengths, data converters applied (MoneyConverter, HistoryConverter, TrimLeadingZeros), special handling (Ace Direct SKU suffix removal, zone pricing, MAP pricing), and notes on unique behaviors like Catalyst's comma-to-hyphen description cleaning or CounterWorks' margin percentage history fields.
-
Improvement
Reduced per-store query timeout from 10 minutes to 2 minutes
Each store's data will now timeout after 2 minutes instead of 10 minutes if the server isn't responding, making failed imports complete faster.
-
Improvement
Enhanced retry logic with extended timeouts
Replaced the standard database execution method with an enhanced version that includes automatic retry logic (up to 3 attempts), exponential backoff between retries, and extended command timeout (120 seconds, doubling on each retry up to 480 seconds). This ensures large imports can complete successfully even on slower hardware like SQL Server Express.
-
Improvement
Better FTP connection error message
If the Eagle server connection fails, you'll now see a clearer error message that directs you to the correct settings location.
-
Improvement
Automated file management and logging
Processed files are automatically organized into an "Imported" folder so you can track what's been imported, and a log file shows exactly what happened during each import.
-
Improvement
Enhanced import logging for troubleshooting
Reality check validation messages now clearly distinguish between "pre-sync" and "post-sync" checks, and include detailed statistics (row counts, percentages, and thresholds) to help diagnose import issues. The pre-sync threshold was adjusted from 80% to 50% to reduce false positives while still catching seriously incomplete data.
-
Improvement
Enhanced logging for SKU Level Exceptions processing
The strategy execution report now shows more detailed information about SKU Level Exceptions processing, including why exceptions were skipped or how many items were affected.
-
Improvement
Reduced unnecessary database error retries
The system now recognizes when database tables don't exist (SQL error 208) and immediately reports the issue instead of wasting time retrying the operation. Also added special handling for view-related migration errors (SQL error 4909).
-
Improvement
Removed unnecessary delays during catalog import
Catalog imports now complete more quickly without unnecessary pauses.
-
Improvement
Removed unnecessary delays during bulk import
Removed artificial 1-2 second delays after bulk insert operations that were slowing down the import process without providing user benefit, now that proper progress messages are displayed instead.
-
Improvement
Store number tracking for batch imports
The import service now maintains a map of which store each CSV file belongs to during batch processing, preserving store-level visibility throughout the import workflow. Store numbers are normalized to match the cleanup script's format (trimming quotes and leading zeros).
-
Improvement
Optimized column mapping with pre-computed setters
Replaced per-row dictionary lookups with pre-computed column setter actions, eliminating repetitive header-to-column resolution during bulk data loading. This micro-optimization reduces CPU overhead during high-volume CSV parsing.
-
Improvement
Reduced memory usage during large BisTrack imports
Implemented a 50,000-row buffer that flushes periodically during import, keeping memory usage bounded even when importing very large datasets across multiple files. This prevents memory spikes while maintaining fast import speeds.
-
Improvement
Optimized BisTrack multi-file batch processing
Importing multiple BisTrack CSV files is now significantly faster—all files are loaded in one batch before store tables are created, reducing processing time and preventing duplicate cleanup operations.
-
Improvement
Added handler completion tracking for BisTrack imports
Enhanced the Import Manager to track whether the BisTrack preload handler has already completed all store builds on its own service instance. When the handler completes successfully, individual files are now marked as imported and renamed without running additional SQL processing, improving efficiency and preventing conflicts.
-
Improvement
Support for legacy raw-character store identifiers
The store matching system now handles both modern ordinal format ("135") and legacy raw-character format ("W") for stored values, ensuring backward compatibility with older data while maintaining correct behavior across different MySQL character set configurations.
-
Improvement
Enhanced Epicor Import Manager integration messaging
If you're using Epicor with MySQL Import Manager, the settings screen now clearly explains that you need to set excluded stores in the Import Manager instead.
-
Improvement
Enhanced STOREMATCHUP value format handling
Updated the STOREMATCHUP migration logic to use PosStoreCharHelper.OrdinalToChar() for converting POS store identifiers, allowing it to correctly handle both ordinal format (e.g., "87") and legacy character format (e.g., "W") stored in GlobalFileConfig.Value. This ensures robust parsing regardless of how the original configuration was stored.
-
Improvement
Enhanced store character conversion logic
Introduced PosStoreCharHelper.OrdinalToChar to handle conversion of both numeric ordinals (e.g., "87") and legacy character values (e.g., "W") when processing STOREMATCHUP entries, making migration more robust across different configuration formats.
-
Improvement
Renamed supplement method to reflect upsert behavior
Renamed InsertMissingStorematchupEntriesAsync to UpsertMissingStorematchupEntriesAsync to accurately reflect that it now both inserts new entries and updates existing ones, rather than only inserting.
-
Improvement
Active stores summary now excludes "Not Found" stores
The store configuration summary now gives a more accurate count by excluding stores that no longer exist in your POS system.
-
Improvement
Debugger mode protection
Added a guard to prevent MySQL imports from running while the debugger is attached, matching the behavior of the standard Compass import path and preventing unexpected runtime behavior during development troubleshooting.
-
Improvement
Automatic recovery from failed imports
If an import fails to retrieve all products, the system will automatically try again with a full download before showing an error.
-
Improvement
Store number normalization in Data Aging screen
Store numbers shown in Data Aging now match the store numbers you use everywhere else in Margin Master.
-
Improvement
Progress callback mechanism for index rebuild operations
Added an optional progress callback parameter to RebuildAllManagedIndexesAsync that reports per-table progress, wired to the splash screen at the post-import call site. This is an additive change with no modification to the underlying rebuild logic or SQL.
-
Improvement
Enhanced post-import feedback
The loading screen now warns you when an operation might take several minutes, so you know to be patient.
-
Improvement
Reduced telemetry noise from recoverable conditions
Eliminated excessive error logging (62+ occurrences affecting Do-It-Best stores) from two scenarios that are recoverable and do not represent actual failures. These conditions now handle gracefully with appropriate warnings or auto-remediation.
-
Improvement
Import file selection now prefers most recent export
The system will always use your most recent export file, even if older files are still in the import folder.
-
Improvement
Store matching logic improved for partial imports
Enhanced the store-skipping logic to correctly identify stores by vendor store number (e.g., DIB numeric codes like "1818") in addition to single-character Epicor store identifiers, ensuring accurate subset filtering during partial imports.
-
Improvement
Store mapping now mandatory for all Epicor users
All Epicor stores now use the Store Manager to map POS store numbers to vendor store numbers—this is no longer optional.
-
Improvement
Extended command timeout for catalog cleanup operations
Increased the command timeout to 600 seconds for discontinued item cleanup queries to prevent timeouts when processing very large manual catalog item sets, particularly during concurrent import scenarios on SQL Express.
-
Improvement
Added diagnostic logging throughout MySQL import pipeline
Added logging at key steps: eligible store count, per-store update counts, date filters applied, Compass_IN row count after import, and warnings when zero SKUs are found. Also populated empty catch blocks with error logging. This makes it easier to diagnose silent import failures.
-
Improvement
Enhanced MySQL Compass import logging
Added comprehensive diagnostic logging throughout the MySQL Compass import process, including: total store count vs. eligible stores, per-store update counts with date filters, final Compass_IN row counts, and specific warnings when zero SKUs are found. Also added error logging with full exception details when INX processing fails. This will significantly improve troubleshooting for silent import failures.
-
Improvement
Enhanced Add Catalog Items dialog layout
Restructured the Add Catalog Items dialog to include a new menu bar at the top with the Tools menu, increasing the dialog height slightly to accommodate the additional functionality while maintaining the existing search and manual add workflows.
-
Improvement
Batch SKU lookup optimization
Implemented batched database queries that process up to 500 SKUs at a time when performing bulk lookups, preventing SQL parameter limit errors and improving performance for large imports. Query logic supports both Ace Hardware and Do-It-Best catalog formats.
-
Improvement
Automatic duplicate handling in bulk imports
When importing multiple SKUs, duplicates are automatically removed and you'll see a summary of what was added and what wasn't found.
-
Improvement
Integrated rebuild workflow
After importing new products, you'll be asked if you want to rebuild your data right away so the new items appear in your pricing grid immediately.
-
Improvement
Enhanced error logging for data type issues
Added specific logging for DateTime overflow errors and improved error messages to include entity type names, making it easier to diagnose data import problems and invalid date values.
-
Improvement
Component license caching
IPWorks runtime licenses are now cached locally using encrypted storage via RetailerSoft.ComponentLicensing. Cache is checked first on startup (avoiding API call), with automatic fallback to Blazor API fetch and appsettings.json base64 values. Added RefreshFromApiAsync method called by StartupCheckService when license validation fails, ensuring the next startup gets fresh keys. Also removes obsolete HasMultipleRSCs application setting (now computed on-demand from STORERSC global config).
-
Improvement
Store Mapping Validation During Import
The system now better validates which store data should be imported based on your store mapping configuration.
-
Improvement
Removed connection test popup dialogs
Connection test results no longer appear in popup windows that you have to close—everything stays visible on the settings screen.
-
Improvement
New service methods for INDecoded file management
Added three new methods to the Epicor FTP service: FindMostRecentINDecodedFilePath() locates the newest cached scan file, CanConnectToFtpAsync() tests server availability, and DownloadAndDecodeINFileAsync() downloads and decodes the IN file without importing. These enable smarter file handling throughout the application.
-
Improvement
Consistent special-character handling across all MySQL queries
Updated all MySQL Compass queries throughout the import pipeline—including inventory (IN), deleted items (dw_item), discontinued items (INX), group pricing, and orphan reconciliation—to use ASCII() for store character matching instead of UNICODE(). This ensures all queries use the same Windows-1252 byte key (matching MySQL ORD()) regardless of how the character is encoded in the local database.
-
Improvement
Validation against live MySQL as canonical source
Enhanced the store reconciliation logic to use the live MySQL database as the authoritative source of truth when recovering corrupted identifiers, ensuring recovered values are always validated against actual data rather than relying solely on string parsing.
-
Improvement
Main Table Rebuild Progress Messages
Sync progress now shows actual store numbers (e.g., "store 12345") instead of technical table names, making it easier to track which stores are being updated.
-
Improvement
Main table rebuild now uses STOREMATCHUP as authoritative store list for Epicor
When Epicor store mapping is enabled, the main table rebuild process now uses the store numbers defined in STOREMATCHUP configuration as the authoritative list, rather than scanning for distinct StoreNumber values in the Epicor table. This ensures main tables are created for all configured stores even if they temporarily have no data in the POS extract.
-
Improvement
Handler registration and priority ordering
Handlers are registered in `ServiceCollectionExtensions` with explicit priority: DIB6828 first (most specific headers), DIB1040 second (≥10 generic header matches), DirectConnect last (empty file list + valid config). The factory tests each handler's `CanHandleAsync` in registration order and returns the first match, ensuring the most specific handler wins when multiple formats could apply.
-
Bug Fix
Import engine now handles native SQL libraries correctly
POS file imports will no longer fail with compilation errors on computers where certain SQL Server support files are installed.
-
Bug Fix
Fixed Paladin .map file compilation failure on .NET 10
Paladin imports that were failing with compilation errors will now complete successfully.
-
Bug Fix
Improved native DLL detection during Paladin .map compilation
Fixed an error that prevented Paladin .map files from importing successfully on some computers.
-
Bug Fix
RockSolid import no longer hangs during file processing
If RockSolid imports were previously getting stuck with the app showing "Not Responding," they will now complete almost instantly.
-
Bug Fix
RockSolid import no longer hangs on network paths
If your RockSolid data file is stored on a network server and imports were freezing, they will now complete successfully. The import process is also faster and more reliable.
-
Bug Fix
Settings migration duplicate key errors resolved
Fixed a crash during application startup that could occur when migrating settings from older versions of Margin Master. When multiple legacy configuration entries shared the same setting name, the migration process could attempt to create duplicate database records, causing the application to fail to start. The migration now properly detects and skips duplicates within each batch of settings being converted.
-
Bug Fix
Support issue pill now shows correct issue ID
The title bar pill that displays open support issues now shows the actual issue ID (e.g., "MM-1099") instead of the hardcoded placeholder "#1". This makes it easier to identify and reference support issues directly from the main window.
-
Bug Fix
Critical crash fix in data mapping system (MM-1105)
Fixed a crash that could occur during data import.
-
Bug Fix
Data Aging screen now displays accurate import record counts
When you view the Data Aging screen, you'll now see the correct number of items that were imported from your POS system, making it easier to verify that imports are working properly.
-
Bug Fix
Data Aging screen now displays correct import record counts
When you view the Data Aging screen after importing POS data, you'll now see the actual number of records imported instead of zero.
-
Bug Fix
Fixed broken file path in Epicor FTP download
Stores using Epicor POS systems with FTP connectivity will no longer see "No Data Imported" errors caused by the download failing silently.
-
Bug Fix
Corrected FTP download path construction for Epicor imports
FTP downloads for Epicor POS data now save to the correct folder and complete successfully.
-
Bug Fix
Corrected help button placement in Import Manager
The help button on the Import Manager screen now appears next to the Import Path label instead of floating over the grid, making it easier to access without blocking your view of import files.
-
Bug Fix
RockSolid imports now recorded in ImportProcessing table
After importing from RockSolid, the Data Aging View now shows the correct number of records imported and when the import occurred.
-
Bug Fix
RockSolid imports now recorded in import history
After importing from RockSolid, you can now see when the last import occurred and how many records were imported in the Data Aging View.
-
Bug Fix
Data Aging View now tracks Epicor INFILE imports
When you import Epicor data, the Data Aging View will now show the correct import date and number of records processed for each store location.
-
Bug Fix
Epicor import tracking in Data Aging View
The Data Aging screen will now show the last import date and record counts for Epicor stores, making it easier to verify that your pricing data is current.
-
Bug Fix
Order Indicator field now imports from MySQL Compass
If you've renamed the PL field to "Order Indicator" (or any other name), the selection box will now show values after importing from MySQL Compass instead of appearing empty.
-
Bug Fix
Order Indicator field now imports from Compass data
The Order Indicator column now properly shows values like T, C, or S for items after importing Compass data.
-
Bug Fix
Data Aging View now displays import history for MySQL Compass
The Data Aging screen now correctly shows when your pricing data was last imported and how many items were imported for each store location.
-
Bug Fix
Data Aging View now displays correct record counts for MySQL Compass Epicor
When viewing the Data Aging screen after importing MySQL Compass Epicor data, you will now see the correct number of imported records for each store location instead of zero.
-
Bug Fix
MySQL date filter now includes NULL timestamps
Stores using MySQL Compass that had missing or NULL date stamps in their inventory data will now import successfully instead of silently skipping all records.
-
Bug Fix
MySQL Compass import now handles NULL update timestamps
Stores using MySQL Compass will now see all products imported successfully, even if some products are missing update timestamps in the database.
-
Bug Fix
CounterWorks Excel import file format mismatch
If you use CounterWorks POS, the Import Manager will now correctly find and process Excel export files from your system.
-
Bug Fix
BCP version check now works without .map files
Data imports will no longer fail with an error when certain internal configuration files are missing. The import process now finds the files it needs using a backup method.
-
Bug Fix
BCP version check now works without mapping files
Fixed an issue where Margin Master might fail to start properly with certain POS system types that don't require mapping files.
-
Bug Fix
Fixed Excel file detection in Import Manager
When clicking to select an import file, Excel files (.xlsx) now appear correctly in the file browser instead of being hidden.
-
Bug Fix
Import file detection no longer requires .map files
The Import Manager will now show available files to import for all supported POS systems. Previously, some systems would show an empty file list even when import files were present in the selected folder.
-
Bug Fix
Import file detection for pre-compiled POS types
When opening the Import Manager, all available files from your POS system will now be properly detected and displayed, regardless of how your system is configured.
-
Bug Fix
Counterworks Excel import column mapping corrected
If you import Counterworks data from Excel files, the import will now complete successfully instead of failing with column errors.
-
Bug Fix
Fixed CounterWorks Excel column mapping
When importing a CounterWorks Excel file, the product numbers (PARTNO) are now correctly recognized and imported as SKU numbers.
-
Bug Fix
STORE column incorrectly named in COUNTERWORKS import
Store numbers from COUNTERWORKS imports now correctly populate the STORE column in the pricing grid.
-
Bug Fix
Epicor MySQL import crash resolved
Fixed an error that prevented Epicor MySQL stores from importing their sales data — imports now work correctly.
-
Bug Fix
Removed non-existent columns from BisTrack catalog insert
Fixed an error that stopped Do-It-Best items from being added to your store's inventory when using BisTrack.
-
Bug Fix
Removed unsupported DIB multiplier columns from catalog add operation
Previously, trying to add Do-It-Best items from the catalog would fail with a database error on BisTrack systems. This now works correctly.
-
Bug Fix
MySQL Compass connection test button restored
You can now click "Test & Save Connection" to verify your MySQL Compass database settings are correct. The button will be disabled while the test is running.
-
Bug Fix
Added cancel button support to Spruce data import
If a Spruce data import is taking too long, you can now click the Cancel button on the progress screen to stop it instead of having to restart your computer.
-
Bug Fix
SQL timeout during vendor data merge
Stores with large catalogs will no longer experience failed imports that result in missing vendor pricing information.
-
Bug Fix
Epicor + Do-It-Best main table data now displays correctly
If you use Epicor and are a Do-It-Best member, your store data will now appear correctly in the pricing grid after import. Previously, the grid would be empty even after a successful import.
-
Bug Fix
Fixed incremental import logic after database schema changes
Pricing data from MySQL Compass stores will now fully reload automatically when the system detects the database needs maintenance, instead of showing incomplete inventory.
-
Bug Fix
Fixed import order causing data loss during SQL Express upgrades
After a database upgrade, the system will now automatically import your complete inventory from MySQL Compass instead of only importing recent changes, preventing missing products in your pricing grid.
-
Bug Fix
Automatic cleanup of orphaned store data on import
If your database had leftover data from old stores or a previous setup, those phantom stores will no longer appear in reports or affect your pricing calculations.
-
Bug Fix
BisTrack import now handles commas in product descriptions
If your BisTrack import was failing with an error about "Delimiter ',' not found," this fix resolves that issue. Product descriptions with commas (like brightness ratings or compound item names) will now import correctly.
-
Bug Fix
Prevent SqlDateTime overflow in pre-compiled POS imports
Imports from Paladin, Falcon, RockSolid, RockSolidMax, Transact, Bistrack, and Epicor will now complete successfully instead of failing silently.
-
Bug Fix
Added database index to prevent timeout during group table creation
Fixed a performance bottleneck that caused the application to freeze or timeout when working with pricing groups across multiple stores with large inventories.
-
Bug Fix
Resolved store group creation timeout for MySQL Compass stores
Large store groups (like RURAL items) will now save successfully without timeout errors when using Compass POS systems.
-
Bug Fix
Display Summary panel shows all zeros after strategy execution
After executing a pricing strategy, the Display Summary panel at the bottom left now correctly displays the totals for price increases, decreases, average change, and inventory value instead of showing all zeros.
-
Bug Fix
Removed timeout limit on BisTrack main table imports
Large BisTrack stores will now see their complete inventory imported into Margin Master instead of only a partial list.
-
Bug Fix
Suppress confirmation dialog during automatic catalog item restoration
When you import from BisTrack, manually-tracked catalog items are still restored automatically, but you won't see a pop-up message about it anymore.
-
Bug Fix
BisTrack import no longer shows unnecessary SKU dialog
You will no longer see an unexpected SKU selection popup after completing a BisTrack import.
-
Bug Fix
Store number list fallback for unconfigured stores
The system now correctly identifies your store number during catalog imports, even if store settings haven't been fully configured yet.
-
Bug Fix
Import failure after database restore
If you restored a database from backup, your next import from Paladin, RockSolid, or Transact may have failed silently. This is now fixed and imports will work properly after restoring backups.
-
Bug Fix
Import history now excludes zero-record import attempts
The Import History panel now shows only successful imports. Previously, failed import attempts with zero records could appear as your "most recent" import, making it unclear when your store data was actually last updated.
-
Bug Fix
Automatic migration of legacy SKU Level Exceptions steps
When loading a pricing strategy, the application now detects SKU Level Exceptions steps that were imported with prefixed names (such as "SP: Sku Level Exceptions" from legacy systems). If the canonical special step already exists, the duplicate is automatically removed. If no canonical version exists, the legacy step is migrated to the correct key and configuration format. This prevents the step from being incorrectly executed as a regular pricing step, which would cause strategy execution to fail.
-
Bug Fix
Handle missing vendor store number column in Epicor MySQL
Fixed an error that prevented some stores from importing data from Epicor POS systems with older database configurations.
-
Bug Fix
Epicor MySQL import compatibility with older schemas
If your Epicor system doesn't store vendor store numbers in its database, imports will now complete successfully instead of showing an error.
-
Bug Fix
Data import no longer crashes on stores without DIB mailbox pricing table
Importing data will no longer fail for Do-It-Best stores that aren't set up with mailbox pricing integration.
-
Bug Fix
Paladin import now handles missing DIB mailbox table
If your store uses Paladin and Do-It-Best but doesn't have DIB mailbox pricing data, imports will now work correctly instead of failing with an error.
-
Bug Fix
Fixed Validate License button remaining disabled
The Validate License button now becomes available as soon as you enter a store number and select your vendor and POS system, allowing you to proceed without getting stuck.
-
Bug Fix
Import no longer fails when POS system is actively writing to file
Imports will no longer fail with "file in use" errors when your POS system is writing data at the same time.
-
Bug Fix
Guard against empty vendor store number during MySQL import
The system now safely skips stores with missing vendor store numbers during import instead of crashing.
-
Bug Fix
Import validation now checks for empty vendor store numbers
If your Epicor system has stores with missing vendor numbers, the import will no longer crash—those stores will simply be skipped.
-
Bug Fix
Skip malformed database tables during pricing analysis
The pricing analysis tools will no longer crash when encountering incomplete store data from MySQL Compass imports—the system will skip the problematic data and continue working with valid store information.
-
Bug Fix
SQL bracket protection for table names with dots
The application will no longer crash when processing data for stores whose table names contain version numbers with dots.
-
Bug Fix
Fixed Epicor import failures due to unbracketed table names
Custom Groups and SKU Exceptions will now update correctly during Epicor imports without encountering database errors.
-
Bug Fix
Propello long item code handling
Propello imports will no longer fail when item codes are longer than 25 characters—they'll be automatically shortened to fit.
-
Bug Fix
Propello import now handles long item codes and descriptions
If your store uses long item codes or product descriptions, Propello imports will now complete successfully instead of showing an error. Item codes and descriptions will be shortened automatically if needed.
-
Bug Fix
Mi9 competitor price filters now work correctly
Competitor price filters (Comp1-Comp5) in Mi9 stores no longer cause database errors when applied to the pricing grid.
-
Bug Fix
Automatic cleanup of manually-added catalog items after import
When you manually add catalog items and they later show up in your regular store data, they're now automatically cleaned up so you don't see duplicates or unnecessary tracking entries.
-
Bug Fix
Clean up manual catalog items after successful import
Items you manually added to your catalog will automatically be removed from manual tracking once they show up in your regular vendor files, preventing duplicates.
- Bug Fix Corrected BisTrack import column references
-
Bug Fix
Corrected BisTrack column name references in import query
Updated the SQL query that moves BisTrack data from staging into the main pricing table to use the correct shortened column names (Store instead of StoreNumber, PG instead of ProductGroup, Desc2 instead of Description2, H1-H12 instead of History1-History12, OM instead of OrderMultiple). Previously, the staging table schema was updated with abbreviated column names, but the insert query still referenced the old full names, causing import failures.
-
Bug Fix
BisTrack imports now remove per-store manual catalog entries
When items you've manually added to the catalog appear in your BisTrack store data, the manual entries are automatically removed to prevent duplicates.
-
Bug Fix
BisTrack manual catalog cleanup now removes per-store entries
If you manually added a catalog item for a BisTrack store, it will now be automatically removed once that item appears in your store's official import data.
-
Bug Fix
BisTrack multi-store import progress counter now advances correctly
The progress display during BisTrack imports now accurately shows which file is being processed (e.g., "5 of 20") instead of appearing stuck on the first file.
-
Bug Fix
Fixed BisTrack preloaded import processing all stores per file
BisTrack imports that were taking much longer than expected will now complete significantly faster.
-
Bug Fix
Eliminated redundant store processing in BisTrack imports
Multi-store BisTrack imports now complete much faster, especially noticeable for retailers with many store locations.
-
Bug Fix
Whitespace-only fields now treated as empty in BisTrack imports
When importing BisTrack data, fields that look empty (containing only spaces) are now correctly treated as empty instead of being imported with invisible space characters.
-
Bug Fix
BisTrack whitespace handling corrected
The BisTrack CSV import process now properly trims whitespace from all field values and treats whitespace-only cells as empty rather than storing them as single-space strings. This prevents phantom data in fields that appear empty but actually contain spaces.
-
Bug Fix
Splash screen progress now updates during BisTrack preload
When importing multiple BisTrack files, you'll now see the progress bar and status messages update during the entire import, including the initial file loading phase that previously appeared stuck.
-
Bug Fix
BisTrack preload progress events not wired
When importing BisTrack data, you'll now see progress updates on the loading screen instead of it appearing stuck or frozen.
-
Bug Fix
BisTrack preload guard added for multi-file imports
Fixed an issue where importing multiple files from certain POS systems could fail or behave incorrectly due to BisTrack-specific processing being applied to them.
-
Bug Fix
BisTrack preload incorrectly triggered for other POS systems
When importing multiple files from POS systems other than BisTrack, you will no longer see the preload screen that was meant only for BisTrack imports.
-
Bug Fix
BisTrack SQL column name mismatch
BisTrack imports no longer fail with column name errors.
-
Bug Fix
Fixed BisTrack staging table column name mismatches
BisTrack imports will no longer fail with column name errors.
-
Bug Fix
Fixed critical async handling bug in BisTrack import handlers
Corrected the WithEventsAsync method in BisTrack DIB 1040 and 6828 handlers to properly await asynchronous operations. The previous implementation was returning unawaited tasks, which could cause import failures or incomplete data loading during BisTrack POS imports.
-
Bug Fix
Fixed async timing issue in BisTrack import handlers
Corrected async/await implementation in BisTrack DIB 1040 and 6828 handlers that could cause import progress events to be missed or reported incorrectly during store builds.
-
Bug Fix
Automatic detection of missing stores in BisTrack imports
If you import BisTrack data and some store files are missing, Margin Master will now ask if you want to delete the old data for those stores. This prevents accidentally using outdated pricing information.
-
Bug Fix
Missing store detection for BisTrack imports
If you're importing BisTrack data and a store's files are missing, Margin Master will now warn you and ask if you want to remove that store's old data.
-
Bug Fix
Fixed slow BisTrack per-store data processing
BisTrack imports will now run significantly faster, particularly noticeable for stores with thousands of products or multiple store locations.
-
Bug Fix
Pricing strategy backup restore now handles legacy date values
Pricing strategies from older backups will now restore successfully without errors.
-
Bug Fix
Import Manager now ignores NEWRETAILS.CSV export files
If you export new retail prices to a NEWRETAILS.CSV file in your POS import folder, the Import Manager will no longer try to read it as a POS file and fail.
-
Bug Fix
NEWRETAILS.CSV excluded from import file detection
When selecting files to import from your POS system, NEWRETAILS.CSV will no longer appear in the list, making it easier to find the correct files.
-
Bug Fix
Direct upload finalization now runs correctly
Previously, some SpruceWareNet imports would appear to complete but show no data in the pricing grid or dropdown menus. This has been fixed, and all imports now display data correctly.
-
Bug Fix
Transact import timeout resolved for SQL Express installations
If your Transact import previously failed or left department/class dropdown boxes empty after importing, it will now complete successfully.
-
Bug Fix
Mi9 column header whitespace tolerance
Mi9 POS files with extra spaces in headers will now import successfully instead of showing column mismatch errors.
-
Bug Fix
Mi9 import KeyNotFoundException crash resolved
Stores with Mi9 systems can now reliably import data even when their POS export files have extra spaces around column names like "StoreNumber" or "ItemID".
-
Bug Fix
Mi9 import now handles whitespace in column headers
If your Mi9 POS system exported files with extra spaces around column names (like " StoreNumber"), the import would crash. This now works correctly.
-
Bug Fix
MySQL Compass import timeout resolved
If you previously experienced "timeout" errors when importing MySQL Compass data, especially with large inventory files, these imports will now complete successfully and much faster.
-
Bug Fix
Resolved MySQL Compass inventory import timeout
MySQL Compass inventory imports that were previously timing out or running very slowly will now complete successfully in a reasonable time.
-
Bug Fix
Store number reading from import spreadsheets
Import spreadsheets with store numbers entered as plain numbers (like 1, 2, 3) now work correctly instead of being ignored.
-
Bug Fix
Cloud sync now validates connection before starting
If cloud sync can't connect, you'll now see a clear error message instead of the app appearing to freeze.
-
Bug Fix
UseAverageCost setting now works for MySQL Compass imports
If you've enabled "Use Average Cost" in MySQL Compass settings, your pricing grid will now correctly show average cost values instead of replacement cost after importing data.
-
Bug Fix
Use Average Cost setting now applies to MySQL Compass Epicor imports
If your store has "Use Average Cost" enabled, margin calculations will now correctly use the average cost from your Epicor system instead of the last cost.
-
Bug Fix
Splash screen now displays before processing large Epicor data files
The progress window now appears correctly when importing Epicor data, so you'll always see that the import is running rather than the application appearing frozen.
-
Bug Fix
Splash screen now displays when reprocessing Epicor INdecoded files
Progress indicators now display correctly when reprocessing Epicor data that was already downloaded today.
-
Bug Fix
Epicor store character encoding corrected for non-ASCII values
If your Epicor system uses store codes with special or non-printable characters, those codes will now appear correctly in the store mapping screen and can be successfully mapped to vendor store numbers.
-
Bug Fix
Epicor store character mapping now preserves all byte values
If your Epicor system uses store codes that previously showed as garbled characters or question marks, you can now re-scan your INDecoded file and map them correctly.
-
Bug Fix
Store number encoding now correctly scoped to Epicor only
If you use RockSolid, Transact, BisTrack, Catalyst, Falcon, Paladin, or MySQL Compass, your store number mappings will now save correctly in the Store Match Up screen instead of being corrupted.
-
Bug Fix
Store number display and storage corrected for non-Epicor POS systems
If you use RockSolid, Transact, BisTrack, Catalyst, Falcon, Paladin, or MySQL Compass, store numbers in the Store Match-Up dialog will now display correctly instead of showing unexpected characters. Your store number assignments will save properly.
-
Bug Fix
Data Aging View now displays all Epicor store numbers correctly
When viewing data aging information, all Epicor stores now show their store numbers clearly instead of appearing as blank rows.
-
Bug Fix
Epicor store number display in Data Aging View
When viewing data age by store for Epicor imports, store numbers that previously appeared blank now display as readable numbers.
-
Bug Fix
Extended Epicor store characters now visible in matchup dialog
If your store uses Epicor with extended store designations beyond the standard range, you'll now see these displayed as numbers (like "128") instead of blank spaces in the POS Store Matchup screen.
-
Bug Fix
Corrected display of extended ASCII store characters for Epicor
When setting up store matching for Epicor, any stores using special or extended characters will now show up correctly instead of appearing blank or garbled.
-
Bug Fix
Extended character display in Epicor store mapping
In the Epicor store character matchup screen, special punctuation and symbols now appear correctly. Previously, characters like the dagger symbol or smart quotes would show up as numbers (like "135") or be invisible; now they display as the actual symbol.
-
Bug Fix
Store matching now handles special characters correctly
If your store identifier in Epicor uses a special character or symbol, it will now be recognized correctly when importing data.
-
Bug Fix
Epicor store number display with mapping enabled
If your store uses Epicor with store mapping turned on, the Data Aging View will now show the correct Ace store numbers instead of confusing numeric codes.
-
Bug Fix
Data Aging View shows correct store numbers for Epicor
When viewing import history in the Data Aging screen, you'll now see your actual Ace store numbers (like "13201") instead of confusing internal codes when store mapping is turned on.
-
Bug Fix
Do-It-Best taxonomy data now loads correctly for Transact POS
When viewing Do-It-Best items in the pricing grid, you'll now see the correct category and classification information in the taxonomy columns instead of blank fields.
-
Bug Fix
DIB taxonomy data now loads correctly for Transact stores
Do-It-Best product categories and classifications now appear properly in the pricing grid for Transact stores instead of showing blank.
-
Bug Fix
MySQL queries now respect custom database configuration
If your store uses a custom database name for Epicor MySQL Compass, imports will now work correctly using your configured database name.
-
Bug Fix
Removed hardcoded EAGLEDW schema from MySQL queries
If your store's MySQL Compass database is not named "EAGLEDW", imports will now work correctly instead of failing with database errors.
-
Bug Fix
Skip import records with missing store numbers
Fixed a crash during import that affected stores with incomplete configuration data.
-
Bug Fix
Epicor backup file deletion resolved
Backup files created during Epicor POS imports will no longer be accidentally deleted, providing better data safety and troubleshooting capability.
-
Bug Fix
Epicor backup cleanup now working correctly
When Epicor files are reprocessed, old backup copies are now properly deleted, freeing up disk space that was previously being consumed by unnecessary files.
-
Bug Fix
Per-store tables are now fully deleted during POS data reset
When using the "Reset POS Data" support tool, per-store main tables (which are created separately for each store location during import) are now completely dropped from the database instead of being truncated to empty tables. The staging table for each POS system continues to be truncated as before. This change prevents accumulation of orphaned table structures when stores are added and removed over time.
-
Bug Fix
Reset POS Data drops per-store main tables
When you reset POS data in Import Manager, the system now fully removes store-specific tables instead of just clearing them, which prevents potential errors when re-importing data.
-
Bug Fix
Epicor import now runs in background to prevent UI freezing
When importing large Epicor data files, the application will no longer freeze or appear to hang. You'll see progress updates throughout the import process instead of a frozen window.
-
Bug Fix
Excel file export routing for Mi9
When exporting to an Excel file in Mi9 mode, you'll now get a single file with all your data as expected, rather than the three-file branch export format.
-
Bug Fix
Fixed Mi9 export triggering for wrong destinations
Mi9 exports now only occur when you select Text File or Custom Text File as the export destination.
-
Bug Fix
Data Aging screen displays correct counts after POS reset
When you reset your POS data using the Reset POS Data tool, the Data Aging screen will now correctly show that you have zero records instead of displaying old counts from previous imports.
-
Bug Fix
Data Aging screen now updates correctly after POS data reset
After you reset your POS data in Settings, the Data Aging screen will now correctly show zero records instead of showing outdated counts from your previous imports.
-
Bug Fix
MySQL Compass grouped stores rebuild after cloud sync
If your store uses MySQL Compass with grouped pricing, your pricing tables will now update correctly after syncing from the cloud instead of remaining unchanged.
-
Bug Fix
MySQL Compass rebuild now works after cloud sync
If you use MySQL Compass with multiple stores, you can now successfully rebuild your pricing tables after syncing data from the cloud.
-
Bug Fix
Removed phantom store 99999 for Epicor systems
If you use Epicor, you'll no longer see a fake store "99999" appearing in your zone assignment list.
-
Bug Fix
One Click Statistics now calculates correctly for all vendors and POS systems
The One Click Statistics screen will now show accurate pricing level breakdowns for Ace Hardware and stores using Epicor, instead of displaying all zeros.
-
Bug Fix
Prevented SQL timeout when updating extended fields during Compass import
Added a composite database index (in_store, in_item_number) to the shared Compass_IN table to eliminate full table scans during per-store UserE1/E2/E3 updates. Previously, stores processed last in multi-store installations (~1.3 million rows across 10 stores) would experience SQL timeouts due to inefficient table joins. The index is created automatically before store processing begins.
-
Bug Fix
Backup now handles large databases without running out of memory
Creating backups for stores with large amounts of data will no longer freeze or crash the application.
-
Bug Fix
Added missing database index for MySQL Compass imports
MySQL Compass imports will no longer fail or time out when processing stores in multi-store setups, especially stores with large inventories processed later in the import sequence.
-
Bug Fix
Corrected Epicor Store Manager menu detection logic
When using Epicor POS, the menu now correctly shows "Manage Epicor POS/Vendor Store Info" and opens the right configuration screen.
-
Bug Fix
Store Manager Rescan now offers smart file selection for Epicor
When rescanning stores, Margin Master will now check if you have a recent scan file and ask if you want to use it or download a fresh copy from your Epicor server.
-
Bug Fix
Auto-switch to Backup Files tab when no current files available
If you open the Import Manager and there are no new files to import, you'll now automatically see your previously imported backup files instead of a blank screen.
-
Bug Fix
Auto-map Epicor store identifiers after format change
If you have Epicor POS and recently started seeing import warnings about unassigned stores, this update automatically fixes the problem by recognizing the new store identifiers without requiring you to manually re-configure your store mappings.
-
Bug Fix
Auto-map Epicor INDecoded store characters after format change
If your Epicor system recently changed how store numbers are formatted in downloaded files, Margin Master will now automatically transfer your existing store-to-vendor assignments to the new format instead of showing them as unmapped.
-
Bug Fix
Store mapping migration now processes all legacy STOREMATCHUP entries
Stores that were configured in your system but missing from the Store Manager screen will now be properly migrated and visible.
-
Bug Fix
Missing STOREMATCHUP entries now properly migrated
Stores configured in your system that were missing from the Store Manager will now appear correctly and be available for data import.
-
Bug Fix
Auto-map vendor numbers before import starts
After Epicor changes the inventory file format, your first import will now correctly process all inventory records instead of skipping them.
-
Bug Fix
Epicor INDecoded store mapping format migration
When you sync an Epicor INDecoded store, the system now automatically corrects store number mappings that were created in an older format, ensuring vendor catalogs link to the correct store numbers.
-
Bug Fix
Epicor store ordinal migration now runs at startup
For stores using Epicor, store numbers are now automatically converted to the correct format when you start Margin Master, before any data imports run. This happens in the background and prevents potential issues with store identification during imports.
-
Bug Fix
Duplicate store rows no longer created during GlobalFileConfig import
When the system imports vendor store mappings from GlobalFileConfig, it will now correctly update existing store entries instead of creating duplicate rows in the Store Manager.
-
Bug Fix
NonCore items now show correct cost values after MI9 import
Items marked as NonCore will no longer show blank cost fields after importing data. The system now correctly calculates and displays their average cost across all store locations.
-
Bug Fix
MI9 NonCore items showing blank cost values
When importing data from MI9 POS systems, items that are not stocked in your store (NonCore items) will now show their correct cost values instead of appearing blank in the pricing grid.
-
Bug Fix
Eliminated duplicate store rows in Store Manager
If you previously saw two rows for the same store in Store Manager (one with and one without a store number), those duplicates will now be automatically cleaned up and prevented from recurring.
-
Bug Fix
Fixed store group import failure for MySQL Compass
Imports will no longer fail unexpectedly when loading store information from MySQL Compass systems.
-
Bug Fix
Fixed Epicor store number mapping in group processing
Pricing strategies will now execute properly for Epicor stores during import operations.
-
Bug Fix
Preserve configured Epicor stores with raw-byte ordinals
Configured Epicor stores will no longer disappear from your store list after sync, even if they use numeric store codes between 0 and 31.
-
Bug Fix
Epicor store numbers now display correctly for control-character identifiers
Fixed a bug where Epicor stores using raw-byte ordinals (non-printable control characters) would appear with blank or invisible store numbers in the POS Store column. The system now automatically normalizes these invisible values to their numeric ordinal equivalents (e.g., store ordinal 5) so they are visible and identifiable in the store mapping grid. This correction applies during initial migration, automatic mapping, and new store creation during import.
-
Bug Fix
Epicor raw-byte store ordinals now display correctly
Epicor stores with special low-number store identifiers now show up correctly in store lists instead of appearing as blank entries.
-
Bug Fix
MySQL Compass store numbers now display correctly
If your store number appeared blank in the store manager, it will now show as a readable number.
-
Bug Fix
Normalize invisible store numbers in MySQL discovery
Store numbers from MySQL Compass now appear as readable numbers instead of blank spaces in the Store Manager.
-
Bug Fix
Epicor store deletion now marks as Excluded instead
If you try to delete an Epicor store that's still in your POS system, it will be marked Excluded instead to prevent it from coming back during the next import.
-
Bug Fix
Store Manager delete button now functions correctly
Corrected a technical issue where the delete button in the Store Manager grid was not properly connected to the selected store row, which prevented deletion from working.
-
Bug Fix
Epicor store deletion guard now covers INDecoded path
If you try to delete an Epicor store that still exists in your system, you'll now see a more accurate message explaining which data source it comes from (MySQL Compass or INDecoded file), and the store will be marked as Excluded instead of deleted.
-
Bug Fix
Fixed delete guard for Epicor INDecoded stores
When you try to delete an Epicor store that's still active in your system, Margin Master now correctly prevents the deletion and marks it as Excluded instead—whether you're using MySQL Compass or INDecoded imports.
-
Bug Fix
Pre-flight connection validation for MySQL imports
You'll now see an immediate, clear error message if MySQL isn't configured or can't be reached, instead of the import appearing to run but not actually importing anything.
-
Bug Fix
Connection validation before MySQL import
If MySQL isn't set up or can't be reached, you'll now see a helpful message right away instead of getting an error partway through the import.
- Bug Fix Progress bar now reflects true overall import progress for MySQL Compass
-
Bug Fix
Overall progress bar now tracks multi-store imports correctly
When importing multiple stores from MySQL Compass, you'll now see the progress bar advance smoothly across the entire import process instead of appearing to reset for each store.
-
Bug Fix
Added substatus messages during MySQL Compass merge operations
When importing MySQL Compass data, you'll now see messages like "Merging data into store table..." and "Rebuilding SKU index..." instead of the screen appearing stuck.
-
Bug Fix
Corrected MySQL query encoding for Epicor store character identifiers
If your store uses a special character (like extended ASCII characters) as its Epicor store identifier, inventory imports from MySQL Compass will now work correctly instead of returning no items.
-
Bug Fix
Corrected MySQL query encoding for Epicor store characters
If your store identifier in Epicor contains special characters, the import process will now correctly pull your store's data instead of potentially missing items or pulling incorrect store data.
-
Bug Fix
Vendor filter applied to post-sync reality check
Stores using a primary vendor filter in MySQL Compass will no longer see false error messages about incomplete imports.
-
Bug Fix
Missing vendor data after BisTrack import
After importing data from BisTrack, all product and vendor information now appears correctly in the pricing grid instead of showing empty selection boxes.
-
Bug Fix
Corrected store number recording during Epicor imports
When importing Epicor POS data, your store numbers are now saved correctly in the system.
-
Bug Fix
Corrected special character store handling in Store Manager
Store Manager was incorrectly treating special Windows-1252 characters (bytes 0x80-0x9F, such as '‡' or '†') as two different stores—one keyed by the raw byte value (135) and another by the Unicode code point (8225). This caused duplicate entries to appear in the Store Manager screen that couldn't be removed, and excluding or deleting the wrong one would delete Compass_IN data for the actual store, resulting in zero SKUs imported. The reconciliation process now consistently uses Windows-1252 byte ordinals (the same method used throughout the rest of the import pipeline) to identify stores.
-
Bug Fix
Corrected store character ordinal storage for Epicor MySQL
Stores with numeric characters in their Epicor MySQL setup will now import inventory data correctly instead of showing 0 SKUs.
-
Bug Fix
MySQL store ordinal persistence corrected
Stores with numeric characters in their Epicor MySQL store identifiers will now import correctly instead of returning zero items.
-
Bug Fix
Added validation to reject invalid multi-byte store characters
When discovering Epicor MySQL stores, the system now detects and logs a warning if any store character has an ordinal value above 255, which indicates the MySQL IN.in_store column is incorrectly configured as UTF-8/multibyte instead of the expected latin1 encoding. These invalid stores are skipped during discovery and import, with a clear message explaining that the MySQL column collation needs to be latin1. Previously, such stores would silently fail to import any data.
-
Bug Fix
MySQL Compass imports no longer fail on fresh stores
Fixed "Invalid object name 'Compass_IN'" errors during MySQL Compass imports on new store databases. The import process now ensures the Compass_IN table exists before attempting to read from it, allowing imports to proceed successfully on fresh installations instead of logging errors and aborting.
-
Bug Fix
Retry file deletion when export file is locked
If you have the export file open in Excel or Notepad when running an export, the system will now retry automatically instead of immediately failing. If the file is still locked after a few attempts, you'll see a clear message asking you to close the file first.
-
Bug Fix
Epicor store key collision in cloud sync
If you use Epicor POS, store-specific settings like RSC codes and zone overrides will no longer get mixed up between different stores during cloud sync.
-
Bug Fix
Cloud store settings now key on character ordinal for Epicor
Previously, cloud store settings for Epicor stores used the POS store number string directly, which could cause mismatches when store identifiers contained control characters or when digit characters were ambiguous (e.g., the character '1' vs. control character 1). The system now uses the character's byte ordinal value (PosStoreCharOrdinal) as the canonical key for Epicor stores, ensuring unambiguous identification. For other POS systems (Mi9, RockSolid, etc.), the POS store number continues to be used as before.
-
Bug Fix
Falcon CSV import restored after being silently skipped
If your store exports Falcon data as a CSV file, the import will now work correctly instead of using old data or showing incomplete rows.
-
Bug Fix
Falcon CSV import now properly recognized and processed
If your Falcon system exports a CSV file instead of Excel, Margin Master will now import all your inventory rows correctly instead of only importing a partial set.
-
Bug Fix
Epicor special-character stores now import correctly
If your store uses a special character like ‡ or † as its store number, inventory will now import correctly instead of showing zero items.
-
Bug Fix
Special-character Epicor store data not loading from MySQL
If your store number contains special symbols like '‡' or '€', inventory imports from MySQL Compass will now work correctly. Previously these stores would appear to import zero records.
-
Bug Fix
Partial store import now scopes rebuild to selected stores only
When you Shift-click to import data for specific stores, only those stores will be updated — other stores keep their existing data.
-
Bug Fix
Partial import now rebuilds only selected stores
When you Shift-click to import only specific stores, the system now updates only those stores instead of rebuilding everything.
-
Bug Fix
Store number mapping now works for all Epicor import methods
If you use Epicor and import via FTP, store selection dropdowns will now properly show both your POS store number and vendor store number (e.g., "Store 01 (Vendor 123)") instead of just the vendor number.
-
Bug Fix
Epicor store mapping no longer auto-enabled on every launch
If you disabled store mapping in Epicor settings, your choice will now be remembered instead of being reset every time you open the app.
-
Bug Fix
Eliminated slow imports from orphaned manual catalog items
If you previously experienced very slow Do-it-Best imports (20+ minutes), this will now complete in seconds. The system automatically removes catalog items that were added for stores not configured on your machine.
-
Bug Fix
Optimized discontinued manual catalog item cleanup
Manual catalog items that are no longer in the vendor's catalog are now removed much faster during imports, preventing long delays.
-
Bug Fix
Require valid yard for new-product imports at multi-yard stores
If you're importing new products at a store with multiple yards and forget to include the Yard # in your spreadsheet (or enter an invalid yard), you'll now see a clear message telling you which yards are valid. Previously, the import would silently fail and show all items as already existing.
-
Bug Fix
Automatic repair of corrupted store ordinals in multi-store Epicor accounts
If your multi-store Epicor account previously showed empty selection boxes after importing data, the system will now automatically fix the underlying store configuration issue and imports will work correctly.
-
Bug Fix
Automatic recovery of corrupted multi-store identifiers
If your store identifiers were showing incorrectly or stores were missing from analysis, they will now automatically fix themselves during the next data import.
-
Bug Fix
Import Manager no longer auto-displays non-importable backup files
When you open the import window and there are no new files to import, you'll see a clear message explaining that your previous files were already imported and renamed to backups, rather than seeing a list of files that won't actually import.
-
Bug Fix
Import window no longer surfaces already-imported backup files
After importing all your files, the import window will now tell you "No new files to import" instead of showing backup files that can't be imported again.
-
Bug Fix
Prevent foreign store identity adoption at startup
If you switch between databases, Margin Master now correctly uses the store number from the database you opened, not a leftover number from a previous session.
-
Bug Fix
Malformed CSV rows no longer block entire import
If your POS export file has a few corrupted or incomplete data rows, the import will now succeed and load all the valid rows instead of failing completely.
-
Bug Fix
Import scan no longer blocked by wrong-format files
If you accidentally save unrelated CSV or text files in your import folder, the system will now skip them and continue importing your POS data normally. Previously, even one wrong file would stop all imports without showing an error.
-
Bug Fix
Import scan no longer blocked by non-matching files in import folder
If you accidentally copy a price-change CSV, text file, or export from a different system into your import folder, Margin Master will now skip over it and still import your correct POS files. Previously, that one wrong file would stop all imports without showing an error.
-
Bug Fix
Data Aging view now detects partial import history
If import history records are missing or incomplete for some stores, the Data Aging screen will now automatically read the actual store tables to show you complete, accurate counts instead of appearing to lose data.
-
Bug Fix
Data Aging screen now detects incomplete import history coverage
If you have multiple store locations, the Data Aging screen will now show accurate import counts for all stores instead of sometimes displaying data for only one or two locations.
-
Bug Fix
Newly imported stores now receive RSC assignment automatically
When you import POS data and the system discovers new store locations, those stores will now automatically show their correct RSC assignment in Store Manager instead of appearing blank. This means vendor pricing will sync correctly for all your locations right away.
-
Bug Fix
Splash screen now closes reliably after New Product Import
The loading splash screen will now close properly after importing new products and choosing to rebuild the database, instead of getting stuck on screen.
-
Bug Fix
Splash screen teardown during New Product Import
The loading screen will no longer get stuck on screen or appear on top of other windows when importing new products and choosing to rebuild data.
-
Bug Fix
MySQL import log message corrected
Corrected an incorrect error message that appeared in log files during data imports, making it easier to troubleshoot actual configuration issues.
-
Bug Fix
Support issue pill now shows actual issue number
When you have an open support issue, the notification bar now shows the actual issue number (like "#12345") instead of just "#1", making it easier to discuss issues with support.
-
Bug Fix
Corrected download destination folder for Epicor files
Fixed a secondary issue where downloaded files were being saved to a "temp" subfolder that the decoder never checked, which would have caused failures even after the path bug was fixed. Files now download directly to the expected folder where the decode step looks for them.
-
Bug Fix
Aligned FTP and SFTP download behaviors for Epicor
Epicor imports now work consistently whether your store uses FTP or SFTP connections.
-
Bug Fix
Corrected 12-hour to 24-hour time format in MySQL queries
Changed date format from `hh:mm:ss` (12-hour) to `HH:mm:ss` (24-hour) in all MySQL date filter queries. The 12-hour format was causing incorrect filtering for afternoon/evening timestamps, potentially excluding valid records.
-
Bug Fix
Corrected date format in MySQL Compass queries
Fixed incorrect 12-hour time format (hh:mm:ss) that should have been 24-hour format (HH:mm:ss) in all MySQL date filter queries. This could cause imports to skip products updated in the afternoon/evening hours due to incorrect timestamp comparisons.
-
Bug Fix
Null store number crash prevention
Imports no longer crash when encountering missing or invalid store numbers.
-
Bug Fix
MySQL Compass import reality check
MySQL Compass imports are now more reliable — if your local data is incomplete (like having only 19 items when you should have 28,000), the system automatically detects this and reimports everything correctly.
-
Bug Fix
Removed command timeout limit for very large group operations
Large pricing groups with many SKUs will now complete successfully instead of timing out partway through.
-
Bug Fix
Fixed fallback import path timeout for BisTrack
The fallback import method (used when RSC data is unavailable) was using a default 30-second timeout, which was also too short for large inventories. This path now also uses an unlimited timeout to ensure complete imports.
-
Bug Fix
Do-It-Best catalog import for No-POS stores
Do it Best catalog imports now successfully add items to your store instead of showing an error message that no items were added.
-
Bug Fix
Skip execution of misidentified SKU Level Exceptions marker steps
If a strategy execution encounters a SKU Level Exceptions step that was imported incorrectly, it will now skip over it gracefully instead of failing, and will log a recommendation to reload the strategy for a permanent fix.
-
Bug Fix
Fixed Proceed button staying disabled after license validation
The Proceed button now enables immediately after your license is validated, letting you continue creating your database without delays.
-
Bug Fix
Null reference protection in SKU exceptions
Added null coalescing operator (?? []) in SkuLevelExceptionsViewModel.QueryAsync to prevent NullReferenceException when the query returns null before OrderBy operations. This ensures the exception loading process completes successfully even when no records are found.
-
Bug Fix
Fixed crash when pricing strategies have empty margin values
Pricing strategies with missing margin values now show a clear error message instead of causing the application to crash.
-
Bug Fix
Epicor table imports with version numbers in names
Epicor data imports with version numbers in table names (like 1.07) now complete successfully without database errors.
-
Bug Fix
BisTrack handler instance tracking
BisTrack imports now run once per file as intended, completing faster and without duplicate processing.
-
Bug Fix
Fixed BisTrack handler instance not completing multi-store builds
BisTrack imports now complete faster and won't get stuck reprocessing the same files.
-
Bug Fix
Removed "ALL" option from BisTrack catalog store list
When adding catalog items in BisTrack, the store dropdown now only shows your actual store numbers instead of including an "ALL" option that didn't work.
-
Bug Fix
Epicor MySQL vendor import handles missing creation dates
Epicor vendor catalog imports will no longer fail when store information is missing creation dates.
-
Bug Fix
Non-import file detection for Mi9 folders
If you accidentally place a non-import file in your Mi9 import folder, it will be skipped with a warning instead of stopping the entire import.
-
Bug Fix
Prevent products from being added to all stores unintentionally
New products imported without a valid store number now default to your primary store instead of being accidentally added to every store in your system.
-
Bug Fix
Auto-repair for corrupted Ace Hardware zone pricing tables
Zone pricing data for Ace Hardware will now sync successfully even if your local database structure was corrupted.
-
Bug Fix
Character encoding normalization for MySQL databases
Added PosStoreCharHelper.MatchesMySqlStoreChar() method that normalizes both stored ordinal strings ("87", "135") and MySQL character values to Windows-1252 byte ordinals before comparison. This handles the difference between UTF-8 MySQL databases (where ORD() returns Unicode code points like 8225 for dagger U+2021) and Latin-1 MySQL databases (where ORD() returns raw byte values like 135), ensuring consistent matching across different database configurations.
-
Bug Fix
Increased timeout for large catalog deduplication
Fixed timeout errors that prevented stores with large vendor catalogs from completing imports.
-
Bug Fix
Fixed store mapping validation during Epicor INDecoded import
Epicor imports now correctly skip records from stores that haven't been assigned vendor store numbers in the connection settings.
-
Bug Fix
Mi9 branch export success message count
After exporting to Mi9 branch files, the success message now shows the correct number of items that were exported.
-
Bug Fix
Corrected Mi9 export record count in success message
The export success message now shows the correct number of items exported instead of zero.
-
Bug Fix
Ace Hardware catalog import now updates product information correctly
Ace Hardware catalog imports will now correctly update product departments, pricing, vendor details, and other catalog information that was previously being skipped.
-
Bug Fix
Store Manager groups now apply consistently
Store groups you assign in Store Manager will now always appear correctly in your pricing reports and filters.
-
Bug Fix
Store Manager groups now applied during pricing rebuilds for Epicor
Pricing rebuilds now correctly use your Store Manager group assignments for Epicor stores.
-
Bug Fix
Corrected import log messages for file renaming
Fixed logging to correctly show the original file path when renaming imported files to .bak format. Previously, the log message would incorrectly show the backup path for both the "from" and "to" names, making it difficult to trace which original file was processed.
-
Bug Fix
Corrected logging for file rename operations
Fixed logging messages during import file backup operations to display the correct original filename before the rename. Previously, the log would incorrectly show the new backup filename in both the "before" and "after" positions.
-
Bug Fix
Missing store mappings are now auto-repaired on every startup
If you previously had stores that weren't importing correctly, they will be automatically fixed the next time you open Margin Master.
-
Bug Fix
Repair Store Manager display on open
The Store Manager screen now shows correct vendor assignments after a format change, even before running another import.
-
Bug Fix
Store mapping runs before imports and rebuilds
Store numbers will now be correctly matched during imports, fixing issues where items might have been assigned to the wrong store location.
-
Bug Fix
Automatic cleanup of existing duplicate store rows
Any duplicate store rows that were previously created will be automatically cleaned up the next time you open the Store Manager.
-
Bug Fix
Automatic repair of existing store records
Existing stores with blank or invisible store numbers will be automatically fixed the next time you start Margin Master.
-
Bug Fix
Repair existing stores with invisible store numbers
Any existing stores that appeared blank in the Store Manager will now show readable store numbers after the next application restart.
-
Bug Fix
Active stores count now excludes "not found" stores
The store count at the top now shows a more accurate number by excluding stores that no longer exist in your POS system.
-
Bug Fix
Removed confusing debug simulation messages
Fixed an issue where the import progress would show store numbers being processed even when no actual import was happening.
-
Bug Fix
MySQL zero-date rows now imported during full re-imports
Full re-imports from MySQL Compass will now include all products, even those with invalid date stamps.
-
Bug Fix
Auto-correction of legacy corrupted store numbers in Data Aging view
If your Data Aging screen previously showed incorrect store numbers, it will now automatically correct itself by looking at your actual store data.
-
Bug Fix
Added one-time repair for existing duplicate store entries
A one-time automatic cleanup now runs on Store Manager initialization to soft-delete any existing StoreManagerInfo rows with invalid ordinal values above 255 (artifacts created by the previous bug). This repair is idempotent and will only remove the erroneous duplicates, preserving the legitimate store entries. Store 6484 had 7 such duplicate rows that have now been identified and will be cleaned up.
-
Bug Fix
Prevented re-introduction of digit store character bug
Added 121 regression tests that lock in the correct handling of store characters, especially digit characters like '1', '2', '9'. The tests verify that digit store character '1' is always stored as ordinal "49" (its ASCII code and MySQL ORD() value), never as "1". This prevents the MM-1272 bug from being re-introduced where the character was mistakenly stored as its numeric face value, causing the import filter to compare against the wrong value and pull zero rows.
-
Bug Fix
Export-to-file handles locked files gracefully
If you try to export pricing data while the output file is still open in Notepad or Excel, you'll now see a helpful message asking you to close the file instead of an error.
-
Bug Fix
Ensure Compass_IN table exists during MySQL import
The MySQL Compass import process now proactively creates the Compass_IN table if it doesn't exist, rather than failing with an error. This prevents import failures on fresh stores or after database resets where the table hasn't been created yet. The table creation is idempotent and safe to run multiple times.
-
Bug Fix
Store reconciliation creating duplicate entries for special characters
Special-character stores will no longer appear twice in the Store Manager with one entry showing the symbol and another showing a number.
-
Bug Fix
Import history preservation for non-imported stores
The Data Aging screen will now show correct import history for all stores, even when you only import some of them.
-
Bug Fix
Import history preserved for non-imported stores
Previously imported stores now remain visible in the Data Aging View even when you perform a partial import of different stores.
-
Bug Fix
Improved discontinued catalog item cleanup performance
The cleanup of discontinued catalog items during import is now much faster and won't fail with timeout errors on slower systems.
-
Bug Fix
Added orphaned manual catalog item purge for multi-store systems
Manual catalog items for unconfigured stores are now automatically removed, speeding up imports by skipping items that can't be used.
-
Bug Fix
RSC assignment is backfilled without overwriting existing values
If you've already manually assigned an RSC to a store, this fix won't change it—it only fills in missing RSC assignments.
-
Bug Fix
Rebuild entry state hardening
When the user chooses to rebuild all data after a New Product Import, the application now ensures the splash screen is fully closed before starting the rebuild operation. This prevents competing splash screen owners from causing UI issues during the lengthy rebuild process.
-
Bug Fix
Bulk merge operations no longer leave orphaned records
Previously, the bulk merge operation only inserted or updated records, meaning items deleted from Epicor would remain in Margin Master indefinitely. The new reconciliation step solves this by explicitly identifying and removing records that no longer exist in the source system.
-
Bug Fix
Pre-create Compass_IN and Compass_INX tables before import
Import Manager now ensures Compass_IN and Compass_INX tables exist before starting the store processing loop. Previously, if all stores returned zero updates, these tables would never be created, causing downstream errors when the Main Table tried to query them.
-
Bug Fix
Compass tables now pre-created before import
The pricing grid will now properly initialize even when there are no recent product updates from MySQL Compass.
-
Bug Fix
Removed manual CSV conversion requirement for CounterWorks
CounterWorks users no longer need to manually prepare files before importing—just use the file directly from your POS system.
-
Bug Fix
Counterworks deduplication now includes STORE field
Updated the deduplication logic in the finalization SQL to remove duplicates based on both SKU and STORE instead of just PARTNO, ensuring proper handling of multi-store environments where the same SKU may exist in different stores.
-
Bug Fix
Improved duplicate detection for CounterWorks imports
Updated the duplicate removal logic to check both SKU and STORE fields instead of only PARTNO, ensuring accurate deduplication when the same product appears multiple times in multi-store configurations.
-
Bug Fix
Missing store data visibility in Data Aging
Store data that was previously hidden due to missing import records is now visible in the Data Aging screen.
-
Bug Fix
Improved fallback logic for missing import data
The Data Aging screen is smarter about finding and displaying your store data when import tracking is incomplete.
-
Bug Fix
Eliminated repeated timeout delays during import strategy execution
Import operations will no longer freeze repeatedly when MySQL Compass is unavailable.
-
Bug Fix
Fixed buttons not updating immediately after validation
Buttons in the wizard now enable immediately when conditions are met, instead of requiring you to click or move your mouse to trigger the update.
-
Bug Fix
Eliminated startup errors on fresh installations
Starting Margin Master for the first time or launching multiple instances at once no longer generates error reports.
-
Bug Fix
Simplified manual catalog cleanup logic
Removed vendor-specific cleanup queries for Do-It-Best, Ace Hardware, and Emery Jensen that checked if items existed in store import data. This logic is now handled consistently during the import process for BisTrack, and age-based expiration handles all other cases.
-
Bug Fix
Fixed Store='ALL' catalog items in BisTrack multi-store imports
Added automatic purge of Store='ALL' ManualCatalogItems before BisTrack multi-store catalog re-import to prevent invalid fan-out. BisTrack imports own their SKU/Store data from POS CSV files, so Store='ALL' entries are invalid in this context and could cause incorrect data distribution across stores.
-
Bug Fix
Automatic purge of invalid manual catalog items for BisTrack
Manual catalog items are now properly scoped to individual stores during BisTrack imports instead of incorrectly applying to all stores.
-
Bug Fix
Mi9 index creation idempotency
If an Mi9 import is interrupted and restarted, it will continue successfully instead of failing on duplicate indexes.
-
Bug Fix
Composite primary key handling in bulk sync operations
RowVersionTableSync now correctly handles tables with multi-column primary keys by relying on the database constraint rather than the single-column AutoMapKeyName parameter. This prevents bulk merge operations from failing on tables with composite keys.
-
Bug Fix
Corrected average cost setting lookup
Fixed a build error where the "Use Average Cost" application setting was being retrieved using an obsolete method call. Now uses the standard GetValue<bool> pattern with the correct ApplicationSettingKey.
-
Bug Fix
Corrected average cost setting lookup causing build failure
Fixed a method call error where GetUseAverageCost() was called incorrectly. Changed to use the proper GetValue<bool> method with the UseAverageCost application setting key, resolving a compilation error in the Epicor import cost calculation logic.
-
Bug Fix
Network scan button now functional
The "Scan Network" button on the MySQL/Compass tab now works properly to discover MySQL servers on your local network.
-
Bug Fix
Ace Hardware zone pricing now applies store-specific pricing correctly
Ace Hardware zone pricing will now correctly update retail, level 1, and level 2 prices based on your store's assigned pricing zone instead of being skipped.
-
Bug Fix
Removed silent fallback for MySQL connection failures
If the MySQL Compass connection isn't available when you try to refresh store data, you'll now see a clear error message instead of the system silently using old data.
-
Bug Fix
Store Manager Rescan requires active MySQL connection
Rescanning stores now requires an active connection to your MySQL Compass database to ensure you get current data.
-
Bug Fix
Delete button now functions correctly in store grid
Corrected a CommandParameter binding issue that prevented the delete button from working properly in the store manager grid.
-
Bug Fix
Changed store reconciliation to query live MySQL instead of local cache
The Store Manager will now correctly detect available stores even after a failed import, allowing recovery from configuration errors.
-
Bug Fix
Extended store matching for numeric vendor store numbers
Generalized the store-skipping logic to match both single-character Epicor store numbers and multi-digit vendor store numbers (such as Do-It-Best numeric stores like "1818"). This ensures zone, MSU, and INX processing steps correctly skip non-imported stores regardless of store number format.
-
Bug Fix
Accurate status reporting when yard doesn't match
If you specify a yard that doesn't exist in the database, items will now clearly show "No matching store/yard" instead of incorrectly appearing as if they already exist.
-
Bug Fix
Accurate row deduplication in bulk operations
The bulk insert uses ROW_NUMBER deduplication on the catalog side to handle cases where multiple catalog records exist for the same SKU. This reproduces the single-row selection behavior of the per-item path, ensuring idempotency—re-running the operation inserts zero additional rows and prevents duplicate (SKU, StoreNumber) combinations in the main tables.
-
Bug Fix
Changed duplicate detection to use HashSet for better performance
Improved the efficiency of duplicate record detection during imports by switching from List to HashSet, which provides faster lookups on large datasets.
-
Bug Fix
Bypass CSV validation for Excel files
Excel imports no longer fail with "invalid file format" errors during the validation step.
-
Bug Fix
Excel import validation bypass
Excel import files are now handled correctly without false validation errors.
-
Bug Fix
MMVendorData table/view conflict resolved
Fixed a database conflict where legacy sync code attempted to create an MMVendorData TABLE even when a modern MMVendorData VIEW already existed (created by the modern sync's catalog builder). The legacy sync now detects the VIEW and skips the conflicting CREATE TABLE operation, allowing both sync systems to coexist gracefully during the transition period.
-
Bug Fix
Resolved BisTrack import progress stuck at "1 of 20"
BisTrack imports no longer get stuck at "1 of 20" files—you'll now see progress as each store file is processed.
-
Bug Fix
Corrected store number sorting in Data Aging screen
Store numbers in the Data Aging screen now appear in correct numeric order (1, 2, 3... 10, 11) instead of alphabetic order.
-
Bug Fix
Fixed store number sorting in Data Aging screen
Store numbers in the Data Aging screen now appear in the correct numerical order.
-
Bug Fix
Database migration NULL handling
Database updates that make fields required will now complete successfully even if some existing records have blank values.
-
Bug Fix
Null price column handling in One-Click pricing analysis
One-Click pricing analysis will no longer crash when some items have missing price data.
-
Bug Fix
Store exclusion format now consistent across POS systems
Updated the StoresToExclude setting to use pipe-delimited format for Epicor systems (matching other POS systems) instead of the legacy concatenated character format. This supports both single-character store codes and multi-digit vendor store numbers in the exclusion list. The setter now always writes pipe-delimited format regardless of POS system type.
-
Bug Fix
Fixed unmapped store sentinel value handling in Store Manager
The discovery sentinel value "99999" is now correctly recognized as indicating an unmapped store rather than being treated as a vendor store number. This ensures unmapped stores appear properly in the Store Manager interface awaiting assignment.
-
Bug Fix
Improved error handling in INX processing
Added error logging to the ProcessINXItemsAsync catch block that was previously empty, ensuring exceptions during INX processing are now captured in logs with store context.
-
Bug Fix
Epicor/MySQL Compass import now satisfies database constraints
Importing data from Epicor or MySQL Compass POS systems will no longer fail with database constraint errors.
-
Bug Fix
Multi-RSC detection logic
Stores with multiple distribution centers now have their RSC assignments detected automatically.
-
Cloud Sync
Improved store identification logic
Updated the cloud sync key generation in Store Manager to use a new CloudPosKey method that selects the appropriate identifier format based on POS system: Epicor stores use their character ordinal value (PosStoreCharOrdinal), while all other systems use the standard POS store number. This ensures consistent identification across save and retrieval operations.
-
Cloud Sync
Improved store matching reliability
Both saving and loading cloud store settings now use the same canonical key logic, ensuring that settings saved to the cloud will be correctly matched and retrieved during sync operations.
-
Cloud Sync
Cloud store settings now normalize special-character keys
Modified CloudPosKey generation and ApplyCloudStoreSettings to normalize PosStoreKey values greater than 255 back to Windows-1252 bytes. This ensures cloud-synced settings created by older builds (which stored code points) still match local stores after the fix, and the next save automatically heals the cloud row.
-
Cloud Sync
Cloud settings normalized for special-character stores
Enhanced cloud synchronization to normalize special-character store keys when saving and loading organization POS store settings. Keys stored as Unicode code points by older versions are automatically converted to Windows-1252 byte values, ensuring consistent cloud-to-local matching after upgrade.
-
Data Import
Automatic SKU reconciliation after sync
When you delete items from your Epicor system, those deletions will now automatically appear in Margin Master after the next data import completes.
-
Data Import
Falcon POS Excel import with direct bulk loading
When importing Falcon POS data, you'll now see detailed progress updates showing how many rows have been imported and the percentage complete.
- Data Import Completed search index for POS import documentation
-
Data Import
Direct Excel import for CounterWorks POS
You can now drag CounterWorks Excel files directly into the Import Manager without converting them to CSV first.
-
Data Import
Direct Excel import for CounterWorks POS
You can now import CounterWorks data files directly without opening Excel and converting them to CSV first. Just select the .xlsx file in the Import Manager.
-
Data Import
CounterWorks Excel file support
When importing CounterWorks data through the Import Manager, you can now select Excel files (.xlsx) directly instead of having to save them as CSV files first.
-
Data Import
Pre-sync incomplete data detection and recovery
If your local inventory data is incomplete, the system will now automatically detect this before importing and start fresh to ensure all items are present.
-
Data Import
Per-file merge pipeline for BisTrack imports
When importing BisTrack data, each store's file is now processed individually with visible progress, and the system correctly handles items that have been added, changed, or removed since the last import.
-
Data Import
Per-file merge strategy for BisTrack batch imports
When you import multiple BisTrack store files, each file now processes individually with visible progress, making it easier to track which stores have been imported.
-
Data Import
Added database index to BisTrack stage table
Created a nonclustered index on Store and SKU columns in the BisTrack staging table. This index improves query performance during the import process, particularly when matching and updating products across multiple store locations with large catalogs.
-
Data Import
Cross-file batch processing with detailed progress tracking
BisTrack imports now accumulate rows across all CSV files and flush to the database in 50,000-row batches, with progress percentages that accurately reflect the current stage (reading files 0-85%, inserting rows 85-95%, cleanup 95-100%). This replaces the previous per-file database insertion approach that caused the progress dialog to freeze during large operations.
- Data Import BisTrack preload table now stores numbers as typed decimals
-
Data Import
Phase 2 builds all stores from typed preload data
When importing data for multiple stores, Margin Master now processes all store files in one batch, then builds each store's tables from shared staging data instead of re-reading each file separately.
-
Data Import
Improved assembly reference validation
Added AssemblyName.GetAssemblyName() pre-validation check before creating Roslyn metadata references. This ensures only valid .NET assemblies are loaded during the dynamic compilation phase of import file matching, preventing lazy-load errors that would occur later during code emission.
-
Data Import
Optimized Excel cell reading for faster imports
The DevExpress Excel importer now reads cells directly into DataTables instead of using the double-copy DataTableExporter pattern, reducing memory overhead and improving performance for large Excel files. Progress is logged every 50,000 rows during the read phase.
-
Data Import
Import tracking now captures mainTable rebuild results
After MySQL Compass imports complete and the main pricing tables are rebuilt for each store, the system records the actual record counts from each store's mainTable (pattern: Epicor_{StoreNumber}_mainTable) into import history. This happens before the store mapping information is cleared, ensuring accurate tracking of what was successfully imported.
-
Data Import
Import history tracking improved for multi-store MySQL Compass setups
Import processing history is now recorded for each individual store location in MySQL Compass Epicor configurations. The system tracks record counts from each store's mainTable (named Epicor_{StoreNumber}_mainTable) and saves them to the ImportProcessing table after the import completes, ensuring accurate reporting in the Data Aging View.
-
Data Import
Chunked bulk import with automatic retry
Large Excel imports are now more reliable and will automatically retry if temporary errors occur, reducing the need to restart failed imports from scratch.
-
Data Import
CounterWorks column header configuration
Added JSON-formatted column header specification for Excel BCP import, defining all 22 expected columns including LINCODE, PARTNO, COST, DESCR, department fields (DM00-DM11), MULT, ORDQTY, PRCB, QOH, SUBLINE, and VENNO. This ensures Excel files are parsed correctly during bulk import operations.
-
Data Import
Enhanced Excel import service to support column transformations
Extended the Excel BCP import process to apply column mappings defined by each POS system's layout class. The service now supports renaming columns (e.g., PARTNO→SKU), dropping unwanted columns (e.g., VENNO), and adding new columns with default values (e.g., STORE='0') before performing the SqlBulkCopy operation.
-
Data Import
Enhanced Excel import with flexible column mapping
Added a new ExcelColumnMapping system that allows POS-specific import definitions to rename, drop, or add columns during Excel imports. This makes the import pipeline more flexible and handles cases where Excel column names differ from the expected database schema.
-
Data Import
Added import completeness validation
Post-import validation now compares the number of imported SKUs against the expected count from MySQL and logs an error if the imported count is less than 10% of expected. This helps detect and diagnose incomplete imports early, with guidance pointing to SQL Express upgrade scenarios as a common cause.
-
Data Import
Automated spreadsheet processing workflow
After import completes, processed Excel files are automatically moved to an "Imported" subfolder, and a detailed log file is created in the "Logs" subfolder showing which SKUs were imported and which were invalid.
-
Data Import
Post-sync completeness verification
After each inventory import completes, the system verifies that all your items were successfully imported and alerts support if anything is missing.
-
Data Import
Added single-store detection for POS systems
Introduced a new IsSingleStorePOS property to identify POS systems whose export format has no store column and hardcodes all rows to StoreNumber='0'. Currently applies to CounterWorks, with the infrastructure in place to easily flag other single-store systems if needed.
-
Data Import
Improved import history ranking accuracy
Each store now shows the date when inventory data was actually last imported, not when an import was attempted but failed.
-
Data Import
Persistent BisTrack data table survives across import sessions
BisTrack pricing data is now preserved between imports, so you only update what's changed rather than reloading everything each time.
-
Data Import
Improved data quality for BisTrack imports
Import validation logic now checks trimmed value length rather than just checking for null/empty, ensuring that CSV fields containing only whitespace characters don't populate database fields with meaningless space characters.
- Data Import New two-phase BisTrack multi-store pipeline
-
Data Import
DIB6828 format support with typed preload
BisTrack DIB6828 export files are now fully supported — Margin Master automatically recognizes and imports them without manual configuration.
-
Data Import
Store information logged during New Product Form import
The import summary will now show which store the products are being added to when using the new format.
-
Data Import
Column name cache now resets between files
The Mi9 import service now clears its column index cache when processing each new file, preventing column position mismatches when importing multiple files with different structures in sequence.
-
Data Import
Improved store designation handling for Epicor
Added new helper method ToDisplayString() that intelligently formats store characters based on whether they're printable or control characters, and updated ToOrdinal() to correctly handle cases where the display value is already showing an ordinal number.
-
Data Import
Improved messaging for unassigned store characters
The warning message when new stores are found is now clearer about what you need to do next and where to find the settings.
-
Data Import
Improved cost calculation logic for multi-store aggregation
Changed the cost aggregation formula from filtering by "OnHand > 0" to using NULLIF to exclude only invalid zero-cost entries. This ensures that stores with valid cost data contribute to the average even when they currently have no inventory on hand. The original formulas are preserved as SQL comments for reference.
-
Data Import
Improved store mapping cleanup during auto-detection
Refined the automatic store mapping logic to properly remove obsolete raw-byte store entries when their ASCII counterparts are detected, preventing duplicate store rows after Epicor system migrations.
-
Data Import
Auto-mapping distinguishes legacy from active raw-byte stores
Enhanced the Epicor FTP auto-mapping logic to correctly differentiate between raw-byte ordinal rows that are legacy/pre-migration duplicates (which should be soft-deleted) versus stores that genuinely use raw-byte ordinals (which should be normalized and retained). This prevents accidental deletion of valid store configurations while still cleaning up obsolete duplicates.
-
Data Import
Enhanced progress tracking for single-table and multi-table imports
Both single-table and multi-table MySQL Compass import modes now pass store index and total store count through the import pipeline to enable accurate overall progress calculation. The progress bar updates incrementally as each block of inventory items is processed within each store.
-
Data Import
Updated reality check and incremental sync queries for MySQL Compass
Modified pre-sync SKU count verification and incremental update queries in the Import Manager to use corrected store identifier matching. This ensures the application can accurately detect partial imports and properly synchronize inventory changes for affected stores.
-
Data Import
Improved store data reconciliation accuracy
Enhanced the SKU reconciliation and deleted item detection processes to use the corrected character encoding, ensuring that the pre-sync reality check (which compares local SKU counts to MySQL counts) accurately identifies when a full reimport is needed.
-
Data Import
New CSV parser handles Falcon's comma-delimited format
The import now correctly handles special characters and formatting in product descriptions and pricing, preventing data corruption or missing items.
-
Data Import
Store matching standardized on Windows-1252 byte values
Standardized all Epicor store matching logic to use the MySQL ORD / Windows-1252 byte value (1-255) consistently. Updated all SQL merge scripts, import queries, deleted-item reconciliation, and store filters to use ASCII() in T-SQL instead of UNICODE(). Parameterized all MySQL queries that previously interpolated the store character directly into ORD() expressions to prevent SQL injection and ensure correct key binding.
-
Data Import
Normalize legacy POS store character settings
If you upgraded from an older version of Margin Master, your POS store matching settings are automatically fixed to work correctly with the current version.
-
Data Import
Added optional trailing field to RockSolid mapping
Added an optional `TrailingField` to the RockSolid data mapping to handle edge cases where extra columns appear at the end of exported data files, preventing parsing errors that could cause incomplete imports.
-
Data Import
Updated Falcon import mappings for Excel format
Falcon import configuration now expects Excel column headers ("Stock #", "Warehouse #", "On Hand") instead of CSV headers, with updated SQL scripts to handle the Excel BCP format. The import scripts now rename columns after bulk insert (Stock→SKU, Warehouse→StoreNumber) and use TRY_CONVERT for safer decimal conversions. Search pattern changed from "MM*.csv" to "*.xlsx".
-
Data Import
Updated Falcon import mapping and SQL scripts
Updated Falcon field mapping to match new Excel column structure: Stock # maps to SKU, Warehouse # to StoreNumber. Revised SQL finalization scripts to handle column renaming, remove duplicate records by SKU+Store, and properly trim leading zeros from warehouse numbers. Updated search pattern from "MM*.csv" to "*.xlsx" to match new file format.
-
Data Import
Updated CounterWorks column mapping
The CounterWorks import now correctly handles the native Excel format with 22 columns, mapping PARTNO to SKU, defaulting STORE to '0' for single-store operations, and properly processing the 12 department margin fields (DM00-DM11) along with cost, description, quantity, and vendor data.
-
Data Import
Automatic cleanup of manual catalog items after BisTrack merge
Manual catalog entries are automatically removed when those items appear in your BisTrack data, preventing duplicate or conflicting records.
-
Data Import
Smart merge logic for incremental updates
BisTrack imports now intelligently update only the data that has changed, keeping your pricing and inventory information in sync with your POS system while preserving records from other stores.
- Data Import Simplified BisTrack data cleanup
-
Data Import
ImportAsync short-circuits after Phase 2 completion
Once `PostPreloadBuildAllStoresAsync` completes, subsequent `ImportAsync` calls return immediately without executing SQL. The per-file loop still runs to rename processed files to backup names, but all database work is finished. This eliminates ~100 redundant database operations across a typical 20-store import batch.
-
Data Import
Unified DIB1040, MAP1, and MAP2 handler
MAP1 and MAP2 store files now import using the same fast batch process as standard BisTrack files.
-
Data Import
Import handler now reports successfully imported stores
All three BisTrack import handlers (DIB1040, DIB6828, and DirectConnect) now expose which store numbers were successfully imported through a new ImportedStores property. This enables downstream validation and cleanup workflows to ensure data consistency across multi-store BisTrack installations.
-
Data Import
Backward compatibility with existing New Product Form files
New Product Form spreadsheets without the Yard # column (legacy format) continue to be processed normally, ensuring no disruption to existing workflows.
-
Data Import
Do-It-Best taxonomy fields now populated during store rebuild
The vendor data temp table now conditionally populates all eight DIB taxonomy fields (4 ID fields and 4 description fields) from DIB_Sku_4ClassificationLevel if that table exists in the database, ensuring complete catalog metadata is available in the main pricing table.
-
Data Import
Epicor store conversions now correctly handle all byte values
The data import process now correctly converts stored ordinal values back to single-character strings when comparing against incoming Epicor data, ensuring that all store codes—including those with byte values above 127—are properly matched and converted during import. Both the FTP-based Epicor import and MySQL Compass Epicor import services apply this conversion.
-
Data Import
Improved Epicor import reliability for multi-store configurations
Store number conversion during Epicor import now correctly handles the new ordinal storage format, ensuring that mapped POS store codes are accurately translated to vendor store numbers regardless of character type.
-
Data Import
Duplicate store detection prevents re-adding existing entries
Before inserting new store entries into StoreManagerInfo, the import process now queries for existing entries with matching PosStoreCharOrdinal values to avoid creating duplicates. Only truly new store characters are inserted into the database.
-
Data Import
Normalize store numbers during Epicor data import
When importing Epicor POS data and auto-creating new store records, raw-byte ordinals now generate readable PosStoreNumber values using the numeric ordinal instead of the control character.
-
Data Import
New Epicor store creation handles raw-byte ordinals
Updated the initial store creation process during Epicor MySQL Compass imports to properly handle raw-byte ordinals by storing the numeric ordinal value as a readable string, ensuring stores are immediately visible after first import.
-
Data Import
Exclusion of not-found stores from import processing
Stores marked as "Not Found" are automatically skipped during imports to prevent errors. If a store comes back in future imports, it will automatically be reactivated.
-
Data Import
Improved Compass_IN cleanup to handle both MySQL character encodings
When removing data for deleted or excluded stores, the cleanup process now matches both possible encodings of the store character in Compass_IN: the raw Windows-1252 byte and the UTF-8 display glyph. This ensures that data is deleted correctly regardless of whether the MySQL database stored the character as a single byte or as its UTF-8 equivalent, preventing accidental deletion of the wrong store's data.
-
Data Import
Live MySQL store reconciliation before import
The import process now validates store connections against live Epicor data each time, ensuring stores aren't incorrectly marked as missing.
-
Data Import
Import Manager now selects most recent file when multiple formats present
If you have both old and new export files in your import folder, Margin Master will automatically use the newest one.
-
Data Import
Automatic repair of existing code-point artifacts
Added one-time repair logic that rewrites StoreManagerInfo rows with PosStoreCharOrdinal > 255 back to the correct Windows-1252 byte value (e.g., 8225 → 135 for ‡). This preserves the mapped VendorStoreNumber so special-character stores import correctly after the fix. Cloud sync settings are also normalized on load and save, ensuring cloud PosStoreKey values are automatically corrected from code points to bytes.
-
Data Import
Automatic repair of legacy special-character store mappings
When you first open Margin Master after this update, any special-character stores that weren't working will be automatically fixed to load data correctly.
-
Data Import
Repair persisted store matchup configuration
After correcting a drifted store identifier, the system now updates the stored matchup configuration in the database to ensure the correct vendor store number association persists across future imports and prevents the corruption from reoccurring.
-
Data Import
Added diagnostic text file backup for RockSolid
While RockSolid now imports directly from Access to SQL, the intermediate RockSolidData.txt file is still written as a diagnostic backup for troubleshooting and compatibility purposes. This file is no longer used in the import pipeline but remains available for review if needed.
-
Data Import
DirectConnect imports migrated to handler pattern
BisTrack DirectConnect imports now show consistent progress messages and work the same way as file imports.
-
User Interface
Catalog availability date display
You can now see when the most recent vendor catalog became available in the "Catalog Available" field.
-
User Interface
Help button repositioned in Import Manager
The help button is now located right next to the "Import Path" field instead of the top corner, making it easier to find when you need help with imports.
-
User Interface
Sync history table display on Data Aging View
The Data Aging screen now shows a detailed list of vendor data tables with the number of records and last sync date for each, including Ace Catalog, Ace Zone Pricing, DIB Catalog, Planograms, and other vendor data sources.
-
User Interface
Sync history table added to Data Aging View
You can now see exactly when each vendor catalog (Ace, DIB, etc.) was last updated and how many items were downloaded.
-
User Interface
POS import reference documentation
The Help menu now includes detailed guides for your specific POS system showing exactly how to export files, which fields are imported, and how to troubleshoot common import issues.
-
User Interface
MI9 data pipeline documentation
Added detailed reference documentation to the Help system explaining the complete MI9 import-to-main-table pipeline. The guide walks through how MI9 export files (MM*.txt) are imported, how stores are grouped into teams (Core, NonCore, etc.), how per-store data is aggregated into team-level pricing tables, and how Ace catalog enrichment and calculated fields are applied. Includes field mapping tables for all 75+ import columns, aggregation logic explanations, and common troubleshooting scenarios.
-
User Interface
Dialog windows now auto-size to content
Import dialogs now appear smaller and better fitted to their content.
-
User Interface
Enhanced bulk SKU input dialog
When adding items by SKU, you'll now see an example showing how to format your SKU list with commas or spaces.
-
User Interface
Help button added to Add from Catalog dialog
Click the help button next to the search box to learn how to add items from the catalog, including how to import many items at once from Excel files or pasted lists.
-
User Interface
Dynamic POS settings tab visibility
POS-specific settings tabs (like Connections for Epicor, SpruceNet/RockSolid, NCR Counterpoint, and Bistrack) now appear or disappear right away when you change the POS system dropdown, making it faster to configure your system.
-
User Interface
Dynamic POS configuration tabs in Settings
The Settings screen now shows only the configuration tabs that apply to your selected POS system, making it easier to find the settings you need.
-
User Interface
New product import results grid
When you import new products from spreadsheets, you'll now see all results in one organized grid showing which SKUs were added, which already existed, and which weren't found in the catalog, instead of multiple pop-up messages.
-
User Interface
Filter out zero-record imports from history
You'll now see only successful imports in the import history — failed imports with no records won't appear in the list anymore.
-
User Interface
Import Exclude moved to dedicated section
The "Exclude Stores" setting now appears in its own section in Settings, making it easier to locate.
-
User Interface
Import Exclude moved to dedicated section
The Import Exclude setting is now easier to find in its own section in Settings.
-
User Interface
Inline connection test results panel
When you test your MySQL connection, detailed results now stay on screen showing which server you connected to, how many stores were found, and SKU counts for each store.
-
User Interface
Unified Store Manager routing for all Epicor configurations
All Epicor users now access the same modern store management screen from the Tools menu, making setup more consistent.
-
User Interface
Store Grouping section hidden for all Epicor stores
If you use Epicor, you'll now see a message in Options reminding you to manage store groups in Store Manager (under Tools menu) instead of on the Options screen.
-
User Interface
Store grouping UI hidden for Epicor POS systems
If you use Epicor, you'll no longer see the Store Grouping section in Settings. Instead, use Tools → Store Manager to assign stores to groups.
-
User Interface
Auto-select Backup Files tab when no imports available
If there are no new files to import, the screen will now automatically show you the backup files tab instead of an empty list.
-
User Interface
Simplified POS Store column display
Store numbers are now displayed more simply in the POS Store column, making them easier to read at a glance.
-
User Interface
New deletion reason dialog for active POS stores
When removing a store that's still in your Epicor system, you'll see a dialog asking you to pick why you're removing it: reassigned store number, closed, new ownership, not retail, or other reason.
-
User Interface
Enhanced progress display for MySQL Compass imports
When importing MySQL Compass data, you'll now see more detailed progress messages showing exactly what step is running and which store is being processed, making it easier to understand what's happening during lengthy imports.
-
User Interface
Live progress during cost-field synchronization
You'll now see which table is being processed during the cost-field sync step after importing data.
-
User Interface
Live progress tracking during index rebuild
When rebuilding indexes after an import, you'll see which table is currently being processed and how many remain, so you know the operation is still running.
-
User Interface
Dynamic column headers in store import picker
Column headers in the store picker now show your actual POS system name (like "Epicor" or "RockSolid") and vendor name (like "Ace" or "Orgill") instead of generic text.
-
User Interface
Consolidated Epicor settings into single tab
All Epicor connection settings are now on a single "Epicor" tab in the Options window. Check or uncheck "Connect via MySQL / Compass" to switch between the two connection modes.
-
User Interface
Merge Epicor connection tabs into single "Epicor" tab
Epicor users now find all connection settings under Options → Epicor. Toggle between MySQL/Compass and direct FTP by checking or unchecking "Connect via MySQL / Compass" at the top of the tab.
-
User Interface
Removed obsolete Compass configuration checkboxes
The Compass Options section in Epicor settings is now simpler, showing only the options you need to configure manually.
-
User Interface
Removed redundant Compass import options from Epicor settings
The Epicor settings screen now shows only the options you can actually change, making it clearer and less cluttered.
-
User Interface
Added informational banner to Store Manager for unused vendor store numbers
If you're using Epicor and see a new yellow warning at the top of Store Manager, it means the vendor store numbers you enter in that column aren't being used—your imports use the Epicor store number instead. Contact RetailerSoft before changing store mapping settings, as this affects how saved pricing strategies are matched to stores.
-
User Interface
Warning notice for inactive vendor store mapping
If you're using Epicor without store mapping enabled, you'll now see a warning that explains the vendor store numbers you enter aren't used during import. Your stores are identified by Epicor's own store numbers instead.
-
User Interface
Epicor tab layout optimized for small screens
The Epicor settings tab now displays all options on one screen on smaller monitors, making it easier to configure without scrolling.
-
User Interface
Import history section added
A new Import History section shows the latest POS file import for each store, including how many records were imported and when.
-
User Interface
Streamlined Import Manager help access
Consolidated two separate help/info buttons into a single, clearly positioned help button that provides access to data import documentation without cluttering the interface.
-
User Interface
Removed redundant info button
An older info button next to the Import Path field has been removed, as its functionality is now replaced by the repositioned help button that links to comprehensive import documentation.
-
User Interface
Added friendly descriptions for Order Indicator codes
When filtering by Order Indicator, you'll now see helpful descriptions like "Stock/Order Through - T" instead of just "T".
-
User Interface
Improved loading message for pre-compiled import types
The loading screen now shows a clearer message when searching for import files.
-
User Interface
Improved Import Manager splash screen messaging
The Import Manager now shows clearer status messages while loading, making it easier to understand what the application is doing.
-
User Interface
Adaptive column headers in Data Aging screen
The Data Aging screen now adjusts its column labels to match the type of data being shown.
-
User Interface
Dynamic column headers in Data Aging import history
The Data Aging screen adjusts what it shows based on what information is available.
-
User Interface
Added instructional text to bulk SKU input dialog
When entering multiple SKUs at once, you'll now see an example showing the correct format.
-
User Interface
Improved column picker dialog
When importing files with multiple columns, the column selection dialog is now clearer about what it's asking you to choose.
-
User Interface
Conditional menu visibility for store-specific feature
The new import menu option is only visible to Do it Best stores that have store number 1372 in their organization, ensuring the feature is accessible only where it's needed.
-
User Interface
Added progress feedback during catalog field updates
During imports, you'll now see status messages explaining what's happening even after the progress bar completes, so you know the system is still working.
-
User Interface
Added progress feedback during catalog operations
You'll now see messages explaining what's happening during catalog imports instead of just a blank loading screen.
-
User Interface
Enhanced progress reporting for BisTrack imports
The progress bar during BisTrack imports now shows accurate percentages and clearer messages about what step is currently running.
-
User Interface
Removed "All" option from catalog item store selection for BisTrack
When adding catalog items in BisTrack, you must now choose a specific store number instead of "All," since each BisTrack store has its own pricing.
-
User Interface
Store mapping scan grid now shows both character and numeric code
When you scan an Epicor INDecoded file, the store mapping grid now shows both the character (when printable) and its numeric code, making it easier to identify and map unusual store codes.
-
User Interface
Enhanced store mapping grid with ordinal display
When scanning an INDecoded file, you'll now see clearer labels for each store code, including the numeric value in parentheses.
-
User Interface
Store Match Up dialog now handles POS system differences correctly
The Store Match Up screen now correctly handles store numbers based on your POS system type, preventing data corruption when saving mappings.
-
User Interface
Store Match-Up dialog now adapts encoding based on POS system type
Added POS system type detection to the Store Match-Up screen (POSStoreNumberMatchUpViewModel) to conditionally apply character-to-ordinal encoding only when using Epicor, ensuring other systems handle store numbers as literal strings throughout the match-up workflow.
-
User Interface
Loading overlay during connection test
You'll now see a clear "Testing MySQL Connection..." overlay with a progress bar while the connection test runs.
-
User Interface
Visual indicator for unmapped stores in Zone Assignment
Stores that aren't set up in your point-of-sale system now appear crossed out in gray, with a message explaining why you can't change their zone pricing.
-
User Interface
Updated menu text for Epicor store management
The menu item text for Epicor users now reads "Manage Epicor POS/Vendor Store Info" (changed from "POS/Vendor Store MatchUp") to better reflect the expanded functionality of the new Store Manager, which handles store information beyond just store number matching.
-
User Interface
Standardized Epicor menu visibility rules
Updated the logic that controls which store configuration menu items are visible to Epicor users, ensuring consistency across all menu entry points by checking the actual POS system type rather than a database service flag.
-
User Interface
Updated warning dialog for unmapped Epicor stores
The warning message for new stores is now clearer about what action you need to take next.
-
User Interface
Removed unnecessary Store Manager columns
The Store Manager screen now focuses only on the information needed for store mapping, with unnecessary columns removed.
-
User Interface
Display readable values for control-character store ordinals
The POS Store column in the store manager will now show a readable number like "15" instead of appearing blank for stores using low-numbered codes.
-
User Interface
Status column added to Store Manager screen
A new Status column shows which stores need your attention—either because they're missing from Epicor or need their vendor store number assigned.
-
User Interface
Status column and cleanup tool in Store Manager
The Store Manager grid now shows a Status column that tells you which stores need attention. Use Tools → Remove Not Found Stores to clean up stores that are no longer active in your POS system.
-
User Interface
Improved delete prevention message for Epicor stores
The warning message now tells you whether the store would return from MySQL Compass or the INDecoded file, making it clearer why the store was marked Excluded instead of deleted.
-
User Interface
Improved Import Manager feedback for multi-store processing
The import screen now shows which store is being processed out of the total (like "Store 123 [2 of 5]") and what operation is running.
-
User Interface
Live progress during managed index rebuild
The application now shows which table's indexes are being rebuilt and displays a warning that this step can take several minutes, so you know the import hasn't stalled.
-
User Interface
Progress indicator for cost field synchronization
When syncing cost fields after import, you'll see a progress bar and table-by-table updates showing how much work remains.
-
User Interface
Simplified store selection dialog
The store selection window now shows cleaner information: your POS store numbers, vendor store numbers, and when each store was last imported.
-
User Interface
Simplified POS store display for Epicor
Epicor store numbers now display just the character (like "A" or "‡") without extra numbers in parentheses.
-
User Interface
Updated Epicor settings help text for clarity
Changed the Import Options help text on the Epicor settings tab from "POS store numbers are always mapped" to "POS store numbers are mapped" to reflect that store mapping is now optional rather than mandatory.
-
User Interface
Improved messaging when no new import files are available
You'll now get helpful instructions about exporting new files from your POS system when there's nothing new to import.
-
User Interface
Added helpful guidance message when no new import files are available
You'll now see a clear message explaining where your imported files went and what to do next, instead of an empty list or confusing backup files.
-
User Interface
Improved splash screen lifecycle during catalog operations
Changed from debounced (delayed) splash screen hiding to immediate synchronous teardown before modal dialogs. This ensures the splash screen is fully closed before showing results and prevents race conditions where competing splash screen operations interfere with each other across nested message pumps.
-
User Interface
Date label clarification
Date labels now clearly show "Last Synced" for vendor updates and "Last Import" for POS data updates.
-
User Interface
Aligned help button with Export to Excel on Manage Pricing Strategies window
Repositioned the help button to appear next to the Export to Excel button at the top right of the Manage Pricing Strategies screen for better visual alignment and consistency.
-
User Interface
Enhanced selection box display formatting
Added support for displaying alternative text after the main value in selection boxes (AltItemTextAfter property). This allows descriptions to be shown in the format "Code - Description" instead of only "Description - Code", improving flexibility for different field types.
-
User Interface
Column picker dialog for Excel imports
When importing from Excel files with multiple columns, you'll be asked to choose which column contains the SKUs.
-
User Interface
Tools menu bar added
Added a menu bar to the top of the Catalog Add Items dialog with a Tools menu containing Import File and Enter Bulk List options, providing clear access to the new bulk import features.
-
User Interface
Enhanced column picker dialog instructions
When importing files with multiple columns, the dialog now clearly explains why it's asking you to choose a column.
-
User Interface
Dialog window sizing improvements
Configured both dialogs to automatically size to their content, ensuring they display properly regardless of screen resolution or DPI settings.
-
User Interface
Help button added to Add Catalog Items dialog
Click the help button (?) next to the search box to learn how to use the catalog import features.
-
User Interface
Optional data rebuild prompt after import
After importing new products, you'll be asked if you want to rebuild the data now to see the new items in your pricing grid, or you can choose to do it later.
-
User Interface
Enhanced Store Matchup screen for Ace Hardware
Modified the Store Number Matchup screen to load zone data from AceStoreDepartmentZoneRecords on startup and save zone overrides when the user clicks Save. The new columns appear only for Ace Hardware customers and integrate seamlessly with the existing store matching workflow.
-
User Interface
Enhanced progress messages during BisTrack import
Progress dialog now displays specific stage-based messages like "Reading 3/12: store_045.csv", "Inserting 47,500 rows (8/12 files)...", and "Cleaning 245,000 rows across 12 stores..." with matching percentage values, replacing generic "Loading file..." messages.
- User Interface Reorganized Connections tab layout
-
User Interface
Connections tab layout improvements
Redesigned the Connections tab to use a scrollable layout with reorganized sections: "Epicor FTP Connection", "Server Type", "Import Options", and the new "INDecoded Store Mapping Scanner". Increased design height from 450 to 600 to accommodate the new store mapping grid. Added a StoreCharMapping model to support data-binding for the editable POS store char → vendor store number grid.
-
User Interface
Improved visual styling for Import Exclude descriptions
Description text is now styled with italic font, smaller size (11pt), and gray color to visually distinguish helper text from input fields, improving readability and interface hierarchy.
-
User Interface
Hidden redundant Ace Zone Pricing menu for Epicor users
Epicor users no longer see a separate Ace Zone Pricing menu item since zone pricing is now handled directly in the main Store Manager screen.
-
User Interface
Remove Not Found Stores menu option
You can now quickly remove all stores that are no longer in your Epicor system using the "Remove Not Found Stores" option in the Actions menu.
-
User Interface
Clearer MySQL configuration guidance
When MySQL is not configured, the notification now directs users to "Tools > Options" to set up their MySQL connection settings, making it easier to resolve configuration issues.
-
User Interface
New Store Delete Reason dialog
Added a new dialog window (StoreDeleteReasonView) that displays on the Store Manager screen when deleting Epicor Eagle stores. The dialog shows context about which POS store number is affected and which system it exists in, followed by five radio button options for the deletion reason. The "Remove Store" button remains disabled until a reason is selected.
-
User Interface
Validation requires reason selection
The "Remove Store" button in the deletion reason dialog remains disabled until one of the five reason options is selected, ensuring users cannot proceed without providing context for the deletion.
-
User Interface
MySQL Scripts Manager layout adjustments
Added a menu bar to the top of the MySQL Scripts Manager window to accommodate the new Scripts menu. Adjusted grid row definitions to maintain proper spacing with the new menu bar.
-
User Interface
Removed SKUs column from import picker
The SKUs column has been removed from the store picker to simplify the view.
-
User Interface
Enhanced database setup validation
If Margin Master can't read your store number from a database, it now asks you to confirm the number instead of guessing.
-
User Interface
Reconciliation progress display
During import, the splash screen now displays "Reconciling SKUs for Store [X] [Y of Z]" to show reconciliation progress for each store location. The total number of deleted SKUs is logged for reference.
-
User Interface
Improved reset confirmation and messaging
When resetting vendor or POS data, you'll now see clearer messages explaining what will happen and what you need to do next to restore your data.
-
User Interface
Improved reset confirmation and completion messaging
Both the Reset Vendor Data and new Reset POS Data features now include more detailed confirmation dialogs that clearly explain what will be deleted and what actions are required afterward. Success messages explicitly state that the main table has been cleared and provide next-step guidance for re-syncing or re-importing data.
-
User Interface
Dialog layout improvements
Widened the Data Aging dialog from 800px to 950px to accommodate the new import history table, and added a scroll viewer to the POS data panel to handle multi-store environments with many import records.
-
User Interface
Friendly display names for vendor sync tables
Added a dictionary mapping internal table names to user-friendly display names, including "Ace Catalog" for AceCatalogRecords, "DIB SKU Classification" for DIBSkuProductClassificationRecords, "Planograms" for AcePlanogramRecords, and similar mappings for all synced vendor tables.
-
User Interface
Fixed POS dropdown width for non-Ace/non-Orgill vendors
When creating a database for Do-It-Best, Emery Jensen, or United Hardware, the POS system dropdown now uses the full width of the window for easier selection.
-
User Interface
Per-file progress for BisTrack batch imports
You'll now see real-time progress as each store file is imported, instead of waiting for all files to preload before seeing any feedback.
-
User Interface
Progress reporting improvements for BisTrack imports
BisTrack import progress now shows detailed file-by-file status during loading and per-store status during table creation, making it easier to track long-running imports.
-
User Interface
Store selection UI now correctly encodes special characters
Fixed the Store Manager matchup UI and MySQL store selection dialog to use PosStoreCharHelper.CharToWin1252Ordinal when setting the store character, replacing the previous (int)char cast that stored Unicode code points. Updated the legacy migration path to normalize historical UnicodeNumber values greater than 255 back to their Windows-1252 byte equivalents.
-
User Interface
Updated debug import preview labels
The debug import preview dialog now uses vendor-specific labels (e.g., "Ace Store #1715" instead of "Vendor #1715") to match the picker's dynamic labeling approach.
-
User Interface
Improved status messages during partial import rebuild
The import status messages now more accurately show what the system is doing during the import process.
-
User Interface
Import status messages added
The import screen now shows clearer status messages while processing your data.
-
User Interface
Import dialog reflects direct database import
The Import Manager splash screen for RockSolid now displays "Importing RockSolid Data..." instead of "Extracting RockSolid Data..." to better reflect that data is being imported directly to SQL Server rather than extracted to an intermediate file.
-
User Interface
Enhanced progress reporting for Excel imports
SqlBulkCopy operations now report progress every 1% (or minimum 1,000 rows), updating both the splash screen progress bar and status messages. The Import Files screen shows messages like "Loaded 150,000 rows from Excel — bulk inserting to SQL..." followed by per-batch progress updates.
-
User Interface
Import failure notifications
Added user-facing notification on the Import Manager splash screen when vendor data updates fail after all retry attempts, providing immediate visibility when imports encounter unrecoverable errors.
-
User Interface
POS system dropdown now shows friendly names
The POS system dropdown now shows easy-to-read names instead of technical codes.
-
User Interface
Import Manager and Main Table adopt handler workflow
Updated `ImportFilesViewModel` and `MainMMViewModel` to use `IPosImportHandlerFactory.ResolveAsync` instead of direct service calls. Both screens now route BisTrack imports through the handler pipeline, with progress updates flowing through a new `IPosImportProgress` adapter interface. Legacy file-by-file import path is preserved as a fallback when no handler matches.
-
Database
SKU index creation during import
Added automatic creation of a non-clustered index on the SKU column immediately after the initial product data merge. This index converts expensive full table scans into fast index lookups when joining vendor catalog data, reducing query time from over 30 seconds to under a few seconds even on large catalogs.
-
Database
Added performance index for Compass store group operations
Added a new managed index (RSIX_Compass_IN_in_store) on the in_store column of the Compass_IN table. This index is automatically created during data import to ensure fast JOIN performance when building store groups, preventing timeouts on stores with large inventories.
-
Database
Standardized collation for Epicor store number fields
Added explicit case-sensitive collation (Latin1_General_CS_AS) to the EpicorStoreNumber column in both the query JOIN condition and the table creation script to match the Compass database collation and prevent future comparison errors.
-
Database
Persistent BisTrack import table
Added BisTrackPointOfSaleDataImport as a persistent table (BisTrackPointOfSaleDataImportCreateTable.sql) that survives across import sessions. The table includes CreateDate and LastUpdate timestamps to track when records were first added and last modified, plus an index on Store and Sku for efficient merging.
-
Database
Numeric columns stored as DECIMAL during preload
The `BisTrackPointOfSaleDataImport` staging table schema changed: CurrentPrice, OnHand, H0–H12 (history months), Cost, and Comp1–5 columns are now DECIMAL(19,4) instead of NVARCHAR. The Sep CSV reader parses these fields to typed decimals immediately during Phase 1 bulk insert, eliminating all downstream TRY_CONVERT operations in `BCPToStoreImport.sql` and the new `BisTrackPreloadToCurrent.sql` script.
-
Database
Enhanced Compass_IN table indexing strategy
The indexing logic now creates two indexes on the Compass_IN table: a single-column index on in_store for general lookups, and a composite index on (in_store, in_db_update_datetime) specifically optimized for timestamp queries during incremental sync operations.
-
Database
Cleanup of duplicate placeholder store records
When re-pointing a corrupted store identifier to its correct value, the system now automatically removes any unmapped placeholder records that were previously created for that identifier, eliminating duplicate entries in the store manager.
-
Database
New SyncHistorySummary model for Data Aging display
Created a lightweight SyncHistorySummary model to hold per-table sync information, including table name, friendly display name, last sync date, record count, and status. This model uses a SQL query with ROW_NUMBER partitioning to efficiently retrieve only the most recent successful sync per table.
-
Database
SyncHistorySummary model added
Created a new lightweight model to efficiently query and display sync history summaries without loading full SyncHistory records, improving performance when displaying the Data Aging View.
-
Database
Global SKU index seeding
Added SKU to the list of critical columns that receive automatic indexes during database startup and maintenance operations. This ensures all store pricing tables have proper SKU indexes across all code paths, preventing the timeout issue from recurring in any import scenario.
-
Database
BisTrack staging table cleanup script
Added a new SQL script (BisTrackBCPFinalizeCleanup.sql) that strips quotes from all fields, normalizes store numbers, and removes duplicate SKU entries within the batch staging table without performing inserts, specifically designed for the Sep bulk import path.
-
Database
IsNotFound column migration for existing databases
The StoreManagerInfo table schema now includes an IsNotFound bit column (default false). For existing databases, an automatic ALTER TABLE migration adds this column during the EnsureStoreManagerTableAsync initialization step, ensuring seamless upgrade without data loss.
-
Database
IsNotFound field added to StoreManagerInfo
Added IsNotFound boolean field to the StoreManagerInfo table to track stores that exist in Store Manager but are no longer present in Compass_IN data. Includes automatic migration for existing databases. Stores with IsNotFound=true are excluded from VendorStoreNumber editing and import processing.
-
Database
Store matchup discovery entries handled correctly
Discovery entries (GlobalFileConfig with Key "99999") are now correctly processed as unmapped store placeholders rather than actual vendor store numbers, ensuring clean Store Manager records and proper single-store auto-mapping behavior.
-
Database
New DIB6828 typed staging schema
Added BisTrackDib6828PointOfSaleDataImport table with 25 typed columns—numeric fields (CurrentPrice, OnHand, H0-H12, Cost) stored as DECIMAL(19,4) to eliminate downstream TRY_CONVERT calls. Three new SQL scripts handle the DIB6828 pipeline: BisTrackDib6828PointOfSaleDataImportCreateTable.sql (persistent typed table with Store/Sku index), BisTrackDib6828PreloadToCurrent.sql (extracts single store from staging to _current working table), and BisTrackDib6828BCPFinalizeCleanup.sql (strips quotes, normalizes Store, deduplicates rows). RSImportFileHelperService adds PreloadBisTrackDib6828BcpAsync and PostPreloadBuildAllStoresFromDib6828Async methods with BisTrackDib6828BcpRow POCO for CSV mapping.
-
Database
Capture server identity information
Connection test now queries and stores the MySQL server hostname, version, and current database name from the identity query (@@hostname, @@version, DATABASE()), making this information available in the test result model and visible to users in the results panel.
-
Database
DIB6828 SQL schema and pipeline scripts
Added three new SQL scripts for DIB6828: `BisTrackDib6828PointOfSaleDataImportCreateTable.sql` (typed staging table with DECIMAL fields and Store/Sku index), `BisTrackDib6828BCPFinalizeCleanup.sql` (quote stripping, store normalization, deduplication), and `BisTrackDib6828PreloadToCurrent.sql` (per-store extraction from preload table to _current working table). Numeric columns are loaded as DECIMAL during CSV read, eliminating TRY_CONVERT calls in downstream queries.
-
Database
BisTrack schema improvements
BisTrackPointOfSaleDataImport table columns changed from NVARCHAR to DECIMAL(19,4) for CurrentPrice, OnHand, H0-H12, Cost, and Comp1-5. Added BisTrackPreloadToCurrent.sql for zero-cast fills from typed preload table. BisTrackInsertIntoMainTable.sql now references normalized column names (Description2, ProductGroup, OrderMultiple) instead of legacy aliases (Desc2, PG, OM). Updated nsoftware.IPWorksSSH package from 24.0.9545 to 24.0.9624.
-
Architecture
BisTrack import handler interface
Introduced `IPosImportHandler` interface and factory pattern to standardize all POS import workflows. Handlers use a consistent two-phase contract: `PreloadAsync` (load files into typed staging tables) and `BuildAllStoresAsync` (per-store SQL pipeline). The factory resolves the correct handler by testing CSV headers or DirectConnect configuration, allowing multiple format variants to coexist cleanly.
-
Architecture
POS-specific import script framework
Modified RSImportFileHelperService to check for and use POS-specific InsertIntoMainTable.sql scripts when available, falling back to the generic insert logic for other POS systems. The specialized script receives variables for the current table name, mainTable name, store number, and RSC filter condition, and bypasses the duplicate removal step when used.
-
Architecture
BisTrack staging table now reused across files
Refactored the BisTrack batch import process so the staging table is created once at the start, then each file's data is loaded, processed, and truncated before the next file begins. This ensures proper isolation between store files and eliminates the need for tracking "all stores processed" flags. Each file now deletes any existing data for its store before loading new data.
-
Architecture
Handler-based POS import pipeline
Introduced IPosImportHandler contract with factory-based resolution (IPosImportHandlerFactory) to replace direct ViewModel calls to import services. Three BisTrack handlers registered: BisTrackDib6828Handler (checks for DIB6828-specific headers), BisTrackDib1040Handler (requires ≥10 DIB1040/MAP1/MAP2 header matches), and BisTrackDirectConnectHandler (validates SQL configuration for live server queries). Handlers implement CanHandleAsync (format detection), PreloadAsync (batch file loading), and BuildAllStoresAsync (per-store table generation). ImportFilesViewModel and MainMMViewModel now resolve handlers through the factory and delegate progress reporting through IPosImportProgress adapters.
-
Architecture
Shared enrichment for vendor data fields
Extracted the logic that populates pricing levels, taxonomy categories, and vendor-owned flags from the MMVendorData view into a shared method (EnrichDibPosMainTablesFromMMVendorDataAsync). Both the interactive catalog-add workflow and the new bulk re-add process now use the same enrichment code, ensuring consistency and eliminating duplicate SQL update statements. The bulk path enriches via a set-based join instead of building large IN clauses with thousands of SKUs.
-
Architecture
Extracted testable import history coverage logic
Moved the "should we trust ImportProcessing or read the main tables" decision into a standalone `ShouldEnrichFromMainTables` method with 7 new unit tests covering the exact 1-of-22 scenario, full coverage being preserved, leading-zero store number equivalence, and the stale-store case the original guard was written for. This regression happened silently (the view simply showed a smaller number), so the logic is now pinned with direct tests.
-
Architecture
Handler-based POS import resolution
The Import Manager now automatically detects which BisTrack format your files use.
-
Architecture
Enhanced store scanner service
The EpicorFTPFileExtractorService.ScanStoreCharactersAsync method now returns a dictionary mapping store character ordinals to record counts instead of just a list of ordinals, enabling the UI to display both the character and its associated SKU count.
-
Architecture
EpicorFTPFileExtractorService enhancements
Added ScanStoreCharactersAsync() method to EpicorFTPFileExtractorService that reads an INDecoded binary file, extracts unique single-character POS store codes from byte offset 14, and returns them sorted. Modified DecodeEpicorINFileAsync() to support the new streaming import path with MergeIntoStoreTableAsync(), which uses BulkMerge with ColumnPrimaryKeyExpression on (StoreNumber, SKU) for upsert behavior. The method now branches based on the EpicorUseStreamingImport setting to choose between legacy (in-memory dedup + insert) and streaming (SQL-side dedup + merge) paths.
-
Performance
Optimized BisTrack import speed
Importing POS data from BisTrack is now faster, reducing wait time during the import process.
-
Performance
Streamlined BisTrack import pipeline
BisTrack data imports now run faster, especially for larger inventory files.
-
Performance
Improved BisTrack import query efficiency
BisTrack product data imports will now run faster, with the most noticeable improvement for stores with thousands of items.
-
Performance
Typed staging table for BisTrack imports
BisTrack imports now complete faster because price and quantity data is processed more efficiently.
-
Documentation
New troubleshooting guide for Epicor zero-SKU imports
When an Epicor import runs but brings in no inventory, this new guide shows you exactly what to check and how to fix it — usually a store mapping issue in Store Manager.
-
Performance
Bulk re-add for large Do-It-Best catalogs on BisTrack
If you have hundreds or thousands of manually tracked catalog items, they will now re-add almost instantly after a rebuild instead of taking many minutes.
-
Documentation
Field mapping reference for MI9 imports
Documented the complete set of MI9 import fields including all retail price levels (Retail, RetailLevel1-5, RetailZone variants), cost fields (StoreCost, AVGCost, ReplacementCost), 12 months of sales history, competitor pricing (Comp1-5, CompA), store product status codes, and vendor information. Explains how the "current price cascade" logic selects the active retail price from multiple available price levels, and how team aggregation chooses representative values when stores within a team have conflicting data.
-
Documentation
Expanded Add from Catalog documentation with bulk import workflows
The help documentation now explains how to import multiple SKUs at once using Excel files, CSV files, or by pasting a list of SKUs separated by commas or line breaks.
-
Infrastructure
Code modernization and cleanup
Removed over 290 lines of legacy code related to dynamic compilation and intermediate table handling, replacing it with a more efficient and maintainable implementation using modern CSV parsing libraries. The simplified codebase will be easier to maintain and debug going forward.
-
Performance
Optimized duplicate SKU removal during BisTrack import
Updated the duplicate SKU detection logic to work directly with indexed columns instead of applying string trimming functions during the comparison. This allows the database to efficiently identify and remove duplicate entries without scanning every row.
-
Infrastructure
Enhanced store character conversion handling
Added a new `ToDisplayString()` helper method that intelligently converts between stored ordinal values and display strings, with special handling for control characters and extended ASCII. The conversion also handles legacy formats where the ordinal may already be displayed as a number string.
-
Code Quality
Removed unused file retention logic
Removed 18 lines of dead code that was building a file dictionary and attempting to keep only the 3 most recent files, but this logic was never actually functioning. The simplified version now focuses only on removing empty backup directories.
-
Infrastructure
Resolved nullable reference type warnings
Fixed all C# nullable reference type warnings (CS8600, CS8602, CS8618, CS8622, CS8629, CS8632) across view models and services using appropriate null-coalescing operators and pragma directives. Added fallback to empty collections for database query results to prevent potential null reference issues in SKU-level exceptions, column editing, and selection box management.
-
Documentation
Enhanced Store Manager documentation for Epicor matchup
The Store Manager help now clearly explains how Epicor stores are matched up and what the status badges mean for your imports.
-
Infrastructure
New helper method for store ordinal drift recovery
Added PosStoreCharHelper.RecoverDriftedOrdinal method with comprehensive unit test coverage. This helper validates recovered ordinals against live MySQL data rather than trusting string parsing alone, ensuring the system never guesses at store mappings and only applies corrections when the recovered ordinal actually exists in the database.
-
Infrastructure
Transient error classification for MySQL
Added logic to identify and classify MySQL connection errors that are worth retrying (error codes 1040, 1042, 1043, 2002, 2003, 2006, 2013), such as "server temporarily unavailable" or "connection lost". The system logs warnings when retrying these transient errors to help diagnose intermittent connection issues.
-
Infrastructure
Added comprehensive test coverage for Data Aging logic
Added 8 unit tests documenting when the Data Aging screen should trust recorded import history versus reading actual table counts, including the specific regression scenario (one good history row out of 22 stores), full coverage validation, leading-zero handling, empty/zero-record scenarios, and stale history detection.
-
Infrastructure
Issue tracking documentation
Added documentation for four support issues (MM-1158 through MM-1161) covering SQL Server instance detection, database creation flows, MySQL import data integrity, and single-store SKU exception handling. These documents capture root cause analysis and proposed fixes for upcoming maintenance work.
-
Infrastructure
Import handler store tracking
All BisTrack import handlers now expose which store numbers were successfully imported during the most recent import operation. This data is used by the missing store detection feature to identify stores that may have been excluded from an import.
-
Infrastructure
Added diagnostic timing for group table builds
Added detailed timing logs around store group table building operations to help diagnose performance issues in future troubleshooting scenarios. Logs now show SKU count and elapsed time for each group table build.
-
Infrastructure
Enable nullable reference types in Epicor extractor
Added nullable reference type annotations to EpicorFTPFileExtractorService to improve code safety and prevent null reference exceptions during import operations.
-
Infrastructure
Repeatable migration logic with safety checks
The migration logic is safe to call multiple times — it exits immediately if no binary-format rows with vendor numbers exist, preventing unnecessary processing. The system only runs this migration for Epicor INDecoded configurations, never for MySQL Compass stores.
-
Infrastructure
Added organization tracking to license validation
Enhanced the license validation service to capture and store the organization ID from software license details. This supports multi-organization deployments and ensures organization-specific settings like store configurations are properly associated with the correct organization context.
-
Infrastructure
Added Windows-1252 encoding support to test environment
Registered the Windows-1252 code page encoding provider in the test project initialization to enable store character conversion tests to run. Modern .NET requires explicit registration of legacy code pages; the running application gets this transitively from dependencies, but the test host needed it added explicitly.
-
Documentation
Updated Epicor MySQL import guide with store matchup details
Revised Epicor MySQL Compass import documentation to explain store filtering using the store character ordinal, reference the Store Manager for configuration, and link to the new zero-SKU troubleshooting guide. Added technical details about the reconciliation process and how single-store setups auto-map.
-
Infrastructure
Store Manager migration from legacy selector
Removed EpicorMySqlStoreSelectorViewModel, MySqlStoreSelectionViewModel, EpicorMySqlStoreSelectorView, and the MySqlStoreSelectionViewModel DI factory (~680 lines). Replaced with lightweight StoreImportSelectorViewModel and StoreImportSelectionViewModel (~130 lines) that wrap StoreManagerInfo for display only—no database writes occur from the picker. The new architecture separates selection UI from store configuration management.
-
Infrastructure
Remove redundant MySqlCompassTabViewModel wrapper class
The thin wrapper view model (MySqlCompassTabViewModel) that hosted MySqlConnectionDetailViewModel has been removed. EpicorTabViewModel now directly owns MySqlConnectionDetailViewModel as its InnerViewModel property, eliminating one layer of indirection and simplifying the view model hierarchy.
-
Infrastructure
Automatic enforcement of Import Manager for Compass stores
When the Epicor tab loads settings for a Compass store, the application now automatically enables the Import Manager flag and saves this setting. This ensures consistent behavior across all Compass installations without requiring manual configuration.
-
Infrastructure
Documentation search index expansion
Updated docs/index.json with 147 new search entries covering POS systems category with subcategory "Import Guides". Each entry includes targeted search keywords (e.g., "bistrack", "direct connect", "dib1040"), audience tags (user, support), heading structure, and body excerpts for result previews.
-
Infrastructure
New BisTrack cleanup SQL script
Added BisTrackBCPFinalizeCleanup.sql, a cleanup-only version of the BCP finalization script that strips quotes, normalizes store numbers, and deduplicates records without performing INSERT operations. This script is specifically designed for the Sep batch load path where all stores are combined in a single staging table.
-
Infrastructure
Enhanced batch import progress reporting
Added detailed progress messages showing which file is being loaded (e.g., "Loading file 3 of 12") and summary statistics including total rows and store count. The import process now tracks a file-to-store mapping for better diagnostics and validation.
- Infrastructure New PostPreloadBuildAllStoresAsync method
-
Infrastructure
New BisTrackPreloadToCurrent.sql replaces type-casting logic
Created new SQL script that fills per-store `_current` tables directly from the typed preload table using simple column mapping with no CAST or TRY_CONVERT operations. This replaces the conditional logic in `BCPToStoreImport.sql` that previously performed type conversion during per-store extraction. Quote-stripping operations removed from `BisTrackBCPFinalizeCleanup.sql` for numeric columns since they're already typed.
-
Documentation
Expanded search keywords and index coverage
Added search keywords across all updated documentation pages including "0 skus", "store matchup", "pos store character", "store not importing", "nothing imported", and "blank prices" to help users quickly find troubleshooting information when experiencing import issues.
-
Infrastructure
Debug-only preview harness for store picker
Added a debugger-only harness that lets developers preview the "Select Stores to Import" picker without requiring a live MySQL or Compass connection. When running under the debugger with Shift held, the picker sources rows from the local StoreManagerInfo table (falling back to sample data if empty) and reports what would be imported without executing a real import. This facilitates UI testing and QA on non-production machines.
-
Infrastructure
Removed redundant ViewModels and Views
Deleted the separate ConnectionsTabViewModel, MySqlCompassTabViewModel, and their corresponding views. The new EpicorTabViewModel composes the MySQL connection VM and exposes FTP settings, Store Manager, and store-number options in a single unified interface. Updated dependency injection, data templates, and documentation to reflect the single-tab architecture.
-
Documentation
Update Epicor connection documentation for tab consolidation
All user-facing documentation (getting-started/data-import.md, epicor-server-setup.md, import-epicor-ftp.md, import-epicor-mysql.md, mysql-compass-connection.md, troubleshooting-epicor-zero-skus.md) has been updated to reference the unified "Epicor" tab instead of separate "Connections" and "MySQL/Compass" tabs, and to explain the "Connect via MySQL / Compass" toggle.
-
Infrastructure
Configurable reconciliation behavior
A new application setting (ReconcileMySqlDeletedSkus) allows the reconciliation feature to be enabled or disabled. The feature is enabled by default in production and includes safety checks to prevent accidental data deletion if MySQL returns zero SKUs.
-
Infrastructure
Remove deprecated DIB_Current cloud table code
Removed all references to the deprecated DIB_Current cloud table, including the cloudDBDataContext, DIBCurrent entity class, and the UpdateDoitBestCostsAsync method body. This cloud table no longer exists—Do-It-Best cost data is now provided through the locally-synced DIBCatalogRecords table and exposed via the MMVendorData view. This cleanup eliminates dead code and prevents confusion.
-
Infrastructure
Secrets management in CI/CD
GitHub Actions publish workflow now injects component licenses (DapperPlus, IPWorks) and API keys from Azure Key Vault into appsettings.json at build time. Local development uses appsettings.secrets.json (gitignored). Removed separate publish-docs.yml workflow; documentation publishing now integrated into main publish.yml. Added RetailerSoft.ComponentLicensing project reference and checkout step in CI.
-
Documentation
Updated Epicor FTP import guide
Added documentation for the new re-import feature to the Epicor FTP import guide, including step-by-step instructions for renaming the INdecoded.bak file and using the re-import prompt.
Cloud Sync & Vendor Data
-
New Feature
Persistent catalog item tracking
When you add an item from the catalog, it's now permanently saved. Every time Margin Master rebuilds your data, these items are automatically added back in with the latest pricing from your vendor's catalog.
-
New Feature
Persistent catalog item tracking
When you add an item from the catalog, it now stays in your system permanently. Every time Margin Master rebuilds your data, these items are automatically re-added with the latest pricing from your vendor's catalog.
-
New Feature
Catalog Lookup tool with typeahead search
Use Help > Catalog Lookup to quickly search for any vendor item by typing part of the SKU or description—results appear as you type.
-
New Feature
Catalog Lookup tool with cloud comparison
Search for any SKU or item description and see complete catalog details including pricing and zone information. The tool shows if your local catalog matches the cloud data, helping identify sync problems.
-
New Feature
Alternate code field added to vendor catalog items
When viewing Ace Hardware or Do-It-Best items, you'll now see alternate codes displayed in parentheses if the vendor provides them, such as "12345 (ABC) - Product Name".
-
New Feature
Excel import now detects and uses store numbers from files
When importing an Excel file with both SKU and store number columns, items are now automatically added to the correct stores without needing to select the store from the dropdown first.
-
New Feature
In-app Version History window
Click Help > Version History to see a complete list of all Margin Master releases and when you installed each version on this computer. Click any version to read its release notes.
-
New Feature
Version History window
Click Help → Version History to see all Margin Master releases and what changed in each version. You can filter to show only versions you've installed, and click any version to read its full release notes.
-
New Feature
Support for multiple demo databases per vendor
Extended the demo mode system to support multiple demo databases for each vendor, each with its own unique database key for naming (e.g., "AceHardware" and "AceHardwareMAPP"). Added DemoVendorInfo DTO and a new v2 API endpoint (/api/v2/Demo/AvailableDatabases/v2) that returns demos grouped by vendor with hierarchical structure.
-
New Feature
Multiple demo databases per vendor
Each vendor can now provide multiple demo databases with unique names and descriptions (e.g., "Standard Demo (Epicor POS)" or "MAPP Pricing Demo"). The system tracks each demo with a DatabaseKey for local storage while maintaining backward compatibility with existing single-demo-per-vendor configurations.
-
New Feature
Ace Hardware catalog detail display
Ace vendors can view complete catalog details including product groups, pricing strategies, and zone-specific pricing for every item.
-
New Feature
Search dropdown with instant selection
When you search for a SKU, matching items appear in a dropdown list below the search box—just select one and press Enter or click "Lookup" to view its details.
-
New Feature
Comprehensive data reset documentation added
Added detailed user and support documentation covering both Reset Vendor Data and Reset POS Data utilities, including what each reset affects, step-by-step instructions, special considerations for Do it Best mailbox stores, common questions, and technical details about affected database tables. The documentation has been indexed for searchability with keywords covering common user scenarios like "clear data," "start over," and "empty main table."
-
New Feature
Do it Best catalog detail display
Do it Best stores see detailed cost tier pricing for Classic and Vision membership levels, along with recommended selling prices and margin information.
-
New Feature
Copy SKU to clipboard button in detail header
Click the clipboard icon next to the SKU to instantly copy it for pasting elsewhere.
-
New Feature
Copy SKU to clipboard
Click the clipboard icon next to any SKU to instantly copy it for pasting into other applications.
-
New Feature
Cloud data comparison with sync verification
The tool automatically checks if your local catalog data matches the cloud and shows a colored banner indicating sync status—green for matched, yellow/red for differences with details about what doesn't match.
-
New Feature
Deep linking to web catalog with vendor, SKU, and store context
"View in web" now opens directly to the SKU you're viewing with your store number already filled in, saving time switching between desktop and web.
-
New Feature
View in web browser link
Click "View in web" to open the item's detail page in your browser for sharing or additional information.
-
Improvement
Help documentation links added to reset confirmation dialogs
When you reset vendor or POS data, the confirmation message now includes a link to detailed help documentation explaining the process.
-
Improvement
Alternate code display for vendor RSCs
When viewing RSC codes from Ace Hardware or Do-it-Best, you'll now see an alternate code shown in parentheses (e.g., "ABC123 (XY) - Product Name") when that vendor provides one.
-
Improvement
Filter Data Aging catalog list to store's RSCs
Do-It-Best stores now see only the catalog files that apply to their specific RSC locations.
-
Improvement
Vendor data staleness check refined for vendor update schedules
If you're a Do it Best store and you synced vendor data on Friday, you won't see "stale data" warnings when importing POS files on Saturday or Sunday, since Do it Best doesn't update their catalog on weekends anyway.
-
Improvement
Auto-populate RSC code from cloud settings
If you change a store's vendor number and the RSC code field is empty, the system will now automatically fill it in based on your organization's cloud settings.
-
Improvement
Live API fallback for RSC code lookup
When you enter a vendor store number, the system will now contact the cloud to get the matching RSC code if it's not already stored locally, ensuring accurate data even with outdated local information.
-
Improvement
Catalog sync status cache shortened to 2 hours
If a vendor catalog is processing in the cloud, the status you see in the Data Aging View will now update within 2 hours instead of waiting up to a full day for the display to refresh.
-
Improvement
Natural numeric sorting for all code lists
Store numbers, vendor codes, and other numeric fields now appear in the correct numeric order in dropdown lists and tables.
-
Improvement
Numeric-aware sorting for store and vendor code lists
When viewing dropdown lists for store numbers, vendor codes, or other numeric identifiers, they now appear in proper numeric order. For example, store "2" will appear before store "10", and codes like "00001" and "00010" sort correctly by their numeric value.
-
Improvement
Special warning for Do it Best mailbox stores during POS data reset
If your Do it Best store uses mailbox downloads instead of a POS system, you'll now see a clearer warning when resetting POS data, explaining that you'll need to re-download from the DIB mailbox to restore your data.
-
Improvement
Fixed Cost2 missing on Epicor imports
Epicor stores will no longer see blank vendor catalog costs in the pricing grid when cost data is available from the POS system.
-
Improvement
Cost sync progress indication
You'll see a new "Synchronizing cost fields..." message during startup that shows the system is making sure all cost values match.
-
Improvement
Enhanced CatalogFileStatus model with local sync tracking
Added a LocalSyncDate property to the CatalogFileStatus model to store the last local sync timestamp. This property is populated by cross-referencing the cloud catalog's FriendlyName with the SyncHistory table, handling cases where multiple cloud files (like different Ace planogram formats or DIB Regional Service Center catalogs) map to the same local database table.
-
Improvement
Map cloud catalog files to local sync tables
Added intelligent mapping between cloud catalog file names and their corresponding local database tables. This handles complex scenarios where multiple cloud files (such as Ace Hardware's four planogram variants or Do-It-Best's eight RSC catalogs) all sync to the same local table, ensuring the correct sync date is displayed for each file.
-
Improvement
Enhanced catalog item data population
Items added from the catalog now include more detailed information like pricing strategies, velocity codes, and zone pricing data, making them identical to items imported from your POS system.
-
Improvement
Explicit Lookup button and Enter key support added
You can now press Enter or click the "Lookup" button to search for a SKU instead of waiting for auto-search.
-
Improvement
Added BackupAll factory method for safer backup operations
Introduced a new BackupRestoreOptions.BackupAll() factory method that creates a complete backup configuration including all pricing strategies, custom groups, SKU exceptions, rounding schemes, cost breaks, min/max strategies, application settings, custom views, and store configurations. This ensures auto-backup operations always capture complete data snapshots.
-
Improvement
Catalog Add Items file import moved to toolbar
The button to import Excel files is now easier to find at the top of the Catalog Add Items screen.
-
Improvement
Network firewall guidance for SQL connectivity
Error messages now include helpful troubleshooting steps when cloud sync can't connect to the database server.
-
Improvement
Network error diagnosis
Error messages now tell you exactly what's wrong — if the firewall is blocking the connection, the message will specifically mention checking port 1433 settings.
-
Improvement
Added local sync status tracking to catalog file status
Added a new IsLocalSyncCurrent property that compares the local sync date against the cloud processing date to determine if the current machine has the latest catalog data. The overall IsSuccess status now requires both cloud processing success and local sync currency.
-
Improvement
Clearer error messages for network connection failures
Error messages now clearly explain when a firewall is blocking sync and reassure you that the software will automatically try a different connection method.
-
Improvement
Default store sort changed to POS store number
Stores now appear in order by their POS store numbers (1, 2, 3, 4) instead of vendor store numbers.
-
Improvement
Zone override field changed to numeric spinner
The zone override field now has up/down arrows and only accepts valid numbers.
-
Improvement
Automatic Ace zone validation on screen open
Ace zone assignments now update automatically when you open Store Manager, based on your latest catalog data.
-
Improvement
Ace Hardware zone validation
Ace Hardware stores now automatically display the correct pricing zone when you open Store Manager.
-
Improvement
Automatic remediation when post-sync reality check fails
If a sync doesn't import all your items, Margin Master will now automatically retry importing everything to make sure your data is complete.
-
Improvement
Enhanced error logging for DIB mailbox operations
Mailbox connection and download failures are now logged at Error level (previously Warning) so they reach cloud telemetry, allowing support to diagnose remote issues. Each failure now includes the specific host, port, and username (but not password) along with the underlying exception details, making it possible to correlate "couldn't read the mailbox" reports with the actual FTPS connection errors.
-
Improvement
Enhanced demo database metadata
Demo databases now include display names, descriptions, default selection flags, and unique database keys separate from vendor keys. Database keys control the local SQL Server database naming (MarginMaster_Demo_{DatabaseKey}) to prevent conflicts when multiple demos exist for the same vendor.
-
Improvement
Catalog search now uses debounced type-ahead
The catalog add screen now searches as you type instead of loading thousands of items upfront, making it much faster to find products.
-
Improvement
Automatic settings push to Manager server
When settings are saved in the Options dialog, the application now automatically pushes the current store configuration (RSC codes, POS system type) to the Manager server in the background. This ensures the server stays synchronized with local store settings for better support and data accuracy without requiring a full application restart.
-
Improvement
Zone override detection logic
Added properties to detect when a zone number has been manually overridden versus using the Ace-assigned value. The system compares the current zone against the original Ace assignment and automatically removes the override flag if the user enters the original zone number.
-
Improvement
Supplement process now fully populates store data
The background supplement process that runs at startup now includes RSC codes and zone overrides when backfilling missing store entries from GlobalFileConfig. This ensures stores added through the supplement path are as complete as those migrated initially.
-
Improvement
Dynamic zone lookup when vendor store number changes
Changing an Ace store number now automatically updates the assigned zone for that store.
-
Improvement
Store Manager waits for cloud save before closing
Closing the Store Manager window now waits for your changes to finish saving to the cloud, preventing lost updates.
-
Improvement
Auto-search with debouncing
Implements 400ms debounced search with cancellation tokens to provide responsive type-ahead search without excessive database queries. Search status text updates to show "Searching...", result count, or "No results" feedback.
-
Improvement
Deep linking to web Catalog Lookup
Clicking "Open in Web" now opens your browser directly to the same product you're viewing in the desktop app, with your store information already filled in.
-
Improvement
Restore Database launched directly from main app and startup
Database restore is now accessible from the Database menu and automatically switches to the restored database after completion.
-
Improvement
Mode switching clears opposite panel
Switching between Search and Bulk modes automatically clears the other mode's input and results—Search text and results are cleared when switching to Bulk, and Bulk entry text is cleared when switching to Search—preventing confusion from stale data.
-
Improvement
Documentation updated to reflect new workflow
The help documentation has been restructured to explain Search and Bulk modes separately, with clearer guidance on when to use each method. The "Enter Bulk List" section has been replaced with "Bulk Mode" and "Bulk Entry Notes" sections reflecting the new inline workflow.
-
Improvement
Catalog search query optimization
Do-it Best catalog search now uses DISTINCT in subquery to eliminate duplicate SKU entries in search results, providing cleaner results when searching by SKU or description.
-
Improvement
Internet connection check caching improved
Modified ApiClientService to cache successful connection checks for 5 minutes (up from 30 seconds), reducing unnecessary network requests to Google when the application is online. Offline checks continue to retry every 30 seconds.
-
Bug Fix
Cost fields now sync automatically after table rebuild
The pricing grid will no longer show blank cost values when cost information is available from another source. All three cost columns (store cost, POS cost, and vendor catalog cost) now stay in sync automatically.
-
Bug Fix
Cost field synchronization after table operations
If one cost field has a value but another is blank, the system now automatically fills in the missing cost to keep everything consistent.
-
Bug Fix
Data Aging view displays correct sync dates
The Last Sync Date column in the Data Aging screen now shows the correct date and time when each table was last synchronized, instead of showing blank entries.
-
Bug Fix
Fixed catalog item lookup for Do-It-Best stores
When using "Add Item from Catalog," Do-It-Best SKUs are now found correctly and can be added to your store.
-
Bug Fix
DIB catalog add now uses correct data source
Adding Do-It-Best catalog items now pulls the correct product information including descriptions, pricing, and product categories.
-
Bug Fix
Add from Catalog now displays errors instead of failing silently
If adding items from the catalog fails for any reason, you'll now see an error message explaining what went wrong instead of the button appearing to do nothing.
-
Bug Fix
Error messages now display when Add from Catalog fails
You'll now see an error message if something goes wrong when adding items from a catalog, so you'll know the items weren't added and why.
-
Bug Fix
Add from Catalog dialog crash resolved
The Add from Catalog dialog now opens correctly without crashing. Double-clicking items in the search results continues to work as expected.
-
Bug Fix
Catalog Add dialog double-click not working
When searching vendor catalogs and double-clicking an item to add it to your store's pricing list, the item will now be added as expected instead of nothing happening.
-
Bug Fix
ManualCatalogItems table creation now runs reliably
The system now properly tracks items manually added to vendor catalogs on all databases.
-
Bug Fix
Catalog Lookup SKU field now accepts text input
You can now type SKU numbers directly into the Catalog Lookup search field without issues.
-
Bug Fix
Catalog Lookup text input enabled
You can now type directly into the Catalog Lookup search box without interference.
-
Bug Fix
Fixed duplicate key error during batch creation
Stores with multiple location numbers under one Do-It-Best account can now successfully create change batches without errors.
-
Bug Fix
Fixed duplicate key error during batch creation
You can now successfully create change batches even if your store has multiple location numbers registered under the same Do-It-Best member number.
-
Bug Fix
Fixed null reference crash in automatic backup operations
The app will no longer crash when automatically backing up your data during sync or after editing custom groups and exceptions.
-
Bug Fix
Fixed sync timeout on cost field updates for large stores
Stores with large product databases will no longer experience sync failures when updating cost information.
-
Bug Fix
DIB Add to History now handles missing store configuration
Adding Do-It-Best items to history will no longer fail if your store list isn't fully configured in settings.
-
Bug Fix
Prevent SKU loss on first catalog add with immediate rebuild
When you add a SKU from the Do-It-Best catalog and choose to rebuild, the item will now be saved correctly the first time instead of requiring you to add it twice.
-
Bug Fix
Ace Zone columns now hide correctly for non-Ace vendors
When setting up store numbers for vendors other than Ace Hardware, you'll no longer see unnecessary Ace Zone pricing columns in the matchup screen.
-
Bug Fix
Ace Zone columns showing for all vendors in Store Matchup
If your store uses Do-It-Best, Orgill, or other non-Ace vendors, you'll no longer see the confusing "Ace Zone" and "Zone Override" columns in the Store Matchup screen.
-
Bug Fix
Store number filtering corrected for Ace Hardware zone sync
Store department zone pricing for Ace Hardware locations will now download correctly during sync, even when cloud store numbers include leading zeros.
-
Bug Fix
Forward slash now allowed in SKU filters
You can now filter and search for Ace Hardware products with SKU numbers containing forward slashes without encountering errors.
-
Bug Fix
Eliminate redundant "No items were added" message
When you try to add items that are already in your system or can't be found, you'll now see just one clear message explaining why, instead of two confusing messages.
- Bug Fix Populate all vendor fields when adding Do-It-Best catalog SKUs
-
Bug Fix
Complete vendor data population for Do-It-Best manual additions
Adding Do-It-Best items from the catalog now includes complete product information like pricing strategy codes, product category classifications, recommended order quantities, and velocity indicators—not just the basic price levels.
-
Bug Fix
Cloud sync error detection and messaging
If cloud sync fails because of network or firewall problems, you'll now see an error message explaining the issue instead of a confusing "No Changes Found" notification that made it look like everything worked.
-
Bug Fix
Cloud sync failure notification
If cloud sync can't reach the server (for example, due to firewall settings blocking port 1433), you'll now see a clear error message explaining what went wrong, rather than a message saying no changes were found.
-
Bug Fix
Data Aging status icons now reflect local sync state
If you see a dash in the "Local Sync" column, you'll now see an orange warning icon instead of a green checkmark, making it clear you need to run a sync to get the latest data.
-
Bug Fix
Data Aging green check now requires completed local sync
You'll now see the green check mark only after your computer has downloaded and applied the latest vendor catalog updates, not just when they're ready in the cloud.
-
Bug Fix
Automatic API fallback when firewall blocks Azure SQL redirect ports
If your firewall blocks certain database ports, Cloud Sync will now automatically detect the problem and retry using a different connection method that works on almost all networks. You'll see a message "Firewall detected — retrying sync via secure API..." during this process.
-
Bug Fix
Quick Issue Submission now includes system information
When submitting feedback or reporting issues through the Quick Issue tool, submissions will now complete successfully instead of failing with an error message.
-
Bug Fix
Schema prefix normalization in cloud sync proxy
Cloud sync will no longer fail with errors when updating vendor catalogs and pricing data.
-
Bug Fix
Schema prefix handling in cloud sync proxy
Fixed an issue that could cause cloud sync to fail for certain vendor catalogs.
-
Bug Fix
RowVersion hex-to-byte conversion now handles JSON deserialization correctly
Cloud Sync operations that were failing due to internal data format errors will now complete successfully.
-
Bug Fix
Fixed RowVersion data type conversion in cloud sync
Fixed an issue that could cause cloud sync to fail or not properly track which records have been updated.
-
Bug Fix
Prevent phantom store 99999 for Epicor users
Epicor users will no longer see an incorrect "99999" store entry when assigning Ace Hardware zone pricing.
-
Bug Fix
RSC codes now preserved during store matchup migration
For stores using multiple Do-It-Best RSC codes, the system will now correctly remember which RSC each store belongs to after upgrading.
-
Bug Fix
RSC codes now migrate to Store Manager
When migrating from legacy settings, RSC codes (STORERSC) are now properly transferred to the Store Manager for each vendor store number. Previously, stores would lose their RSC assignments during migration and supplementation.
-
Bug Fix
Excluded store status now syncs from cloud
If a store is marked as excluded in your cloud settings, it will now correctly appear as excluded after syncing.
-
Bug Fix
Store Manager database call now properly awaited
Fixed a missing await when updating database records in Store Manager's delete operation for stores that have been reassigned to a POS system. The update operation is now properly asynchronous, preventing potential race conditions or incomplete saves.
-
Bug Fix
Vendor filter now applied to reality check counts
The system will no longer incorrectly warn about missing items when you have vendor filters configured.
-
Bug Fix
Startup window crash when closing during connection
Fixed an InvalidOperationException that could occur if the startup window was closed while the application was still attempting to show it during database connection. The window now checks if it's still loaded before attempting to display.
-
Bug Fix
Store Manager cloud save no longer fails silently
If your store settings can't be saved to the cloud, you'll now see a warning message explaining why, and your changes will remain unsaved so you can try again once the issue is resolved.
-
Bug Fix
Vendor dropdown now populates offline during store setup
If your store has limited internet access or firewall restrictions, you can now complete the initial setup screen — the vendor selection dropdown will always show available vendors.
-
Bug Fix
Vendor dropdown now works offline during store setup
If your internet connection is down or blocked, you can still select your vendor from the dropdown when setting up Margin Master.
-
Bug Fix
Identity column handling in API proxy sync path
At stores where the firewall blocks direct database access, cloud sync would fail with "duplicate key" errors when downloading Ace Hardware taxonomy data. This is now fixed and sync will complete successfully.
-
Bug Fix
Accurate error messages for mailbox download failures
When you can't download a mailbox file, the error message now tells you exactly what went wrong—whether the file is no longer available, your connection failed, or something else—so you know whether to contact IT or simply refresh and try again.
-
Bug Fix
More accurate DIB mailbox error messages
When downloading from your Do it Best mailbox fails, you'll now see exactly what went wrong—whether it's a connectivity issue, a file that's no longer available, or simply nothing being selected—rather than always being directed to check firewall settings.
-
Bug Fix
Fixed catalog SKU list population for Do-It-Best
The full list of available Do-It-Best catalog items now displays correctly when opening the "Add Item from Catalog" dialog.
-
Bug Fix
DIB + multi-store POS systems now insert to individual tables
Adding catalog items now works correctly when your POS system tracks multiple stores in separate tables.
-
Bug Fix
Corrected batch cleanup after creation errors
Fixed an issue where batch IDs were captured before database insertion, causing the ID to be recorded as 0. This prevented proper cleanup when batch creation failed, leaving orphaned records. The system now captures the correct database ID and can properly clean up incomplete batches if an error occurs.
-
Bug Fix
Improved batch cleanup on errors
Fixed an issue where the batch ID was recorded before being saved to the database, causing cleanup routines to fail when errors occurred. Batch IDs are now captured after database insertion, ensuring that failed batch attempts are properly cleaned up and don't leave orphaned data.
-
Bug Fix
Fixed sync timeout on Ace MAP pricing updates for large stores
Ace Hardware stores with large product catalogs will no longer experience sync failures when updating MAP pricing.
-
Bug Fix
RSC column visibility correction in Store Matchup
Fixed the RSC (Retail Service Center) column visibility binding to use the correct format, ensuring it displays only when multiple RSCs are available in the dataset.
-
Bug Fix
Store dropdown now always includes "ALL" option
The Store dropdown now always shows "ALL" at the top, even if you only have one store.
-
Bug Fix
Ace Hardware zone overrides now preserved during migration
For Ace Hardware stores with manually set zone overrides, the zone assignments will now be preserved when upgrading to the new store manager system.
-
Bug Fix
Ace Hardware zone overrides now migrate to Store Manager
Zone number overrides for Ace Hardware stores are now correctly migrated from legacy GlobalFileConfig (ZONE_OVERRIDE) to the Store Manager. When multiple department-specific zone overrides exist for a store, department 1 takes precedence. Previously, these overrides were lost during migration.
-
Bug Fix
Store sync now only updates changed stores
Syncing store settings is now faster because only stores with actual changes are updated.
-
Bug Fix
Zone validation now triggered for all stores
Zone numbers are now properly validated for all stores, including excluded stores.
-
Bug Fix
False error telemetry for Ace stores without zone data
Ace Hardware stores that haven't synced zone pricing yet will no longer generate unnecessary error reports during store setup.
-
Bug Fix
Store Manager now detects and reports cloud API failures
If the cloud doesn't confirm your store settings were saved, you'll see a warning and can retry the save instead of losing your changes.
-
Bug Fix
Automatic recovery for affected stores
If your store previously had sync errors mentioning "AceTaxonomyRecords" or "duplicate key," the next sync will succeed automatically without requiring any action.
-
Bug Fix
Eliminated duplicate Do-it Best search results
When searching for Do-it Best catalog items, you'll no longer see the same item listed multiple times.
-
Bug Fix
Bin tag printing script error resolved
Bin tag printing now works correctly without showing script error messages. Barcodes still automatically hide when product codes are missing.
-
Bug Fix
Store dropdown now always includes "ALL" option
The Store dropdown now always shows "ALL" at the top, making it easier to add items to every store at once.
-
Bug Fix
Support Issues empty state no longer conflicts with error messages
When viewing a support ticket with an error, you'll no longer see the confusing "No messages yet" text at the same time as the error message.
-
Bug Fix
Full re-import now handles MySQL zero-date rows correctly
Full data imports will now correctly include all items, even those with missing or invalid update dates.
-
Bug Fix
Fixed overflow errors with large store or vendor numbers
Store or vendor numbers larger than 2 billion no longer cause sorting problems.
-
Bug Fix
Database rename tolerates non-critical SQL messages
Fixed the database rename RESTORE operation to distinguish between actual SQL errors and non-critical informational messages (version conversion notices, file relocation messages). The system now only fails if the database wasn't actually created, matching the behavior of the working RestoreDatabaseViewModel.
-
Bug Fix
Duplicate department row cleanup
Added logic to detect and remove duplicate department zone rows during initialization, ensuring each store/department combination appears only once in the assignment grid.
-
Bug Fix
Removed broken sorting workaround for large store numbers
Replaced the previous sorting implementation that used int.TryParse, which failed on store numbers larger than 2.1 billion and couldn't handle leading zeros correctly. The old PadLeft workaround has been removed and replaced with .NET's built-in numeric ordering that handles all numeric formats correctly.
-
Bug Fix
Store number comparison now ignores leading zeros
Items imported with store numbers like "06" will now correctly match store "6" in the system.
-
Bug Fix
SKU column width in SKU Lookup
Fixed excessively wide SKU column in the SKU Lookup view by changing from Auto width to fixed 110px width, improving the layout and making more room for other columns.
-
Bug Fix
Store number validation accepts any digit count
Store number fields now accept store numbers of any length (previously required at least 4 digits).
-
Bug Fix
Catalog Lookup memory leak eliminated
Removed manual CancellationTokenSource management from CatalogLookupViewModel. The new AutoSuggestSearchBehavior handles cancellation internally, preventing potential memory leaks from undisposed cancellation tokens.
-
Bug Fix
Restore Database callable from main app
Restoring a database from the main File menu now works consistently with the startup flow.
-
Bug Fix
Splash screen visibility during database dialogs
The loading screen no longer appears on top of database setup windows.
-
Bug Fix
Fixed SKU lookup grid column width conflict
Changed SkuLookupView GridColumn Width from "*" to auto to prevent conflict with AutoWidth property, avoiding layout calculation errors.
-
Cloud Sync
Removed redundant vendor data update for Do-It-Best
Do-It-Best catalog sync now completes faster—you'll no longer see the "Updating from vendor data..." progress message.
-
Cloud Sync
Automatic HTTPS fallback for firewall-restricted networks
If your network blocks cloud database connections, the sync will now automatically switch to a secure web-based method that works through standard HTTPS—you'll see a message confirming the switch, but sync will complete normally.
-
Cloud Sync
Automatic HTTPS fallback for firewall-restricted networks
If your network or firewall blocks database connections, cloud sync will now automatically switch to a secure web method without requiring any configuration changes or IT support.
-
Cloud Sync
Automatic fallback to API proxy on network connection errors
When your network or firewall blocks the normal sync connection, Margin Master will automatically switch to a backup connection method and complete the sync without you needing to do anything.
-
Cloud Sync
Cloud-based store settings storage
Your store settings (vendor numbers, RSC codes, zones) now sync with the cloud, so changes made on one computer will appear on others in your organization.
-
Cloud Sync
Store Manager cloud synchronization
Store Manager now loads and saves POS store settings to the cloud, including vendor store numbers, RSC codes, zone overrides, and exclusion flags. Settings are automatically downloaded when the screen opens and saved when it closes or when the Save button is clicked. This ensures store configuration is consistent across installations.
-
Cloud Sync
RSC codes now retrieved from cloud Stores table
When you enter a vendor store number, the RSC code will automatically fill in if it's available in your cloud account, reducing manual data entry.
-
Cloud Sync
Catalog sync status refreshes more frequently
When checking for new vendor catalog files, you'll now see newly published catalogs within 2 hours instead of waiting up to a full day.
-
Cloud Sync
New cloud API endpoint for catalog SKU detail
Added GET /api/v2/CatalogLookup/{vendorType}/{sku} endpoint to ApiClientService to fetch master catalog details from the cloud for comparison. Returns SKU details, description, pricing history, and zone pricing records when available.
-
Cloud Sync
Defensive table name handling
Added belt-and-suspenders protection against schema prefix mismatches by normalizing table names on the client side, complementing the server-side fix already deployed in Manager. This ensures sync reliability regardless of which server version stores are running.
-
Cloud Sync
Improved table name compatibility
The sync proxy now consistently handles both qualified ("dbo.AceCatalogRecords") and unqualified ("AceCatalogRecords") table names across all sync operations including schema retrieval, pending row counts, and batch fetching.
-
Cloud Sync
Improved reliability of incremental sync operations
This fix ensures the RowVersion-based incremental sync mechanism works correctly by properly handling the version tracking data sent from the cloud API. Without this fix, sync operations would fail when attempting to store RowVersion data in the local database.
-
Cloud Sync
Improved RowVersion handling for incremental sync
Enhanced the logic that processes RowVersion values received from the cloud API by checking the column name first, then properly extracting the hex string value regardless of whether it arrives as a JsonElement or plain string before converting it to the required byte array format.
-
Cloud Sync
Version history cloud sync on startup
The app now automatically downloads version history from the cloud when you start Margin Master and tracks which versions have been installed on your computer.
-
Cloud Sync
Version history synchronization
Margin Master now automatically downloads and saves version history in the background, so you can view release notes even if you're offline.
-
Cloud Sync
Cache cloud settings for faster lookups
Cloud store settings are now cached during initialization and reused when vendor store numbers change, improving responsiveness when editing multiple stores without requiring repeated cloud queries.
-
Cloud Sync
Enhanced demo database management
The demo reset and cloud upload features now correctly identify specific demo databases using the hierarchical DatabaseKey system. When updating the cloud demo database, the system matches against both the vendor key and specific database key to ensure the correct demo is uploaded or downloaded.
-
Cloud Sync
RSC alternate code synchronization
The cloud sync process now includes the AlternateCode field when downloading and updating retailer soft code records from the server, ensuring local data stays current with vendor-provided alternate identifiers.
-
Cloud Sync
Alternate code synchronization enabled
The cloud sync process now includes alternate codes when downloading and updating vendor catalog information from Ace Hardware and Do-It-Best.
-
Cloud Sync
Settings changes pushed to Manager server
When you save settings changes, they now automatically sync to the cloud in the background.
-
Cloud Sync
Proxy-aware schema and key detection
SchemaMirror and RowVersionTableSync now accept an optional ICloudSyncProxy parameter. When provided, schema introspection (column definitions, primary keys, identity flags) and row operations (count pending, fetch batch) use the proxy's HTTP endpoints instead of direct sys.columns and sys.indexes queries. Table key detection falls back to the schema endpoint's primary key metadata when operating in proxy mode.
-
Cloud Sync
Network error detection now checks all connection failure types
Expanded network connection error detection to recognize SQL error codes 53 (named pipes/server not found), 258 (TCP wait timeout), and -1 (network connection lost). Previously only error 53 triggered proxy fallback, which meant timeout failures on Azure SQL redirect ports would not trigger the automatic retry mechanism.
-
Cloud Sync
Enhanced error detection for SQL network failures
Expanded the network error detection logic to recognize additional SQL error codes: 53 (server not found), 258 (TCP wait timeout), and -1 (network connection lost). User-facing error messages now consolidate these errors and explain that Margin Master will automatically retry via the secure API.
-
Cloud Sync
Zone overrides and exclusion flags applied from cloud
Store exclusion settings and zone overrides from your cloud account now automatically sync to the Store Manager.
-
Cloud Sync
Connection test with 5-second timeout
Added CloudConnectionService.TestDirectConnectionAsync() to probe SQL connectivity before sync. Uses a 5-second timeout to avoid blocking the UI; failure triggers proxy mode activation.
-
Data Import
Enhanced catalog field mapping
Catalog items you add now include more complete information like pricing levels, velocity codes, and manufacturer details, giving you better analysis data.
-
Data Import
Automatic cleanup of discontinued manual catalog items
When updating your vendor catalog, items you manually added that are no longer available from the vendor will be automatically removed from your catalog.
-
Data Import
Auto-cleanup discontinued manual catalog items
Items you manually added to the catalog that have been discontinued by the vendor are now automatically removed when the catalog is rebuilt, keeping your data clean and up-to-date.
-
Data Import
BisTrack import performance optimized with materialized vendor data
Modified RSImportFileHelperService to materialize MMVendorData into a staging table (BisTrackVendorDataStaging) once at the start of the import process, then re-use it for all stores. Previously the view was re-evaluated for every store, causing expensive CROSS APPLY + BETWEEN range joins against DIBPriceLevelRoundingDetails (~327K rows). The staging table is indexed on (SKU, RSC) and dropped after import completes. Updated BisTrackInsertIntoMainTable.sql to reference the staging table via a new {vendorDataTable} variable (version bumped to 1.1).
-
User Interface
Two-panel vendor and database selection
When entering demo mode, you now first select a vendor, then choose from their available demo databases in a side-by-side view.
-
User Interface
Hierarchical vendor and database selection
The demo mode selection screen now shows vendors on the left and available demos on the right, making it easier to find the demo you want.
-
User Interface
Added Local Sync column to Vendor Catalog Data table
Each vendor catalog file now shows two dates: "Cloud Date" (when the file was last updated in the cloud) and "Local Sync" (when you last downloaded it). This makes it easy to see which catalogs need updating.
-
User Interface
Add Local Sync column to catalog file listing
When viewing data aging information, you'll now see two dates for each vendor file: the cloud processing date and the local sync date. This helps you understand if newer data is available in the cloud but hasn't downloaded to your computer yet.
-
User Interface
Catalog Lookup screen redesigned to match web layout
The Catalog Lookup screen now has a simpler layout with search results appearing in a dropdown instead of a separate side panel, making it easier to focus on product details.
-
User Interface
Redesigned Catalog Lookup screen layout
The Catalog Lookup screen now shows product details in a wider, easier-to-read layout that matches the web version, instead of splitting the screen between search results and details.
-
User Interface
Modern auto-suggest search for catalog lookup
The catalog search box now filters results as you type, with faster and more reliable text entry.
-
User Interface
Catalog Lookup search redesigned with AutoSuggestEdit
The Catalog Lookup search bar now shows matching items instantly as you type, with matching text highlighted in the dropdown suggestions.
-
User Interface
Data Aging screen filtered to store's RSC catalogs
If your store uses Do-It-Best, the Data Aging screen now shows only the catalogs you actually sync instead of all 8 regional catalogs.
-
User Interface
Visual indicator for overridden zone assignments
Zone numbers you've changed appear in blue bold text. Hover over them to see what Ace originally assigned.
-
User Interface
Auto-clear search after adding catalog item
When you add a catalog item, the search box now clears automatically so you can type the next SKU right away without having to delete the previous search.
-
User Interface
Clear search box after adding catalog item
When you add a catalog item, the search box now clears automatically so you can immediately start typing your next search without having to manually delete the previous text.
-
User Interface
Search/Bulk mode toggle replaces Tools menu
Instead of hunting for a Tools menu, you now see Search and Bulk buttons right at the top of the dialog. Click Bulk to paste a list of SKUs and add them all at once.
-
User Interface
Mode toggle added to Add from Catalog dialog
Click the "Search" or "Bulk" radio button at the top to choose how you want to add items—either by searching one at a time or by pasting a list of SKUs.
-
User Interface
Simplified department view with toggle
Zone overrides now apply to all departments at once by default. Check "Show by Department" if you need to set different zones for individual departments.
-
User Interface
Split zone display into two columns
You can now see both the Ace-assigned zone and your custom zone override in separate columns, making it easier to tell which stores have been manually adjusted.
-
User Interface
Zone columns split into assigned and override
You can now see both the Ace-assigned zone and your custom zone override in separate columns, making it easier to understand which value is being used.
-
User Interface
Per-row delete button added to Store Manager grid
You can now delete a store by clicking the red X button at the end of its row, instead of having to select it and use the delete button.
-
User Interface
Per-row delete button added to Store Manager grid
You can now delete a store by clicking the red X button at the end of its row, instead of selecting it and using the Delete Selected button.
-
User Interface
Increased Add from Catalog dialog size
The Add from Catalog window is now larger, making it easier to browse and select items.
-
User Interface
Enlarged Add from Catalog dialog window
The Add from Catalog window is now larger, making it easier to browse and select items.
-
User Interface
Improved spacing in SKU search results
Search results in the Ctrl+F dialog now have better spacing and are easier to read.
-
User Interface
Improved Ctrl+F search result spacing
Search results in the Ctrl+F quick search dialog now have better spacing, making highlighted matches easier to read.
-
User Interface
Unified database screen navigation
Database setup screens now have matching menus at the top. You can easily switch between connecting to an existing database, creating a new one, restoring from backup, or using the demo database without closing and reopening windows.
-
User Interface
Database screen navigation consolidated
Database setup screens now have File menus that let you switch between connecting, creating, restoring, or using a demo database without closing windows.
-
User Interface
RSC location names added to catalog display
Catalog names now show the warehouse location (like "Dixon, IL") so you can easily see which regional catalog you're viewing.
-
User Interface
Display RSC location names in Data Aging screen
Catalog names now show the distribution center location (e.g., "Dixon, IL") for easier identification.
-
User Interface
More accurate freshness warnings during POS import
You'll only see warnings about outdated vendor data when the vendor has actually published updates you haven't downloaded yet.
-
User Interface
Bulk mode now includes inline text area
When in Bulk mode, you can paste your SKU list directly into the text box and click "Look Up & Add" without opening another window.
-
User Interface
Improved sync progress messaging for firewall detection
The sync screen now shows a clear message when it detects a firewall and switches to the backup connection.
-
User Interface
Visual zone-type badges in store list
Stores now show colored badges: gray "N" means using national pricing, red "A" means using Ace's assigned zone, and orange "O" means a custom zone override is active.
-
User Interface
Visual indicator for unmapped stores in Zone Assignment
Stores that aren't mapped to your POS system are now shown with strikethrough text and you can't edit their zone assignments, making it clear which stores need setup.
-
User Interface
Dynamic vendor-specific column header for store numbers
The store number column now shows your vendor's name (like "Ace Store #" or "Do It Best Store #") instead of the generic "Vendor Store #".
-
User Interface
Dynamic vendor-specific column header in Store Manager
The vendor store number column now shows your vendor's name (like "Ace Store #" or "Do It Best Store #") instead of the generic label.
-
User Interface
Store Manager Save and Close buttons upgraded to SVG icons
Save and Close buttons in Store Manager now have sharper, higher-quality icons.
-
User Interface
Fixed sorting in dropdown filter lists
Dropdown lists with numeric values now show options in the correct numeric order, making it easier to find specific codes.
-
User Interface
Updated sorting across multiple screens
Store numbers and vendor codes in dropdown menus, filter lists, and summary screens now appear in intuitive numeric order throughout the application.
-
User Interface
Clarified database connection instructions
The initial database connection screen now has clearer instructions about where to enter your store information.
-
User Interface
Improved guidance message for missing credentials
When a database is missing vendor or store information, the app now gives clearer instructions on how to fix it.
-
User Interface
Catalog Lookup dialog with split-pane layout
The search results appear on the left side; click any SKU to see full details on the right including pricing, vendor information, and cloud sync status.
-
User Interface
Redesigned Connect to Database screen
The Connect to Database screen is now simpler with the Connect button right next to the database list.
-
User Interface
Type-to-filter support added to dropdown lists
You can now type to quickly filter dropdown lists like vendor names, POS systems, and SQL servers instead of scrolling through the full list.
-
User Interface
Inline bulk entry replaces modal dialog
You can now type or paste SKUs directly in the Bulk mode panel without opening a separate window.
-
User Interface
Loading indicator added during file import and lookup
The screen now shows a loading indicator when importing large Excel files or looking up many SKUs at once.
-
User Interface
Dynamic dialog title and menu item renamed
The Ace zone assignment window title now clearly indicates whether you're working with individual stores or store groups.
-
User Interface
Help menu renamed from "What's New" to "Version History"
The Help > What's New menu item has been renamed to Help > Version History and now opens the new in-app VersionHistoryView window instead of launching a web browser. The startup prompt that previously asked "View What's New?" now displays "View Version History" and opens the same in-app window. The "Show What's New at Startup" checkbox remains functional and controls whether the prompt appears after version updates.
-
User Interface
Ace Zone Pricing dialog improvements
The Ace zone pricing setup screen now shows color-coded badges (N, A, or O) to quickly identify which stores use national pricing, Ace zones, or custom overrides. You can also toggle between simple one-line-per-store mode and detailed per-department mode.
-
User Interface
Zone Override uses numeric spinner control
Zone overrides can now be adjusted using up/down arrows, and only valid numbers are accepted.
-
User Interface
Store Manager default sort changed to POS Store Number
Stores now appear in the same order as your POS system instead of by vendor store number.
-
User Interface
Save button added to Store Manager
Click the Save button in Store Manager to save your store settings to the cloud.
-
User Interface
Active stores configuration summary in footer
The bottom of the Store Manager now shows how many stores are fully set up (e.g., "8 of 10 stores fully configured") so you can see at a glance if any stores need attention.
-
User Interface
Active store configuration summary footer
The bottom of the Store Manager now shows how many of your stores have all required information filled in (e.g., "12 of 15 stores fully configured").
-
User Interface
Corrected store number ordering in sync change summary
After syncing, the list of stores with changes now appears in numeric order.
-
User Interface
Clearer messaging for common mailbox scenarios
If you try to download a file that's already been retrieved or has expired, the message now tells you that directly and suggests clicking Refresh, rather than suggesting firewall changes.
-
User Interface
Dialog title shows full vendor name
The Add from Catalog window now shows your vendor's full name in the title bar instead of an abbreviation.
-
User Interface
Catalog add dialog column sizing improvements
The "Add from Catalog" dialog now uses BestFitMode for automatic column sizing and disables AutoWidth, providing better readability for SKU and description columns in both the search results grid and the items-to-add grid.
-
User Interface
Redesigned Restore Database screen
The Restore Database screen now matches the look and feel of other database screens and includes a help button in the header.
-
User Interface
Dialog height increased for better bulk entry visibility
The dialog height was increased from 450 to 460 pixels to accommodate the mode toggle controls and provide more comfortable text entry space in Bulk mode.
-
User Interface
Sync Dialog displays firewall detection status
The sync screen will let you know if it's using the firewall-friendly connection method, so you understand why the initial connection test takes a few extra seconds.
-
User Interface
Help menu reorganization
The Help menu now says "Version History" instead of "What's New" and opens release notes inside Margin Master rather than your web browser.
-
User Interface
Save button and auto-save on close
A new Save button appears when you make changes to store settings. Changes are also automatically saved when you close the window.
-
User Interface
Catalog Add dialog redesigned for search workflow
The "Add Catalog Items" screen now has a search box at the top where you type to find products by SKU or description.
-
User Interface
Auto-sized grid columns in catalog dialog
Column widths in the Add from Catalog dialog now automatically adjust to fit the content, making it easier to read long SKUs and descriptions.
-
User Interface
Type-to-filter enabled on all dropdowns
All dropdown lists in database screens now let you type to filter options, making it faster to find what you need.
-
User Interface
Store number validation relaxed
Store numbers of any length are now accepted as long as they contain only digits.
-
User Interface
Sync Dialog status messaging for proxy mode
When the firewall fallback activates, the Sync Dialog now displays "Firewall detected — syncing via secure API..." to inform users the system is operating in HTTPS proxy mode. All vendor sync operations (Ace, DIB, EJ, Orgill, United) support the proxy path.
-
User Interface
WebBrowser control with HtmlContent attached property
Added WebBrowserHelper attached property to enable data-binding for WebBrowser.NavigateToString in WPF. The VersionHistoryView uses this to render PublicHtml release notes directly in the detail pane without external web navigation.
-
User Interface
Database restore documentation added
Adds comprehensive database-restore.md with user and support documentation covering backup location, available backups, backup metadata, restore settings, SQL authentication, tips, common questions, and technical details. Added to docs/index.json for search.
-
Database
Local database schema update for RSC alternate codes
Added AlternateCode column to the local Rscs table with automatic migration. The migration detects existing databases without the column and adds it seamlessly on next application startup.
-
Database
Local database schema updated for alternate codes
The Rscs table schema has been updated to include the AlternateCode column. An automatic migration adds this column to existing databases during the next sync or startup.
-
Database
Add LocalSyncDate property to catalog status model
Enhanced the CatalogFileStatus model to include a LocalSyncDate field, which is populated from the local SyncHistory table when the Data Aging view loads. This allows the application to cross-reference cloud catalog processing dates with local synchronization timestamps.
-
Database
LocalVersionHistory table for install tracking
Created a new LocalVersionHistory table with fields LocalVersionHistoryId, Version, PublishedAt, BriefSummary, PublicHtml, InstalledAt, and SyncedAt. The table is created automatically on first startup via CreateLocalVersionHistoryTable.sql script and uses a MERGE statement to sync cloud data while preserving local InstalledAt timestamps.
-
Database
New OrgPosStoreSettingDto model
Added a new data transfer object (OrgPosStoreSettingDto) to represent cloud-stored store settings, including PosStoreKey, VendorStoreNumber, RSCCode, ZoneOverride, and IsExcluded fields. This model is used by the new cloud sync API endpoints.
-
Database
ManualCatalogItems tracking table
New ManualCatalogItems table created with columns for ID, SKU, Store, VendorType, Description, and CreateDate. Includes unique index on (SKU, Store, VendorType) to prevent duplicate tracking entries. Table creation is idempotent and runs automatically during database updates.
-
Database
LocalVersionHistory table
Added new LocalVersionHistory table with fields for Version, PublishedAt, BriefSummary, PublicHtml, InstalledAt, and SyncedAt. Table is created automatically via SQL script on first run. Unique constraint on Version ensures no duplicates. InstalledAt is null for versions never installed on this machine, allowing distinction between cloud-synced releases and locally-installed versions.
-
Database
New OrgPosStoreSettingDto for cloud API communication
Added OrgPosStoreSettingDto to MarginMaster.Common as a data transfer object for the new GetOrgStoreSettingsAsync and SaveOrgStoreSettingsAsync API methods. The DTO includes PosStoreKey, VendorStoreNumber, RSCCode, ZoneOverride, and IsExcluded fields.
-
Database
ManualCatalogItems table creation
Added automatic creation of the ManualCatalogItems tracking table during database updates, with fields for SKU, Store, VendorType, Description, and CreateDate. Includes a unique index on (SKU, Store, VendorType) to prevent duplicate tracking entries.
-
Architecture
ICloudSyncProxy abstraction for vendor catalog sync
Introduced a new proxy interface that decouples the sync engine from direct SQL Server access. The ApiCloudSyncProxy implementation translates schema queries, row counts, and batch fetches into REST API calls. ProxySyncFilter replaces raw SQL filters with serializable parameters (zone, vendor, store numbers, RSC numbers, scheme IDs) that can be safely transmitted over HTTP and reconstructed server-side. All existing sync features—incremental RowVersion sync, batch size optimization, count validation, and out-of-scope pruning—work identically in proxy mode.
-
Architecture
ICloudSyncProxy abstraction layer
Introduced ICloudSyncProxy interface to decouple cloud data reads from direct SQL, implemented by ApiCloudSyncProxy which calls Manager API endpoints (/schema, /count, /rows). SchemaMirror and RowVersionTableSync now accept optional proxy and route all cloud queries through it when present.
-
Architecture
Consolidated duplicate migration logic
Refactored the migration code to share a common InsertMissingStorematchupEntriesAsync helper between the one-time migration process and the supplemental catch-up routine that runs on each startup. This ensures both code paths apply the same RSC and zone override population logic.
-
Architecture
Typed exception handling for mailbox operations
Introduced DIBMailboxFailureException with specific failure kinds (NothingSelected, Connection, FileNotInMailbox, TransferIncomplete) to distinguish between failure scenarios. This replaces generic exceptions that couldn't convey why an operation failed, enabling the UI to display contextually appropriate messages and guidance.
-
Architecture
Backward compatibility with legacy demo API
The application automatically falls back to the older flat demo list API if the new hierarchical vendor/database endpoint is unavailable, ensuring compatibility with older server versions during the transition period.
-
Architecture
Multi-RSC support in Data Aging screen
The Data Aging screen now properly handles stores configured to sync multiple RSC codes, mirroring the same logic used during actual sync operations to determine which RSCs apply to the store.
-
Architecture
Catalog Add Items ViewModel refactored with testable file reader
Extracted file-reading logic (Excel/text parsing, column detection, SKU extraction) from CatalogAddItemsViewModel into a new CatalogSkuFileReader class. Added a full xUnit test suite (CatalogSkuFileReaderTests and CatalogAddItemsViewModelTests) covering single-column files, multi-column auto-detection, header-row detection, store-column handling, and end-to-end import flows. Also added InternalsVisibleTo to make internal components testable without exposing them publicly.
-
Architecture
Store settings retrieval enhanced with bundled data
The cloud API now returns store settings bundled with a map of vendor store numbers to RSC codes from the Stores table. This bundle is cached in memory during Store Manager initialization and reused when vendor store numbers change, improving performance and reducing redundant API calls.
-
Architecture
Version history service layer
Introduced IVersionHistoryService with methods for table creation, cloud sync, installed version stamping, and querying history with optional filtering. Service integrates with ApiClientService (new GetVersionHistoryAsync endpoint with 24-hour cache TTL) and uses Dapper for local database operations.
-
Architecture
Database screen navigation enum and service methods
Adds DatabaseScreenNavigation enum (None, ConnectToDatabase, CreateNew, RestoreBackup, DemoDatabase) for cross-screen routing. DatabaseConnectionService now implements navigation loop pattern to show child screens without recursive ShowDialog nesting. CreateNewDatabaseViewModel and other VMs track NavigationRequest and IsStartupFlow properties to coordinate screen transitions.
-
Documentation
Zone override instructions and guidelines
Help documentation now explains how to change store zones and when you might need to do this.
-
Infrastructure
ProxySyncFilter serializable filter model
Added ProxySyncFilter class to safely translate table filter parameters (zone, vendor, RSC numbers, store numbers, scheme IDs) into HTTP query strings for the API proxy. This avoids sending raw SQL over the wire while preserving all filter intent for server-side reconstruction.
-
Infrastructure
Session-level RSC caching
Results from live RSC lookups are now cached in memory for the duration of the session. This prevents multiple API calls when processing multiple stores with the same vendor store number during a single work session.
-
Infrastructure
Enhanced logging for mailbox connectivity issues
Connection and login failures are now logged at Error level instead of Warning, ensuring they reach cloud telemetry. Each failure type (connection, missing file, incomplete transfer, or empty selection) is logged with detailed context including mailbox name, host, and port, making customer issues visible to support without requiring manual log collection.
-
Infrastructure
Backward compatibility with flat API responses
Maintains compatibility with older Manager API servers that return a flat list of demo databases by automatically grouping them by vendor when the v2 hierarchical endpoint is unavailable. Demo mode state now tracks both VendorKey and DemoDatabaseKey for accurate reset and cloud update operations.
-
Infrastructure
License service enhanced with settings push capability
Added a new RefreshLicenseSettingsInBackground method to the License Validation Service that pushes current store configuration (RSC and POS type) to the Manager server via the ValuesDictionary parameter in the license request. Unlike the startup license refresh, this method executes immediately since it's user-initiated. The RSC and POS system type are now included in all license validation calls to keep the server synchronized.
-
Infrastructure
Server-side authentication configuration improved
Root cause of 401 authentication errors was resolved server-side by adding Manager--JwtSettings--SecretKey to Azure Key Vault, ensuring proper JWT token validation.
-
Infrastructure
Documentation updated for new UI
Updated the Add from Catalog help document and search index to reflect the new Search/Bulk mode toggle UI, removing references to the Tools menu and Enter Bulk List modal, and adding guidance on the new inline workflow.
-
Infrastructure
Auto-deploy tool now publishes to version history API
The AutoUpdateDeploy tool now posts to /api/version-history after each build, submitting BriefSummary (auto-generated from top 3 items), PublicHtml (customer-facing release notes), AdminHtml (includes GitHub commit links), GitCommit hash, GitHubReleaseUrl, and JSON-serialized PosSystemsAffected/VendorsAffected arrays. This parallels the existing /api/releases endpoint and populates the new AppVersionRelease cloud entity.
-
Infrastructure
Cloud API endpoints for store settings
Added GetOrgStoreSettingsAsync and SaveOrgStoreSettingsAsync methods to ApiClientService, enabling retrieval and storage of organization-wide POS store settings via the api/v2/OrgStoreSettings endpoint.
-
Infrastructure
Removed obsolete SemiNumericComparer class
Deleted the legacy SemiNumericComparer helper class that has been superseded by the new NumericStringComparer. Added comprehensive unit tests to ensure the new comparer handles edge cases like leading zeros, very large numbers, and null values correctly.
-
Infrastructure
WebBrowser HTML binding helper
Added WebBrowserHelper attached property to enable XAML data binding for WebBrowser.NavigateToString, used in the Version History window to display HTML changelogs from view model bindings.
-
Documentation
Add from Catalog feature guide
Added comprehensive documentation covering the Add from Catalog feature, including how persistent tracking works, field mappings for both vendors, step-by-step usage instructions, and technical details about the tracking table structure.
-
Infrastructure
AutoSuggestSearchBehavior added
Created new AutoSuggestSearchBehavior (Xaml/Behaviors/AutoSuggestSearchBehavior.cs) to bridge AutoSuggestEdit's QuerySubmitted event to async search functions in ViewModels. AutoSuggestEdit requires ItemsSource to be set synchronously during the event (standard XAML binding doesn't work), so the behavior calls the ViewModel's search delegate and sets ItemsSource directly. Includes configurable debounce delay (default 300ms) and minimum character count (default 3).
-
Infrastructure
DatabaseScreenNavigation enum added
Added DatabaseScreenNavigation enum to support navigation between database setup screens (None, ConnectToDatabase, CreateNew, RestoreBackup, DemoDatabase). Child dialogs return navigation requests to the parent DatabaseConnectionService, which dispatches the next screen without recursive ShowDialog() nesting.
-
Infrastructure
Unit testing framework added
Added MarginMaster.Tests project with xUnit, Microsoft.NET.Test.Sdk, and ClosedXML dependencies. Integrated into the solution for automated testing of ViewModels and file-parsing logic.
-
Documentation
Database Restore documentation added
Added comprehensive documentation for the Restore Database feature at docs/marginmaster/getting-started/database-restore.md, covering backup sources (local files, cloud storage), restore settings, metadata display, and common troubleshooting scenarios.
-
Infrastructure
AutoSuggestSearchBehavior for MVVM async search
New reusable behavior bridges DevExpress AutoSuggestEdit (which requires synchronous ItemsSource setting) with async ViewModel search functions. Handles debouncing, cancellation, and minimum character requirements. Accepts SearchFunction delegate and SuggestionChosenCommand from ViewModel.
User Interface
-
New Feature
Restore Backup option during startup
When starting Margin Master, you can now click "Restore Backup" to restore your database from a backup file, which will automatically connect you to the restored database.
-
New Feature
Support Issue History menu option
Click "Support Issue History" in the Help menu to see all support tickets your store has submitted, including open and closed issues. You can add comments or reopen old issues if needed.
-
New Feature
Issue Contact editor dialog
When submitting support issues, you can now update your contact details (name, email, phone) by clicking Help > Support Issues > Issue Contact. The phone number field will automatically format your entry with parentheses and dashes.
-
New Feature
Password-protected Support Scripts button in Database Setup
Support technicians can now run database maintenance scripts from the initial setup screen without needing to fully connect to the database first.
-
New Feature
Support Issues management screen
Open the "Support Issues" screen from the Help menu or click the red notification badge to view and manage all your support tickets in one place with a chat-style interface.
-
New Feature
SQL script clipboard copy in Installation Scripts
Support staff can now copy the database creation script directly from the Installation Scripts screen and paste it into SSMS for manual database setup.
-
New Feature
Auto Update options tab with configurable idle delay
When an update is available, you can now choose how long the notification waits before installing automatically. Go to Tools > Options (New) > Auto Update and select from Never (manual only), 1 Minute, 5 Minutes, 30 Minutes (default), 1 Hour, or Update on Shutdown (installs silently when you close the app).
-
New Feature
Auto Update options tab
All update settings are now in one place: Tools > Options (New) > Auto Update tab.
-
New Feature
Optional note field for issue description
Type a note in the new "Note (optional)" field to explain what's wrong or provide additional context about the issue you're reporting.
-
New Feature
Stable signed bootstrapper for installer downloads
Created a small WPF launcher application (MarginMaster-Setup.exe) that downloads the full installer from Azure blob storage and displays a branded progress window with download speed and size. Because this bootstrapper's file hash remains stable across Margin Master version updates, it builds Windows SmartScreen reputation over time, reducing security warnings when users download the application.
-
New Feature
File > Reconfigure Store menu option
Click File > Reconfigure Store to update your store number, vendor, POS system, or RSC credentials without closing Margin Master.
-
New Feature
Reconfigure Store menu option
To change your store number or update credentials, click File > Reconfigure Store, enter your information, click Validate, and save. If you changed your store number, you'll need to restart Margin Master.
-
New Feature
Schedule an Appointment menu item
When support appointments are available, a new "Schedule an Appointment" option appears in the Help menu. Clicking it opens your web browser to book a time with the support team.
-
New Feature
Schedule an Appointment menu item
Look for "Schedule an Appointment" in the Help menu to book a one-on-one support session. This option only appears when support slots are available.
-
New Feature
Scripts menu with pre-built diagnostic queries
A new Scripts menu provides ready-to-run diagnostic queries to help troubleshoot MySQL Compass data issues, especially problems with store identifiers showing up incorrectly.
-
New Feature
Configurable store number display format
In Settings > Connections / Epicor, you can now choose how store numbers appear in dropdown lists—for example, showing "1715 (00042)" instead of "00042 (1715)" if you prefer to see your POS store number first.
-
New Feature
Update failure tracking and visibility
If an update won't install, Margin Master now tells you what went wrong and offers to fix it rather than silently staying on the old version.
-
New Feature
Install OLEDB 12.0 driver script for RockSolid POS support
A new script can install the OLEDB driver needed to import RockSolid POS data, automatically detecting and warning about conflicts with 32-bit Office.
-
New Feature
Email-style contact editor for issues
Click the new "Edit Contacts" button next to the contact list to add or remove people from an issue using an easy-to-use contact picker with removable name chips.
-
New Feature
Add new contacts directly from issue submission
When selecting contacts for a support issue, you can now click "Add Contact" to create a new contact on the spot instead of having to go to Settings first.
-
New Feature
Issue description and comments panel
You can now read the full issue description and comments in the right panel before downloading the customer's database.
-
New Feature
Update on Shutdown mode
Choose "Update on Shutdown" to have updates install automatically the next time you close Margin Master, without showing the update notification dialog during your workday.
-
New Feature
Configurable auto-update idle delay
Update notifications now auto-install after 30 minutes if left untouched (you'll see a 10-second countdown first). Change the delay or turn this off in Tools > Options (New) > Auto Update.
-
New Feature
Custom file attachment support
Click "Add Files..." to attach screenshots, Excel files, or other documents that help explain the issue. You can attach multiple files and remove any you don't need.
-
New Feature
File attachment support for diagnostic submissions
Click "Add Files..." to attach screenshots, Excel files, or other documents that help explain the issue you're reporting.
-
New Feature
Copy results to clipboard
A new "Copy to Clipboard" button lets you quickly copy query results to paste into Excel or share with support.
-
New Feature
Configurable store number sort order
The Store Number list can now sort by either your POS store numbers or vendor store numbers, whichever makes it easier to find the store you need.
-
New Feature
One-click repair install
Click "Download and Install Now" and Margin Master will close itself, download the installer, and run it for you—this fixes updates that won't install the normal way.
-
New Feature
Edit existing contacts in-place
You can now click the edit icon next to any store contact to update their name, email, or phone number right from the contact picker.
-
New Feature
Rename option when restoring over existing database
If a database with your restore name already exists, you can now choose to give it a different name instead of only being able to overwrite or cancel.
-
New Feature
Update on Shutdown mode
You can now set updates to install silently when you close Margin Master (Tools > Options (New) > Auto Update > "Update on Shutdown").
-
New Feature
Save button for contact changes
When editing a contact's information, click the new "Save" button to save your changes before moving forward.
-
New Feature
Added Edit Contacts dialog with store/support toggle
Created a new Edit Contacts dialog that allows users to manage which contacts should be notified about a specific support issue. The dialog features an email-To-style chip picker with selected contacts displayed as removable pills at the top, and a toggle to switch between viewing store contacts and support contacts. Selected contacts are shown as colored chips that can be clicked to remove them.
-
New Feature
Delete contacts from contact picker
You can now remove outdated store contacts by clicking the delete icon next to their name in the contact picker.
-
New Feature
File attachment support for issue updates
You can now attach files (like screenshots or documents) when updating support issues, making it easier to share information with the support team.
-
New Feature
Require manual approval for auto-updates setting
A new setting in Options lets you turn off automatic update installation. When checked, Margin Master will notify you about updates but wait for you to approve them instead of installing automatically.
-
New Feature
Support Issues management screen
Open the "Support Issues" screen from the Help menu or click the red notification badge to view and manage all your support tickets in one place with a chat-style interface.
-
New Feature
File attachment support for issue updates
You can now attach files (like screenshots or documents) when updating support issues, making it easier to share information with the support team.
- Improvement Support scripts now download from cloud storage
-
Improvement
Automatic script preloading with freshness detection
Scripts download automatically in the background when you open the Installation Scripts dialog, so the latest versions are ready immediately when you need them.
-
Improvement
Optional note field added to issue submission
Add a description or notes about the issue you're reporting directly in the Quick Issue dialog.
-
Improvement
Smart refresh of selection boxes after Options changes
After changing how store numbers are displayed or sorted in Options, all store selection dropdowns will automatically update to show your new preference without needing to restart the app.
-
Improvement
Background license validation suppressed in demo mode
Added safeguards to prevent background license status checks from displaying error dialogs while in demo mode. Since demo mode uses a synthetic license that doesn't require validation, these checks are now bypassed entirely during demo sessions.
-
Improvement
Demo mode license handling at startup
License approval checks during application startup now recognize demo mode and skip standard validation, immediately approving the synthetic demo license. This prevents any license-related startup delays or dialog prompts when launching the application in demo mode.
-
Improvement
Scripts copied to log folder for support re-execution
Each executed PowerShell script is now automatically copied to the log folder alongside its execution log. This allows support staff to re-run the exact same script directly on the customer's machine without needing Margin Master, which is helpful for troubleshooting or repeating operations.
-
Improvement
Scripts copied to log folder after execution
When you run a support script, a copy of the script is now saved in the logs folder for your records.
-
Improvement
Live issue polling and notification system
The red support notification badge will now flash when support has responded to your issues or when there's new activity, so you won't miss important updates.
-
Improvement
Auto-select issue when opening from notification pill
Clicking the support issues notification now automatically opens the issue if you only have one, or shows your most recent issue if you have several.
-
Improvement
Asynchronous loading of issue descriptions and comments
Added LoadIssueDetailAsync method that fetches full issue descriptions and comments via GetIssueDetailForDevAsync when an issue is selected. This replaces the previous behavior of only showing attachment lists, providing developers with complete context about each customer issue before downloading files. The detail panel shows a loading indicator while fetching data and displays error messages if the load fails.
-
Improvement
Connection window automatically hides during database setup
The connection window now hides while you're creating or restoring a database, then comes back automatically when you're finished.
-
Improvement
Added save verification logging for pricing strategy steps
Added diagnostic logging to track pricing strategy step order at initial load, before save, and after save. This helps verify that step sequences, rounding settings, and active status are being preserved correctly during save operations. The logging also prevents the strategy from being marked as "dirty" during initial load, avoiding false save prompts.
-
Improvement
Legacy/New Settings dialog preference handling
The choice between the legacy and new Settings dialogs now resets each time you restart Margin Master, so you won't get stuck using one version if you click the preference button by mistake.
-
Improvement
Added rename option when restoring to existing database name
If you restore a backup with a name that already exists, you can now choose to rename it to something else instead of only being able to overwrite the existing database.
-
Improvement
Enhanced restore dialog logging for backup file scanning
The restore dialog now logs the raw count of .bak and .zip files found in the backup folder before processing, plus warnings for any files where header/metadata reads fail (including the file name, exception, and new HeaderStatus field). This gives a clear before/after picture in the log to help diagnose why backups might be missing or why a restore might fail.
- Improvement Enhanced diagnostic logging for backup file scanning
-
Improvement
Database creation script now available in UI
The full Margin Master database creation script is now accessible through the Installation Scripts screen under the "SQL Server" category. The description clarifies that this script is retained for emergency and manual recovery scenarios, while normal database creation should use the built-in setup wizard. Staff can click "Copy to Clipboard", then paste and execute the script in SSMS to create a fresh database with all required tables, stored procedures, and seed data.
-
Improvement
Consistent focus behavior for Reset Vendor Data workflow
When using Reset Vendor Data, the main window will now properly come back to focus just like it does during regular sync operations.
-
Improvement
Main table schema verification progress counter
When verifying column schemas across multiple main tables (e.g., AceMainTable, OrgillMainTable), the splash screen now shows "Main table X of Y" to indicate progress through the collection, providing visibility when this step processes many vendor tables.
-
Improvement
Faster backup file scanning with timeout protection
The restore window now scans backup files much faster and won't freeze if it encounters a corrupted backup file.
-
Improvement
Enhanced debug mode for update testing
Improved debug mode simulation to allow developers to preview the update installation window without requiring a real update package or installed application. The debug mode now simulates an available update with a test version number and shows the full installation workflow including progress and window display.
-
Improvement
.NET 10 Desktop Runtime installation script
If Margin Master won't launch due to a .NET error, support can now run an automated installer from the Support Tools screen to fix the issue.
-
Improvement
Auto-select first checked contact as primary
When you check the first contact box, they'll automatically become the primary contact. Additional contacts you check will be CC'd on the issue.
-
Improvement
Auto-show exception column when SKU overrides exist
The exception icon column now appears automatically after running a pricing strategy that creates item-level overrides, making it easier to identify which items have special pricing rules.
-
Improvement
Streamlined restore workflow at startup
The restore process automatically configures the restored database as the active connection when initiated from startup, skipping the manual connection step. Progress messages and logging were added to track when databases are restored during the startup sequence.
-
Improvement
Session-based password caching for Support Scripts
You only need to enter the support password once per session instead of every time you open Support Scripts.
-
Improvement
System information auto-trimmed from issue descriptions
Issue descriptions now hide the technical system information when you're viewing your own issues, making them easier to read.
-
Improvement
Added direct "Create New Database" command
Added a new SwitchToCreateNewCommand that allows users to quickly switch to Create New mode from Connect Existing mode without losing their server connection settings. This command is exposed in the new File menu and is enabled only when in Connect Existing mode.
-
Improvement
Enhanced attachment summary layout
The attachments panel has been reorganized within the new layout to better fit the full-screen design, maintaining all existing functionality for viewing and processing database backups, screenshots, and log files while integrating seamlessly with the new detail panel.
-
Improvement
Options screen toggle now resets each session
The Options screen will now default to the new version each time you open Margin Master, but you can still click "Use Legacy" if you prefer the old layout for that session.
-
Improvement
Enhanced splash screen display during database operations
Replaced separate "ShowSplashScreen" and "SetSplashScreenState" calls with a single "ShowSplashScreenImmediate" method for database restore, strategy restore, and settings transfer operations. This ensures the splash screen appears immediately with the correct message and eliminates timing gaps.
-
Improvement
Moved auto-update settings from Miscellaneous tab
The "Automatically check for updates" and "Require approval before applying updates" checkboxes have been relocated from the Miscellaneous tab to the new Auto Update tab, providing a single location for all update-related configuration. The idle delay dropdown is automatically disabled when "Require approval" is checked, since the countdown would be irrelevant when manual approval is required.
-
Improvement
Added automatic tab reload when switching between tabs
Settings tabs now refresh automatically when you switch between them, ensuring you always see current data.
-
Improvement
Automatic file compression
Attached files are automatically compressed using ZIP if they're larger than 100KB and not already compressed (e.g., not .jpg, .pdf, .zip files). Compression progress is shown during upload. This reduces upload time and storage costs while handling already-compressed formats efficiently.
-
Improvement
Rebuild respects cancellation between pipeline steps
When you cancel a rebuild, the system now stops immediately and skips all remaining steps instead of continuing in the background.
-
Improvement
Data Aging excludes all-stores aggregate table
The Data Aging screen now skips the "99999" all-stores aggregate main table when enumerating real stores, preventing it from appearing as a separate store entry in the import history display.
-
Improvement
Splash screen ownership tracking prevents conflicts during startup
Added ownership tracking to the column loading routine so it only hides the splash screen if it was the one that showed it. This prevents one startup operation from closing a splash window that another operation is still actively using, which was a key contributor to the stranded splash issue.
-
Improvement
Pre-filled support tickets for update failures
If you choose "Contact Support" from the update dialog, we already know what failed—just add anything you want to say and send it.
-
Improvement
Script execution logging with log viewer
Script output is now saved to log files that you can view or send to support for troubleshooting.
-
Improvement
"Require approval before applying updates" setting
You can now choose to approve each update manually instead of having them install automatically.
-
Improvement
Added File menu command for Create New mode
Added SwitchToCreateNewCommand that allows users to quickly return to Create New Database mode from the File menu, complementing the existing mode-switching functionality. This command is only enabled when in Connect to Existing mode.
-
Improvement
Improved dialog window positioning
Updated Support Scripts dialogs to open centered over the Database Setup window (CenterOwner) rather than CenterScreen, providing better visual context. Also set the password prompt and scripts window to have the Database Setup as their owner window, improving focus management.
-
Improvement
Auto-generated database names with availability checking
The system now automatically creates your database name based on your store information and checks that it's available, so you don't have to worry about naming conflicts.
-
Improvement
Multi-contact support for issues
Issues can now have multiple people assigned to them, not just the original submitter.
-
Improvement
Smart compression for uploaded files
Attached files over 100KB are automatically compressed before upload, unless they're already in a compressed format (ZIP, JPEG, PNG, PDF, Office documents, etc.). The system displays upload progress with file size information, making large file uploads more transparent.
-
Improvement
Show deleted contacts option
Check "Show Deleted" to see contacts that were previously removed, which appear grayed out and crossed out.
-
Improvement
Pre-population of store info from current database
If you're creating a second database for your store, your store information is automatically filled in from your current database to save time.
-
Improvement
Contact list refreshes after modifications
After you add, edit, or delete a contact, the contact list updates automatically so you always see current information.
-
Improvement
Auto-update settings moved from Miscellaneous tab
Update settings have moved from the Miscellaneous tab to the new Auto Update tab in Options.
-
Improvement
Update problem dialog throttled to once per day
The "Could Not Update" dialog shows at most once a day so it doesn't keep interrupting you.
-
Improvement
Downgrade failures now tracked
If you downgrade to an older version and it doesn't work, Margin Master now tracks that the same way it tracks regular update failures.
-
Improvement
Live issue polling and notification system
The red support notification badge will now flash when support has responded to your issues or when there's new activity, so you won't miss important updates.
-
Improvement
User-driven update failures shown immediately
If you click "Update Now" and it fails, Margin Master shows you the fix-it dialog right away instead of just a notification.
-
Bug Fix
Version display consistency across startup and main window
The version number shown on the startup splash screen now matches the version displayed in the main window title bar.
-
Bug Fix
Splash screen version display now matches main window
The version number shown on the startup splash screen now matches the version displayed in the main window, eliminating confusion about which version of Margin Master is running.
-
Bug Fix
Database rename now properly reports SQL errors
The database rename feature was configured to receive SQL error messages but only checked for progress updates, causing actual errors during the restore step to be silently swallowed. Now properly collects and reports SQL errors using the same pattern as the backup service, and verifies the database actually exists after restore completes.
-
Bug Fix
Demo mode license validation errors eliminated
Demo mode now starts cleanly without showing incorrect license expiration warnings.
-
Bug Fix
Demo mode license dialog suppression
When using demo mode for training or demonstrations, you will no longer see pop-up warnings about license expiration or validation issues.
-
Bug Fix
Fixed clipped buttons on startup and configuration dialogs
You can now see and click all buttons on the Create Database, Store Configuration, Restore Database, and Database Connection screens, even on laptops with smaller screens.
-
Bug Fix
Dialog windows now display all buttons and controls
You can now see and click all buttons in the setup screens, even if you have a smaller monitor or lower screen resolution.
-
Bug Fix
Support Scripts menu item now appears in Utilities menu
You can now access Support Scripts from the Utilities menu as intended.
-
Bug Fix
Fixed Support Scripts execution failure
The "Support Scripts" screen now correctly runs SQL Server and OLEDB installation scripts when you click the Execute button.
-
Bug Fix
Support Scripts execution error resolved
The "Execute" button on Support Scripts now works correctly for all SQL Server and OLEDB installation scripts.
-
Bug Fix
Corrected missing attachment button icon
The attach file button now shows its icon correctly instead of appearing blank.
-
Bug Fix
Fixed attach file button icon
The attach file button in the Support Issues screen now displays the correct attachment icon instead of a generic action icon, making it more visually consistent with standard file attachment controls.
-
Bug Fix
Send button now enables with attachments only
When you attach files to a support request, the Send button will now activate immediately, letting you submit attachments without typing a message.
-
Bug Fix
Submit Issue dialog now displays at correct size
When you click "Create New Issue" from the Help menu, the window now opens at the correct size so you can see the full form including where to type your issue description and the submit button.
-
Bug Fix
Dialog windows no longer pin above all applications
When you open database setup, license configuration, database restore, or support tools windows, they will no longer cover your other open programs like web browsers or email. You can now easily switch between Margin Master dialogs and other applications on your computer.
-
Bug Fix
MySQL Compass connection test button not functional
You can now click the "Test & Save Connection" button in MySQL Compass settings to verify your database connection works before saving it.
-
Bug Fix
POS system selection now saves correctly
When you select your POS system in the Options screen, it will now save properly and remain selected when you restart Margin Master.
-
Bug Fix
Settings persistence in Settings dialog
When you change your POS system or set a primary store in Settings, those changes will now save correctly and persist after closing the dialog.
-
Bug Fix
Splash screen now displays continuously during restore operations
The progress window now stays visible during the entire restore process, showing you what's happening at each step.
-
Bug Fix
Restore Database dialog message handling corrected
When restoring a database backup, you'll now see proper error messages if something goes wrong and confirmation prompts when needed.
-
Bug Fix
Submit Issue dialog handles missing database
When submitting a support ticket without a database loaded, the database backup option is now grayed out and cannot be selected.
-
Bug Fix
Restore dialog now lists all backup files regardless of SQL server permissions
If you're connected to a remote SQL server or a named instance with restricted permissions, you'll now see all backup files in the restore list. Previously, the dialog would silently hide all backups when the SQL server couldn't read your backup folder.
- Bug Fix Restore dialog now shows all valid backup files
-
Bug Fix
Fixed buttons not unlocking after validation
Resolved an issue where the "Validate License" and "Create Database" buttons would not unlock or become clickable after filling in required fields. The dialog now properly refreshes button states when database name availability is checked, store information is validated, or license validation completes.
-
Bug Fix
Options dialog now activates properly
When opening the Options window, it will now always appear on top where you can see and interact with it, instead of sometimes appearing behind the main window.
-
Bug Fix
Fixed blank Retail Service Center dropdown on Store Information tab
The Retail Service Center (RSC) dropdown was appearing empty when opening the Store Information tab. The tab now explicitly loads vendor and RSC data when initialized, ensuring the dropdown is properly populated.
-
Bug Fix
Main window focus restored after splash screen
After syncing or resetting data, Margin Master will now automatically come to the front of your screen instead of staying hidden behind other windows.
-
Bug Fix
Main window focus restored after startup
When you launch Margin Master, the main window now automatically appears ready to use without needing to click on it first.
-
Bug Fix
Version History menu icon restored
The Version History option in the menu now shows the correct icon instead of appearing broken or blank.
-
Bug Fix
Restore What's New menu item
You can now click Help → What's New to see the latest Margin Master updates in your web browser.
-
Bug Fix
What's New menu item restored
You can now find "What's New" in the Help menu to see recent updates and new features added to Margin Master.
-
Bug Fix
One Click dialog splash screen no longer appears on main window
Opening the One Click Pricing Strategy dialog no longer shows a loading indicator on the main window behind it.
-
Bug Fix
One Click Statistics splash screen timing corrected
The loading screen that appears when opening One Click Statistics will now disappear properly instead of staying visible over your results.
-
Bug Fix
Fixed contact edit and delete operations in issue submission
You can now successfully edit contact details and delete unwanted contacts when submitting an issue — these operations previously failed silently.
-
Bug Fix
Store delete button restored
You can now click the delete button (X icon) next to each store to remove it from your store list.
-
Bug Fix
Quick Submit button restored to Support Issues header
The Quick Submit button (with the lightning bolt icon) is now visible again in the Support Issues screen, allowing you to quickly report issues without filling out the full form.
-
Bug Fix
Quick Submit button restored to Support Issues header
You can now use the Quick Submit button at the top of the Support Issues screen to quickly report problems without going through the full issue creation form.
-
Bug Fix
Selection boxes reload after database restore
After restoring a backup, all dropdown menus and filter options automatically update to match the restored data without needing to restart Margin Master.
-
Bug Fix
Local backup filtering by store number
When "Show All Stores" is unchecked on a support machine, you'll now see only backup files that belong to your current store, making it easier to find the right backup to restore.
-
Bug Fix
Data Aging screen displays correct store numbers
When you open the Data Aging screen, you'll now see your actual store numbers (like "554") instead of confusing internal codes or blank values.
-
Bug Fix
Support Reps tab now populates correctly
The Support Reps tab in the Submit Issue screen will now show available support contacts instead of being blank.
-
Bug Fix
Support reps now load correctly in Submit Issue dialog
Support representatives now appear in the Support Contacts tab when submitting an issue.
-
Bug Fix
Selection boxes now update immediately after changing store-number settings
When you change how store numbers are shown (display mode) or sorted in the Settings > Connections tab, all dropdown lists throughout Margin Master will now update as soon as you close Settings. Before, you had to wait until the next sync to see the change take effect.
-
Bug Fix
SKU-level exception icon now renders correctly
When individual items have special pricing rules applied, the grid now correctly shows an icon in the "*" column indicating what type of override is in effect.
-
Bug Fix
Status message no longer covers input fields
When setting up your store configuration, all the fields (vendor, store number, POS system) are now visible. Previously a message box was covering them up so you couldn't type anything in.
-
Bug Fix
Store Configuration dialog fields now visible
When opening Store Configuration from startup or settings, all text boxes and dropdowns now appear correctly instead of being hidden.
-
Bug Fix
Splash screen no longer gets stuck blocking the main window
Fixed a race condition (MM-1327/MM-1311) where competing splash screen close attempts during startup could leave the splash window visible and blocking all input. The root cause was improper async/await handling when dispatching work to the UI thread — the code would resume execution before inner tasks completed, allowing multiple sections to simultaneously try to control the splash. Store 5645's logs documented this occurring for 27 minutes straight.
-
Bug Fix
Compiler warning resolved in Falcon import
Fixed a nullable reference annotation warning in the Falcon POS Excel import code that could have caused future build issues. This is a code quality improvement with no impact on functionality.
-
Bug Fix
Fixed support scripts dialogs appearing behind window
The password prompt and support scripts windows now appear in front of other windows instead of hiding behind them.
-
Bug Fix
Fixed Thread view toggle clipping
Adjusted padding and margins in the Support Issues view toggle bar to prevent the "Thread" radio button from being cut off at the right edge of the screen.
-
Bug Fix
Fixed Connect window visibility during database setup
The database connection window now stays out of the way while you're creating or restoring a database, then comes back automatically if you need to make changes.
-
Bug Fix
Primary store designation now persists correctly
Setting a store as your primary store will now save correctly and stay selected after closing and reopening the application.
-
Bug Fix
Removed duplicate store validation check
Removed an extra validation requirement that was preventing users from validating their license and creating databases even when all required information was correctly entered. The "Validate License" button now activates as soon as store number (digits only), vendor, and POS system are selected.
-
Bug Fix
Fixed unassigned stores appearing when Store Grouping was disabled
Stores were incorrectly appearing in the "Unassigned Stores" list even when Store Grouping was turned off. All three store grouping collections (groups, assigned stores, and available stores) are now properly cleared and hidden when the feature is disabled.
-
Bug Fix
Window focus restored after vendor data updates
After updating vendor data, the Margin Master window will automatically come back to the front so you can continue working.
-
Bug Fix
Fixed delete button visibility and functionality
The delete button for removing stores from the list now appears and works correctly in all situations.
-
Bug Fix
Cancel button persists across all rebuild steps
The cancel button now stays visible throughout the entire rebuild process, so you can stop the rebuild at any step, not just at the beginning.
-
Bug Fix
Store Manager async database operation
Deleting stores in Store Manager now runs more smoothly without freezing the interface.
-
Bug Fix
Epicor multi-character store numbers preserved during import
Epicor stores with multi-digit store numbers (like "554") will now show correctly throughout the application instead of being corrupted during import.
-
Bug Fix
Restored automatic contact selection fallback logic
When you open Submit Issue, a contact will always be pre-selected for you—either your store's primary contact or a default support representative—so you can submit issues faster.
-
Bug Fix
Restored default support rep selection when no primary contact exists
If your store doesn't have a primary contact set up, the system will now automatically select a default support representative when you submit an issue.
-
Bug Fix
Escalation safety net now correctly triggers after repeated splash close failures
Fixed the splash reaper's escalation counter, which was being incorrectly reset when the splash was re-shown. This made the three-strike escalation safety net unreachable when startup operations interleaved splash shows with failed closes. The counter now only resets when a close is actually verified successful, ensuring the watchdog can properly detect and recover from persistent splash problems.
-
Bug Fix
Background license validation in demo mode
Background license validation checks that run during normal application use now detect demo mode and suppress status change notifications. This prevents license warning dialogs from appearing mid-session when demonstrating the software to prospective customers.
-
Bug Fix
Blob migration tool vendor name authentication
Fixed vendor name resolution in the BlobMigration command-line tool to correctly map vendor abbreviations (Ace, EJ, DIB, Orgill, UH) to numeric vendor IDs for API authentication. Added proper error handling for 4xx HTTP responses to skip stores with bad data rather than treating them as tool errors.
-
Bug Fix
Fixed startup window dismissal issue
The database connection screen no longer closes unexpectedly when creating a new database or restoring a backup during first-time setup.
-
Bug Fix
Fixed off-screen button rendering issue
The Refresh and Cancel buttons now appear correctly at the bottom of the update window instead of being hidden off-screen.
-
Bug Fix
Prevent auto-update loops during development
Added safeguard to prevent automatic update application at startup when running in debug mode, avoiding interruption of normal development workflow while still allowing manual testing of update functionality.
-
Bug Fix
Show All Stores toggle now refreshes local files
Checking or unchecking "Show All Stores" now immediately updates both local and cloud backup files in the list.
-
Bug Fix
Zone pricing icon column restored
Items with zone-specific pricing now correctly show the "Z" indicator icon in the grid.
-
Bug Fix
Splash screen properly hidden before message boxes in strategy restore
Message boxes during strategy restore now appear properly without the loading screen visible behind them.
-
Bug Fix
Improved startup cancellation error handling
Changed startup cancellation to throw OperationCanceledException instead of a generic Exception when users cancel database or license configuration, providing clearer error handling and logging.
-
Bug Fix
Store number list ordering corrected
Fixed a fragile ordering mechanism that was re-sorting store numbers after building the dictionary. The list now sorts correctly by the chosen preference (vendor or POS number) using a single stable sort operation.
-
Bug Fix
Proper async handling when showing dialogs during startup
Fixed multiple locations in the startup sequence (OLEDB driver check, vendor data availability check) where modal dialogs were shown using Dispatcher.InvokeAsync incorrectly. The previous code would complete before the inner async work finished, allowing startup to continue while dialogs were still being processed. Now uses ExecuteOnDispatcherAsync to properly await the complete dialog workflow before proceeding.
-
Bug Fix
Failed updates now visible instead of silent
Margin Master used to stay on old versions without telling you when something went wrong—now it tells you the update failed and helps you fix it.
-
Bug Fix
Fixed contacts display to show only issue-specific contacts
Corrected the contacts display to show only contacts assigned to the currently selected issue rather than all store contacts. The contact summary now accurately reflects who will be notified about updates to that specific issue, with the text "No contacts assigned" shown when no contacts are linked to the issue.
-
Bug Fix
Contact delete and edit operations in issue submission
You can now delete contacts from your store's contact list directly in the support request form (after confirming). The "Continue" button is now disabled until you select at least one contact to notify.
-
Bug Fix
Server selection validation in database setup
Added null-check for selected server before attempting to load database list, preventing errors when the server dropdown is cleared or no server is selected.
-
Bug Fix
Update problem dialog shown after startup completes
The update problem dialog now waits until Margin Master finishes starting so it doesn't get stuck behind the splash screen.
-
Cloud Sync
Available appointment check on startup
The application now queries the RetailerSoft API during startup to check for available appointment slots, which controls the visibility of the Schedule an Appointment menu item. The check runs as part of deferred startup work to avoid impacting initial load time.
-
User Interface
Support Issue History menu option
Click "Support Issue History" in the Help menu to see all your past support tickets in your browser.
-
User Interface
Support Issue History moved to submenu
You can now find Issue History inside the Support Issues menu, right below Submit Issue.
-
User Interface
Support menu reorganization
The "Support Issue History" option is now found inside the Support Issues submenu instead of at the top level of the Help menu.
-
User Interface
Type-to-filter enabled for all dropdown menus
When you click any dropdown menu, you can now start typing to quickly find what you're looking for — for example, typing "org" in the vendor list will show only Orgill, or typing "rock" in the POS system list will show only RockSolid.
-
User Interface
Type-to-filter enabled on all dropdown menus
When clicking on any dropdown menu, you can now start typing to immediately filter the list and find what you're looking for—especially helpful for long lists like vendor catalogs or POS system options.
-
User Interface
Redesigned Support Scripts dialog with master-detail layout
Scripts are now organized by category in a tree on the left side. Click any script to see its full description before running it.
-
User Interface
Support Scripts button added to Database Setup screen
Support staff can now access diagnostic tools directly from the database setup screen by clicking the Support Scripts button (password required).
-
User Interface
Enhanced SKU Lookup results display
When searching for items using Quick Find, results now appear in a cleaner grid format with SKUs and descriptions in separate columns, making it easier to scan multiple matches.
-
User Interface
Auto-select issue from notification pill
Clicking the support issues notification now shows your issue immediately without extra clicks.
-
User Interface
Redesigned contact selection in Support Issues screen
When submitting a support issue, you'll see all your store contacts in a list. Check the boxes next to anyone who should receive updates about the issue. Click a contact to edit their information on the right side, or use the "Add Contact" button to create a new one.
-
User Interface
Added menu bar to Database Setup window
The database setup screen now has a menu at the top for faster access to create, restore, and support tools.
-
User Interface
Removed obsolete database connection screens
Deleted multiple deprecated database connection views and windows (DatabaseConnectionWindow, DatabaseConnectionView, and associated ViewModels) that were no longer being used. All database configuration functionality is now consolidated in the modern DatabaseSetupWindow. This cleanup removes over 1,200 lines of unused code and eliminates confusion from having multiple similar screens.
-
User Interface
New dedicated Create New Database dialog
Creating a new database now uses a separate, simpler screen that walks you through entering your store information, shows your auto-generated database name, and validates your license before proceeding.
-
User Interface
Context help added to database configuration screens
When setting up or creating a database, you can now click the help button in the window header to open instructions and guidance for that specific task.
-
User Interface
Modernized Support Issues screen layout
Redesigned the entire Support Issues screen with a card-style layout featuring a blue accent bar and shadow effects for better visual hierarchy. Action buttons (View Online, Mark Resolved, Create New Issue) have been moved to a colored header bar at the top of the screen for easier access. View Online is now blue with a white background, Mark Resolved is green, and Create New Issue uses the company's dark blue color scheme.
-
User Interface
Redesigned Support Issues screen layout
Action buttons are now at the top of the screen for easier access, and you can switch between bubble and threaded views using the View menu.
-
User Interface
Full-screen master-detail layout for Support Issue dialog
The Become Support Issue User dialog has been redesigned from a compact list-over-detail view to a side-by-side master-detail layout. The left panel contains the issue list with filter bar (status dropdown and search box) and status counts. The right panel shows the selected issue's header information, full description, comments thread, attachments list, and download actions. The dialog now opens maximized instead of auto-sizing to a fixed minimum size.
-
User Interface
Full-screen master-detail layout for Support Issue dialog
The Support Issue dialog now fills your screen and can be resized to fit your workflow.
-
User Interface
Dialog window behavior improved
Setup and configuration windows will no longer stay pinned on top of all your other programs, making it easier to switch between Margin Master and other applications when you need to look up information during setup.
-
User Interface
Renamed database connection menu item
The database menu option now says "Connect to Database" instead of "Manage Database Connections" to make it clearer what it does.
-
User Interface
Renamed database connection menu item
The menu option is now called "Connect to Database" instead of "Manage Database Connections" for easier understanding.
-
User Interface
Moved "Use Legacy View" to hamburger menu
To switch back to the older pricing strategy editor, click the hamburger menu (three lines) in the top-right and select "Use Legacy View" from the bottom of the menu.
-
User Interface
New Options screen set as permanent default
Removed the database setting that allowed routing back to the legacy Options screen on startup. The application now consistently launches with the new Options interface, though the "Use Legacy" button remains available as a session-only fallback for users who need temporary access to the old screen.
-
User Interface
Always use new Options screen
When you open Settings from the menu or at startup, you'll always see the updated Options screen design.
-
User Interface
Improved splash screen continuity during restore operations
The loading screen now stays visible continuously during restore operations instead of briefly disappearing between steps.
-
User Interface
Granular splash screen progress messages during startup
The splash screen now breaks down the previously monolithic "Verifying Database Configuration" step into 8 distinct sub-steps with specific messages: Verifying Rounding Tables, Verifying Field Mappings, Checking Rounding Schemes, Checking Configuration Integrity, Migrating zone data, Checking column schemas (with per-table progress like "Main table 3 of 12"), and Applying schema updates. This provides visibility into what the application is doing during startup and prevents the appearance of the application being frozen during database maintenance operations.
-
User Interface
Inline cloud credential entry in restore dialog
When restoring a cloud backup, you can now enter your vendor and store number right in the restore window if you haven't set it up yet.
-
User Interface
Modern styling for update installation screen
The update installation window now has a modern blue accent bar at the top and buttons with icons for easier recognition.
-
User Interface
Update splash screen visual redesign
The Velopack installation splash screen now features a blue-gray gradient background, a blue accent bar matching the application's DevExpress styling, Impact Bold title font per brand standards, a two-line subtitle explaining the update is installing and that the app will restart, and the full-color RetailerSoft logo with a bottom divider frame. This replaces the previous plain white background with simple text.
-
User Interface
Update screen visual redesign
The update installation dialog now features a blue accent bar at the top, improved typography with hierarchical font sizes and weights, and better-organized status messages. The layout has been adjusted to improve spacing and readability, with the wait indicator displaying "Margin Master Update" as a header followed by "Please wait…" and detailed status text below.
-
User Interface
Custom branded update installation window
Added a new custom WPF window that displays during update installation with Margin Master branding, a blue accent strip, and an indeterminate progress bar (#0078D4). The window shows the version being installed and explains that the app will restart automatically. This replaces the generic Velopack Update.exe progress window at all three update application points: manual update installation, startup auto-apply, and What's New dialog updates.
-
User Interface
Custom update installation window
When Margin Master installs an update, you'll now see a cleaner, branded window with clear information about which version is being installed.
-
User Interface
New knowledge base article for download blocking issues
Created a comprehensive help document titled "Microsoft Edge Download Block" in the Getting Started section. The article includes step-by-step instructions with screenshots-ready descriptions for getting past Edge's "This file can't be downloaded safely" warning and Windows Defender SmartScreen's "Windows protected your PC" dialog. It also provides a plain-English explanation of why SmartScreen flags software with limited download footprints, clarifies that the warnings are not virus alerts, and answers five common questions about the security prompts, IT policies, and auto-updates.
-
User Interface
Improved update installation window visibility
When Margin Master installs an update, you'll now see a cleaner transition to the installation window without the startup screen lingering in the background.
-
User Interface
Removed Status column from Store Manager grid
The Status column has been removed from the store list to make the screen cleaner and easier to read.
-
User Interface
Cancel button appears immediately on rebuild start
The cancel button now shows up right away when you start rebuilding data, so you don't have to wait to cancel if needed.
-
User Interface
Store Manager button modernization
The Save and Close buttons in the Store Manager window now have a more modern, polished appearance.
-
User Interface
Click support rep rows to select as primary contact
You can now click directly on a support representative's name to select them as the primary contact, just like you can with store contacts.
-
User Interface
Enhanced contact selection methods
You can now select who to send the issue to by clicking their checkbox or clicking on their name.
-
User Interface
Legacy option identification in store number preferences
When choosing how store numbers appear in the Settings screen, options marked "(legacy)" show stores the same way they appeared before this setting was added, making it easier to keep your familiar view.
-
User Interface
Legacy options labeled in store number preferences
When choosing how store numbers appear in Settings, options labeled "(legacy)" show stores the same way they appeared before this choice was added.
-
User Interface
Streamlined submit button layout in Support Issues
The "Quick Submit" button has been renamed to "Submit" and now shows a menu when clicked, making the toolbar more compact.
-
User Interface
Quick Submit converted to dropdown menu
Click the "Submit" button in Support Issues to see a menu of submission options.
-
User Interface
Password-protected feature activation on Background Service tab
A new "Enable (password)" button appears at the top of the Background Service settings. Support staff must enter the password to activate this feature on your machine. Once enabled, you'll see all the scheduling and configuration options. You can disable it anytime without a password.
-
User Interface
Live download progress on auto-update splash screen
When Margin Master checks for or downloads updates at startup, you'll now see clear status messages like "Contacting update server…" and live download percentages (e.g., "45%") so you know the app is working and not frozen.
-
User Interface
Enhanced update progress feedback
When Margin Master checks for updates at startup, you'll see more detailed information about what's happening, including download progress percentages and clearer messages about each step.
-
User Interface
Developer build indicator on splash screen
When running a developer build, the splash screen now displays "-DEVELOPER" after the version number, matching the indicator shown in the main window title bar.
-
User Interface
Startup Database Setup button layout updated
The Database Setup screen now shows a new "Restore Backup" button in the bottom-left corner.
-
User Interface
Fixed text wrapping in issue resolution dialog
The comments field in the issue resolved dialog now properly wraps text and includes a scrollbar, improving usability when entering longer resolution notes.
-
User Interface
Enhanced dropdown navigation in Database Creation wizard
When creating a new database, you can now type to quickly find your vendor or POS system instead of scrolling through the complete list.
-
User Interface
Enhanced database setup dropdown menus
When setting up a new database, you can now type to quickly find your vendor (like "Ace" or "Orgill") or POS system instead of scrolling through the entire list.
-
User Interface
Standardized dialog window sizing behavior
Dialog windows now consistently use dynamic sizing with a maximum height of 800 pixels, allowing them to adapt to their content while preventing them from exceeding reasonable screen boundaries. Scroll bars appear automatically if content still exceeds the available space.
-
User Interface
Added scroll support to configuration screens
If a setup screen is too tall for your monitor, you can now scroll down to see all the options and buttons.
-
User Interface
Database Setup window height limit with scrolling
The database setup screen now scrolls automatically on smaller monitors instead of extending off the screen.
-
User Interface
Database Setup window height capped for smaller displays
The database setup screen now fits better on smaller laptop screens by scrolling when needed.
-
User Interface
Cleaner issue descriptions in Support Issues screen
Issue descriptions are cleaner and easier to read, and the latest comments are always visible without scrolling.
-
User Interface
Added menu bar to Database Setup window
The Database Setup window now has a menu bar at the top with File and Tools menus, making it easier to find options like creating a new database or restoring from a backup.
- User Interface Installation Scripts dialog auto-resizes to content
-
User Interface
Fixed view toggle label clipping
The "Thread" view option now displays fully without being cut off at the edge.
-
User Interface
Simplified Database Setup window to focus on connection
The Database Setup screen is now simpler and focused on just connecting to SQL Server and picking an existing database. To create a new database, you click the "Create New Database" button.
-
User Interface
Added menu bar with view mode toggle
Added a DevExpress BarManager menu bar to the top of the Support Issues screen with a View menu containing options to toggle between Bubbles and Thread chat display modes. This replaces the previous radio button controls and provides a more standard menu interface.
-
User Interface
License configuration window positioning updated
The license configuration window's positioning logic was simplified, removing the fallback behavior that would set the window as topmost when the main window wasn't available. The window will now properly center on screen without forcing itself above other applications.
-
User Interface
Enhanced splash screen coverage during database switching
When switching between databases, the loading screen now stays visible until all data is fully loaded.
-
User Interface
Status message during script preload
You'll see a status message showing which scripts are downloading while the dialog loads.
-
User Interface
Improved Submit Issue dialog feedback
The support form now clearly shows when database backup is not available by graying out the option.
-
User Interface
Wire up What's New command
Connected the previously unused BuildWhatsNewUrl() method to a new ShowWhatsNew() command that properly launches the browser. The command includes error handling to log any issues that occur when attempting to open the URL.
-
User Interface
Help menu organization improved
The What's New menu item has been positioned between "Catalog Lookup" and "Version History" in the Help menu for better organization and discoverability.
-
User Interface
Improved text hierarchy during update installation
Text during updates is now organized into clear sections showing the update title, status message, and detailed progress in an easy-to-read format.
-
User Interface
Enhanced action buttons
The Refresh and Cancel buttons have been updated to use DevExpress SimpleButton controls with icons, consistent sizing (30px height, 100px minimum width), and improved spacing. The buttons now include visual glyphs (refresh and close icons) for better recognition.
-
User Interface
Branded download progress window
When downloading Margin Master, you'll see a branded progress window showing download speed and file size.
-
User Interface
Smart restart prompting after store reconfiguration
If you change your store number using Reconfigure Store, you'll be prompted to restart Margin Master. Other changes (vendor, POS, RSC) don't require a restart.
-
User Interface
Dynamic menu visibility based on availability
The appointment scheduling option only appears when time slots are actually available, so you won't see it if the calendar is full.
-
User Interface
Two-tab layout for store contacts vs. support representatives
Store contacts and support representatives now appear in separate tabs, making it easier to find and select the right person for your issue.
-
User Interface
Status column removed
The Status column has been removed from the store list to simplify the view.
-
User Interface
Primary contact visual indicator
The main contact for your issue is now marked with a blue "(Primary)" label so you can easily see who will receive the issue.
-
User Interface
Eliminate splash screen flashing during auto-continue strategy execution
When running pricing strategies with auto-continue enabled, the loading screen stays visible throughout execution instead of flashing between steps.
-
User Interface
Visual icons for backup source identification
Backup files in the list now show an icon next to "Local" or "Cloud" to help you quickly identify where each backup is stored.
-
User Interface
Optimized Options dialog performance
Implemented a flag-based tracking system where individual Options tabs signal when they modify settings that require selection box updates. The Options dialog aggregates these flags and triggers a rebuild only when necessary, avoiding unnecessary work on routine open/close operations.
-
User Interface
Softened installation window message
The message shown just before the app restarts to complete an update is now friendlier and clearer about what's happening.
-
User Interface
Clarified Installing Update window message
The update installation screen now says "Finalizing" so you know the update is still processing before the automatic restart.
-
User Interface
Improved Settings screen dropdown navigation
In Settings screens, all dropdown menus now let you type to filter options — useful for quickly selecting mailbox numbers, cost types, and other configuration values.
-
User Interface
Improved Settings screen dropdown menus
In the Settings screens, you can now type to quickly filter options in any dropdown, making it faster to configure vendor preferences, cost types, and other settings.
-
User Interface
Code cleanup for combo box controls
Removed redundant AutoComplete, IncrementalFiltering, and ImmediatePopup properties from multiple combo box controls across Settings screens, as these are default behaviors in DevExpress controls.
-
User Interface
Enhanced error messages for missing scripts
Improved error reporting when an embedded script cannot be found, now showing only relevant script resources in the diagnostic output instead of all embedded resources.
-
User Interface
SMS-style chat bubbles for issue comments
Issue conversations now look like text messages, with your comments in blue on the right and support responses in gray on the left, making it easier to follow the discussion.
-
User Interface
Contact selection redesigned with split-panel layout
You can now select multiple contacts to notify about an issue using checkboxes, and add or edit contacts directly from the submission form.
- User Interface SKU Lookup dialog auto-resizes to content
-
User Interface
Redesigned chat area with phone-style interface
The chat conversation area now displays in a phone-style container with a gradient header and pill-shaped message input field at the bottom, providing a more familiar messaging interface similar to modern chat applications.
-
User Interface
Enhanced contact display with pill chips
Contacts are now shown as colored pills with names and emails, making it easier to see who's assigned to each issue at a glance.
-
User Interface
Status count display and enhanced filtering
Added visual status counts in the filter bar to show the number of Open, Closed, and total issues at a glance. The filter bar now displays in the left panel above the issue list, making it easier to locate and filter issues while viewing details in the right panel.
-
User Interface
Improved RSC and POS dropdown layout
Fixed the side-by-side layout of RSC (Retail Support Center) and POS System dropdowns so that when RSC is hidden (for non-Ace/Orgill vendors), the POS dropdown expands to use the full width. Previously, both fields would stay half-width regardless of RSC visibility.
-
User Interface
Quick Issue Submit dialog expanded and reorganized
The Quick Issue window is slightly wider with clearer instructions about what you can include.
-
User Interface
Startup-only UI hidden during reconfiguration
The Store Configuration window now adapts its interface based on context. When opened via File > Reconfigure Store, startup-only buttons like "Back to Database Selection" are automatically hidden since they're not relevant when the application is already running.
-
User Interface
Store Configuration dialog startup mode detection
Modified StoreConfigurationWindow and its ViewModel to detect whether it's being opened during application startup or from the File menu. The new IsStartupMode property controls visibility of startup-specific UI elements, providing a cleaner experience when reconfiguring an already-running application.
-
User Interface
Booking link generation with authentication
Implemented secure booking link generation through the API authentication system, ensuring users are automatically logged in when accessing the appointment scheduling page. Failed API calls are logged as warnings but don't disrupt the user experience.
-
User Interface
Updated delete button styling
Replaced the custom red "✕" text button with a standard DevExpress close icon button for better consistency with the application's overall design and improved visual clarity.
-
User Interface
Support Issues empty state messaging
When viewing a support issue with no messages, you'll now see clearer messaging about whether the conversation is empty or if there's a temporary connection issue.
-
User Interface
Primary contact badge in contact list
The primary contact now shows a blue "(Primary)" label so you can easily see who will be submitting the issue.
-
User Interface
Submit Issue contact step improvements
Enhanced the Submit Issue dialog's contact selection step to ensure users can always submit issues without manually hunting for a contact. Both the initial load and the reload-contacts paths now use consistent logic for populating the Store Contacts and Support Reps tabs and selecting a default contact.
-
User Interface
MySQL Query Utility screen enhancements
The MySQL Query Utility screen now includes a menu bar at the top for accessing diagnostic scripts. The Scripts menu contains four pre-configured queries designed to help diagnose common MySQL Compass import issues related to character encoding and store identifier mapping.
-
User Interface
Enhanced store number tooltips
Hover over any store number to see both the vendor and POS store numbers, even when only one is displayed in the list.
-
User Interface
Modal password dialog for feature authorization
Implemented a programmatic password prompt dialog using ThemedWindow that appears when clicking the Enable button. The dialog includes a PasswordBoxEdit control and validates the entered password against the standard support password (case-insensitive). The dialog is modal, centers over the active window, and supports both Enter (OK) and Escape (Cancel) keyboard shortcuts.
-
User Interface
Streamlined title bar notification behavior
Clicking the red notification badge at the top of the window now opens the full Support Issues screen directly.
-
User Interface
Auto-scroll comments to most recent message
The conversation view in Support Issues now automatically scrolls to show the newest messages.
- User Interface Database Setup window spacing refinements
-
User Interface
Improved filter and action button positioning
The status filter, search box, and action buttons have been repositioned to work optimally with the new left-right split layout, ensuring all controls remain easily accessible in the full-screen interface.
-
User Interface
Capped window height at 780 pixels
Added a maximum height constraint to prevent the Create New Database window from growing too tall on screens with many available options, ensuring the dialog remains fully visible and accessible.
-
User Interface
Idle delay controls snooze dialog auto-trigger behavior
The UpdateSnoozeViewModel now accepts an injectable `IdleDelayMinutes` property (previously hard-coded to 30) that controls when the auto-trigger countdown begins. When set to `null` (corresponding to "Never"), no idle timer starts and the progress bar is hidden. The idle progress bar now fills over the user-configured duration before the 10-second countdown begins. All six delay options are mapped from string values stored in application settings to integer minute values or special behaviors (null for Never, exit handler for OnShutdown).
-
User Interface
What's New link in update notification
The update notification now includes a "What's New in This Version" link to review the changes before updating.
-
User Interface
Added loading indicators to all Options tabs
A loading spinner now appears when opening or switching between settings tabs.
-
User Interface
Updated validation and progress tracking
You can now submit a report with just attached files, even if you don't include logs or a database backup.
-
User Interface
Help link added to Auto Update options tab
A "Help — Auto Update Configuration" button with info icon appears below the settings, linking to the updated auto-updates.md documentation that now includes full descriptions of all six idle delay options, the shutdown mode behavior, and the new centralized options location.
-
User Interface
Enhanced license error display in store configuration
License problems during setup now show a clearer error message with a warning icon.
-
User Interface
Removed "Do Not Contact" checkbox
If you don't want to be contacted about an issue, just leave all contacts unchecked.
-
User Interface
Updated issue description display with card styling
Replaced the plain description text box with a card-style layout featuring a blue accent bar on the left, drop shadow, and an icon for better visual presentation of the issue description.
-
User Interface
Idle progress bar in update notification
A progress bar in the update notification shows how much time remains before auto-install begins.
-
User Interface
Adaptive window sizing for high-DPI displays
Database setup windows (Connect, Create New, Store Configuration) now use screen-aware maximum heights instead of fixed pixel values, preventing windows from being cut off on laptops or displays with taskbars.
-
User Interface
New update problem dialog and settings
Added `UpdateProblemView.xaml` and `UpdateProblemViewModel` to present the three-choice dialog (repair install / contact support / remind me later). Added `UpdateRepairService` to download and launch the installer. Added five new `ApplicationSettingKey` values: `AutoUpdateConsecutiveFailures`, `AutoUpdateLastFailureUtc`, `AutoUpdateLastFailureTarget`, `AutoUpdateLastFailureReason`, and `AutoUpdateProblemPromptLastUtc` to persist the failure state across restarts.
-
User Interface
SMS-style chat bubbles for issue comments
Issue conversations now look like text messages, with your comments in blue on the right and support responses in gray on the left, making it easier to follow the discussion.
-
User Interface
Streamlined title bar notification behavior
Clicking the red notification badge at the top of the window now opens the full Support Issues screen directly.
-
Database
Contact phone persistence
Added ContactPhone property to ApplicationSettingsService to store and retrieve the contact person's phone number alongside existing contact fields (first name, last name, email).
-
Database
Removed DatabaseSetupMode enum
Deleted the DatabaseSetupMode enum (CreateNew/ConnectExisting) as the two-dialog approach eliminates the need for mode switching. DatabaseSetupAction enum remains for tracking user's final action (CreateNew, ConnectExisting, Cancel, RestoreBackup).
-
Database
New AutoUpdateIdleDelay setting key
Added new `ApplicationSettingKey.AutoUpdateIdleDelay` to store the user's preferred idle delay value (Never, 1Minute, 5Minutes, 30Minutes, 1Hour, OnShutdown). Default is 30Minutes.
-
Architecture
Feature enablement logic moved from tab-level to control-level
The Background Service tab is now always enabled in the Settings screen navigation, but the individual settings controls within the tab are gated by the IsFeatureEnabled flag. This allows users to see the Enable button and activate the feature without needing support to first enable it remotely via the database flag. The SetFeatureEnabledAsync method updates the ApplicationSettingKey.BackgroundServiceFeatureEnabled flag and refreshes service status and history when enabled.
-
Architecture
Session-cached support authorization
Support script authorization is cached in a static field shared across the application session. Once the support password is entered successfully, the user won't be prompted again until the application is restarted, streamlining repeated access for support scenarios.
-
Architecture
Created CreateNewDatabaseViewModel with focused responsibilities
New ViewModel contains all logic for store validation, database name generation with conflict checking, license validation, and database creation orchestration. Removed ~700 lines of intertwined logic from DatabaseSetupViewModel, including store validation methods, database name generation, license validation, and mode-switching code. The two ViewModels now have clear separation: setup handles connection, creation handles store config.
-
Architecture
Framework-dependent .NET 10 single-file executable
The bootstrapper is published as a framework-dependent single-file executable targeting .NET 10, keeping the file size small (441 KB) while requiring users to have the .NET runtime installed. The stable file structure and signing certificate help establish trust with Windows SmartScreen.
-
Architecture
New IssueContactEditorViewModel
Created a dedicated ViewModel (IssueContactEditorViewModel) to manage contact selection state with SelectableContact wrapper objects. Handles bidirectional synchronization between the checkable list and the selected chips display, automatic toggle handling between store/support contacts, and loading contacts from the API with support employee filtering.
-
Infrastructure
Build warning cleanup
Resolved a compiler warning in the Falcon Excel import code related to nullable reference type annotations, improving code quality without changing behavior.
-
Infrastructure
Hide native Velopack update dialog
Added Win32 helper function HideVelopackWindowAsync() that automatically hides the native Update.exe window after ApplyUpdatesAndRestart() is called, ensuring only the custom branded window is visible during the 3-5 second installation process. Runs in background for up to 5 seconds to catch the Velopack process when it appears.
-
Infrastructure
Enhanced documentation search coverage
Updated the documentation index with comprehensive search keywords including "edge blocked," "can't download safely," "windows protected," "smartscreen," "keep anyway," "run anyway," and related phrases. This ensures users encountering download warnings can quickly find the help article through the in-app documentation search or support portal.
-
Infrastructure
Removed obsolete database connection screens
Deleted eight unused files including DatabaseConnectionWindow (both startup and in-app versions), DatabaseConnectionView, DatabaseConnectionViewModel, and DatabaseConnectionAction enum. These screens were fully replaced by the newer DatabaseSetupWindow but remained in the codebase. Also removed their dependency injection registrations and dialog service references from MainMMWindow.
-
Infrastructure
Enhanced debug mode testing for updates
Modified debug mode behavior to simulate an available update (version "2026.DEBUG.TEST") during CheckForUpdatesAsync(), allowing the new installation window to be previewed and tested without requiring a real update or installed application. The window displays for 3 seconds then closes without restarting. AutoApplyUpdateAtStartupAsync now skips entirely in debug mode to avoid blocking normal development.
-
Infrastructure
Automated bootstrapper build and signing pipeline
Added GitHub workflow (publish-bootstrapper.yml) that automatically builds, code-signs with Azure Trusted Signing, and uploads the bootstrapper to Azure blob storage whenever the bootstrapper project changes. The workflow includes verification steps to ensure the signature is valid before publishing.
-
Infrastructure
Reorganized script folder structure by category
Scripts are now organized into category subfolders (scripts/SqlScripts/Powershell/, scripts/OLEDB/Powershell/) mirroring the UI categories. Updated the .csproj to embed scripts using a recursive glob pattern (**/*.ps1) and updated CLAUDE.md with a PR checklist for adding new scripts (requires .ps1, .md, catalog entry, support doc, and index entry).
-
Infrastructure
Store number display formatter with unit tests
Created StoreNumberDisplayFormatter helper class with comprehensive unit tests covering all four display modes and the fallback behavior when no POS mapping exists. This ensures display logic remains consistent and correct across future changes.
-
Infrastructure
Updated documentation for two-dialog workflow
Revised database-setup.md and database-creation.md to reflect the new two-dialog architecture, including updated screenshots, step-by-step instructions, and architectural diagrams showing the separation between connection setup and database creation flows.
-
Infrastructure
Update health policy with test coverage
Extracted the pure escalation logic into `UpdateHealthPolicy.ShouldPromptUser()` (static, no I/O, testable). Added `UpdateHealthPolicyTests.cs` with 16 test cases covering the failure threshold, behind threshold, snooze interactions, throttle behavior, and unparseable/future timestamps. Mirrors the design of `UpdateDeferralPolicy`.
-
Infrastructure
Background service stop before repair install
`UpdateRepairService.LaunchInstaller()` calls `BackgroundWindowsServiceController.TryStopServiceNoElevation()` before running Setup.exe. The background service executable lives inside `current\`, the folder the installer must replace, and is the most common cause of locked-folder update failures. Sets the restart sentinel only when a running service was actually stopped.
-
Infrastructure
Documentation updated for update failure workflow
`docs/marginmaster/getting-started/auto-updates.md` expanded with a "When an Update Will Not Install" section explaining the three-choice dialog, the repair install flow, the 24-hour throttle, and the most common causes (background service, antivirus, locked folders). Added search keywords: `update failed`, `could not update`, `stuck on old version`, `repair install`, `reinstall`, `folder locked`. Added new technical sections: "Update-Failure Detection and Escalation" and "Repair Install Flow" with implementation detail.
Reporting & Exports
-
Improvement
Clear guidance for backup path permission errors
If a backup fails because SQL Server can't reach the folder, you'll now see an explanation telling you to either choose a folder on the SQL Server's own hard drive, or grant the SQL Server service account permission to access the network location.
-
Improvement
Debouncer cancellation support
Added the ability to cancel pending debounced operations, allowing the application to immediately override scheduled actions when the desired state changes. This prevents stale operations from executing after they're no longer relevant.
-
Improvement
Added confirmation dialog before removing stores
Before removing any stores during a MySQL refresh, you'll now see exactly which stores will be removed and can choose whether to proceed.
-
Improvement
Centralize update-marker tracking to prevent inconsistencies
All four code paths that apply updates (startup auto-apply, two interactive apply paths, and the version downgrade tool) now route through a single `UpdatePendingSentinel` class that manages both halves of the tracking marker together. This architectural change prevents the target version and starting version from drifting out of sync, which would make the next launch's classification unreliable. Three separate clearing sites also now use the same centralized method.
-
Improvement
Added detailed change summary after refresh
After a MySQL refresh completes, you'll see a clear summary showing exactly what changed—which stores were added, reactivated, updated, or removed.
-
Improvement
Settings screen now warns when Export Path is not writable
The Settings screen now warns you immediately if you pick a folder that Windows won't let Margin Master write to, helping you choose a better location upfront.
-
Improvement
One-time notification when fallback occurs
If backups fall back to the default location, you'll see a notification explaining why and where to update your export path.
-
Improvement
Improved reliability of MySQL refresh processing
If there's a problem with one store during a MySQL refresh, the other stores will still be processed correctly instead of the whole operation failing.
-
Bug Fix
Drop ship SKU suffix missing in newretails exports
Drop ship items that should end with "D" were being exported without the "D" at the end. This has been fixed so the "D" suffix now appears correctly in your newretails export files.
-
Bug Fix
Splash screen timing issue during fast exports
When exporting a small number of records to a text file, the "Exporting changes" splash screen would sometimes get stuck on screen behind the success message. This has been fixed.
-
Bug Fix
Splash screen stuck after export completion
Fixed a bug where the loading screen would sometimes stay on screen after an export finished, blocking you from seeing whether the export succeeded. The loading screen will now properly disappear when operations complete.
-
Bug Fix
Excel export crash when columns are hidden or filtered
Exporting to Excel will no longer crash when you've hidden or filtered certain columns from the view.
-
Bug Fix
Excel export no longer removes columns with matching field and header names
When exporting pricing data to Excel, columns like SKU and Description will now appear correctly instead of being missing from the exported file.
-
Bug Fix
Excel export column removal bug
Some columns were being removed from your Excel exports by mistake. This has been fixed so all columns now export correctly.
-
Bug Fix
Fixed MySQL refresh failing to restore deleted stores
Stores that were previously removed but exist again in your POS system will now correctly reappear in Store Manager after a MySQL refresh.
-
Bug Fix
Custom group strategy no longer errors when no future pricing actions configured
Custom pricing groups with no future pricing actions will now process silently without logging errors.
-
Bug Fix
Ace MAP pricing update now handles older database schemas
Ace Hardware stores with older databases will no longer see errors during import or sync when MAP pricing is updated.
-
Bug Fix
Automatic backup no longer crashes when Export Path is read-only
Automatic backups will no longer fail silently if your Export Path points to a protected Windows folder.
-
Bug Fix
Automatic fallback for read-only export paths
Backups will no longer fail if your export folder becomes read-only or unavailable — they'll save to a safe default location automatically.
-
Bug Fix
Schema errors now properly escalate to telemetry
When the application encounters a missing database column or table (SQL errors 207/208), it was previously logging these as warnings, which could be filtered below the telemetry threshold and go unnoticed. These errors are now logged at Error level to ensure they reach telemetry systems, making it easier to identify and diagnose schema drift issues between the application and the database. This fix addresses a case at store 3875 where a genuine schema problem was being silently ignored.
-
Bug Fix
Eliminate false update-failure alerts for machines updated by alternate paths
If a technician or Windows service updates Margin Master while you're not using it, the app will now correctly recognize it's up to date instead of showing an incorrect update-failure message.
-
Bug Fix
Database retry failures due to SQL parameter conflicts
Fixed an error where database operations with automatic retry logic would fail on the retry attempt with "SqlParameter already contained by another SqlParameterCollection." The system now creates fresh parameter copies for each retry iteration, ensuring database commands can be safely retried without conflicts. This error was affecting store 6615.
-
Bug Fix
Missing version tracking for new product line
Resolved an issue where the new Margin Master 20.x line was not sending its version number during license validation, preventing the licensing server from recognizing that version 20 had run on a machine. This fix works in conjunction with RetailerSoft.Manager to enforce version compatibility and data integrity.
-
Bug Fix
Version history file locking no longer crashes application
Resolved UnauthorizedAccessException crashes (4 occurrences at store 1372) when the version history file was temporarily locked by antivirus software or other processes. The delete operation now retries a few times and treats persistent locks as non-fatal warnings instead of crashing.
-
Bug Fix
Import validation now tolerates malformed data rows
Importing a file with a few bad rows will now succeed instead of failing entirely, as long as most rows are valid.
-
Bug Fix
Dropdown list failures due to database collation mismatches
Dropdown menus for filtering and searching will now work correctly even if your database has mixed text comparison settings.
-
Bug Fix
Ace MAP pricing updates now work on all database versions
Ace MAP pricing updates will no longer fail on stores with older database structures.
-
Bug Fix
SKU Detail dialog no longer crashes when MainTableList is null
Opening SKU details will no longer crash in rare cases when the pricing grid hasn't fully loaded.
-
Bug Fix
Database migration no longer fails on fresh installations
Fixed a migration error (3 occurrences at store 119) where adding the IsNotFound column to StoreManagerInfo failed when the table didn't exist yet. The migration now checks for table existence before attempting the ALTER statement.
-
Bug Fix
Custom group processing skips groups with no future-price actions
Custom groups with no configured future-price actions are now treated as a benign no-op and skipped silently, rather than logging "Not Future Price Setting to Load" errors for every batch in the group.
-
Bug Fix
SKU Detail dialog no longer crashes when opened
The SKU Detail window will no longer crash when opening certain items.
-
Bug Fix
Version history file cleanup now handles locked files gracefully
The version history maintenance routine now retries file deletions when files are transiently locked (by antivirus, indexer, or multiple instances) and treats persistent locks as non-fatal warnings rather than failing the entire save operation.
-
Bug Fix
StoreManagerInfo schema update now checks table existence
The startup migration that adds the IsNotFound column to StoreManagerInfo now verifies the table exists before attempting the ALTER TABLE, preventing errors in edge-case database states.
-
Cloud Sync
Application version reporting in license validation
After upgrading to Margin Master 20, any older versions on your computer will be blocked from starting, preventing accidental data corruption from version conflicts.
-
Data Import
Improved drop ship SKU handling for Ace vendors
The Main Table screen now loads the necessary tracking columns (AltSKU and UserE1) when processing Ace Hardware or Emery Jensen data with drop ship SKU conversion enabled. This ensures the complete import/export pipeline preserves drop ship identifiers throughout the workflow.
-
User Interface
One-time notification when backup falls back to default location
You'll see a notification if backups are being saved to a different folder than expected, with instructions on where to fix the setting.
-
User Interface
Export path validation warning in Settings
When setting your export path in Options › Miscellaneous, you'll now see a warning if the folder can't be written to, letting you choose a different location.
-
Database
Add AutoUpdatePendingFromVersion setting key
A new application setting key `AutoUpdatePendingFromVersion` records the version running when an update attempt begins. This complements the existing `AutoUpdatePendingVersion` (the target) and enables three-way classification on the next launch. Markers written by older builds have no from-version and fall back to the original two-state logic, ensuring that upgrading to this build never hides a real failure.
-
Architecture
Backup failures excluded from automated error reporting
Created a new BackupFailedException type that is filtered out of telemetry reporting. Backup failures are almost always environmental (permissions, unreachable paths, disk space) rather than application defects, so they're now logged locally and shown to the user but not reported to the development team's error tracking system.
-
Architecture
Background services can now request user notifications
Added IUserNotificationService as a lightweight relay allowing background services (like AutoStrategyBackupService) to request toast notifications without depending on UI components. The main window routes these requests to the DevExpress NotificationService at startup.
-
Infrastructure
Enhanced debouncer cancellation
Added a Cancel() method to the Debouncer helper class that cancels pending scheduled work without triggering new actions. This allows immediate show/hide operations to cleanly abort any in-flight debounced operations, preventing timing conflicts in the UI.
-
Infrastructure
User notification service for background operations
Added a lightweight notification relay service that allows background services (like the automatic backup system) to request toast notifications without directly depending on UI components. The main window subscribes to these requests and displays them appropriately.
Performance & Reliability
-
Improvement
Session-based MySQL connection caching
Added a connection availability service that tracks MySQL reachability for the entire session. After the first connection failure, subsequent operations immediately skip MySQL attempts and use SQL Server cached data, eliminating repeated 10-second timeout delays during import operations and pricing analysis. Connection availability is restored when the user successfully tests the connection via Tools > Options > Save & Test.
-
Improvement
Cost break level navigation safety
Added bounds checking when navigating between prior and next cost break levels during property changes. This prevents index out of range errors when the collection size changes during background updates.
-
Improvement
Reduced MySQL connection timeout
Decreased the default MySQL connection timeout from 300 seconds (5 minutes) to 10 seconds to provide faster failure detection and improved responsiveness when the MySQL server is unreachable.
-
Improvement
Extended SQL Express connection retry timing
Database creation is now more reliable on slower computers or when SQL Server takes a few extra seconds to start up.
-
Improvement
Enhanced logging during database initialization
Added detailed logging to track how long SQL Server takes to bring the database online, including elapsed time reporting and timeout warnings. This helps diagnose setup issues on machines where database initialization is unusually slow.
-
Improvement
Enhanced database creation logging
Added detailed logging during the database online-check phase, including elapsed time tracking and user-facing status messages. If the 30-second timeout is reached, the application logs a warning and proceeds anyway, providing better diagnostics for support scenarios.
-
Improvement
Simplified statistics loading process
Opening the statistics view is now faster since it no longer needs to load all product data first.
-
Improvement
Skip download when Margin Master is already installed
If Margin Master is already installed, the launcher will skip downloading and just open the program immediately.
-
Improvement
Automatic download resume for interrupted installations
If your download is interrupted, you can restart the setup and it will pick up where it left off instead of starting over.
-
Improvement
Permission errors now logged as warnings instead of errors
When connecting to SQL Server instances with restricted permissions (error codes 229/300), these expected permission denials are now logged as warnings rather than errors. This reduces confusion in logs when running on locked-down database servers where certain administrative queries are intentionally blocked.
-
Improvement
Reduced error logging noise for SQL permission checks
SQL permission errors (error codes 229 and 300) are now logged as warnings instead of errors. These permission checks occur during normal operation when the application tests for optional SQL Server features, and do not indicate actual problems. This change reduces false alarms in error logs and support diagnostics.
-
Improvement
Background timer cleanup
Cost break deletion now properly stops the SKU data update timer and rebuild timer before clearing model data, preventing race conditions between timer threads and UI updates. Added null guards to prevent timer callbacks from running against empty data.
-
Improvement
Added dedicated helpers for read-only database operations
Created new ExecuteReadOnly and ExecuteReadOnlyAsync helper methods that execute database reads without acquiring application-level locks. SQL Server's built-in read consistency mechanisms are sufficient for SELECT operations, eliminating unnecessary serialization that caused performance bottlenecks on slower hardware.
-
Improvement
Statistics available without loading main grid
You can now view statistics immediately without waiting for the pricing grid to load first.
-
Improvement
Download resume support for interrupted installations
If your download is interrupted, the installer will resume from where it stopped instead of starting over from the beginning.
-
Improvement
Automatic retry with exponential backoff on network failures
The installer will now automatically retry up to 3 times if your internet connection is temporarily interrupted.
-
Improvement
Enhanced SQL Server account detection compatibility
The SQL Server service account detection now checks for both 'VIEW SERVER STATE' and 'VIEW SERVER PERFORMANCE STATE' permissions, improving compatibility with different SQL Server security configurations used in backup folder access verification.
-
Improvement
Exclude filters now run at database level
The "Exclude Zero OnHand" and "Exclude Zero Sales" options in the Statistics dialog now apply as SQL WHERE conditions during the database query rather than filtering in memory, improving both performance and consistency with other application filters.
-
Improvement
Automatic retry with exponential backoff
If the download fails due to network issues, the installer will automatically retry up to 3 times before giving up.
-
Improvement
PE header verification before installer launch
The setup tool now verifies the downloaded file isn't corrupted before running it.
-
Improvement
Download integrity verification
The installer now automatically checks that downloaded files aren't corrupted before running them.
-
Improvement
Skip download if Margin Master is already installed
If Margin Master is already installed, the setup tool will launch it immediately without downloading anything.
-
Improvement
Direct download fallback link on permanent failure
If automatic download fails repeatedly, you'll see a link to download the installer directly in your web browser.
-
Improvement
Reduced error reporting noise from auto-updater
Filtered out routine operational messages from the Velopack auto-updater in error reports to focus on actual application errors.
-
Bug Fix
Prevent crash when loading empty saved selections
Fixed a crash that could happen when loading certain saved filter selections. The app now handles empty or incomplete saved selections without errors.
-
Bug Fix
Null reference protection in saved selection loading
The application will no longer crash when loading saved selections that have empty or incomplete filter settings.
-
Bug Fix
Application startup crash resolved
The application will now start up successfully instead of crashing when launched.
-
Bug Fix
Cost break deletion crash resolved
You can now safely delete multiple cost break models without the application crashing. After deletion, the next available model will load automatically.
-
Bug Fix
Fixed crash when deleting pricing strategy conditions
Fixed a crash that could occur when deleting conditions from pricing strategies, especially when the condition text had special formatting.
-
Bug Fix
Restore Database dialog crash resolved
The Restore Database dialog will no longer crash when trying to show confirmation messages. The database restore process now works as expected.
-
Bug Fix
Removed unnecessary locking from read-only configuration operations
If you've experienced missing custom selection box views at startup or had to recreate your saved views after restarting the application, this issue is now resolved. Your custom views will load consistently, even during peak system usage.
-
Bug Fix
Selection box views failing to load during startup
Your saved custom selection box views (like "ACE SELECTION BOXES") will now load correctly when you open Margin Master, instead of falling back to default views that may be missing important columns.
-
Bug Fix
Database Setup Window crash on unreachable SQL Server
If your SQL Server connection is configured incorrectly, the Database Setup Window will now open properly so you can fix it. Previously, the app would crash before you could change the settings.
-
Bug Fix
Backup service now handles optional cost break table gracefully
BackupCostBreaksAsync and RestoreCostBreaksAsync were attempting to query the CostBreaks table unconditionally, but this table only exists at stores that have created cost break pricing rules. The service now checks for table existence before running queries, preventing SqlException errors with automatic retries at stores that have never enabled the cost break feature. This fix eliminates approximately 80 database errors reported across 10 stores in a 48-hour period.
-
Bug Fix
Backup service now handles missing CostBreaks table gracefully
Fixed a crash that could occur during backup or restore operations on certain older databases.
-
Bug Fix
Fixed crash when editing prices with empty values in Main Table
You can now clear or leave empty a cell in the pricing grid without causing an error.
-
Bug Fix
Order Multiple field now supports decimal values
Fixed a crash that occurred when importing inventory data from stores using decimal order multiples.
-
Bug Fix
Automatic cleanup of orphaned databases after creation failures
If database setup fails partway through, you can now click "Retry" and it will work — no need to call IT to manually delete the incomplete database first.
-
Bug Fix
Eliminated double-close crash in Edit Columns dialog
You can now safely close the Edit Columns dialog and choose to save your changes without encountering an error.
-
Bug Fix
Prevented double-close crash in Edit Columns dialog
The Edit Columns window will no longer crash when you save your changes while closing it.
-
Bug Fix
Database initialization now waits for SQL Server to complete setup
If you previously experienced "database creation failed" errors during first-time setup on a slower computer, this issue is now resolved. The setup process will wait as long as needed (up to 30 seconds) for SQL Server to be ready.
-
Bug Fix
Database creation now waits for SQL Server Express readiness
When setting up Margin Master for the first time on a computer with SQL Server Express, the application will now wait for the database to be fully ready before continuing, preventing setup failures.
-
Bug Fix
StoreGroup field population timeout on large databases
Margin Master will no longer fail to start on stores with very large inventories (300,000+ items).
-
Bug Fix
StoreGroup initialization timeout resolved
Stores with very large product databases will no longer see timeout errors when opening Margin Master or during store group verification.
-
Bug Fix
Extended timeout for duplicate rounding scheme cleanup
Increased the database timeout from 30 seconds to 300 seconds (5 minutes) when removing duplicate rounding scheme records. This prevents timeout errors in stores with large rounding scheme datasets during import operations.
-
Bug Fix
Settings migration duplicate key error eliminated
Fixed a database conflict that occurred when two instances of Margin Master started at exactly the same time. Previously, both instances would attempt to migrate the same settings data simultaneously, causing a duplicate key error on the unique ApplicationSettings index. The migration process now gracefully handles this scenario by detecting and ignoring duplicate key violations, allowing both instances to continue startup normally.
-
Bug Fix
Settings migration duplicate key error handling
Added error handling to catch and safely ignore duplicate key exceptions during settings migration (SettingsOptions, PersistentValues, and ConnectionSettings). This prevents crashes when multiple Margin Master instances start at the same time and attempt to migrate the same settings concurrently. The migration process now logs these duplicate key situations and continues normally.
-
Bug Fix
Statistics dialog now works with large datasets
The Statistics button now works instantly even for stores with tens of thousands of SKUs, without freezing or crashing.
-
Bug Fix
Installer crash when canceling retry operation
The installer no longer crashes if you close it while it's retrying a download.
-
Bug Fix
Submit Issue dialog crash resolved
If you previously encountered an error when trying to submit a support issue, this should now work without problems.
-
Bug Fix
Submit Issue crash resolved
The Submit Issue feature will now work reliably even on systems with restricted Windows management permissions or limited WMI access.
-
Bug Fix
Fixed SQL syntax error in future price cleanup
Corrected a SQL syntax error in the "Remove CP Equals FP All" operation where ISNULL function was missing its required second parameter. This would have caused the operation to fail with a database error.
-
Bug Fix
Installation script preload handles missing blob paths
The Support Tools screen will no longer crash when downloading installation scripts if some script records are incomplete.
-
Bug Fix
Extended database operation timeout to prevent failures on large queries
Database commands now use a 10-minute (600 second) timeout by default instead of SQL Server's 30-second default. This prevents timeout errors when processing large imports, generating complex reports, or performing bulk pricing updates that legitimately take longer to complete.
-
Bug Fix
Increased database operation timeout to prevent failures
The timeout for database operations has been raised from 30 seconds to 600 seconds (10 minutes). This prevents timeout errors during long-running operations such as large imports, complex pricing analysis calculations, or database maintenance tasks.
-
Bug Fix
Loading overlay now dismisses before error dialogs
If a database restore fails, you'll now see the error message immediately instead of the app appearing to freeze.
-
Bug Fix
Restore crash with pre-metadata backup files
You can now restore older database backup files without the application crashing during the restore process.
-
Bug Fix
Diagnostic Tool launch failure resolved
The Diagnostic Tool will no longer crash when launched for the first time or if log files have been cleaned up.
-
Bug Fix
Corrected assembly version binding in build pipeline
Build 2026.625.23688 introduced an assembly version override that propagated to MarginMaster.Common (which is pinned to version 1.0.0.0). This created a version mismatch where the main executable expected Common@20.26.625.23688 but the shipped library remained at 1.0.0.0, causing a FileNotFoundException during application startup before logging or auto-update could run. The build pipeline now only stamps FileVersion (used for dashboard reporting) while preserving AssemblyVersion stability to prevent binding failures.
-
Bug Fix
Condition list now refreshes immediately after editing
When you add or remove values from a pricing strategy condition, the condition list now updates immediately on screen instead of appearing unchanged until you close and reopen the editor.
-
Bug Fix
Restored missing custom selection box views after startup timeout
Your saved custom selection box views (like "ACE SELECTION BOXES") will now appear correctly in the selection box editor and remain active when running pricing strategies.
-
Bug Fix
Fixed crash when applying pricing strategies with invalid price or margin values
Pricing strategies with missing or invalid price/margin values now show a helpful error message instead of crashing.
-
Bug Fix
Improved handling of missing database columns
Modified SQL query error handling to immediately stop retrying when encountering "Invalid column name" errors (SQL error 207), treating them as permanent structural issues rather than transient failures. Previously, the system would exhaust all 3 retry attempts before logging the error, causing unnecessary delays and error log noise.
-
Bug Fix
SQL timeout logging restored to error level
Reverted a change that logged SQL timeouts as warnings instead of errors. Timeouts indicate the operation did not complete successfully and must remain visible as errors in diagnostic logs for proper troubleshooting.
-
Bug Fix
Added guard against empty store numbers during import
Imports will no longer fail if some records are missing store number information—they'll be safely skipped instead.
-
Bug Fix
License dialog cross-thread crash resolved
Fixed an error that could cause Margin Master to crash when checking your license at startup.
-
Bug Fix
License validation dialog cross-thread exception
Margin Master will no longer crash when showing license error messages during startup.
-
Bug Fix
Fixed zero on-hand counts for Epicor stores in statistics
Epicor stores now see accurate on-hand inventory counts in the Statistics dialog.
-
Bug Fix
Unresponsive close button in installer
The X button now always closes the installer window, even when showing an error or "already installed" message.
-
Bug Fix
Prevented crashes when checking SQL Server backup folder permissions
Added permission check before querying SQL Server service account information. Previously, on systems where the database user lacked VIEW SERVER STATE permission, the application would crash with a SqlException when attempting to configure backup folder access.
-
Bug Fix
ZIP extraction errors are now properly reported
When a backup ZIP file is corrupted or can't be extracted, you'll now see a clear error message explaining what went wrong.
-
Bug Fix
Strategy execution errors due to missing fields
Strategy execution will no longer fail with "missing field" errors after the application falls back to default views.
-
Bug Fix
Fixed duplicate column name error when exporting to Excel
Exporting reports to Excel no longer fails when column names are duplicated.
-
Bug Fix
One-Click screen no longer crashes with null inventory values
Fixed a crash that could occur on the One-Click screen when filtering items with missing On Hand or sales history data.
-
Bug Fix
Fixed startup crash when importing POS data
Moved the creation of the IsNotFound column on StoreManagerInfo table to run earlier in the startup sequence, before the store reconciliation process attempts to reference it. This prevents crashes during POS data import operations that occur immediately after application launch.
-
Bug Fix
SQL Server 2022 permission model now supported
The backup folder access check now recognizes SQL Server 2022's new VIEW SERVER PERFORMANCE STATE permission in addition to the older VIEW SERVER STATE permission. This ensures the feature works correctly on newer SQL Server versions where Microsoft split the permission into two separate grants.
-
Bug Fix
All early-exit error paths now clear loading state
Fixed multiple code paths in the restore process (cloud download failures, missing backup file) that could show error dialogs while the loading overlay was still active. All error conditions now properly dismiss the loading overlay before displaying error messages.
-
Bug Fix
Fixed crash during application startup migration
Corrected a duplicate key error that could occur during the automatic migration of persistent settings when upgrading the application. The migration process now properly tracks already-migrated settings to prevent conflicts.
-
Bug Fix
Future Price rules validate margin values before saving
Fixed an issue where saving a Future Price rule with an empty margin value could create invalid pricing strategies.
-
Bug Fix
Fixed crash when running pricing strategies at startup
Ensured the SkuExceptions table is created during startup initialization, before pricing strategies execute. Previously, strategies could attempt to query this table before it existed, causing startup failures.
-
Bug Fix
Fixed crash when parsing pricing strategy rules with duplicate parameters
Resolved an ArgumentException that occurred when pricing strategy rules contained duplicate parameter keys (e.g., multiple rounding specifications). The parser now handles duplicates by using the first occurrence.
-
Bug Fix
Fixed crash in MySQL Compass store mapping lookup
Corrected an InvalidOperationException in the MySQL Compass import process when the EpicorUseStoreMapping configuration was missing. The lookup now safely handles missing configuration values.
-
Cloud Sync
Resilient cloud sync bulk upsert operations
Cloud sync is now more reliable when handling large amounts of data, automatically recovering from temporary database busy conditions.
-
User Interface
Modern frameless bootstrapper design
The Margin Master installer now has a sleeker, more modern appearance with a green header and rounded window edges.
-
User Interface
Modern bootstrapper design with green header bar
Redesigned the bootstrapper window with a modern appearance featuring a green header bar with drag-to-move capability, rounded corners, drop shadow, and a borderless design. The window now matches the visual style of the main Margin Master application.
-
User Interface
Connection test resets availability cache
Successfully testing the MySQL connection in Tools > Options now resets the availability cache, allowing the system to resume querying MySQL directly for store and inventory data in the Import Manager.
-
User Interface
Real-time statistics updates
The statistics screen stays responsive when changing filter options, even with large product catalogs.
-
User Interface
Enhanced download progress display
You can now see how much time remains during download, and clicking the X button will cancel the download in progress.
-
Database
Added table existence validation
Both BackupCostBreaksAsync and RestoreCostBreaksAsync methods now query for table existence using SQL Server's OBJECT_ID function and skip the operation if the table is not present, returning an empty list or exiting early respectively.
-
Database
Improved error classification and logging
Refined error logging to distinguish between transient errors (which are retried and logged as warnings if they persist), permission-denied errors (logged as warnings for best-effort operations), and genuine SQL errors (logged as errors). This reduces log noise from temporary issues that resolve themselves while maintaining visibility into real problems that require attention.
-
Architecture
SQL-based statistics calculation
Statistics calculations are now faster and more responsive, particularly when analyzing large product selections.
-
Architecture
Improved database read performance under load
Eliminated application-level locking (semaphore) from all read-only GlobalFileConfig operations. SQL Server's native concurrency controls are sufficient for SELECT queries — only write operations (INSERT/UPDATE/DELETE) require application-level coordination. This prevents slow reads on SQL Express instances from blocking other operations throughout the application, improving responsiveness during startup and normal operation.
-
Architecture
Lazy initialization for auto-update service
Moved database-dependent initialization in AutoUpdateService from the constructor to a deferred EnsureInitialized() method that runs on first use. This prevents database queries during dependency injection resolution, allowing the application to start and display configuration dialogs even when the database is unreachable.
-
Architecture
Separated save logic from dialog close handling
Extracted the column view save logic into a new CommitSave() method that returns success/failure without attempting to close the dialog. This allows the same save logic to be used both during explicit saves (which should close the dialog) and during close-with-prompt scenarios (where WPF is already handling the close).
-
Infrastructure
Automatic retry logic for transient SQL errors
When the database is temporarily busy or the network connection hiccups, the app now automatically tries again instead of immediately showing an error.
-
Infrastructure
Improved error logging for database timeouts
Removed special handling that was downgrading SQL timeout errors to warnings. All database errors are now consistently logged at the Error level, making it easier to diagnose issues. The previous approach was masking real timeout problems that needed to be fixed at their source.
-
Infrastructure
Removed System.Management dependency
Eliminated the System.Management package reference from both the Common library and main application, reducing the application's dependency footprint and avoiding potential deployment issues with this library.
-
Infrastructure
Removed System.Management dependency
Eliminated the System.Management package dependency from both the Common and UI projects, reducing the application's attack surface and removing a potential source of deployment issues on locked-down systems.
-
Infrastructure
Restored stable assembly binding behavior
Removed the global AssemblyVersion property override from the publish workflow while retaining FileVersion and InformationalVersion stamping. This ensures the version reported to the dashboard (OrganizationComputers.MMVersion) remains accurate while preventing CLR binding failures that cause startup crashes.
Infrastructure & Internal
-
Improvement
One-click restart installs latest version
When you click "Restart to Update," the app now checks one final time for the newest version and installs it automatically—you no longer need to download updates multiple times if new versions are published quickly.
-
Bug Fix
SQL backup fails when metadata contains apostrophes
Database backups will no longer fail if your store name or other settings contain apostrophes (like "Joe's Hardware").
-
Bug Fix
Fixed SQL datetime overflow error in timeout tracking
SqlTimeouts records loaded from the database with NULL dates now initialize to the current UTC time instead of DateTime.MinValue, preventing "SqlDateTime overflow" errors when updating timeout records.
-
Bug Fix
Automatic publish flag reset after deployment
After each software update is deployed, the system now automatically makes it available to all stores without requiring manual intervention from the support team.
-
Bug Fix
Prevent rebuild loops during concurrent sync and import operations
Fixed an issue where concurrent sync or import operations could re-add rebuild requests to the processing queue while a rebuild was already in progress, causing the system to rebuild multiple times unnecessarily. The system now defers any rebuild requests that arrive during processing and schedules them for the next processing cycle instead.
-
Bug Fix
Crash when saving new SKU-level exceptions
The SKU Exceptions screen will no longer crash when saving a new exception in certain scenarios.
-
Bug Fix
Eliminated settings migration crash on concurrent startup
If two people open Margin Master at the exact same time, both will now start successfully without errors.
-
Bug Fix
DIB catalog items now populate all price levels correctly
Adding items from the Do-It-Best catalog will now immediately show all five price levels in the pricing grid without needing to wait for a rebuild.
-
Bug Fix
Logging error when cost break value is null
Future pricing panel will no longer encounter errors when cost break values are empty.
-
Bug Fix
Fixed foreign key failures during schema updates
Schema migration now creates all missing tables first before adding foreign key constraints. Previously, if a parent table and child table with a foreign key relationship were both missing, the foreign key creation would fail because it ran before the parent table was created.
-
Bug Fix
Graceful fallback if latest version download fails
If downloading the newest version fails during restart, the app will still install the previously downloaded update instead of canceling.
-
Bug Fix
Database rename now uses accessible backup location
Database rename operations now work more reliably on systems with restricted SQL Server backup folder permissions.
-
User Interface
Quick Find SKU column now auto-sizes to content
When searching for items using Quick Find, the SKU column will now automatically adjust to show the full SKU number without being cut off.
-
User Interface
Progress indication during inline update download
If a newer update is found when you click restart, you'll see a progress bar showing the download of the latest version before the app restarts.
-
Infrastructure
Improved deployment reliability
Added a fail-safe mechanism that ensures the update availability flag is properly reset at the end of every publish run, regardless of whether the deployment succeeded, failed, or was cancelled. The step includes error handling and will continue even if the API call fails, preventing one failure from blocking future deployments.
Other Changes
-
New Feature
Restore Backup button added to startup Database Setup window
If Margin Master can't find your database at startup, you can now click "Restore Backup" to load a saved backup file directly from the setup screen.
-
New Feature
Multi-monitor detection and display information service
Added comprehensive display detection that identifies all connected monitors, their resolutions, DPI scaling factors, and physical arrangement (left/right/above/below primary). The system properly handles high-DPI displays and accounts for taskbar positions when calculating available screen space.
-
New Feature
Display configuration detection service
Added a new service that detects monitor count, resolution, DPI scaling, working area (accounting for taskbars), and multi-monitor arrangement. This service automatically refreshes when monitors are connected or disconnected and provides DPI-aware sizing calculations for proper window placement on high-DPI displays.
-
New Feature
Issue Contact editor dialog
Click Help > Support Issues > Issue Contact to update the name, email, and phone number that will be used when you submit support issues.
-
New Feature
Submit Issue tool added to Database Setup window
If you encounter an error during setup, click the "Report this issue" link to quickly submit details to support without needing to complete database setup first.
-
New Feature
Submit Issue from Database Setup window
If you encounter an error while setting up your database connection, you can now click "Report this issue" to send details directly to support without completing the setup.
-
New Feature
Item-level backup selection with tree view dialog
When backing up or restoring, you can now expand categories like "Pricing Strategies" to select only the specific strategies you want, instead of including everything in that category.
-
New Feature
V3 backup format with comprehensive configuration coverage
Extended backup system to include cost breaks, min/max strategies, minimum margins, selection box views, column views, custom field names, custom sort orders, and store match-ups. These were previously scattered across GlobalFileConfig entries and are now organized into discrete, strongly-typed sections. Format version incremented to 3 with automatic backward compatibility for V1 and V2 formats.
-
New Feature
SQL script support in Installation Scripts dialog
Added a new script type system that distinguishes between PowerShell scripts (executable) and SQL scripts (clipboard-only). The dialog now dynamically shows either "Execute Script" or "Copy to Clipboard" buttons depending on the selected script type, preventing accidental automated execution of SQL commands.
-
New Feature
Software installation detection
The diagnostic assistant can now see what database and development software is installed on your computer to give better troubleshooting help.
-
New Feature
Installed software inspection
Added `get_installed_software` tool that reads Windows Registry to identify installed SQL Server instances, ODBC drivers (SQL Server, MySQL, PostgreSQL), and .NET Framework versions. The AI can now diagnose issues related to missing database drivers or SQL Server connectivity problems by checking what's actually installed on the machine.
-
New Feature
AI-assisted SQL Server 2025 Express upgrades
Ask the AI assistant to check your SQL Server version — it can upgrade you to SQL Server 2025 automatically, walking you through each step and handling any installation issues.
-
New Feature
Network scanning for MySQL servers
Click the search button next to the Server field to automatically find MySQL servers on your network.
-
New Feature
Idle auto-trigger with 10-second countdown
If you leave the update notification open for 30 minutes, it will count down from 10 seconds and then install the update automatically. Click Cancel during the countdown to wait another hour.
-
New Feature
Quick Issue Submission dialog
Support staff can now capture diagnostic files quickly through a streamlined form in the Support Issues window, with real-time progress updates during upload.
-
New Feature
Unified Store Manager window
Click "Open Store Manager" in Settings > Connections to manage all store mappings in one place. The grid shows your POS stores, vendor store numbers, zones, and import settings. For Epicor systems, store characters are displayed as "W (87)" format.
-
New Feature
Store Manager screen
Open Store Manager from Settings → Connections to view all stores, edit vendor store numbers and zones, enable/disable stores for import, and refresh store data from your POS system.
-
New Feature
SQL Server edition detection
When setting up your database, Margin Master now shows which version of SQL Server you're using (like "Express" or "Standard") and gives helpful advice based on that version.
-
New Feature
System Diagnostics window
A new System Diagnostics tool is now available under File > Utilities. This window shows you a complete overview of your system's health—database connection, license status, disk space, and recent errors—with one-click options to copy the information or send it to support for faster troubleshooting.
-
New Feature
System Diagnostics window
Click Support > System Diagnostics to view a complete overview of your Margin Master installation, including database status, license details, and recent errors.
-
New Feature
Prerequisites category in Installation Scripts dialog
Support staff will see a new Prerequisites section in the Installation Scripts dialog.
-
New Feature
Delete submitted issues
When viewing one of your previously submitted issues, you'll now see a "Delete Issue" button (in red) next to the "Update Issue" button. Clicking it will ask you to confirm, then permanently delete the issue from the system.
-
New Feature
Show all toggle for organization-wide backup viewing
Support technicians will see a new "Show all" checkbox next to the cloud scan button. Unchecking this box limits the backup list to only the current store, making it easier to find the right backup file.
-
New Feature
Store number display format options
In Settings → Connections, you can now choose how store numbers appear in dropdown lists. For example, you can display "1715 (00042)" instead of "00042 (1715)" if you prefer to see the POS store number first.
-
New Feature
Window placement persistence across sessions
When you close Margin Master, it remembers your window size, position, and which monitor you were using. The next time you open it, the window appears exactly where you left it—even if you have multiple monitors.
-
New Feature
Window placement persistence
The main window will now reopen at the same size and position where you left it, even on multi-monitor setups.
-
New Feature
Added OLEDB 12.0 installer script for RockSolid POS support
If you're setting up a new workstation for RockSolid POS data import, you can now install the required OLEDB driver directly from the Support Scripts menu instead of downloading it manually.
-
New Feature
Demo Database download added to Database Setup window
Click "Demo Database" to download sample data and explore Margin Master before connecting to your store's database. The demo database will be automatically selected once downloaded.
-
New Feature
Demo Database download from Database Setup window
You can now download a demo version of Margin Master directly from the connection screen to explore the software before setting up your store's data.
-
New Feature
Support issue reopen capability
You can now reopen support issues that were previously marked as resolved by clicking the "Reopen Issue" button in the Support Tools screen.
-
New Feature
V3 backup format with comprehensive configuration coverage
Backups now capture all pricing rules and view settings, including cost breaks, min/max strategies, and custom column layouts that were previously incomplete.
-
New Feature
Backup history browser for cloud restore
When restoring from the cloud, you can now see all your saved backups and choose which one to restore, rather than only getting the latest version.
-
New Feature
Database creation script with clipboard workflow
Support staff can now access the complete database creation script directly from the Support Tools menu, useful for troubleshooting or manual server setups.
-
New Feature
Windows Package Manager integration
The diagnostic tool can now help you install missing software like SQL Server automatically using Windows Package Manager.
-
New Feature
Windows Package Manager (winget) integration
Added `run_winget` tool allowing the AI assistant to execute winget commands (list, search, show) to check for available software updates or search for specific packages. This enables the AI to suggest installing missing dependencies or checking software versions through Windows Package Manager.
-
New Feature
AI-assisted SSMS installation and upgrades
The AI assistant can install or upgrade SQL Server Management Studio for you — just ask it to check your SSMS version.
-
New Feature
Zone editing popup for Ace/EJ stores
Click the "Edit" button in the Zone column to change a store's zone. You can override the Ace-assigned zone or clear your override to use the original assignment.
-
New Feature
Start SQL Server Service button
If SQL Server is installed but not running, you can now start it with one click directly from the database setup screen.
-
New Feature
Optional SSMS installation and upgrade during setup
If you don't have SQL Server Management Studio installed (or have an old version), Margin Master will now detect this and offer to install or upgrade it for you with a single click.
-
New Feature
Detect existing installation and offer launch or reinstall
If Margin Master is already installed, the installer will let you choose to launch it or reinstall a fresh copy. Reinstalling will automatically close Margin Master if it's running.
-
New Feature
Install .NET 10 Desktop Runtime script
When a workstation can't launch Margin Master due to missing .NET, support staff can run this script to automatically download and install the required runtime instead of doing it manually.
-
New Feature
Add support representatives to contact list
You can now add Margin Master support staff to your contact list using the "Add Support Representative" button.
-
New Feature
Save button for editing existing contacts
Added a Save button under Contact Details that allows you to update existing store contacts (name, email, phone). Previously, you could only create new contacts or delete existing ones. The save function works for both new contacts being created and existing contacts being modified, and all contact fields now refresh immediately after saving.
-
New Feature
Store number sorting preference
You can now sort the store number list by either vendor store numbers or POS store numbers, whichever makes more sense for your workflow.
-
New Feature
Cloud backup access prompt when store information unavailable
If you try to restore from cloud backup before connecting to a database, you'll now be asked to select your primary vendor and enter your store number so the system can find your backups.
-
New Feature
Cloud backup access without active database connection
You can now browse and restore cloud backups even if you don't have a database connected yet. If needed, you'll be asked to enter your vendor and store number once per session.
-
New Feature
AI-assisted Margin Master updates
The AI assistant can check for and install Margin Master updates — ask it to update the application and it will handle the process automatically.
-
New Feature
Configurable authentication and SSL options
If you see SSL or authentication errors, try selecting "SSL Disabled" or "Public Key Retrieval" from the Auth/SSL dropdown on the MySQL connection screen.
-
New Feature
What's New button in update dialog
Click "What's New in This Version" to see what changed in the update before deciding to install it.
-
New Feature
Store detail popup
Click the "Detail" button to view cloud sync information for a store, including whether it's open or closed and when it was last synced.
-
New Feature
SQL Server Management Studio (SSMS) detection and installation
Margin Master can now detect if SQL Server Management Studio is installed and help you install or upgrade it with guided progress tracking.
-
New Feature
Add support representatives as contacts
You can now add support representatives to your contact list using the "Add Support Representative" button.
-
New Feature
Backup inventory service for item enumeration
New BackupInventoryService queries the database before backup to build summary lists of pricing strategies (with step/group/exception counts), non-system rounding schemes, cost breaks, min/max strategies, selection box views, and column views. Powers the tree view population in the backup dialog and provides item-level filtering options.
-
New Feature
Auth/SSL dropdown for MySQL 8+ compatibility
A new Auth/SSL dropdown helps you connect to newer MySQL 8 servers that use different authentication methods.
-
New Feature
Troubleshooting panel for installation failures
If the installer encounters an error, you'll see options to retry, download directly, or contact support.
-
New Feature
Remove Issue action
Added ability to remove an issue from your local issue list via a new "Remove Issue" button in the action bar. This connects to the existing backend deletion API and removes the issue from both open and closed issue lists after confirmation.
-
New Feature
Delete draft issues
You can now delete a draft issue using the "Delete Issue" button on the review step when updating an issue.
-
Improvement
Streamlined issue status filtering
When viewing open issues in Support Tools, you'll see a simpler list focused on the most important status categories.
-
Improvement
Support scripts download from cloud storage
When you run a support script (like "Install SQL Express"), it now downloads the newest version from the cloud automatically, so you always get the latest bug fixes and improvements without needing to update Margin Master itself.
-
Improvement
Local attachment staging with removal support
After clicking the paperclip to attach a file, you'll see it listed in an amber-colored bar. You can remove any file by clicking the red X next to it before sending. Files are only uploaded when you click Send.
-
Improvement
Deferred attachment uploads in Support Tools
You can now add multiple attachments to a support ticket and remove any you don't want before clicking Send. Files appear in a yellow "Pending Attachments" section until you're ready to submit.
-
Improvement
Automatic file compression for issue attachments
Large files you attach to support requests are now automatically compressed before upload, reducing upload time and making submissions faster. You'll see a "Compressing..." message while this happens.
-
Improvement
Automatic compression for large file uploads
Large files you attach to support issues are now automatically compressed before upload, which speeds up the submission process and reduces bandwidth usage.
-
Improvement
Connection validation gate for database operations
The Create and Restore buttons are now grayed out until you successfully connect to a SQL Server. This ensures you can't accidentally try to create or restore a database on a server that isn't accessible.
-
Improvement
Bulk cost break model deletion script
If you've accumulated many cost break models (especially test models with names like "New Model 1", "New Model 2", etc.), your administrator can now use this script in SQL Server to delete multiple models at once. The script shows you what models exist and lets you delete them by pattern (like all models starting with "New") or by specific name. This is much faster than clicking through each model individually in the Cost Break View screen.
-
Improvement
Database backups always compressed with metadata
Every database backup is now automatically compressed to a ZIP file, reducing file size by approximately 70-80%.
-
Improvement
SQL Server service status diagnostics
Added Windows service checking to detect SQL Server installation and running status. When no servers are found during scanning or when a connection test fails, the system now examines SQL Server services (MSSQLSERVER and MSSQL$* instances) and provides one of three diagnostic messages: SQL Server is not installed (suggests installing SQL Server Express or connecting to a remote server), SQL Server is installed but the service is stopped (lists stopped services and suggests starting them from Windows Services), or SQL Server is running but unreachable (suggests verifying the server name matches the installed instance).
-
Improvement
SQL Server service status detection
When you can't connect to SQL Server, the window now tells you exactly what's wrong—whether SQL Server isn't installed, needs to be started, or has a different connection issue.
-
Improvement
Smart issue pill visibility based on installed version
If you're experiencing an issue that's been fixed in a newer version, the notification will remind you to update. After updating, the notification will automatically go away.
-
Improvement
Issue notification timing improved
Email notifications for new issues now include all your attached files and descriptions in the initial email, making it easier for support to see what you've sent.
-
Improvement
Intelligent SQL Server instance detection and selection
During initial setup, if you have both SQL Express and full SQL Server installed, the app will now automatically pick the right one that has your database.
-
Improvement
Intelligent instance auto-selection
If you have multiple SQL Server instances installed (like SQLEXPRESS and SQL2019), the setup wizard will now find and select the one with your MarginMaster databases automatically.
-
Improvement
Organization-wide cloud backup discovery
When you click "Scan Cloud Backups," the system now finds backup files from all your stores, not just the current one. A progress message shows which store is being scanned (e.g., "Scanning store ACE 12345 (2/5)...").
-
Improvement
Organization-wide cloud backup discovery
When you click "Scan Cloud Backups," the system now finds backups from all stores in your organization. You'll see a progress message showing which store is being scanned (e.g., "Scanning store ACE 12345 (3/8)..."). This makes it easier for multi-store operators to restore data from any of their locations.
-
Improvement
Automatic Visual C++ Redistributable installation
Both the Install-SQLExpress.ps1 and Upgrade-SQLExpress.ps1 scripts now include a new prerequisite verification step that checks for Visual C++ 2015-2022 x64 Redistributable v14.40 or newer (required by SQL Server 2025). If the installed version is older than 14.40 or missing entirely, the script automatically downloads the latest version from Microsoft's evergreen URL and installs it silently. This prevents SQL Server setup failures due to missing prerequisites.
-
Improvement
SQL Server default instance updated for first-time setup
If you're installing Margin Master for the first time, the database setup will now automatically find SQL Server Express without needing to change the server name.
-
Improvement
Auto-detect large sector NVMe drives during SQL Express installation
Install-SQLExpress.ps1 now checks the physical sector size of the target data drive before installation. If a 512e or 4Kn NVMe drive is detected (sector size > 4 KB), the script automatically enables trace flag 1800 and persists it as a SQL Server startup parameter. This prevents error 0x851A001A during setup, which previously required manual intervention or running the installer with special flags.
- Improvement Automatic large sector drive detection and workaround
-
Improvement
Batch processing for SKU-level exceptions
When running pricing strategies with many SKU exceptions, the system now processes all exceptions together in one operation rather than one at a time, dramatically reducing wait time.
-
Improvement
Extended timeout for open issues API call
Increased the timeout from 10 to 30 seconds when loading open issues in the background. The previous 10-second timeout was too aggressive for this non-critical feature, causing 43 timeouts across 18 stores over a 48-hour period.
-
Improvement
Extended timeout for open issues retrieval
The timeout for loading open issues from the cloud has been increased from 10 to 30 seconds to accommodate slower network connections and larger datasets. This should reduce timeout failures when the server takes longer to respond.
-
Improvement
Automatic multi-RSC detection
The system now automatically determines if your stores use multiple RSCs instead of requiring you to check a box in settings.
-
Improvement
Automatic multi-RSC detection
You no longer need to check or uncheck the "Multiple RSCs" option in Settings — Margin Master now automatically detects this from your store assignments.
-
Improvement
Local encrypted license cache for component keys
IPWorks and Z.EntityFramework component licenses (Z.Dapper.Plus and Z.BulkOperations) are now stored in a local encrypted cache after first fetch. On subsequent startups, licenses load from the cache first, falling back to the API only when the cache is empty or stale, and finally to appsettings.json as a last resort. This three-tier approach reduces startup time and API dependency while maintaining security.
-
Improvement
Connection settings persistence improved
When setting up FTP or MySQL connections, your entered values are now saved even if the test fails, so you only need to fix what's wrong and test again.
-
Improvement
Save connection settings before testing
When setting up FTP or MySQL Compass connections, your settings are now saved even if the test fails, so you only need to fix the incorrect field instead of re-entering everything.
-
Improvement
Multi-step connection diagnostics
When testing your MySQL connection, the system now automatically tries multiple approaches and tells you exactly which method worked, making it easier to diagnose connection problems.
-
Improvement
Manager API now coordinates auto-update checks
Update checks will succeed even if your store's firewall blocks access to Azure cloud storage, because the app now checks through the Manager API first.
-
Improvement
SQL Server version detection and validation
You'll now see which version of SQL Server you're connecting to, with a warning if your server is older than SQL Server 2022.
-
Improvement
Resume interrupted downloads automatically
If your download is interrupted, the installer will pick up where it left off instead of starting over.
-
Improvement
Enhanced update availability messaging
The update checker will now show you more helpful information, like "check back soon" if a new version is currently being prepared, rather than just saying you're up-to-date.
-
Improvement
Server-controlled status messages during update checks
When you check for updates, you may see specific messages explaining why updates aren't currently available, such as during scheduled maintenance or while a new version is being published.
-
Improvement
Bootstrapper no longer requires pre-installed .NET runtime
Installing Margin Master on a new computer no longer shows confusing prompts about downloading .NET — the installer just runs.
-
Improvement
Self-contained installer eliminates .NET runtime dependency
You can now run the Margin Master installer on any Windows computer without needing to install additional software first.
-
Improvement
Contact selection is now optional when submitting issues
You can now skip selecting a contact when submitting an issue by checking "Do not contact me about this issue."
-
Improvement
Optional contact information
You can now check "Do not contact me about this issue" if you don't want to be contacted about a submitted issue.
-
Improvement
Automatic retry for failed issue notifications
When submitting an issue from the Support Tools screen, if the notification to RetailerSoft fails to send, the system now automatically retries once after a 4-second delay before giving up.
-
Improvement
Automatic retry for issue submission notifications
Issue submissions are now more reliable with an automatic retry if the notification doesn't send on the first attempt.
-
Improvement
Enforce contact selection on issue submission
When creating a support issue, you'll now see a warning if you try to continue without selecting a contact. The Submit button won't be available until you've chosen someone from your store contacts or a support rep.
-
Improvement
Smart version mismatch handling
When opening a database that was last used with a newer version of Margin Master, the app will now try to update itself automatically before asking you whether to continue or quit. This prevents accidental data issues from running an outdated version.
-
Improvement
Intelligent view selection on database restore
When you open a restored customer database, Margin Master will now automatically use the customer's custom view if there's only one, instead of defaulting to the standard view and showing warnings.
-
Improvement
Smart view selection on database restore
When you restore a database backup that contains your custom column layout, the application will now automatically use that layout instead of switching to the default columns, so you don't have to manually reselect your preferred view.
-
Improvement
Database fallback for IPWorks component licenses
The license retrieval system now includes a four-tier fallback: memory cache, cloud API, local database (new), and appsettings.json. When licenses are successfully retrieved from the cloud, they're now persisted to the local database. If the cloud service is unavailable on subsequent launches, the application will use the database-stored licenses instead of falling back immediately to the build-time defaults.
-
Improvement
Descriptive backup file naming for support issues
Backup files created when you submit support issues now show your store's vendor, number, and name in the filename, making them easier to identify.
-
Improvement
Enhanced issue backup file naming
When you submit a support ticket that includes a database backup, the backup file now includes your store information in its name, helping the support team identify and prioritize your issue more quickly.
-
Improvement
Support machine cloud backup scope control
When restoring a database on a support machine, you'll now see only the current store's backups by default. Check the "Show all" box to see backups from all stores in your organization.
-
Improvement
Smart update installation
You no longer need to click the update badge twice if a new version is published while you're working — one click always gets you the latest version.
-
Improvement
Version tracking in license validation
The system now prevents you from accidentally opening an old version of Margin Master after you've upgraded to the latest version, avoiding potential data compatibility issues.
-
Improvement
Version detection fallback
Added a fallback mechanism for local development builds that don't have CI-generated version information. If the preferred version metadata isn't available, the app will still derive a valid version number from assembly information, maintaining compatibility with local development scenarios.
-
Improvement
Improved update restart safety logic
Renamed the internal flag from `updateFailed` to `skipAutoApply` to more accurately reflect its purpose. The flag now prevents auto-apply in both success and failure scenarios: successful updates are blocked from chaining into another immediate update, and failed updates won't retry the same broken installation automatically.
-
Improvement
Check server fallback flag before attempting blob upload
The upload process now checks the FallbackToIssueAttachments flag returned by the server's upload-target endpoint. When this flag is set, the system skips blob storage entirely and uses the legacy HTTP upload path immediately, avoiding unnecessary retry delays.
-
Improvement
Better error handling for attachment upload failures
File uploads will complete successfully more often, even when there are temporary connectivity issues or server configuration changes.
-
Improvement
Streamlined database recovery workflow
Restoring a backup during startup now takes you directly into Margin Master once the restore finishes—no extra steps needed.
-
Improvement
Enhanced Order Indicator dropdown display for Do-It-Best Epicor stores
When filtering by Order Indicator, the dropdown now shows the code letter first (like "T - Stock/Order Through"), making it faster to find the option you need.
-
Improvement
Remove button for attachments in local display
You can click the red X next to any attachment to remove it from your view (this doesn't delete the file from the support ticket).
-
Improvement
Remove attachment from display
You can now click the X button next to any attachment to remove it from your view of the conversation.
-
Improvement
Send button enabled for attachments-only submissions
You can now send attachments to a support ticket without typing a comment—just attach the files and click Send.
-
Improvement
Restore database dialog uses validated server credentials
The Restore Database dialog now receives the SQL Server name and authentication credentials that were already validated in the Database Setup window, instead of defaulting to localhost. This ensures the restore operation targets the correct server without requiring users to re-enter connection information.
-
Improvement
Single database backup per issue
If you submit a database backup with a support request, any previously attached backup will be automatically replaced with the new one, ensuring support staff always have your latest data.
-
Improvement
Single database backup enforcement
When submitting multiple database backups with an issue, only the most recent backup is kept to avoid confusion.
-
Improvement
Connection credentials passed to restore dialog
When launching the Restore Database dialog from the Database Setup window, the validated server name and SQL authentication credentials (if using SQL Server authentication) are now automatically passed through, eliminating the need to re-enter connection information.
-
Improvement
Increased minimum database timeout threshold
Raised the adaptive timeout minimum floor from 200ms to 500ms for lightweight database operations in CentralSemaphoreRepository. This provides more breathing room during startup when multiple operations compete for database access, reducing the likelihood of transient timeout failures.
-
Improvement
Warning dialog when custom views fail to load
If your custom view fails to load (rare), you'll now see a warning message explaining what happened and how to fix it by restarting the application. Your saved views are never lost.
-
Improvement
Direct condition manipulation
Removing condition values now happens instantly without needing to understand or edit the rule syntax manually.
-
Improvement
Enhanced download progress logging
Cloud backup downloads now log progress at 25%, 50%, 75%, and 100% completion milestones, making it easier to track long-running downloads in the application logs without flooding the log file with continuous updates.
-
Improvement
Automatic instance switching on Database Setup screen
If your MarginMaster database moved to a different SQL Server instance, the setup screen will now detect this and switch automatically.
-
Improvement
Smart instance switching on initial load
If your databases were moved to a different SQL Server instance, the setup screen will detect this and switch to the correct instance automatically.
-
Improvement
Enhanced prerequisite verification documentation
Both SQL installation markdown documents now include the Visual C++ verification as an explicit step in the "What It Does" section, and the troubleshooting tables include a row explaining the "Version 14.40 or newer" error message with instructions to re-run the script or install manually.
-
Improvement
Auto-detect large sector NVMe drives during SQL Express upgrade
Upgrade-SQLExpress.ps1 now queries sys.master_files to identify the drive hosting existing SQL data files and checks its physical sector size. If a large-sector drive is detected, the script automatically enables trace flag 1800 for the upgrade and persists it as a startup parameter. This prevents upgrade failures on systems with newer NVMe hardware.
- Improvement Removed obsolete trace flag 1800 logic from SQL Express scripts
-
Improvement
Real-time performance metrics for batch operations
The batch processing system now logs detailed performance metrics including total exceptions processed, SKUs affected, and processing mode ("Batch" vs. fallback). Strategy execution logs display the batch mode status and provide visibility into which approach was used.
-
Improvement
Enhanced error reporting during database setup
If database setup fails, you'll now see a clear explanation of what went wrong instead of a generic error message.
-
Improvement
Increased connection retry attempts for new databases
Increased retry attempts from 3 to 5 and retry delay from 500ms to 1000ms when connecting to newly-created databases. SQL Server Express sometimes requires additional time before accepting connections to databases created via master connection, and the longer retry window improves success rates on slower systems.
-
Improvement
Automatic license recovery on validation failure
When any component license (Z.Dapper.Plus, Z.BulkOperations, or IPWorks) fails validation during startup, the system now automatically invalidates the cached entry and attempts to refresh from the API. This ensures users aren't stuck with stale or corrupted license keys and reduces manual intervention needed for license issues.
-
Improvement
Automatic license refresh on validation failure
When a component license validation fails (e.g., due to expired or corrupted cache entry), the system automatically invalidates the cache and re-fetches fresh keys from the API. This self-healing mechanism ensures FTP/SFTP/ZIP operations and bulk database operations remain functional without manual intervention.
-
Improvement
Simplified issue status logic
Streamlined the logic that determines which support issues to display by removing the version comparison check. This makes the behavior more predictable and ensures stores always see the current status of their issues.
-
Improvement
Reduced issue polling frequency and automatic stop
The system now checks for support issue updates every 30 minutes instead of every 60 seconds, reducing unnecessary network traffic. Once all support issues are resolved or closed, the system automatically stops polling until the application is restarted, eliminating unnecessary background requests when no issues are open.
-
Improvement
Optimized issue polling behavior
Once your support issues are resolved, Margin Master will stop checking for updates automatically.
-
Improvement
Actionable error messages with fix instructions
Error messages now tell you exactly how to fix connection problems instead of just showing technical error codes.
-
Improvement
Multi-step connection testing with smart error messages
When a connection test fails, you'll now see specific instructions on how to fix the problem instead of technical error codes.
-
Improvement
View settings cleanup added to migration process
View-specific settings (grid layouts, column widths, etc.) that are now handled by a dedicated migration process are also marked for deletion from the legacy GlobalFileConfig table, preventing them from accumulating and slowing down future startups.
-
Improvement
Action buttons disabled during processing
Support issue action buttons are now properly disabled while an action is being processed, preventing duplicate submissions if the user clicks multiple times during the server request.
-
Improvement
Enhanced support ticket context
Support tickets now include 12 key data points about the user's environment (product version, operating system build, SQL Server edition and version, active database and server names, machine name, store configuration, vendor settings, and POS system type). This comprehensive snapshot enables faster troubleshooting and reduces back-and-forth communication.
-
Improvement
Shared server advisory banner
If you're connecting to a SQL Server that's shared with other programs, you'll now see a helpful reminder that Margin Master creates its own separate database and won't affect your other data.
-
Improvement
Database size monitoring with Express edition warnings
The diagnostics window now shows your database size with a visual progress bar and warns you if you're approaching the 10GB limit on SQL Server Express edition, so you can upgrade before running out of space.
-
Improvement
Enhanced database size tracking
The diagnostics window now warns you if your database is getting close to the 10GB limit for SQL Express, helping prevent database issues before they occur.
-
Improvement
Persistent retry tracking across restarts
If installation fails multiple times, you'll see helpful links to download directly or contact support, even if you close and reopen the installer.
-
Improvement
Faster installation experience
By removing the framework check parameter from the build process, the installer now runs more quickly and with fewer potential points of failure during deployment to retail stores.
-
Improvement
Improved license expiration error message
If you see a license expired error, the message now shows which store number failed and suggests checking if it's correct, making it easier to identify configuration issues.
-
Improvement
Store Manager auto-saves on window close
When you close the Store Manager window, your changes are now automatically saved—you don't need to click Save first.
-
Improvement
Reduced bootstrapper download size
Changed the bootstrapper executable from self-contained to framework-dependent deployment, reducing the initial download size from ~66MB to ~6MB. Users must have .NET Desktop Runtime installed, which is standard on modern Windows systems and is already required for the main application.
-
Improvement
Automatic duplicate contact removal
Duplicate contacts are now automatically removed from the contact list.
-
Improvement
Clearer messaging for missing contact
Changed the contact validation message from a Yes/No question to a direct warning that explains a contact is required and instructs users where to select one (Store Contacts tab or Support Rep dropdown). This eliminates confusion about whether contact selection is optional.
-
Improvement
Corrected log messages for SQL user creation
Fixed misleading log messages in the SQL user creation process. Success messages now correctly indicate "Created MarginMaster SQL user successfully" instead of suggesting it was already done. Failure messages now spell "SUCCESSFUL" correctly and provide clearer context about permission requirements.
-
Improvement
Automatic filename sanitization for backup files
Special characters and spaces in store names, vendor names, and POS system identifiers are automatically cleaned up and replaced with underscores in backup filenames, ensuring compatibility across different operating systems and file storage systems while maintaining readability.
-
Improvement
Default cloud backup view restricted to current store
By default, only the current store's backups will be shown, making it faster to find the right file to restore.
-
Improvement
Refactored package directory resolution
Package directory resolution logic was extracted into a shared GetPackagesDir() helper method to eliminate duplication between the logging and fallback recovery code paths.
-
Improvement
Enhanced update failure logging
Delta-patch failures are now logged as warnings with clearer messaging ("Delta update patch failed — retrying with the full package") rather than errors, making it easier to distinguish between recoverable update issues and genuine failures that require user intervention.
-
Improvement
Confirmation prompt before removing stores from MySQL
Store Manager now asks for confirmation and shows you exactly which stores will be removed before making any changes.
-
Improvement
Store Manager now displays warnings when cloud save fails
You'll now see a clear warning message if your store changes can't be sent to the cloud, and the changes will remain pending so you can retry.
-
Improvement
Enhanced audit trail for store configuration
Changes to store settings can now be traced back to the specific computer that submitted them, making it easier to troubleshoot configuration issues when multiple users manage store setups across different workstations.
-
Improvement
Settings sections disabled until feature is enabled
All vendor sync schedules, POS import schedules, service installation controls, and run history are now wrapped in an enabled/disabled state that reflects the BackgroundServiceFeatureEnabled database flag. This prevents configuration of a feature that isn't active on the current machine while keeping the tab accessible for viewing status.
-
Improvement
Clear error messaging for oversized file uploads
Error messages for failed uploads now clearly explain that your file was too large and couldn't be uploaded, instead of showing confusing technical errors.
-
Improvement
Splash screen positioning on correct monitor
The loading screen now appears on the same monitor where you last had Margin Master open, instead of appearing between monitors.
-
Improvement
Multi-monitor splash screen placement
The startup splash screen now appears on the correct monitor instead of spanning across multiple displays.
-
Improvement
Added session-based password authentication
After entering the support password once, you won't be asked for it again until you restart Margin Master.
-
Improvement
Duplicate attachment filename detection
If you try to attach a file with the same name as one already uploaded, you'll see a warning and the upload will be stopped.
-
Improvement
Duplicate attachment prevention
If you try to attach a file that's already been added to the issue, you'll see a warning message and the duplicate won't be uploaded.
-
Improvement
Send button now processes text and files together
You can now send attachments without typing a message, and the Send button shows upload progress when transmitting files.
-
Improvement
Simplified Database Setup validation
Connecting to an existing database is now faster — you don't need to re-enter store information if it's already saved in the database.
-
Improvement
Increased timeout for store number updates
Store number updates will no longer fail with timeout errors on large pricing databases.
-
Improvement
Added retry logic for view loading
If your saved views don't load immediately at startup, Margin Master will now automatically try again after a brief pause to make sure they're loaded correctly.
-
Improvement
Enhanced SQL restore progress tracking
The restore process now subscribes to SQL Server InfoMessage events to capture and log STATS restore progress messages, providing detailed visibility into the SQL restore phase in both the UI and log files.
-
Improvement
Optimized UI responsiveness during cloud operations
Replaced blocking Dispatcher.Invoke calls with BeginInvoke throughout the cloud backup scanning and download process, preventing UI freezes when loading cloud backup lists or downloading large files.
-
Improvement
Enhanced connection test error reporting
Connection test failures now trigger service diagnostics to supplement standard SQL error codes. Instead of only showing generic connection errors, the system combines SQL error information with service status to provide contextual guidance. For example, a connection timeout now differentiates between "service not running" versus "service running but not responding."
-
Improvement
Detailed connection failure messages
Error messages now tell you exactly which SQL Server service needs attention, including its current status like "Stopped" or "Paused."
-
Improvement
Automatic V1/V2 to V3 conversion during restore
Old backup files automatically convert to the new format when restoring, so you can still use backups created with previous versions.
-
Improvement
Enhanced scanning progress messages
You'll now see which store is being scanned and how many stores remain when searching for cloud backups across your organization.
-
Improvement
Network-aware error messages
Network errors (HttpRequestException, TaskCanceledException) now show a user-friendly message about checking internet connection, while other errors display a generic retry prompt. This helps users quickly identify whether the issue is local connectivity or a server-side problem.
-
Improvement
Enhanced error messaging and troubleshooting
The installation and upgrade documentation now includes troubleshooting guidance for Visual C++ prerequisite errors, explaining that the script handles this automatically and providing the manual download URL (https://aka.ms/vs/17/release/vc_redist.x64.exe) as a fallback. The script also handles multiple exit codes from the VC++ installer, including graceful handling when a newer version is already installed (exit code 1638).
-
Improvement
Manual override for large sector fix
Both scripts now accept a `-LargeSectorFix` parameter to force trace flag 1800 manually if auto-detection fails or if the user knows the drive requires special handling. The parameter is documented in usage examples and parameter tables.
-
Improvement
Backup query now includes cost break configuration
Added COSTBREAKVIEW section to the GlobalFileConfig backup query and excluded it from the catch-all configuration backup to prevent duplicate data. This ensures cost breaks are captured once with full detail rather than being missed or duplicated.
-
Improvement
Six automatic backup trigger points
The system now automatically backs up your pricing strategy whenever you make important changes, including when opening the program, saving strategies, updating rounding rules, or changing column layouts.
-
Improvement
Expanded AI system knowledge
Updated the AI assistant's system prompt to include SQL Server installation and configuration troubleshooting, SSMS usage, and general Windows IT support scenarios. This broadens the assistant's ability to help with database connectivity issues and environment setup problems.
-
Improvement
Database schema inspection
Added `get_table_schema` tool that queries INFORMATION_SCHEMA to retrieve column definitions, data types, and nullability for any table. This helps the AI understand database structure when diagnosing data-related issues or writing diagnostic SQL queries.
-
Improvement
Epicor char-based store handling
Enhances Epicor INDecoded and MySQL Compass store handling by storing both the character string (PosStoreNumber) and its Unicode ordinal value (PosStoreCharOrdinal) for all 256 possible byte values, including non-printable characters. Uses PosStoreCharHelper.ToDisplayLabel() for consistent "W (87)" style display throughout the UI. EpicorFTPFileExtractorService now sources store conversions and exclusions from StoreManagerInfo when UseStoreManagerInfo is enabled, falling back to legacy sources otherwise.
-
Improvement
Better SQL Server instance scanning and version detection
Enhanced SqlServerScannerService to query and display SQL Server product version strings (e.g., "16.0.1000.6") for each detected instance. Version information is now shown in server dropdowns and used to generate version warnings. Added GetServerVersion method that connects to each instance's master database to retrieve SERVERPROPERTY('ProductVersion'). Updated SqlServerInstance.DisplayName to include version labels with year mappings (e.g., "— SQL 2022 v16.x").
-
Improvement
Enhanced version warnings
SQL Server version warnings in the Database Setup Window are now edition-aware. When connecting to an older Standard/Enterprise server, the warning suggests contacting your IT administrator before upgrading a shared server. When connecting to Express edition, it recommends upgrading to SQL Server 2022 Express (a free upgrade) from microsoft.com.
-
Improvement
Expanded debug startup profiles to 18 scenarios
Extended the debug startup profile system from 14 to 18 scenarios, adding support for SSMS detection states (NotInstalled, NeedsUpgrade) and reconnection workflows with local SQL instances available. New profiles include "First DB — SSMS Missing", "First DB — SSMS Needs Upgrade", "Reconnect — Local SQL Available", and "DB Gone — Local SQL Ready". The debug chooser window now displays a fourth scenario row showing SSMS state, and appsettings.Development.json supports SsmsScenario configuration.
-
Improvement
Local SQL Server instance detection in diagnostics
The diagnostics window shows which versions of SQL Server are installed on your computer and whether SQL Server Management Studio needs to be installed or updated.
-
Improvement
Enhanced license validation context messaging
If your license needs attention, the store configuration screen now clearly explains what went wrong and what you need to do.
-
Improvement
Consolidated RSC code lookup logic
Created a unified helper method (LookupCloudRsc) that centralizes the logic for finding RSC codes from cloud data, eliminating duplicate code and ensuring consistent behavior across different parts of the Store Manager.
-
Improvement
Simplified message compose area
Replaced the pill-shaped chat input box with a standard labeled text area titled "Messages" (renamed from "Conversation"), providing a more conventional and accessible interface for composing support messages.
-
Improvement
Simplified sender name display
Message senders now show cleaner names without extra labels like "(Support)" or "(User)".
-
Improvement
Detailed change summary after MySQL store refresh
After refreshing stores from MySQL, you'll now see a summary showing exactly what changed (how many stores were added, updated, or removed).
-
Improvement
Simplified combo box configurations
Removed redundant AutoComplete, IncrementalFiltering, ImmediatePopup, and IsTextEditable properties from multiple combo boxes across Database Create, Do-It-Best options, Export options, Miscellaneous options, and Store Information views to simplify XAML and rely on default DevExpress control behavior.
-
Improvement
Enhanced script execution logging
After running a script, you can click "View Log" to see the full output or "Send to Support" to share the log file for troubleshooting.
-
Improvement
Smart sender labels with role identification
All support conversation messages now display formatted sender labels that combine the user's name with their role (e.g., "Brad Green (Support)" or "John Smith (User)"). If a name is missing or appears as a GUID, the system displays generic labels like "Support (Support)" or "User (User)" to ensure clarity. In thread view, sender initials are extracted and displayed in the avatar circle (e.g., "BG" for Brad Green).
-
Improvement
Demo Mode supports startup workflow
DemoModeViewModel now supports a startup mode (IsStartupMode) that accepts an override server name and returns the restored database name to the caller instead of triggering an automatic connection change. When opened from DatabaseSetupWindow, the demo database is restored and the setup form refreshes to display it in the database list.
- Improvement Obsolete large sector parameter removed
- Improvement Install and upgrade scripts now check hardware compatibility before downloading
-
Improvement
Enhanced SQL Server instance analysis
The `get_sql_instances_detail` tool provides comprehensive analysis of each SQL Server instance including version, year, database list, upgrade eligibility, and recommended action (upgrade vs. new instance). The tool identifies instances with mixed databases (MarginMaster + other apps) and blocks in-place upgrades to prevent data loss for other applications.
-
Improvement
Zone assignment workflow
For Ace and Emery Jensen stores, zones can now be viewed and overridden directly in the Store Manager grid or via the zone edit button, with clear indication of Ace-assigned vs. overridden zones.
-
Improvement
First-run welcome experience
New users now see a personalized welcome message when setting up Margin Master for the first time.
-
Improvement
SQL service diagnostics and startup flow error handling
Improved detection and display of SQL Server Windows service status during database setup. Enhanced CheckSqlServerServicesAsync to provide detailed diagnostics. Added TryStartWindowsServiceAsync method to programmatically start stopped SQL services with timeout handling. Changed startup flow to throw OperationCanceledException instead of generic Exception when users cancel database selection, improving error handling clarity.
-
Improvement
Pre-fill support for issue submission dialog
Enhanced SubmitIssueViewModel with PreFillTitle and PreFillDescription properties that override default title generation and pre-populate the description field when set before InitializeAsync. This enables the System Diagnostics window (and other tools) to open the support form with context-specific information already filled in, streamlining the support workflow.
-
Improvement
Expanded debug startup profiles for SSMS scenarios
Internal testing improvements — no user-facing impact.
-
Improvement
Enhanced installer launch diagnostics
Added detailed logging around the installer launch process, including process ID on success and specific Win32 error codes on failure. This improves troubleshooting capability when users report installation issues.
-
Improvement
Smoother UI updates during restore
Replaced blocking UI calls (Dispatcher.Invoke) with non-blocking calls (BeginInvoke) throughout the restore process, preventing UI freezes during cloud backup scanning and downloading.
-
Improvement
Better state management for download operations
Added caller-controlled loading state management to the download process, allowing the restore operation to maintain proper progress indicator visibility throughout the entire download-and-restore workflow.
-
Improvement
Discrete section extraction from GlobalFileConfig
V3 format separates previously lumped GlobalFileConfig entries into discrete sections: SelectionBoxViews (FIELDVIEW entries grouped by name), ColumnViews (SETTINGS/VIEWS and VIEWMANAGER entries), CustomFieldNames (VIEWMANAGER/NAMEMAPPINGS/USER), CustomSortOrders (PresetSortSequence entries), and StoreMatchUps (SETTINGS/STOREMATCHUP). Makes section-level and item-level restore filtering possible.
-
Improvement
Database schema inspection
Added get_table_schema tool allowing the AI to query and display the column structure of any database table, enabling more precise SQL troubleshooting and data investigation.
-
Improvement
PowerShell 7 preferred for script execution
The PowerShell engine now prefers PowerShell 7 (pwsh.exe) over Windows PowerShell 5.1 to avoid CLIXML-serialized progress records polluting captured output. Falls back to powershell.exe when PowerShell 7 is not installed.
-
Improvement
Epicor char-based store handling
Stores both PosStoreNumber (single char as string) and PosStoreCharOrdinal (Unicode ordinal 0-255) for Epicor INDecoded and MySQL Compass systems, ensuring unambiguous round-trip of all byte values including non-printable characters. PosStoreCharHelper.ToDisplayLabel() formats as "W (87)" for grid display. EpicorFTPFileExtractorService updated to read from StoreManagerInfo when UseStoreManagerInfo flag is true, extracting exclusions and store conversions.
-
Improvement
Move migration to automatic startup
Store data migration happens automatically in the background on first launch after update.
-
Improvement
Prevented silent server switching on reconnect
Auto-switching to a different SQL Server instance (when the selected one has no MarginMaster databases) now only occurs during first-run setup. When reconnecting after a connection failure, the application no longer silently redirects to a different server, avoiding user confusion.
-
Improvement
Installation diagnostic logging
The installer now logs detailed diagnostic information to %TEMP%\MarginMaster-Setup.log, including download attempts, errors, registry lookups, and process termination steps. This log file helps support staff diagnose installation issues more quickly.
-
Improvement
Relaxed contact requirements for next step
Removed the requirement to have a contact selected with first name and email before proceeding to the issue details step, allowing users to move forward even without selecting a contact (especially when using the "Do not contact" option).
-
Improvement
Removed "Do not contact me" checkbox with warning flow
If you try to continue without selecting a contact, you'll now see a warning asking you to confirm this choice.
-
Improvement
Clearer sender labels in message timeline
Updated how message senders are displayed: system-generated messages show as "Margin Master Tech Support," support team messages show as "RetailerSoft Support," and store messages show as "Store" (when no specific user name is available). Removed the redundant "(Support)" and "(User)" suffixes from sender names.
-
Improvement
Format detection extended for V3 identification
BackupFormatDetector now recognizes V3 format via explicit FormatVersion field (value >= 3) or presence of V3-specific fields (CostBreaks, MinMaxStrategies). Falls back to V2 detection (BackupPricingStrategies) or V1 detection (BackupGlobalFileConfigs) for legacy files. All restore paths automatically convert older formats to V3 internally.
-
Improvement
Installation script logs accessible to AI
The `get_sql_setup_logs` tool reads script transcript logs from the DiagnosticTool\Logs\Scripts directory, allowing the AI assistant to diagnose installation failures by analyzing the full PowerShell output, SQL Server Bootstrap logs, and error messages.
-
Improvement
Added composite index for MySQL Compass imports
Multi-store MySQL Compass imports now create a composite index on Compass_IN (in_store, in_item_number) to prevent timeout errors when updating extended fields on stores processed last in large installations.
-
Improvement
One Click Statistics now respects current filter selections
One Click Statistics now shows data for only the items you've filtered in the main screen, making the numbers more relevant to your current analysis.
-
Improvement
POS connectivity diagnostic enhancements
The POS connectivity module now classifies POS systems by connection mode (FTP-based, direct connection, file import only) and skips unnecessary network tests for file-import-only systems like RockSolid, Paladin, and TransAct. Added support for detecting 20+ POS system types.
-
Improvement
POS file format diagnostic improvements
The POS file format validator now reads the configured POS type and default import path from the database, pre-populates the file dialog with the correct folder and filter, and displays expected file format hints before file selection. The module now shows skip reasons when no file is selected instead of reporting a generic error.
-
Improvement
Log analyzer warning detection
The log analyzer module now detects both `[ERR]` and `[WRN]` level messages, groups warnings separately from errors, and reports issue severity accurately. Improved error key extraction strips Serilog source tags for better deduplication.
-
Bug Fix
Version number alignment with updater
Fixed a timezone-related mismatch where the version displayed in the app's About dialog and title bar differed from the version reported by the Velopack updater. The app now uses the CI-generated version (UTC-based) instead of deriving it from local build metadata (Eastern Time), ensuring consistency across all version displays. This prevents situations where users might see "version 26.317.5" in the app but the updater reports "26.316.5" due to timezone calculations.
-
Bug Fix
Prevent update chaining after successful updates
After installing an update, Margin Master will no longer immediately check for and install additional updates in a loop, preventing repeated unexpected restarts.
-
Bug Fix
Automatic fallback to legacy upload when blob storage fails
If the primary file upload method fails when you're submitting a support issue, the system now automatically tries an alternative upload method so your files still get attached successfully.
-
Bug Fix
Automatic fallback to legacy upload when blob storage fails
When you attach database or log files to a support request, the upload will now automatically try a backup method if the first attempt fails, making it much more likely your files will reach the support team successfully.
-
Bug Fix
Database rename now detects restore failures
The database rename operation now properly captures and reports SQL errors that occur during the backup restore step. Previously, certain SQL errors could be silently ignored, causing the rename process to appear successful when the restore had actually failed. The system now validates that the restored database actually exists on the server before proceeding.
-
Bug Fix
Authentication token invalidation on database switch
Fixed a critical bug where the JWT authentication token from the previous database was reused after switching stores, causing magic link authentication failures and API requests to be associated with the wrong store. The token is now properly cleared and regenerated when changing databases.
-
Bug Fix
Fixed empty grid when StoreNumber filter absent from view
If your view setup doesn't show the store number selector, the pricing grid will now display data from all stores instead of showing nothing.
-
Bug Fix
Graceful handling of already-resolved support issues
If you confirm a fix for an issue that was already marked as resolved, the confirmation window will now close normally instead of showing an error message.
-
Bug Fix
Handle already-resolved issues gracefully during confirmation
When you click "Confirm Fix" on a support issue that's already been marked as resolved, the dialog will close normally instead of showing an error message.
-
Bug Fix
Support issue count excludes resolved issues
The support badge number now accurately shows only issues that still need your attention, making it easier to know when you need to check the Support Tools screen.
-
Bug Fix
Support badge count excludes resolved issues
The notification badge will no longer show a count for support issues that have already been resolved or closed.
-
Bug Fix
Wildcard conversion in excluded filters
When you exclude items using a wildcard pattern (like "ABC*" to exclude all items starting with ABC), the filter now works correctly instead of failing to apply.
-
Bug Fix
Quick Find SKU column now auto-sizes
When you search for products using Quick Find, the SKU column now automatically widens to show the full SKU number, so you won't see partial SKUs cut off anymore.
-
Bug Fix
Allow hyphens in filter values
Filters on values with hyphens (like 'STORE-PACK') now work correctly on the Main Table.
-
Bug Fix
Support issue resolution error fixed
Marking support issues as resolved now works without showing an error message.
-
Bug Fix
Saved selection box views lost on startup
Fixed a problem where your custom saved views could disappear when opening Margin Master, forcing you back to the default Ace/DIB/Orgill selections and sometimes causing errors about missing fields.
-
Bug Fix
Support issue comment author fallback
When you submit a comment on a support issue, your name will now appear correctly even if your store hasn't set up a primary contact person.
-
Bug Fix
Quick Find no longer auto-selects single search results
When you search for an item and only one match appears, the search box stays active so you can keep typing. You'll need to click the result to select it, but you won't lose your search text anymore.
-
Bug Fix
Quick Find search text preservation
When typing a SKU in Quick Find, your text will no longer be replaced automatically. You can continue typing without interruption, or click a search result to select it.
-
Bug Fix
Quick Find search no longer overwrites typed text
When you select a SKU from the Quick Find dropdown and click "Show", the correct SKU now appears in the pricing grid or detail screen, even if you typed additional characters after selecting it.
-
Bug Fix
Custom selection box views no longer silently fail at startup
Your custom selection box view will now load reliably at startup, even when the database is busy. Previously, you might have noticed your custom view occasionally reverting to the default view without explanation.
-
Bug Fix
Guard stale index removal during view fallback
If the app can't load your saved selection box views at startup, it will now preserve all database indexes instead of accidentally removing ones you actually need. This prevents "field missing from view" warnings when running pricing strategies.
-
Bug Fix
Selection box view startup reliability improved
Dropdown menus for vendors and categories will now load reliably when opening Margin Master, even on slower systems or during busy startup periods.
-
Bug Fix
Inactive row styling now renders correctly in Main Table
When a product is marked as inactive, its entire row in the pricing grid will now display with strikethrough text and a gray color, making it immediately obvious which products are no longer active.
-
Bug Fix
Restore Database window now closes after successful restore
After successfully restoring a database backup, the window will now close automatically instead of staying open.
-
Bug Fix
Restore Database window now closes after successful restore
After restoring a database backup, the window will now close automatically instead of staying open, making the workflow smoother.
-
Bug Fix
Notification emails now include attachment details
When you submit a support ticket with attachments, the notification email now includes all your uploaded files instead of being sent too early.
-
Bug Fix
Submit Issue dialog no longer hangs when no database is active
If you submit a support ticket before loading a database file, the backup option will be grayed out automatically so your ticket can be sent without errors.
-
Bug Fix
Store Configuration now initializes full database schema
The Store Configuration dialog now properly sets up all required database tables when connecting to a new database, preventing errors on the next app launch.
-
Bug Fix
Empty-state handling when no demo databases available
If demo databases aren't available or can't be loaded, you'll now see a clear message explaining what happened and a Retry button to try again, instead of a blank screen.
-
Bug Fix
Store Configuration bootstraps full schema on empty databases
When you connect to a brand-new database and enter your store information, the app now fully sets up the database structure automatically. Previously, this could cause errors when trying to open the app again.
-
Bug Fix
Automatic backup folder permissions grant
If you see a UAC prompt on first launch asking to grant SQL Server access to the backup folder, click Yes — this fixes the issue where backup files would not appear in the restore dialog.
-
Bug Fix
Automatic backup folder permissions for SQL Server
When you first launch this version, you may see a Windows security prompt asking for administrator permission to grant SQL Server access to your backup folder. Approving this prompt will fix issues where database backups would disappear from the restore list.
-
Bug Fix
Automatic Visual C++ Redistributable prerequisite handling
SQL Server 2025's installer would halt with a cryptic error message when the Visual C++ 2015-2022 x64 Redistributable was present but older than version 14.40. The install and upgrade scripts now check the installed version before touching SQL Server, prompt the user, and automatically download and install the latest redistributable from Microsoft's evergreen URL if needed. Exit codes 0, 3010 (reboot recommended), and 1638 (newer already installed) are handled gracefully, while other errors provide a manual installation link.
-
Bug Fix
Display Summary panel shows all $0.00 values
After running a pricing strategy, the summary panel at the bottom left now correctly displays total increases, decreases, average change, histogram counts (H0-H12), and inventory value instead of showing all zeros.
- Bug Fix Large sector NVMe drive compatibility check added to SQL Express scripts
-
Bug Fix
SQL Express registry access failures no longer block database creation
When the app attempts to determine the SQL Server default data path using xp_instance_regread, some SQL Express configurations deny this registry access. Previously this would abort database creation entirely. The app now catches this error, logs a warning, and falls back to using SQL Server's default file location.
-
Bug Fix
Forward slash now supported in SKU filtering
Previously, searching for products with slashes in their SKU (like NM6112/6) would fail. This now works correctly in the Main Table filtering.
- Bug Fix Window sizing improved for smaller displays
-
Bug Fix
Better error handling for database rename failures
Improved how the application responds when it cannot rename database files, preventing crashes and providing clearer error messages to help diagnose issues. This addresses scenarios where file locks or permissions might prevent database operations from completing successfully.
-
Bug Fix
Removed duplicate notification in Do-It-Best catalog import
When a Do-It-Best catalog item can't be added due to a specific problem, you'll now see only the error explaining why, not an extra "No items were added" message.
-
Bug Fix
Fixed crash during settings migration with duplicate keys
Resolved an issue where migrating persistent values could fail if duplicate setting keys were encountered in a single migration batch. The system now tracks already-added keys in memory to prevent database constraint violations.
-
Bug Fix
Database creation now succeeds on SQL Server Express
Database setup now completes successfully on first-time installations without connection errors.
-
Bug Fix
Added retry logic for initial database connection
Database setup during first-time installation will now complete successfully without connection errors.
-
Bug Fix
Automatic cleanup of orphaned databases after failed creation
If database setup fails partway through, you can now click "Create" again immediately — the app will clean up the incomplete database automatically instead of showing "database already exists" errors.
-
Bug Fix
Fixed memory leak in SKU Exceptions screen causing redundant loads
Opening and closing the SKU Exceptions tab multiple times no longer causes the application to slow down or trigger duplicate loading screens.
-
Bug Fix
PowerShell script launcher now handles special characters in file paths
If your Windows username has an apostrophe in it (like O'Brien or D'Angelo), the installation scripts in the Support Tools screen will now launch successfully instead of showing an error.
-
Bug Fix
PowerShell script launcher now handles special characters in paths
If you store Margin Master or your installation scripts in a folder path containing an apostrophe (like "C:\John's Files\"), the scripts will now launch successfully instead of failing with an error.
-
Bug Fix
SQL Error 447 resolved for numeric column filters
Dropdown filter boxes now work correctly for numeric fields without causing database errors.
-
Bug Fix
CPFPDif strategy filter now treats dollar changes as absolute values
When you filter for price changes by dollar amount, the filter now finds both price increases and decreases that meet your criteria. Previously, it would miss price decreases.
-
Bug Fix
Selection Box Views backup and restore now works correctly
Custom selection box views you create will now be included in backups and restore correctly.
-
Bug Fix
Cost break backup now reads from correct storage location
When you back up your pricing data, cost breaks will now be included correctly in the backup file.
-
Bug Fix
Issue notification pill clears on resolution
The yellow notification bar at the top of the screen that alerts you to support issues will now disappear right away when we resolve the issue, instead of waiting until you update to a newer version.
-
Bug Fix
Database setup now detects SQL Server Express for new installations
If you're setting up Margin Master for the first time with SQL Server Express installed, the setup wizard will now correctly find and connect to your database server, allowing you to complete the initial setup process.
-
Bug Fix
Database setup now prefers scanned server over generic placeholders
If your saved database settings contained a generic server name, the database setup screen will now automatically select the correct SQL Server instance that was found on your computer, preventing errors when loading your existing databases.
-
Bug Fix
Startup delay eliminated by cleaning up orphaned default settings
If Margin Master was taking several minutes to start up, this update will restore normal startup times by removing unnecessary default settings that had accumulated in your database.
-
Bug Fix
Default settings entries now deleted during cleanup
Fixed an issue where GlobalFileConfig entries matching default values were being left in the database during the settings migration process. These orphaned entries accumulated over time, causing database bloat and slower startup performance. The cleanup process now marks these default-value entries for deletion, ensuring they are removed from GlobalFileConfig even when they don't need to be migrated to the new ApplicationSettings table.
-
Bug Fix
System information now included in Quick Issue submissions
When you submit a support ticket using the Quick Issue feature, your system details (like software version, store number, and POS system) are now automatically included, helping our support team assist you faster.
-
Bug Fix
Installer corruption detection and automatic recovery
The installer will now automatically detect and fix corrupted download files instead of failing with cryptic errors.
-
Bug Fix
Store manager deduplication now works correctly
When the system finds duplicate store manager entries, it now correctly removes the extras and keeps only one active record per store.
-
Bug Fix
Store identity settings now update correctly during database re-initialization
Your store number and related settings will now always update correctly when you reconfigure your store in the Store Configuration dialog, even if the database was previously used by a different store.
-
Bug Fix
Store identity settings now update correctly during database initialization
When you enter your store information in the Store Configuration dialog, your store number and other details will now always save correctly, even if the database was previously set up for a different store. This fixes an issue where some stores saw "license expired" errors because the app was checking licenses using an old store number instead of their own.
-
Bug Fix
RSC code lookup now handles leading-zero variations in store numbers
When you enter a vendor store number, the RSC code will now fill in automatically even if the store number in cloud data has more or fewer leading zeros.
-
Bug Fix
Organization ID now captured from license response
The license validation process now extracts and stores the Organization ID from the license server response. Previously, this ID was never populated, causing the Store Manager's cloud save feature to silently skip uploading changes (due to a null organization ID check).
-
Bug Fix
Cached installer verification improved
When checking for updates, Margin Master now properly re-downloads the installer if it can't verify the cached copy is current, preventing installation of outdated versions.
-
Bug Fix
Fixed SQL Server service account detection on restricted environments
The backup folder access check now gracefully handles environments where the sys.dm_server_services system view is unavailable (such as SQL Express or databases without VIEW SERVER STATE permission). Previously, this would generate false error telemetry; now it returns NULL without errors.
-
Bug Fix
Fixed stale installer cache vulnerability
The bootstrapper now discards any cached installer file when the ETag verification file is missing, not just when it mismatches. Previously, if Windows temp cleanup deleted the .etag file but left the installer file, the bootstrapper would incorrectly assume the cached installer was current based on file size alone. This could result in launching an outdated installer. The fix ensures fresh downloads whenever cache integrity cannot be verified.
-
Bug Fix
SQL Server service account detection now handles restricted permissions
The backup folder access service now checks if the sys.dm_server_services dynamic management view is available before querying it. In some SQL Server environments with restricted permissions, this DMV may not be accessible, which previously caused errors. The service now falls back gracefully when the view is unavailable.
-
Bug Fix
Fixed contact deletion crash
Added missing message box service that was causing contact deletion attempts to silently fail. The delete confirmation dialog now appears correctly and deletions are properly saved to the cloud.
-
Bug Fix
Contact validation now enforced in Support Tools
When submitting an issue, you'll now see a clear warning if you haven't selected a contact, and you won't be able to proceed until you choose someone from your Store Contacts or select a Support Rep.
-
Bug Fix
Empty and placeholder contacts no longer appear in contact selector
When selecting contacts for support tickets or issue reports, you'll no longer see empty or placeholder entries in the list—only valid contacts will appear.
-
Bug Fix
Filter out empty and placeholder contacts from contact picker
You will no longer see empty or "Add New" placeholder entries when picking contacts for support issues.
-
Bug Fix
Resolve startup failures during Key Vault outages
The application previously failed to start with licensing errors when Azure Key Vault was unreachable. Now, after successfully retrieving licenses from the cloud, they are persisted to the local ApplicationSettings database. On subsequent startups when Key Vault is unavailable, the app falls back to these cached database values before attempting the final appsettings.json fallback, ensuring the application can start even during network outages.
-
Bug Fix
Store change summary query now uses correct database table
Fixed error messages that appeared when building pricing summaries for store groups, especially after recent database updates.
-
Bug Fix
Store change summary query corrected for non-MySQL POS systems
Store change summaries now display correctly regardless of which POS system your store uses.
-
Bug Fix
Installation Scripts dialog preload error resolved
The Installation Scripts screen was attempting to download scripts from cloud storage even when those scripts were intentionally stored on local disk. This caused an error each time the dialog opened. The preload process now correctly skips locally-stored scripts and only attempts to download those actually hosted in cloud storage.
-
Bug Fix
Suppress SQL permission error during database user creation
When Margin Master attempts to create internal SQL database users (MarginMasterDataExtractor) at startup, it now gracefully handles situations where the connecting user lacks sysadmin or securityadmin permissions. Previously, SQL error 15247 was logged as an error and sent to telemetry. Now it's logged at debug level only and won't trigger alerts. The application also sets a guard flag to prevent retrying this operation on every startup.
-
Bug Fix
Loading overlay now dismisses before error dialogs
When a database restore fails, you can now see and click the error message instead of being stuck on a loading screen.
-
Bug Fix
Cloud backup restore now filtered to current store
When restoring from cloud backup, you'll now only see backup files for your own store, making it easier to find the right backup to restore.
-
Bug Fix
Database restore compatibility with legacy backups
You can now restore database backups created by older versions of Margin Master without encountering errors during the restore process.
-
Bug Fix
Diagnostic Tool startup crash resolved
The Diagnostic Tool will now open successfully every time, even on computers where it hasn't been used before.
-
Bug Fix
Corrected ordinal calculation for special-character store identifiers
Stores identified by special characters like '€' will now import SKUs correctly without creating duplicate database entries.
-
Bug Fix
Auto-update recovery from delta patch failures
If an update download gets corrupted, the app will now automatically clean up and retry with a fresh download instead of failing silently.
-
Bug Fix
Automatic recovery from delta-patch checksum failures
If an update download fails due to file corruption, the app now automatically cleans up the problem files and retries the download to complete the update successfully.
-
Bug Fix
MySQL refresh now reactivates previously deleted stores
If a store was removed but later reappears in your POS system, it will now be automatically restored in Store Manager.
-
Bug Fix
Store Manager now resolves missing OrganizationId before cloud save
If your store settings can't be sent to the cloud due to missing organization information, you'll now see a warning message and can retry after confirming your license is active.
-
Bug Fix
Prevent adoption of foreign store identity at startup
Fixed a critical issue where the app could incorrectly display pricing and data from a completely different store if an old database file was on your computer.
-
Bug Fix
Clear explanations for backup folder access failures
If your backup fails with a path error, the message will now explain that SQL Server needs access to the backup folder and suggest using a folder on the SQL Server machine itself or adjusting permissions.
-
Bug Fix
Fixed "Invalid object name 'SkuExceptions'" startup error
Startup will no longer fail with table errors when opening Margin Master after restoring a database backup.
-
Bug Fix
Automatic recovery from corrupted updates
If a bad automatic update breaks Margin Master, the app will now fix itself automatically when you try to open it, instead of staying broken until someone manually reinstalls it.
-
Bug Fix
Wildcard selection now combines with other filters instead of replacing them
When you exclude specific locations and also type a wildcard pattern (like "81*"), both filters now apply together. Before this fix, typing a pattern would erase your other selections.
-
Bug Fix
Wildcard filter now combines with other selections instead of replacing them
If you exclude specific locations (like 64 individual stores) and also use a wildcard pattern, both filters will now work together correctly instead of the wildcard erasing your other selections.
-
Bug Fix
Support ticket upload errors now show meaningful messages
If a support ticket or attachment upload fails, the error dialog will now show the actual reason from the server instead of appearing blank, making it easier to understand what went wrong and how to fix it.
-
Bug Fix
Server error messages now display correctly for support ticket uploads
If your support ticket upload fails, you'll now see a helpful error message explaining why instead of a blank error.
-
Bug Fix
Large backup file upload failure now reported accurately
If you try to submit a Quick Issue with a very large database backup and the cloud upload isn't working, you'll now see a clear error message right away instead of waiting for a long upload that will fail. This prevents losing your backup without knowing it.
-
Bug Fix
Prevent silent failure when uploading large support attachments
If you're submitting a support request with a large database backup and the upload fails, you'll now see a clear message explaining the file is too large (over 128 MB) rather than the upload appearing to succeed but actually failing silently.
-
Bug Fix
False error message when creating new cost breaks
When you click "<< New >>" to create a cost break, you'll no longer see a red error message saying "No Cost Break Models Found." The screen now opens directly to the editable grid where you can set up your new cost break. The warning message will only appear when viewing existing cost breaks if you haven't saved any yet.
-
Bug Fix
Empty state message now respects cost break creation mode
When you create a new cost break, you'll no longer see a confusing "No Cost Break Models Found" error message that didn't apply to what you were doing.
-
Bug Fix
API response cache clearing on database switch
Store-specific API data (contacts, support issues, release notes) is now cleared when switching databases. Previously, cached data from the old store would incorrectly appear in the new store's context.
-
Bug Fix
Wildcard selection detection for excluded items
Corrected the logic that detects when a wildcard filter is active to properly handle excluded selections. Previously, unchecked wildcard items were incorrectly bypassing wildcard conversion logic.
-
Bug Fix
Correct wildcard filter processing
Wildcard searches using asterisks now filter results correctly on the Main Table.
-
Bug Fix
ZIP comment metadata persistence
Fixed a bug where backup metadata was not being saved in the ZIP comment due to incorrect property ordering. The ArchiveFile property must be set before ZipComment for the IPWorks library to persist the comment correctly.
-
Bug Fix
Fixed loading overlay timing during cloud restore
The "Please Wait" screen now stays visible for the entire restore process instead of disappearing early.
-
Bug Fix
Restore dialog backup file visibility
Backup files will now appear consistently in the restore dialog instead of showing an empty list.
-
Bug Fix
Explicit file path creation now has automatic fallback
If CREATE DATABASE with an explicit file path and size specification fails (due to file system permissions or SQL Express MAXSIZE restrictions), the app now automatically retries using the simple CREATE DATABASE syntax, allowing SQL Server to use its own default locations and settings.
-
Bug Fix
Better handling of timeout and network errors
Timeout and network errors when loading open issues are now logged as warnings instead of errors and will no longer display alarming error messages. The application gracefully handles these situations by returning no issues rather than crashing or showing confusing error dialogs.
-
Bug Fix
Reduced error noise from auto-updater
Velopack auto-updater operational events are now filtered out of error reporting, preventing false alarms from routine update check activities.
-
Bug Fix
Accurate error messages during database setup
When database setup fails, you'll now see a clear explanation of what went wrong instead of a generic error message.
-
Bug Fix
Batch execution now respects per-store assignments from exception rules
SKU-level exceptions assigned to specific stores (e.g., "HURST ACE STORE 5") now only update pricing for those stores instead of incorrectly changing prices across all stores.
-
Bug Fix
Empty value filtering corrected for all column types
Selection boxes no longer show blank entries and properly exclude empty values for all field types.
-
Bug Fix
CPFPDif exclude filters now work correctly
When you exclude items by dollar price change amount, the filter now correctly excludes both large increases and large decreases.
-
Bug Fix
Column Views backup and restore now works correctly
Custom column views you create will now be included in backups and restore correctly.
-
Bug Fix
Cost break restore now writes to correct storage location
When you restore a backup, your cost breaks will now be properly restored and ready to use.
-
Bug Fix
View settings entries now properly cleaned up
View setting keys (like window positions and column widths) are now marked for deletion from GlobalFileConfig during migration, even though they're migrated separately by GetViewSettingsAsync. Previously, these entries were skipped but not cleaned up, causing duplicate storage of the same settings.
-
Bug Fix
Fixed database setup window behavior after restore
Resolved an issue where the database setup window could return early with a false result when DialogResult assignment threw InvalidOperationException. The window now properly closes and sets the active connection after successful database restore or demo installation.
-
Bug Fix
RSC codes now appear immediately in the grid after auto-assignment
When an RSC code is automatically filled in from cloud data, it now shows up right away in the grid instead of requiring a refresh.
-
Bug Fix
Installer launch failures now properly reported
Added Win32Exception handling around the installer launch process. Previously, failures during Process.Start were silently swallowed; now they are surfaced in both the error UI and the bootstrapper log with the specific Windows error code and message, making installation issues easier to diagnose.
-
Bug Fix
Fixed SkuExceptions table validation crash
Corrected the SkuExceptions Description column validation logic to properly check for table existence before attempting to add the column. Previously, if the table didn't exist, the system would attempt to alter a non-existent table, causing an error. The validation now only runs the ALTER TABLE command if both the table exists and the Description column is missing.
-
Bug Fix
SKU exception validation guards against missing table
The SKU exception description validation now verifies that the SkuExceptions table exists before attempting to add the Description column. This prevents errors during startup when working with older or incomplete database schemas.
-
Bug Fix
Handle server-side contact validation
If the server rejects an issue submission due to a missing contact (unlikely given UI enforcement), the dialog now navigates back to Step 2 with a clear error message rather than showing a generic failure.
-
Bug Fix
Contact cache now correctly distinguishes between store and support employee lists
Fixed a cache collision where store-only contact lists and lists that include support employees could incorrectly share cached data. The cache key now includes whether support employees are included, and cache invalidation clears both variants when contact data changes.
-
Bug Fix
Fix support contacts cache invalidation
Corrected a caching issue where support employee contacts were stored under a different cache key but not properly cleared when contact changes were made. The system now correctly invalidates both regular and support employee contact caches when contacts are modified.
-
Bug Fix
Improved ZIP extraction error handling
If a backup ZIP file is damaged or invalid, you'll now see a clear error message explaining what went wrong instead of the screen appearing frozen.
-
Bug Fix
Restore POS store matching for stores upgraded from version 3.9.x
Fixed store matching problems for customers who upgraded from older versions of Margin Master (3.9.x).
-
Bug Fix
Fixed "There is already an object named 'GlobalFileConfigBackup'" migration error
Settings migration will now complete successfully on all database configurations during startup.
-
Bug Fix
Wildcard-only patterns no longer generate broken SQL operators
Entering only wildcards (like "*" or "**") in a filter now correctly ignores the pattern instead of breaking the filter or returning zero results.
-
Bug Fix
Wildcard patterns consisting only of asterisks are now ignored
If you accidentally type only asterisks in a wildcard filter (like "*" or "**"), the filter will be ignored rather than causing unexpected results in your pricing grid.
-
Bug Fix
Handle upload-target endpoint failures gracefully
When the initial request to determine the upload destination fails, the system now falls back to the legacy upload method instead of returning an error to the user. This prevents attachment upload failures when the blob storage configuration endpoint is temporarily unavailable.
-
Bug Fix
Cloud connection string refresh on database switch
The cached cloud connection string is now invalidated when switching databases, ensuring each store uses its correct cloud database connection rather than the previous store's connection.
-
Bug Fix
Removed invalid MSSQLSERVER named instance entry
Corrected the local server scanner to stop treating "MSSQLSERVER" as a named instance. MSSQLSERVER is the Windows service name for the default SQL Server instance, not a valid named instance connection string. This prevented confusing connection attempts to non-existent server names.
-
Bug Fix
Removed invalid MSSQLSERVER instance name
Removed an incorrect hardcoded instance name pattern that could cause connection attempts to fail on systems with default SQL Server installations.
-
Bug Fix
Individual ALTER DATABASE settings failures no longer block database creation
The five ALTER DATABASE statements (RECOVERY SIMPLE, AUTO_CLOSE OFF, AUTO_SHRINK OFF, AUTO_CREATE_STATISTICS ON, AUTO_UPDATE_STATISTICS ON) are now executed independently with individual error handling. If one fails (e.g., AUTO_CLOSE OFF on certain Express editions), the remaining settings are still applied and database creation completes successfully.
-
Bug Fix
Fixed crash when MySQL Compass store mapping setting is missing
Fixed a crash that could occur when importing MySQL Compass data if certain configuration settings were not yet defined.
-
Bug Fix
MySQL Compass toggle no longer reset on connection failure
The "Use MySQL Compass" checkbox is no longer automatically unchecked when a MySQL connection test fails. The connection is marked unavailable but the user's choice to use MySQL Compass is preserved, allowing them to fix connection details without reconfiguring the entire setup.
-
Bug Fix
MySQL Compass toggle no longer resets on test failure
The "Use MySQL Compass" checkbox will stay checked even if the connection test fails, so you don't have to re-enable it after fixing connection problems.
-
Bug Fix
Cleanup of temporary files after errors
When an installation error occurs, the bootstrapper now deletes both the temporary installer file and its metadata, ensuring every retry starts with a completely clean download rather than potentially reusing corrupted files.
-
Bug Fix
Duplicate contacts no longer appear in contact list
You'll no longer see the same contact listed multiple times when selecting who to notify about an issue.
-
Bug Fix
Store Manager dialog prevents premature close during cloud save
The Store Manager dialog won't close until your store changes are fully saved to the cloud, preventing accidental data loss.
-
Bug Fix
Wildcard patterns now generate correct SQL operators
Wildcard filters (like "81*" or "*HARDWARE*") now work correctly to find matching items in the pricing grid.
-
Bug Fix
Configuration and settings reset on database switch
File-based configuration options, backup directory paths, and cached JSON settings are now properly reset when changing databases, preventing settings from one store from bleeding into another.
-
Bug Fix
Real-time attachment polling
When someone else adds an attachment to an issue you're viewing, it will now appear automatically in your conversation view.
-
Bug Fix
Automatic database recovery on restore failure
If a database restore fails, the system now automatically tries to fix the database so it can still be used.
-
Bug Fix
Fixed database existence check security and performance
The restore process now uses an asynchronous, parameterized SQL query to check if a database already exists, preventing potential SQL injection vulnerabilities and avoiding UI blocking during the check.
-
Bug Fix
Missing function declaration in Upgrade-SQLExpress script
The Upgrade-SQLExpress.ps1 script was referencing `Get-VCRedistVersion` but the function was not declared in the script body. The function has been added to properly detect and install the required Visual C++ Redistributable (v14.40 or newer) before attempting the upgrade.
-
Bug Fix
Fixed Excel export crash with duplicate column names
Fixed a crash when exporting to Excel if the data contained columns with the same name.
-
Bug Fix
Improved SQL Server instance detection for fresh installations
When no SQL Server instances are found, the setup window no longer adds a placeholder "." server to the list, correctly showing the "Install SQL Server" button instead. Debug mode now bypasses cached instance results when a test scenario is active.
-
Bug Fix
Launch button error handling
Added error handling around the "Launch" button in the installed app prompt. If launching the installed application fails, the error is now caught and displayed properly, and the retry counter is preserved for troubleshooting.
-
Bug Fix
Improved error handling during MySQL refresh
Each store operation during the refresh process is now isolated, so if one store fails to update, the refresh continues processing remaining stores instead of aborting entirely. Errors are logged with specific store details for troubleshooting.
-
Bug Fix
Rounding schemes and validation state reset
Database-specific caches including rounding schemes, SQL query hashes, store number lists, and validation flags are now fully cleared when switching databases, ensuring accurate data for the new store.
-
Bug Fix
Fixed crash when pricing actions have empty or invalid values
Fixed a crash when applying pricing strategies that had blank or invalid price or margin values.
-
Bug Fix
Application settings query correction
Fixed SQL query in `get_application_settings` tool to use correct column names (Setting, Value) instead of incorrect names (SettingKey, SettingValue), resolving errors when the AI attempted to retrieve user settings.
-
Bug Fix
Clean exit when canceling database setup
Canceling the database setup during first launch now closes the application cleanly instead of showing an error message.
-
Bug Fix
Contact form visibility now updates correctly
Fixed toggle behavior where the contact edit form and placeholder text visibility now correctly respond to the DoNotContact checkbox state and contact selection. The right panel now shows the appropriate content based on user actions.
-
Bug Fix
Restore Database Cancel button now closes window
The Cancel button in the Restore Database dialog now properly closes the window.
-
Bug Fix
Fixed crash from duplicate keys in pricing strategy rules
Fixed a crash when applying pricing strategies with duplicate action settings in the rule definition.
-
Bug Fix
Fixed memory issues with large backup files
Backup creation now streams JSON directly to disk instead of building the entire file in memory, preventing out-of-memory errors on stores with very large datasets.
-
Bug Fix
Fixed crash when editing cells with null or whitespace values
Fixed a crash that could occur when clearing a cell value or entering only spaces in the pricing grid.
-
Bug Fix
Improved restored database naming
The restore process now strips backup file extensions (.bak, .zip, .sql) from suggested database names, preventing databases from being created with names like "DIB_3932.bak".
-
Bug Fix
Diagnostic log rotation
DiagnosticTool now clears previous session log files on startup to prevent log accumulation and improve disk space usage.
-
Bug Fix
ApplicationSettings column name corrections
Fixed ApplicationSettings table queries to use the correct `Setting` and `Value` column names instead of legacy `SettingKey`/`SettingValue` naming. Corrected vendor setting name from `VendorType` to `RetailerSoftVendor`.
-
Cloud Sync
SQL-based strategy backup with history tracking
Your strategy backups are now saved to a more reliable system that keeps track of when each backup was created and why.
-
Cloud Sync
Enhanced RSC code retrieval from cloud Stores table
When you enter a vendor store number, the RSC code will now fill in automatically from the cloud database, making store setup faster and more accurate.
-
Cloud Sync
Store-specific cloud backup visibility
The cloud backup restore screen now shows only your store's backups, preventing confusion with backups from other store locations in your organization.
-
Cloud Sync
Added computer name tracking for store settings updates
When saving store settings to the cloud (such as POS-to-cloud store match-ups), the application now includes the submitting computer's machine name in the request. The cloud server records this information to track which workstation last modified each store configuration, improving audit capabilities and troubleshooting for multi-computer setups.
-
Cloud Sync
Computer identification for store settings
When saving organization store settings, the application now sends the computer name in the request header (X-Submitted-By-Machine). The server records this information to track which workstation last modified store match-up configurations, improving visibility for multi-user environments.
-
Cloud Sync
Hidden issue flag
Added an IsHidden flag to the issue submission API that marks issues as internal-only. These issues are excluded from the store's visible issue list, not shown as notification badges in the client, and store contacts are not notified when the issue is created or updated. This allows support staff to gather diagnostic data without creating customer-facing support tickets.
-
Cloud Sync
Attachment list updates during polling
New attachments uploaded by the support team will appear automatically without refreshing the screen.
-
Cloud Sync
Cloud backup/restore updated to V3 format
Both cloud upload and download operations now use the V3 backup format with the same tree-based selection dialog. Cloud-downloaded backups are automatically converted from V1/V2 if necessary before restoration. Maintains backward compatibility with existing cloud backups.
-
Cloud Sync
Multi-RSC detection during sync
Updated Cloud Sync logic to determine multi-RSC status by analyzing STORERSC global values before resolving which RSCs to sync. The sync process now automatically adapts to single or multi-RSC scenarios without requiring a stored configuration flag.
-
Data Import
Updated cloud settings API to include store RSC mapping
The API endpoint for retrieving organization store settings now returns both POS-specific store settings and a complete vendor-store-number-to-RSC-code map from the cloud Stores table. This enriched data bundle enables better fallback logic when local POS data is incomplete.
-
Data Import
Update MySQL import pipeline for unified store management
MySQL/Compass data imports now use the same store management system as other POS types.
-
Data Import
Enhanced backup metadata and section tracking
Added nine new BackupRestoreSectionType enum values (CostBreaks, MinMaxStrategies, MinimumMargins, SelectionBoxViews, ColumnViews, CustomFieldNames, CustomSortOrders, StoreMatchUps) for granular restore control. BackupRestoreOptions extended with per-section flags and item-level filter lists (SelectedStrategyNames, SelectedRoundingSchemeNames, etc.) to support partial restoration.
-
Data Import
RSC assignment improvements
Simplified store-to-RSC matching logic in POSStoreNumberMatchUpViewModel and StoreNumberMatchUpViewModel to always write RSC assignments to STORERSC global configuration, regardless of multi-RSC status. The viewmodels now calculate HasMultipleRSCs from the actual store data after loading mappings rather than reading it from settings.
-
Data Import
Store Manager routing in import pipeline
Import processes now automatically use your Store Manager settings for zone pricing and store mappings.
-
Data Import
Restored Ace Hardware catalog and zone pricing import logic
Re-implemented the SQL queries for importing Ace Hardware catalog data and zone pricing that were accidentally removed in a previous merge. Zone pricing now correctly applies store-specific zones when available, falling back to zone 99999 only when no store-specific zone is configured.
-
User Interface
Order Indicator filter dropdown now shows decoded descriptions
When you click the Order Indicator filter in the pricing grid, you'll see clear descriptions explaining what each code means (T for Stock/Order Through, C for Central Stock, S for Special Order), making it easier to filter products by fulfillment type.
-
User Interface
Configurable alternate text display order in selection dropdowns
Added AltItemTextAfter property to SelectionListItem that controls whether alternate text appears before or after the primary text in dropdown displays. When enabled, items display as "{ItemText} - {AltItemText}" instead of the previous "{AltItemText} - {ItemText}" format.
-
User Interface
Redesigned Support Scripts dialog with categorized tree view
When you open Support Scripts, you'll see scripts organized into categories on the left. Click any script to see its full description on the right before running it.
-
User Interface
Enhanced Quick Find results display
Search results in Quick Find now show in two separate columns (SKU and Description) that you can resize by dragging, making it easier to view long product descriptions.
-
User Interface
iMessage-style bubble view for support conversations
Support conversations now default to a modern bubble chat interface similar to iMessage. User messages appear right-aligned in blue bubbles (with white text), while support team responses appear left-aligned in light gray bubbles (with dark text). Each bubble displays the sender name and role above it (e.g., "Brad Green (User)" or "Support (Support)"), with a timestamp in the bottom corner. Bubbles have rounded corners with a subtle "tail" effect (flat bottom-right for user messages, flat bottom-left for support messages) and a light drop shadow for depth. Bubbles are limited to 75% of the chat area width to maintain readability.
-
User Interface
iMessage-style chat bubbles for support conversations
When viewing support ticket conversations, messages now appear in colored chat bubbles similar to text messages—your messages are blue on the right, support team responses are gray on the left.
-
User Interface
Attachments bar added to Support Issues chat
Attached files now appear in a dedicated section below the chat with their file sizes displayed.
-
User Interface
Attachment display in Support Issues chat
When viewing a support issue, you'll now see all attached files listed in the conversation area with their names and sizes.
-
User Interface
Database creation and restoration gated behind valid connection
The buttons to create or restore a database are now grayed out until you successfully connect to a SQL Server using the "Test Connection" button.
-
User Interface
Cost break model cleanup script
If you've accumulated many test or unused cost break models, IT staff can now run this script to clean them up. The script shows you what models exist before deleting anything, and includes examples for removing models by naming pattern (like "New..." or "Mi9-...") or by exact name.
-
User Interface
Bulk delete SQL for cost break models
If you have many cost break models to delete, you can now use SQL queries to remove them in bulk rather than deleting each one individually in the Cost Break Analysis screen.
-
User Interface
Softer background color for inactive dirty rows
When viewing items that are marked inactive but have unsaved changes in the pricing grid, they now appear with a softer, more subtle background color that's easier to read and less distracting.
-
User Interface
Improved visual indicator for inactive rows with unsaved edits
When you edit a row that's marked as inactive, it now highlights in a muted amber color instead of purple, making it easier to spot unsaved changes at a glance.
-
User Interface
Strikethrough formatting added to inactive product rows
When viewing the pricing grid, products marked as inactive will now show with a line through the text, making it much easier to see which items are no longer active.
-
User Interface
Condition value editor popup
Click the pencil icon next to any condition (like Vendor, Department, etc.) to see all its values in a popup. Click the red "×" next to any value to remove it from the condition.
-
User Interface
Added download progress bar to cloud restore
When restoring a database from the cloud, you'll now see a progress bar showing how much of the backup file has been downloaded.
-
User Interface
Added visual progress bar for cloud backup downloads
A progress bar now appears when downloading backups from the cloud, showing how much of the download has completed.
-
User Interface
Extended visibility for resolved support issues
If a support issue has been fixed in a newer version but you haven't updated yet, you'll continue to see the notification pill reminding you about the issue until you install the update.
-
User Interface
Type-ahead search enabled for configuration dropdowns
When selecting your primary vendor, RSC, or POS system during setup, you can now start typing (e.g., "Ace" or "Rock") and the dropdown will automatically highlight and jump to matching options.
-
User Interface
Support issue pill color now indicates status
The support issue notification now changes color to show you the status of your issue: blue means it's new, orange means it's being worked on, and purple means it's ready for you to test.
-
User Interface
Color-coded support issue pill
The support notification badge now shows blue when your issue is new, orange when we're working on it, and purple when a fix is ready for you to test.
-
User Interface
Documented wildcard selection filter feature
Created detailed documentation explaining how to use the `*Wildcard*` option that appears in selection boxes with more than 5 items. The documentation covers both include mode (left-click) and exclude mode (right-click), pattern syntax using the `*` character, and notes that wildcard selections are mutually exclusive with individual item selections.
-
User Interface
Support Issues date display changed to last-updated
When viewing support issues, you'll now see when each issue was last updated instead of when it was created, helping you quickly find issues that have recent activity or responses.
-
User Interface
Display last-updated date for support issues
When viewing support issues, you'll now see when each issue was last updated rather than when it was created. The most recently updated issues appear at the top of the list, making it easier to track ongoing conversations.
-
User Interface
Support issue action feedback
When you click buttons like "Mark Resolved" or "Confirm Fix" in Support Issues, you'll now see a "Processing..." message until the action completes, so you know it's working.
-
User Interface
Wait indicator added for support issue actions
When you click to mark an issue resolved, confirm a fix works, or reject a fix, you'll now see a "Processing..." message while the action completes instead of the screen appearing frozen.
-
User Interface
Improved note field in Quick Issue Submit dialog
The optional note field in Quick Issue Submit now appears as a clean multi-line text box without any extra buttons.
-
User Interface
Enhanced startup splash screen progress detail
You'll now see exactly what Margin Master is doing during startup with messages like "Verifying Rounding Tables..." and "Checking Configuration Integrity..." instead of just a generic loading screen.
-
User Interface
SSMS detection limited to first-run setup only
When reconnecting to your database, you'll no longer see messages about SQL Server Management Studio installation status—these only appear during initial setup.
-
User Interface
Enhanced Database Setup screen for first-run scenarios
When you first open Margin Master, the database setup screen now shows clearer instructions and helpful warnings if your SQL Server version is outdated. You can also start the SQL Server service with one click if it's not running.
-
User Interface
Streamlined demo database selection during startup
When setting up Margin Master for the first time, you can now browse and install demo databases more easily without selecting a vendor first.
-
User Interface
Streamlined field-dropped warning message
When loading a saved pricing strategy that references fields no longer present in the current dataset, the warning dialog now displays a more concise message. The redundant "This step will be skipped..." sentence was removed since the primary warning already clearly explains why the step cannot execute safely.
-
User Interface
Simplified installer window header
Replaced the full-height branded header (52px with icon and "Margin Master" text) with a minimal 36px green drag strip containing only the close button. The Margin Master logo is now displayed as a high-quality PNG image in the white body area above the status text, creating a cleaner and more professional installer appearance. The window height increased slightly from 260px to 280px to accommodate the new logo placement.
-
User Interface
Removed Store Name column from Store Manager
Store names no longer appear in the Store Manager grid.
-
User Interface
Simplified Support Issues window layout
Removed the dual-view toggle between iMessage-style bubbles and Twitter-style threads. The window now uses only the timeline view, which displays messages in a clean, chronological format with system activity entries (like status changes) appearing as centered timeline events labeled "Margin Master Tech Support."
-
User Interface
Redesigned Support Issues conversation display
Support conversations now appear in a single, easy-to-read format. System notifications like "Issue published" appear with a gray divider line, while messages from you and support staff show with profile circles and names.
-
User Interface
Improved cloud unavailability messaging in Support Issues
When viewing Support Issues, if details can't be loaded, you'll see a clearer message explaining the cloud service may be temporarily unavailable instead of being asked to check your internet connection.
-
User Interface
Password-protected feature toggle added to Background Service tab
When opening the Background Service tab, you'll see whether the feature is enabled or disabled. If disabled, click the "Enable (password)" button and enter the support password to activate scheduled background imports.
-
User Interface
Issue resolution comments field improved
The comments box in the Submit User Issue Resolved dialog now includes text wrapping and a vertical scrollbar, making it easier to read and edit longer multi-line comments.
-
User Interface
Database Setup window margins tightened
The Database Setup screen during first launch now fits better on smaller monitors without needing to scroll.
-
User Interface
Twitter-style thread view as an alternative layout
A new thread view option displays conversations in a full-width, social-media-style layout. Each message shows a circular avatar with the sender's initials, followed by the sender name with role label and timestamp in the header, then the full message text below. Messages are separated by horizontal dividers and fill the entire width of the chat area, making it easier to scan long technical discussions.
-
User Interface
Dual view toggle between bubble and thread layouts
You can now choose how support conversations are displayed by clicking "Bubbles" or "Thread" at the top of the conversation area—your choice is remembered next time you open the screen.
-
User Interface
Staged attachments preview area
Attachments you've selected appear in a yellow area below the message box, where you can review file names and sizes or remove files before sending.
-
User Interface
More accurate support notifications
When checking for open support issues, the application now properly distinguishes between issues that need attention versus those that have been resolved, providing a more accurate indicator of pending support matters.
-
User Interface
Simplified Quick Find selection logic
Removed unnecessary bidirectional binding between the search text field and selected search result. The search field now only triggers searches, while result selection is handled independently, eliminating a source of unexpected UI behavior.
-
User Interface
Simplified SKU selection logic
Removed unnecessary flag-based logic that was attempting to prevent search updates when selecting dropdown items. The search box and dropdown selection are now handled independently, eliminating the circular update issue that caused text to be overwritten.
-
User Interface
Adaptive feedback panel in Database Setup
The information panel at the bottom of the server selection area now adapts its appearance based on SQL Server status. The panel displays blue background and "Install SQL Server Express" button when no SQL Server is detected, but switches to orange background with service-specific guidance (and hides the install button) when SQL Server is installed but services are not running. The panel shows service names and their current status to help users identify which service needs attention.
-
User Interface
Context-aware help messages in Database Setup
The help message at the bottom of the Database Setup window now changes color and content based on what's actually wrong with your SQL Server connection, making it easier to know what action to take.
-
User Interface
Tree view with item-level selection for backup/restore
When backing up or restoring, you'll now see expandable categories where you can choose specific pricing strategies or rounding schemes by name instead of having to include everything at once.
-
User Interface
Store number column added to backup list
The backup list now shows a "Store #" column so you can quickly see which store each backup file came from.
-
User Interface
Store number column added to backup list
Cloud backups now show which store they came from in a "Store #" column, making it easier to find the right backup when multiple stores are displayed.
-
User Interface
Error recovery in Demo Mode dialog
The Demo Mode window now shows helpful error messages and recovery options instead of appearing blank when something goes wrong.
-
User Interface
New prerequisite verification step in setup workflow
A new "Step 2: Verifying Visual C++ Redistributable prerequisite" has been added to both installation and upgrade scripts. The script prompts for confirmation before downloading/installing the redistributable, reports the current installed version, and verifies the installation succeeded before proceeding. All subsequent steps (download, backup, install/upgrade) have been renumbered accordingly.
-
User Interface
Clearer error messages for database operations
You'll now see clearer error messages if the application has trouble working with its database files, making it easier to know what's wrong.
-
User Interface
Multiple RSC checkbox removed from Settings
The "Multiple RSC's" checkbox is no longer visible in Store Information settings.
-
User Interface
Hidden multi-RSC checkbox
The "Multiple RSCs" checkbox has been removed from the Store Information settings screen.
-
User Interface
Improved server selection logic in database setup screen
The Database Setup screen now intelligently handles cases where the saved server name is a generic local placeholder by keeping the server instance discovered during the automatic scan. This ensures the "Load Existing Database" operation can successfully connect to SQL Server even when the configuration file contains a fallback placeholder value.
-
User Interface
Failed connection tests now show warnings instead of errors
Failed connection tests now show a yellow warning message explaining that your settings were saved and you can fix any incorrect details and try again.
-
User Interface
Updated error messages for failed connection tests
When a connection test fails, the warning message now explains that your settings were saved and you can simply correct the mistake and test again.
-
User Interface
Added wildcard pattern examples and syntax guide
Documentation includes a pattern syntax reference table showing common examples like `A*` (starts with A), `*TOOL*` (contains TOOL), and `*0012` (ends with 0012). All patterns are case-insensitive and the `*` character matches any sequence of characters.
-
User Interface
Idle progress bar
A small progress bar shows how close the notification is to automatically updating — when it fills completely, the 10-second countdown begins.
-
User Interface
Table schema verification progress tracking
If you have multiple vendor catalogs, the startup screen now shows "Main table 3 of 8" (for example) so you can see progress through the verification process.
-
User Interface
Removed SKU Count column from Store Manager
The SKU Count column has been removed from the Store Manager screen.
-
User Interface
Improved license expiration error message
If you see a license expired error, the message now suggests checking that your store number is correct, since an incorrect store number can cause this error even when your license is valid.
-
User Interface
Delete button styling and placement
The "Delete Issue" button appears on Step 3 of the Submit Issue screen, positioned to the left of the "Update Issue" button. It uses red text (#C62828) to indicate its destructive nature and is hidden while submission operations are in progress to prevent accidental clicks.
-
User Interface
Visible warning when issue notification cannot be sent
You'll now see a clear warning if your support issue couldn't be sent, so you know to contact RetailerSoft directly instead of waiting for a response.
-
User Interface
Visible warning when notification fails
If your issue submission notification doesn't go through, you'll see a message telling you to contact RetailerSoft support directly instead of wondering if it worked.
-
User Interface
Consolidated issue action buttons
Moved all issue actions (View Online, Mark Resolved, Fix Works, Still Broken, and the new Remove Issue button) into a single row in the detail header, replacing the previous scattered layout with top-bar buttons and separate banners. Also removed the View menu that previously toggled between display modes.
-
User Interface
Added ability to remove issues from your list
You can now remove issues from your list if you no longer need to track them. Right-click an issue or use the remove button to hide it from your view.
-
User Interface
Update progress during version check
You'll see progress messages like "Checking for updates..." on the startup screen if the app needs to update itself before opening your database.
-
User Interface
Improved fallback priority for selection box views
Enhanced the view selection fallback hierarchy to prioritize a sole custom view (priority 0) before checking for vendor-specific default views (priority 1). This ensures customer-specific configurations are preserved during database operations while maintaining backward compatibility with the existing vendor default system.
-
User Interface
Support machine notice banner in restore dialog
Support staff will see an amber banner explaining when they're viewing backups across multiple stores.
-
User Interface
Support machine notice banner added to restore dialog
Support machines will see a yellow notice explaining that they can view backups from all stores in the organization.
-
User Interface
Conditional visibility for support features
Store computers will no longer see support-only options in the Restore Database screen.
-
User Interface
Download progress shown during click-to-restart
If a newer update needs to be downloaded when you click to restart, you'll see a progress bar showing the download status.
-
User Interface
Added Issue Contact menu item
Added a new "Issue Contact" menu item with a contact icon under the Help > Support Issues submenu, positioned below "Submit New Issue" for easy access to contact information management.
-
User Interface
Quick Find dialog auto-sizes to content
The Quick Find search box now automatically sizes itself to fit its content instead of using a fixed size.
-
User Interface
Persistent view toggle with radio buttons
Two radio buttons labeled "Bubbles" and "Thread" appear at the top-right of the chat area, allowing instant switching between the two conversation layouts. The selected view is saved via the new SupportCommentUseBubbleView setting and restored when reopening the Support Issues screen, so each user's preference persists across sessions.
-
User Interface
Avatar initials and enhanced sender identification
Messages now show who sent them more clearly, with support team messages labeled "(Support)" and your messages labeled "(User)".
-
User Interface
Improved attachment upload feedback
When sending multiple files, you'll see upload progress displayed, and if something goes wrong you'll be told which specific file had the problem.
-
User Interface
Enhanced upload progress messages
You'll now see detailed progress messages showing compression and upload status when attaching files to support requests.
-
User Interface
Compression progress feedback
The Support Tools screen now displays real-time compression progress when preparing large files for upload, showing both percentage complete and the original file size in megabytes. This provides transparency during what might otherwise appear as an unresponsive delay for very large attachments.
-
User Interface
Store Information section now hidden until database selected
The setup form is now simpler—just select your SQL Server and database to get started. Store details will appear after you connect.
-
User Interface
Improved backup completion dialog
The backup summary now has a "Show in Explorer" button that opens File Explorer and highlights your backup file, making it easier to find.
- User Interface New support documentation for large sector drive compatibility
-
User Interface
Updated progress messages for batch mode
The Main Table progress display now shows "Processing X SKU Level Exceptions (batch mode)..." instead of "(X groups)..." to reflect the new processing approach, giving users clearer insight into the performance optimization in use.
-
User Interface
Backup dialog now shows correct list of custom views
When creating a backup, you'll now see all your custom views listed in the backup options.
-
User Interface
Script action buttons now conditional
The Installation Scripts dialog now shows different action buttons based on script type: PowerShell scripts show "Execute Script" with a launch icon, while SQL scripts show "Copy to Clipboard" with a copy icon. Status messages updated to guide users to paste and execute SQL scripts in SSMS after copying.
-
User Interface
Enhanced issue tooltip
The support issue pill tooltip now displays the issue status alongside the title and ID, making it easier to see the current state of each issue without opening the full support dialog.
-
User Interface
Upgraded network scanner with response time display
The network scan now shows all available MySQL servers at once with their response times, so you can pick the fastest one with a double-click.
-
User Interface
Progress and error feedback
The submission dialog shows clear progress and provides detailed feedback if any files fail to upload.
-
User Interface
Download progress now shows speed and estimated time
You can now see how fast the download is progressing and how much time is left.
-
User Interface
Simplified POS Store Number display
The POS Store column now shows store numbers in a simpler format.
-
User Interface
Script documentation with troubleshooting guide
The script includes built-in help and troubleshooting steps if the installation encounters problems.
-
User Interface
Improved Store Manager RSC auto-population logic
The Store Manager screen will now show RSC codes for more stores automatically, reducing manual data entry.
-
User Interface
Close buttons now trigger auto-save
Both the Close button and File → Close Window menu command in the Store Manager now use the new auto-save behavior, ensuring consistency across all exit paths from the screen.
-
User Interface
Tabbed interface replaces hidden Shift-key mode
Store contacts and support representatives now appear in separate tabs, making it easier to find and select the right person. You no longer need to hold Shift when opening the Submit Issue dialog.
-
User Interface
Settings screen updated
Look for the new "Store Number Display & Sorting" section on the Connections settings screen to customize how store numbers appear.
-
User Interface
Visual feedback during automatic repair
If the app needs to repair itself, you'll see a window explaining what's happening so you know the app is fixing itself and will reopen shortly.
-
User Interface
Window placement validation
Added validation to ensure saved window positions are still visible on current monitors. Windows are automatically repositioned if their saved location would be off-screen (e.g., after disconnecting a secondary monitor). Validation checks that at least 100 pixels of the window overlap a monitor's working area.
-
User Interface
Visual feedback for connection validation state
The Database Setup window now provides clear visual feedback about connection status through button states. Connection validation occurs automatically when testing connections, loading existing databases, or selecting servers from the dropdown.
-
User Interface
Enhanced Database Setup window layout
Reorganized the Database Setup window to show the store information panel only when connecting to an existing database with saved credentials. Added the new Demo Database and Submit Issue buttons to both the toolbar menu and the main action area. When an error occurs, a clickable "Report this issue" link now appears next to the error message for quick access to support.
-
User Interface
Updated backup success message
After backing up, you'll see a simpler confirmation message showing your local backup file and when it was saved to the cloud.
-
User Interface
Enhanced startup diagnostics display
The diagnostic screen now shows clearer information about your database connection and store license when it starts up.
-
User Interface
Enhanced AI chat experience
The AI chat tab now displays rotating "thinking" phrases (Computing, Reasoning, Cogitating, etc.) with elapsed time while the AI processes requests. Added prominent database connection status display showing active database and server name at startup. The terminal now shows detailed startup diagnostics including database connection, store identity, and license status.
-
User Interface
Real-time connection test status
You'll now see status updates while the connection test runs, showing exactly what step is being tested.
-
User Interface
Updated update notification layout
The update notification dialog has been redesigned to accommodate the idle progress bar, countdown panel, and What's New button. The dialog height increased from 280 to 340 pixels to fit all elements comfortably without crowding.
-
User Interface
Consolidate store management dialogs
Store Manager dialog now handles all store types using a single, consistent interface.
-
User Interface
Warning shown for contacts missing email addresses
Contacts without email addresses now show a "Please add email address" warning so you know which ones need updating.
-
User Interface
Contact email validation warning
Contacts missing an email address now show a warning message to help you identify incomplete contact information.
-
User Interface
Show deleted contacts option
You can now see previously deleted contacts by checking "Show Deleted" at the bottom of the Store Contacts tab.
-
User Interface
DPI-aware window sizing and validation
All window coordinates are now properly converted between physical pixels (used by Win32 APIs) and WPF device-independent pixels (DIPs). The system validates that saved window positions are at least partially visible on current monitors, with a minimum 100-pixel overlap requirement to prevent windows from appearing off-screen after monitor configuration changes.
-
User Interface
Real-time connection test status display
When testing your connection, you'll now see what step is being tested in real-time instead of just a generic "please wait" message.
-
User Interface
Connections tab redesign
The INDecoded scanner has been replaced with a "Store Manager" button that opens a dedicated screen for all store configuration tasks.
-
User Interface
Layout improvements for startup dialogs
Setup windows now handle long messages and lists better without cutting off important information or buttons at the bottom of the screen.
-
User Interface
System Diagnostics submission integration
When viewing System Diagnostics, you can click "Submit to Support" to automatically create a support ticket with all your system information already included.
-
User Interface
Store grouping integration
Enable "Use Store Grouping" to assign zones and manage multiple stores as a group. Zone changes in a group automatically apply to all member stores.
-
User Interface
Fixed content overflow in startup dialogs
Setup screens no longer have buttons pushed off the bottom when showing long error messages or status updates.
-
User Interface
Renamed "Add New Contact" to "Create New"
Changed the button label from "Add New Contact" to "Create New" for consistency and brevity in the updated interface layout.
-
User Interface
Store identity verification improvements
Store identity verification now uses the full license detail API endpoint, displaying license expiration date, store count, and validation status. Background verification confirms license status after the main window loads without blocking startup. Identity cached from the database now takes precedence over the fallback JSON cache.
-
User Interface
Dynamic contact picker header text
The contact picker dialog header text is now configurable, allowing different messages when selecting contacts to CC versus adding support representatives.
-
User Interface
BackupRestoreStrategyOptionsViewModel tree mode initialization
New InitializeV3ForBackupAsync() and InitializeV3ForRestore() methods build tree structure from database inventory or backup file contents. BuildOptionsFromTree() translates tree checkbox states into BackupRestoreOptions with item-level filters. UseTreeView property controls whether legacy flat checkbox list or new tree view is rendered.
-
User Interface
AI assistant system prompt enhancements
The Claude AI assistant's system prompt now includes detailed tool workflow documentation for SQL Express upgrades, SSMS installation, and Margin Master updates, with specific guidance on when to use each tool, how to handle UAC prompts, and how to diagnose common failures like NVMe sector size issues or missing C++ redistributables.
-
User Interface
Settings tab integration
Store exclusions are now managed in Store Manager instead of the old Import Exclude field in Settings.
-
User Interface
Enter key sends AI messages
Pressing Enter in the Claude AI input box now sends the message immediately instead of inserting a newline. Use Shift+Enter for multi-line input.
-
Database
Updated default SQL Server instance name
The default DatabaseConnections.json file now specifies ".\SQLEXPRESS" as the server name instead of "." (local default instance). This change only affects new installations or when the connection configuration is recreated, and better aligns with the typical SQL Server Express setup used by retail hardware stores.
-
Database
Migrate MySqlStoreManagerInfo to StoreManagerInfo
Store configuration now uses a single database table for all POS systems instead of separate tables for MySQL stores.
-
Database
New Duplicate store status type
The store status classification now includes a fourth option "Duplicate" (value 3) to identify stores that are duplicate entries. The existing status types (Open, Closed, Other) have been assigned explicit integer values (0, 1, 2) to prevent data corruption if the list is reordered in future updates.
-
Database
Added contact phone number storage
Extended ApplicationSettingsService to store and retrieve a contact phone number in addition to existing first name, last name, and email fields. This phone number is now saved to the database and persists across sessions.
-
Database
Safe deletion workflow for cost break models
The script enforces a safe workflow by providing SELECT queries first to preview what will be deleted, with all DELETE statements commented out by default. It includes a verification query to check remaining models after deletion, and warns users to close Margin Master before running to avoid database conflicts.
-
Database
Prevent cascading index damage from degraded view state
Added a check for the SavedViewsLoadFailed flag before running RemoveStaleIndexesAsync. This prevents cascading damage when the app is operating with a fallback selection box view that has fewer fields than the user's actual custom view. The stale index removal now only runs when the full set of saved views has been successfully loaded, ensuring index cleanup decisions are based on accurate field usage data.
-
Database
Added version tracking to issue notifications
Added ResolvedInVersion field to the OpenIssueOption data model to track which app version contains the resolution for each support issue, enabling version-aware filtering of issue notifications.
-
Database
Added version tracking to issue records
Added ResolvedInVersion field to the OpenIssueOption model to track which version of Margin Master resolved each issue, enabling version-aware filtering of issue notifications.
-
Database
Seed data insertion now idempotent and safe for re-runs
Rewrote the initial data insertion logic to use INSERT WHERE NOT EXISTS semantics for the About, GlobalFileConfig, and ApplicationSettings tables. This allows the schema initialization process to run safely against empty databases, partially-initialized databases, or fully-populated databases without creating duplicate rows or overwriting existing configuration.
-
Database
Database initialization is now idempotent
Rewrote the initial data insertion logic to use INSERT...WHERE NOT EXISTS semantics across the About, GlobalFileConfig, and ApplicationSettings tables. This makes schema bootstrapping safe to run against empty, partially-initialized, or fully-populated databases without creating duplicate rows or overwriting existing configuration. The new EnsureDatabaseSchemaInitializedAsync method can be safely invoked multiple times on the same database.
-
Database
SQL service account detection
Implemented automatic detection of the SQL Server service account by querying sys.dm_server_services at startup. The system recognizes well-known accounts like LocalSystem and NETWORK SERVICE that already have default access, and can identify custom service accounts (like "NT SERVICE\MSSQL$INSTANCE") that need explicit permission grants.
-
Database
Standardized EpicorStoreNumber column collation
Updated the MySqlStoreManagerInfo table creation script to explicitly set the EpicorStoreNumber column collation to Latin1_General_CS_AS, matching the collation used in Compass_IN tables. This ensures new database installations won't encounter the collation mismatch issue.
- Database SQL Server 2022 support removed from upgrade script
-
Database
Cost break data management
Provides database administrators with a supported method for cleaning up cost break model data when needed during troubleshooting or data correction scenarios.
-
Database
Add UpdateDate field to issue data model
The OpenIssueOption data model now includes an UpdateDate property to track when issues are modified, supporting the updated display and sorting behavior in the Support Issues screen.
-
Database
StoreManagerInfo table and migration
Store configuration is now saved in a new unified database table, with automatic migration from your existing settings on first use.
-
Database
Add license storage fields to ApplicationSettings
Three new ApplicationSettingKey values (IPWorksLicenseFTP, IPWorksLicenseSSH, IPWorksLicenseZip) were added to store nsoftware IPWorks runtime licenses in the local database, enabling offline operation after the first successful cloud fetch.
-
Database
New settings for license persistence
Added three new application settings (IPWorksLicenseFTP, IPWorksLicenseSSH, IPWorksLicenseZip) to store runtime licenses locally. These are automatically populated whenever cloud licenses are successfully retrieved and used as a fallback tier when cloud services are unreachable.
-
Database
Auto-disable orphaned managed indexes
The system now automatically disables managed indexes that reference columns no longer present in the database (such as Formula2/Formula3 after table rebuilds) instead of attempting to recreate them on every startup. This prevents repeated SQL errors 207 and 1911 and improves startup performance.
-
Database
Obsolete setting cleanup
Added a database update routine that removes the obsolete HasMultipleRSCs entry from the ApplicationSettings table during startup. This cleanup runs automatically through June 19, 2026 to handle existing installations, after which the setting will no longer exist in any database.
-
Database
System initialization markers remain idempotent
Preserved the INSERT WHERE NOT EXISTS pattern for System configuration markers (Initialized, CreatedViaEFCore) in GlobalFileConfig, ensuring these timestamp-based values are not overwritten on re-initialization while store identity settings are properly updated.
-
Database
Automatic database repair for legacy store matchup values
Added automatic one-time repair logic (NormalizeLegacyStorematchupOrdinalsAsync) that runs at startup to normalize legacy STOREMATCHUP values in the GlobalFileConfig table from raw characters to ordinal format. The repair only updates rows that actually need normalization and logs each change for audit purposes.
-
Database
Support comment tracking enhancement
Added `IsFromSupport` boolean field to the `IssueCommentForDev` model to reliably distinguish between customer-originated and support team-originated comments, replacing the previous string-based comment type parsing logic. This provides more accurate message direction determination for the new chat bubble alignment and styling.
-
Database
Obsolete setting cleanup
DatabaseUpdateService now includes RemoveObsoleteSettingsAsync, which deletes the HasMultipleRSCs row from ApplicationSettings during startup for installations running before June 19, 2026. This cleanup is automatically performed during the field mappings update phase.
-
Database
StoreManagerInfo table and automatic migration
Your existing store mappings and settings are automatically transferred to the new Store Manager system.
-
Database
Improved database existence check
Database existence checks during restore now use async parameterized queries instead of synchronous string concatenation, improving security and preventing UI blocking.
-
Architecture
Added complete-submission API endpoint call
Introduced a new API call that the WPF client makes after uploading all attachments to signal the server to send the creation notification email. This two-phase submission process (create issue + upload attachments → trigger notification) ensures email accuracy.
-
Architecture
New API endpoint for completing issue submission
Added `CompleteIssueSubmissionAsync` method to the API client service that calls the `/api/issues/{issueId}/complete-submission` endpoint. This endpoint signals the server that all attachments have been uploaded and it's safe to send the creation notification. The workflow only applies to new issues; updates continue to send notifications immediately.
-
Architecture
Remove MySqlStoreManagerInfoViewModel and related dialogs
Deleted MySqlStoreManagerInfoViewModel, EpicorMySqlImportManagerViewModel, MySqlMissingRequiredInformationFixViewModel and their XAML views (4,157 lines removed). All MySQL store management now uses the unified StoreManagerViewModel and StoreManagerInfo entity, eliminating code duplication and simplifying maintenance.
-
Architecture
Exposed condition conversion method
Made the ConvertConditions method public in StrategyStepService to enable the view model to rebuild condition display models after programmatic modifications to the instruction set.
-
Architecture
Discrete backup sections replace lumped configurations
Introduced dedicated model classes (BackupCostBreak, BackupMinMaxStrategy, BackupMinimumMargin, BackupSelectionBoxView, BackupColumnView, BackupCustomFieldName, BackupCustomSortOrder, BackupStoreMatchUp) to replace generic GlobalFileConfig entries. Added BackupInventoryService to query available items from the database for population of the tree view. V2ToV3Mapper handles automatic conversion of legacy backups by extracting discrete sections from lumped V2 fields.
-
Architecture
New schema initialization helper for existing databases
Added EnsureDatabaseSchemaInitializedAsync method to DatabaseCreatorService that exposes EF migration application, seed data insertion, and schema verification as a standalone, idempotent operation. This helper can be invoked by any component that needs to ensure an existing database has the full MarginMaster schema without risking data loss or duplication.
-
Architecture
Added public schema initialization method
Introduced IDatabaseCreatorService.EnsureDatabaseSchemaInitializedAsync as a public interface for idempotently applying EF migrations and seed data to an existing database connection. This complements the existing CreateDatabaseAsync method (used by the New Database wizard) and enables other code paths—like the Store Configuration dialog—to ensure schema readiness without creating a new database file.
-
Architecture
RSC detection logic consolidated
All code paths that previously checked the HasMultipleRSCs setting now use the derived check (counting distinct RSC values in STORERSC data). This affects Cloud Sync, Data Aging analysis, vendor data sync, store matchup screens, and vendor data cleanup routines. The logic is consistent across 18 files including DatabaseService4, StoreDataService, CloudSyncServiceShim, and multiple ViewModels.
-
Architecture
Support machine detection in settings service
The IsSupportMachine flag, previously only tracked in MainMMViewModel, is now also stored in ApplicationSettingsService and set during startup. This allows the restore dialog and other components to check support machine status without coupling to the main view model.
-
Architecture
Feature flag synchronization with UI state
BackgroundServiceTabViewModel now tracks IsFeatureEnabled as a property mirroring the database flag, and provides SetFeatureEnabledAsync to persist changes. When enabled, the view model automatically refreshes service status and run history. The runtime coordination components (banner poller, Windows service) continue to key off the same database flag.
-
Architecture
Window placement stored in local JSON files
Window placement data is saved to local JSON files in the application data directory rather than the database. This eliminates potential deadlocks during application shutdown and ensures window positioning works even if database sync is in progress. The placement file is written synchronously during window close, making it safe and reliable.
-
Architecture
Centralized backup metadata provider
Created IBackupMetadataProvider service to consolidate metadata creation and ZIP compression logic. This ensures all backup operations capture consistent metadata (vendor, store, POS system, database name, version) and handle compression identically, eliminating code duplication across the five different backup scenarios.
-
Architecture
Refactored comment display converters
Removed separate CommentAlignmentConverter and CommentCornerRadiusConverter classes, consolidating message styling logic. Added CommentTemplateSelector to automatically choose between system activity templates and human message templates based on sender name. Streamlined CommentSenderLabelConverter to handle new naming conventions.
-
Architecture
Synchronous placement save during shutdown
Window placement is saved using synchronous file I/O during window close to avoid UI thread deadlocks during application shutdown. Placement data is stored in a local JSON file (last-mainwindow-placement.json) in the common application data folder, independent of the database.
-
Architecture
IsFromSupport flag replaces comment-type parsing
The API response model now includes an explicit IsFromSupport boolean flag on each comment, replacing the previous approach of parsing comment type strings to determine message alignment and styling. This simplifies the UI logic and makes the distinction between user and support messages more reliable. New converters handle alignment, colors, corner radius, initials, and sender labels based on this flag.
-
Architecture
Refactored connection testing logic
Moved connection testing logic from frmOptions code-behind into MySqlConnectionDetailViewModel, improving testability and separation of concerns. Added MySqlServerScanResult model to encapsulate scan results with response times.
-
Architecture
Consolidated connection testing logic
Removed approximately 100 lines of duplicated connection test code from frmOptions.xaml.cs. The legacy form now delegates save and test operations to MySqlConnectionDetailViewModel, ensuring both the old and new Options windows use identical validation and retry logic.
-
Architecture
Store detail and zone edit popups
Adds StoreDetailViewModel and StoreDetailView for read-only display of cloud store state (StoreStatus, IsPrimaryStore, CloudStoreId, StoreStatusLastSync). Adds StoreZoneEditViewModel and StoreZoneEditView for zone override editing with live preview of effective zone. Both are launched as modal dialogs from the Store Manager grid via dedicated view services.
-
Architecture
BackupRestoreOptions extended with V3 section flags and item filters
Added ProcessCostBreaks, ProcessMinMaxStrategies, ProcessMinimumMargins, ProcessSelectionBoxViews, ProcessColumnViews, ProcessCustomFieldNames, ProcessCustomSortOrders, ProcessStoreMatchUps flags. Added SelectedStrategyNames, SelectedRoundingSchemeNames, SelectedCostBreakNames, SelectedMinMaxStrategyNames, SelectedSelectionBoxViewNames, SelectedColumnViewNames nullable lists—null means include all, empty means none, populated means only named items.
-
Architecture
Diagnostic result skip state
DiagnosticResult now supports a `Skipped` state with a `SkipReason` field, allowing modules to report when they were skipped (e.g., user cancelled file selection) without reporting false failures.
-
Infrastructure
Cost break model deletion script
Added a SQL script to safely delete cost break models from the database. This administrative tool can be used for database maintenance tasks such as removing outdated or incorrect cost break configurations.
-
Infrastructure
Optimized update package compression
When Margin Master updates itself, the download will be smaller and faster than before.
-
Infrastructure
Local encrypted license cache for third-party components
Z.Dapper.Plus, Z.BulkOperations, and IPWorks licenses are now served from a local encrypted cache on startup, falling back to the API only on cache miss or validation failure. This eliminates unnecessary API calls on every application launch, speeds up startup, and improves offline reliability. When a license validation fails, the cache is automatically invalidated and refreshed from the API, ensuring the next startup receives fresh keys.
-
Infrastructure
Removed automatic .NET runtime verification from installer
The Velopack installer previously checked for and attempted to install the required .NET 10.0 desktop runtime during setup. This check has been removed to streamline the installation process and avoid conflicts with existing runtime installations. Users must ensure the appropriate .NET runtime is installed separately if not already present.
-
Infrastructure
Support tools directory enhancement
The script is stored in the scripts/SqlScripts directory and includes comprehensive inline documentation, safety instructions (requiring Margin Master to be closed before running), and a two-step process (preview first, then delete) to prevent accidental data loss.
-
Infrastructure
Database lock contention handling enhanced
Modified GlobalFileConfigService to use DataModification operation type instead of StandardQuery for critical startup paths. This change provides longer wait times for database locks that protect configuration data used throughout the application, particularly during the initialization phase when strategies and indexes are being loaded.
-
Infrastructure
Reduced log severity for transient network failures
Network timeouts and connection errors when fetching open issues now log as warnings instead of errors. Since open issues are a non-critical UI enhancement, temporary failures are expected and shouldn't be treated as application errors.
-
Infrastructure
Added typed POST request support to API client
Added PostAndGetAsync<TRequest, TResult> method to IApiClientService and ApiClientService to support strongly-typed POST requests with JSON request bodies and deserialized response objects. This provides a cleaner API for the new Manager update check-in endpoint and future typed POST operations.
-
Infrastructure
Enum value stabilization
Store status types now use explicit integer values to ensure data consistency. This prevents potential data mismatches if the enum order changes during future development.
-
Infrastructure
Build pipeline updated for self-contained deployment
The GitHub Actions workflow and project configuration were updated to publish the bootstrapper as a self-contained application, bundling the .NET runtime directly into the setup executable.
-
Infrastructure
Backup failures excluded from telemetry
Database backup path failures are now classified as environmental issues (specific to each store's network and SQL Server configuration) rather than application bugs. These errors are still logged locally and shown to the user, but are no longer reported to the error telemetry API, reducing noise in bug reports.
-
Infrastructure
Startup self-heal service with minimal dependencies
Created a new StartupSelfHealService that depends only on .NET BCL and WPF framework libraries, with no MarginMaster assembly references, since those assemblies may themselves be corrupted. The service integrates into three startup failure paths: App constructor exceptions, startup checks failures, and terminating AppDomain exceptions. A state file at the install root tracks repair attempts, and the counter is cleared on healthy startup.
-
Infrastructure
SQL injection protection for wildcard characters
Updated the SQL validation pattern to allow asterisk characters (*) in filter values, enabling proper wildcard support while maintaining security protections.
-
Infrastructure
Critical-path database operations with retry logic
Added new critical-path database operation methods to GlobalFileConfigService that use longer timeouts and exponential backoff retry logic for loading essential startup configuration like selection box views and column views. This prevents transient database lock contention from causing silent failures in critical user-facing features.
-
Infrastructure
Parallel cloud container scanning with progress tracking
Cloud backup scanning now processes multiple store containers concurrently (up to 4 at a time) with a semaphore-based throttling mechanism. The loading message dynamically updates to show "Scanning store {VendorShort} {StoreNumber} ({current}/{total})..." when scanning multiple stores, or the simpler "Scanning cloud backups..." for single-store scenarios.
-
Infrastructure
Backup folder ACL caching
Added three new application settings keys (BackupFolderAclAttemptedFor, BackupFolderAclAttemptedDate, BackupFolderAclGrantSucceeded) to track permission grant attempts. The system stores a fingerprint combining the SQL service account name and backup folder path, ensuring permission grants are retried only when the configuration changes, not on every application launch.
-
Infrastructure
ACL inspection and elevation
Added NTFS access control list inspection to verify existing folder permissions, and integrated icacls-based permission granting with UAC elevation. The system gracefully handles declined UAC prompts (Win32Exception 1223) and never blocks application startup if permission checks fail.
-
Infrastructure
PowerShell script step renumbering
Step numbers in both Install-SQLExpress.ps1 and Upgrade-SQLExpress.ps1 have been incremented to accommodate the new Visual C++ verification step (now Step 2), ensuring documentation and console output remain synchronized.
- Documentation Added comprehensive large sector drive compatibility guide
-
Infrastructure
Improved nullable reference type handling
Updated DatabaseConnectionResult class to properly handle nullable reference types, improving code safety and eliminating potential null reference issues during database connection workflows.
-
Infrastructure
Enhanced error logging for database cleanup operations
Added detailed logging when dropping orphaned databases, including warnings if cleanup fails. This helps diagnose scenarios where manual SQL Server cleanup may still be required due to locked connections or permission issues.
-
Infrastructure
Three-tier license fallback strategy
Component licenses now follow a three-tier fallback: (1) local encrypted cache (fastest), (2) Blazor Manager API (fresh keys), and (3) appsettings.json base64 values (offline fallback baked in at build time). This ensures maximum reliability across network conditions while minimizing startup latency.
-
Infrastructure
Component license cache service registration
The new ComponentLicenseCache service is now registered in the dependency injection container and integrated with IPWorksLicenseService and StartupCheckService, providing a centralized encrypted storage mechanism for all third-party component licenses.
-
Infrastructure
Added bootstrapper error telemetry
The bootstrapper now automatically reports errors (exception type, message, stack trace fingerprint, OS version) to a telemetry endpoint. This enables the development team to diagnose installation failures in the field without requiring users to manually submit logs. No personally identifiable information is collected.
-
Infrastructure
Server API integration for issue deletion
Implemented new API endpoint integration at `/api/issues/{issueId}/delete-from-app` that sends store number and vendor ID for server-side ownership verification. The operation includes proper error handling, logging, and timeout configuration (15 seconds) consistent with other API operations.
-
Infrastructure
Separate cache keys for support employee contacts
Modified the cache key system to distinguish between regular store contacts and those that include support employees, ensuring proper cache management for different contact query types.
-
Infrastructure
Support machine detection exposed to application settings
The IsSupportMachine flag, previously only tracked in the main view model, is now exposed through the ApplicationSettingsService interface and set during startup. This allows other parts of the application to conditionally adjust behavior based on whether the installation is a support machine.
-
Infrastructure
Added 15 unit tests for wildcard filter behavior
Added WildcardFilterTests with 15 new test cases covering operator selection (LIKE vs NOT LIKE), preservation of plain value equality filters, and correct handling of wildcard-only patterns. Tests verify patterns like "81%" and "%ARD%" produce the correct SQL operators while bare wildcards are skipped, and that plain values retain their equality operators.
-
Infrastructure
Debug startup profile chooser (developers only)
Added a debug-only window that appears before the splash screen in Debug builds, allowing developers to simulate any startup scenario: new install with no SQL, stopped SQL service, expired license, missing database, no internet connection, multiple SQL instances, old SQL versions, etc. Developers can "remember" a profile to auto-apply it on subsequent launches, or hold Shift at startup to force the chooser to appear. This replaces the previous appsettings.json-based scenario flags with a visual selector that combines all three scenario types (connection, license, scanner) into 11 pre-built profiles like "Brand New Install," "SQL Stopped," "Expired License," and "Lost Server."
-
Infrastructure
Display formatter with unit tests
Created StoreNumberDisplayFormatter helper class with comprehensive unit tests to ensure display labels are correctly formatted for all four display modes and that missing POS mappings gracefully fall back to showing the vendor store number.
-
Infrastructure
Reorganized script embedding and documentation structure
PowerShell scripts are now organized in category subfolders (scripts/SqlScripts/Powershell/, scripts/OLEDB/Powershell/) and embedded using a recursive glob pattern. Each script now requires accompanying markdown documentation in both the scripts/ folder (developer reference) and docs/marginmaster/support/scripts/ (user-facing support docs), with corresponding index.json entries.
-
Documentation
Support documentation updated with LargeSectorFix troubleshooting
All four documentation files (two markdown docs in /docs/marginmaster/support/scripts/ and two in /scripts/SqlScripts/Powershell/) have been updated with new parameter descriptions, usage examples, and a troubleshooting row for error 0x851A001A. Users encountering setup failures related to LargeSectorSizeCheck will now find clear guidance to re-run with the fix enabled.
-
Infrastructure
Blob migration utility
Added MarginMaster.BlobMigration console project to migrate existing strategy backups from Azure blob storage to the new SQL system. Supports both ZIP and JSON blob files, auto-detects V1/V2/V3 formats, and preserves original backup timestamps during migration.
-
Infrastructure
Documentation updates for auto-update behavior
Updated auto-updates.md and search index to document the new idle auto-trigger, countdown, and What's New features. Added FAQ entries explaining how the countdown works and what happens when Cancel is clicked.
-
Infrastructure
SSMS detection service and PowerShell script enhancements
Added new ISsmsDetectionService and SsmsDetectionService that scan Windows registry uninstall keys to detect installed SSMS versions and validate against minimum version requirements (v22). Enhanced Install-SSMS.ps1 and Upgrade-SSMS.ps1 PowerShell scripts with new -LogFile parameter to support real-time transcript output for progress monitoring. Updated scripts to automatically reuse cached installers when running non-interactively from the WPF UI. Fixed SqlExpressMigrationService to properly hide elevated PowerShell windows using WindowStyle.Hidden.
-
Infrastructure
SSMS detection debug scenario support
Extended SsmsDetectionService with debug scenario infrastructure matching the existing patterns for connection, license, and SQL scanner testing. Added configuration support via appsettings.Development.json "SsmsScenario" key with values Normal, NotInstalled, and NeedsUpgrade.
-
Infrastructure
Comprehensive restore logging
Added detailed logging throughout the entire restore pipeline, including download milestones, SQL restore progress, error conditions, and recovery attempts for better troubleshooting and monitoring.
-
Infrastructure
PowerShell script execution improvements
Enhanced Install-SSMS.ps1 and Upgrade-SSMS.ps1 with -LogFile parameter support for real-time transcript tailing. Modified PowerShell invocation to use WindowStyle.Hidden instead of CreateNoWindow when UseShellExecute is enabled, properly suppressing console windows. Added automatic reuse of cached installers when running non-interactively from the WPF application.
-
Infrastructure
Legacy class preservation
Preserves MySqlStoreManagerInfo and STOREMATCHUP access for non-migrated users. StoreManagerInfoMigrated flag guards against re-migration. Cleanup of old classes planned for future release after migration verification period.
-
Infrastructure
Added command-line debug profile support
Debug builds can now auto-apply a startup profile via --debug-profile N command-line argument, skipping the debug chooser dialog entirely for automated testing scenarios.
-
Infrastructure
PowerShell script embedding
SQL Server and SSMS installation scripts (Install-SQLExpress.ps1, Upgrade-SQLExpress.ps1, Install-SSMS.ps1, Upgrade-SSMS.ps1) are now embedded as content files and copied to the DiagnosticTool output directory for reliable script execution.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Automatic self-repair for corrupt installations; Automatic cloud backup of validated POS connections; Automatic cloud backup of validated POS connections.
Strategy & Pricing
-
New Feature
Margin Master database connection cloud backup
Your Margin Master database connection is now automatically saved to the cloud after importing data.
-
New Feature
Per-store pricing support for Mi9 installations
When single-table mode is enabled in Settings, Mi9 stores can now analyze and manage pricing individually for each location rather than being grouped by team, giving you finer control over store-specific pricing strategies.
-
New Feature
MI9 single main table processing mode
MI9 stores can now switch to a processing mode that lets each store have its own prices instead of sharing team prices.
-
New Feature
Unpriced SKU report added to strategy execution logs
After running a pricing strategy, the log file will now show you exactly which items didn't get priced and whether it's because they're missing a cost in your POS system or because your strategy doesn't have a step that matches them.
-
New Feature
Unpriced SKU report after strategy execution
After running a pricing strategy, the execution log will show how many items received no pricing rule and explain whether it's because they have no cost in your POS data or because no pricing step matched them.
-
New Feature
Sort by Name button for custom groups
Click the new "Sort by Name" button to arrange all custom groups alphabetically. This changes the order they run in, so remember to Save if you want to keep the new sequence.
-
New Feature
Sort groups alphabetically by name
You can now click "Sort by Name" to instantly arrange all your custom groups in alphabetical order.
-
New Feature
Restore and apply Margin Master database
Restoring a Margin Master database connection automatically switches you to that database and prompts you to restart the application to complete the change.
-
New Feature
One-click Margin Master database restore and switch
You can now restore your Margin Master database connection with one click — the app will switch to it and prompt you to restart.
-
Improvement
Store matchup sourced from unified store manager
When the StoreManagerInfo system is active, POS-to-vendor store number mappings are now read from StoreManagerInfo.VendorStoreNumber and PosStoreNumber instead of GlobalFileConfig STOREMATCHUP entries. The data is automatically shaped to match the existing format, ensuring all import readers continue working without changes while using the authoritative source.
-
Improvement
Custom Groups load performance and progress feedback
When opening Manage Custom Groups, you'll now see exactly how many groups are loading and the window won't freeze during the process.
-
Improvement
Informative messages for Load SKU Exceptions
When you click Load SKU Exceptions, you'll now get a clear message if no strategy is active or if the current strategy has no exceptions defined, so you know why nothing loaded.
-
Improvement
Enhanced startup logging for vendor data checks
Added detailed logging to the vendor data availability check at startup, recording why the system did or did not download/rebuild data. This provides clear audit trails showing whether the startup followed the fresh-install path (download + rebuild) or the upgrade path (data already present, freshness verified separately), making it easier to diagnose pricing-related issues from field logs.
-
Improvement
Added heartbeat timer to show progress during long operations
During long operations, you'll now see a running timer showing how long the operation has been working, so you know the system hasn't frozen.
-
Improvement
Zone override configuration from unified store manager
Zone number overrides during import now read from StoreManagerInfo.ZoneNumberOverride (applied across all nine departments per store) when the unified system is enabled. Previously, these overrides were stored only in GlobalFileConfig ZONE_OVERRIDE entries. This change centralizes zone pricing configuration alongside other store settings.
-
Improvement
Defensive null handling in SKU write-back
Added null-coalescing guards to all SKU Detail ViewModel collection accesses during the write-back phase, preventing potential crashes when the SkuViewModels collection is null during edge-case dialog lifecycle scenarios.
-
Improvement
Dramatically faster saves when reordering custom groups
Saving after reordering custom groups is now much faster, especially if you have many groups defined.
-
Improvement
Custom Groups save optimized for reordering
Reordering groups now saves much faster, and the window shows progress instead of freezing during save.
-
Improvement
Better error messages for misconfigured strategy steps
When viewing strategy execution logs, skipped steps now show clear instructions on what needs to be fixed, including exactly which setting to configure in the strategy editor.
-
Improvement
Cloud sync fails fast when network or Manager API is unreachable
When your store loses internet connection during sync, Margin Master will now detect this immediately and stop trying instead of slowly testing each table, making sync respond faster when you're offline.
-
Improvement
Better feedback for Load SKU Exceptions
Loading SKU Exceptions now tells you when there are no exceptions to load, instead of appearing to do nothing.
-
Improvement
Zone pricing updates now display per-zone progress
When updating zone pricing, you'll now see which specific zone is being processed instead of a blank screen for several minutes.
-
Improvement
Auto-skip strategy steps with no matching data
When a pricing step's filters don't match any items in your current data, the system will automatically skip it instead of stopping to ask what you want to do.
-
Improvement
Sequence numbers now auto-heal gaps from deleted groups
When custom groups are deleted, the ManageCustomGroupsViewModel now automatically renumbers the remaining groups to close gaps (e.g., 1,2,5,7 becomes 1,2,3,4) so the displayed sequence number always matches the row position. The normalized values reach the database on the next save.
-
Improvement
Automatic sequence normalization on load
Custom group sequences are now automatically normalized when the window opens, healing gaps and duplicates left by deleted groups (e.g., 1, 2, 5, 7 becomes 1, 2, 3, 4). This ensures the displayed sequence number always matches the row position without requiring manual intervention.
-
Improvement
Enhanced save progress reporting
When saving many custom groups at once, you'll see accurate progress counts showing how many groups have been saved.
-
Improvement
Shared table name constants between import and UI
Extracted Mi9 table names into a new shared Mi9TableConstants class in MarginMaster.Common to ensure the import engine and UI always reference identical table names. This prevents potential drift between the components that build and consume the Mi9 pricing tables.
-
Improvement
Steps with no matching data now skip silently instead of prompting
If a pricing strategy step is set to filter by a value that doesn't exist in your current data (for example, a step earlier in the strategy hasn't run yet to create it), the system will quietly skip that step instead of stopping to ask what you want to do—since it wouldn't have changed anything anyway.
-
Improvement
Better error logging for group reordering
Move Up and Move Down operations now log exceptions instead of silently swallowing them, making it easier to diagnose issues with group reordering.
-
Improvement
Non-blocking cloud backup on close
Closing the Manage Custom Groups window after saving is now instant instead of waiting for the cloud backup to finish.
-
Improvement
Report when strategy execution runs with no rules defined
Strategy execution now warns in the log when a strategy has zero pricing rule steps, and the execution summary explicitly states "no steps ran — no prices were changed" instead of showing a misleading "✓ COMPLETED SUCCESSFULLY" message. The log now separately reports rule step count vs. total phases to make empty strategies immediately visible.
-
Improvement
Added comprehensive test coverage for Compass rebuild routing
Added CompassRebuildRoutingTests with 7 tests covering both the routing logic and the safety guards, including specific tests that pin the exact failure scenario reported by store 6324 (four Compass stores losing all main tables on a fresh database).
-
Improvement
Warn when active strategy is missing after restore
If the saved active strategy name doesn't exist after database load (case- and whitespace-insensitively), the app now logs a warning identifying which strategy was requested, which are available, and which fallback was selected, instead of silently switching strategies.
-
Improvement
Table name handling for single main table
Updated table name parsing throughout the application (Cost Break, Implementation Plan, Profit Analyzer, store change summaries) to recognize Mi9_mainTable and return "All Stores" or the "ALL" token instead of attempting to split the table name. Prevents the literal string "mainTable" from being reported as a store number.
-
Bug Fix
Corrected active PS Rule counting logic
When viewing a pricing strategy with no active rules, you'll now see a clear message stating the strategy has no PS Rules, instead of seeing an execute button that doesn't work.
-
Bug Fix
Automatic detection and repair of stale pricing data after upgrades
If your pricing grid shows outdated vendor costs after upgrading, the application will now automatically detect and fix this on the next launch, showing a "Refreshing pricing data..." message during startup.
-
Bug Fix
Splash screen now closes reliably after long startup operations
The startup screen now closes properly every time, even when database maintenance takes longer than usual.
-
Bug Fix
Splash screen now closes before modal dialogs appear
When opening pricing strategies or data aging tools, the loading message now properly disappears before the next window opens, preventing the app from appearing stuck.
-
Bug Fix
SKU Detail dialog crash with empty grid
You can now safely edit SKU pricing details from QuickFind even while the main grid is still loading data or temporarily empty.
-
Bug Fix
Zero-cost SKUs now consistently excluded from margin pricing steps
Previously, items with no cost might have been repriced to $0.02 or silently skipped. Now all no-cost items are consistently excluded from pricing, and you'll see a report explaining why they received no pricing rule.
-
Bug Fix
Zero cost now correctly treated as missing cost
Previously, SKUs with StoreCost=0 and Cost=0 were silently excluded from margin pricing steps but received no explanation in logs. The system treated NULL cost as "missing" but zero cost as valid, causing inconsistent behavior. Now both zero and NULL are treated identically as "no cost," and these SKUs are excluded from margin calculations with clear reporting explaining why they received no pricing rule.
-
Bug Fix
Custom group execution order now respects user sequence
If you rearranged custom groups with the Up/Down buttons to control which pricing rules run first, those groups were actually running in alphabetical order instead. This meant overlapping groups could apply the wrong prices. Now groups run in exactly the order you set, and that order is preserved when you reopen the window.
-
Bug Fix
Custom group order now persisted correctly
When you reorder custom groups using the Up/Down buttons and save, those groups will now appear in the same order the next time you open the window. Previously, they would reset to alphabetical order.
-
Bug Fix
Eliminated NullReferenceException in splash screen timer
Fixed a rare crash that could happen when quickly closing and reopening dialogs like Manage Custom Groups.
-
Bug Fix
Save button now works correctly after reordering groups
The "Saving Changes..." message now appears and updates while custom groups are being saved, so you know the program is working.
-
Bug Fix
Busy indicator now appears during save operation
You'll now see a progress message when saving custom groups as you close the window, instead of the screen appearing frozen.
-
Bug Fix
Pricing steps with exclusion filters no longer skipped after import
If you use pricing strategy steps with "not equal to" conditions (like excluding certain vendor rules or brands), those steps will now correctly apply pricing after you import fresh data from your point-of-sale system. Previously, these steps might have been skipped, leaving items without the correct pricing.
- Bug Fix Exclusion filter steps no longer incorrectly skipped
-
Bug Fix
PSRule filter matching corrected for pricing strategy steps
When configuring a pricing strategy step to only process items last touched by a specific earlier step (or to skip items from that step), the filter now works as intended instead of silently failing.
-
Bug Fix
PSRule filters now match both step name and step index formats
When you filter the pricing grid by a specific strategy step (like "Benjamin Moore"), it will now correctly show all items processed by that step, even if those items were originally processed months or years ago by an older version of the software.
-
Bug Fix
Strategy steps with no pricing action now skip instead of crashing
If a strategy step is missing its pricing instructions, the strategy will continue running instead of stopping completely. The step detail log will show "Skipped — No Pricing Action Configured" with instructions on how to fix the step by editing it and choosing a "Set Future Price To" option.
-
Bug Fix
Strategy steps with no pricing action now skip instead of failing
If a strategy step is missing its pricing instructions (no "Set Future Price To" level selected), Margin Master will now skip that step and continue running the rest of your strategy instead of stopping completely.
-
Bug Fix
Inactive strategy steps now report accurate timing
When a strategy step is disabled, it's added to the run results without executing. Previously, its duration was calculated at summary-write time, showing the elapsed time from step creation to summary (e.g., "6m 08s") instead of near-zero. Now inactive steps close immediately at construction, reporting "<1s" as expected.
-
Bug Fix
Inactive strategy steps now report correct duration
Previously, inactive steps accumulated phantom duration from when they were skipped until the summary was written, sometimes showing minutes of elapsed time. Now they are immediately closed at construction time and always report "<1s" duration.
-
Bug Fix
Fixed store identification when parsing single-table names
Reports and analysis screens now correctly identify stores when working with Mi9 pricing data in single-table mode.
-
Bug Fix
Compass rebuild routing now uses consistent logic across all code paths
Compass stores now correctly use MySQL Import Manager routing, ensuring pricing data is pulled from the right source.
-
Bug Fix
Strategy backup now detects and prevents empty rule exports
If your pricing strategy backup somehow captures no rules, you'll now see a warning instead of silently saving an empty file that could overwrite a good backup.
-
Bug Fix
Detect and prevent empty strategy backups from displacing good history
Fixed MM-1320, where a store's automatic strategy backups silently captured zero pricing rules for months while rules were in daily use. When the rules were eventually lost, every backup in cloud history was empty and worthless. The app now detects when a backup contains no steps, custom groups, SKU exceptions, cost breaks, min/max strategies, or minimum margins, logs a warning, writes the local file for inspection, but refuses to upload it to the cloud so it cannot push good backups out of retention.
-
Bug Fix
PS Rule box consistency after strategy execution
The PS Rule filter now shows the same list of rules whether you're looking at it before or after running a strategy.
-
Bug Fix
Data Aging initialization errors now properly clear splash screen
If an error occurs while loading the Data Aging screen, the loading message will now properly clear instead of staying visible indefinitely.
-
Bug Fix
Window no longer freezes during cloud backup upload
The Custom Groups window now closes immediately after saving your changes, without freezing during the cloud backup.
-
Bug Fix
Deactivated or renamed strategy steps no longer generate invalid filter queries
When a strategy step is renamed or deactivated, the filter can no longer resolve it to a numeric index. The old code would fall back to comparing against "0", which would silently match or exclude everything. The filter now compares against the original filter value directly in these cases, preventing silent failures and preserving the user's intent.
-
Bug Fix
Inactive steps now display INACTIVE marker in summary log
Run summaries now clearly show which strategy steps were skipped because they're disabled.
-
Bug Fix
Inactive steps now display INACTIVE marker in processing logs
The summary log's conditional logic has been corrected so that inactive steps display "*** INACTIVE — step is disabled in the strategy ***" instead of being treated as successfully executed with zero SKUs affected.
-
Bug Fix
Eliminated double-counting in Mi9 pricing impact calculations
Pricing impact numbers and inventory values now display correctly without inflation for stores using Mi9 single-table configuration.
-
Bug Fix
Main table reconciliation no longer drops all tables when store list query fails
The system will no longer delete all pricing tables if it can't properly verify which stores should exist.
-
Bug Fix
Strategy restore no longer deletes rules it cannot replace
Restoring a backup that contains no pricing rules will no longer delete your current working rules — your existing strategies will be left unchanged and you'll see a clear warning message.
-
Bug Fix
Prevent restores from deleting pricing rules when backup has none
Fixed a destructive restore behavior where importing a backup with an empty strategy would delete all existing live rules for that strategy and restore nothing. If a backup contains a named strategy but zero rules for it, the restore now skips that strategy entirely and leaves existing rules untouched, with a warning logged for each skipped strategy, custom group collection, and SKU exception collection.
-
Bug Fix
PSRule filter selection box now refreshes after strategy runs
When creating or editing a strategy step that filters by "PS Rule" or "PS Rule History," the dropdown will now correctly show available values even after running a strategy or rebuilding your data.
-
Bug Fix
Fixed window freeze during Custom Groups loading
The splash screen now updates smoothly with live status messages instead of appearing frozen until the load completes.
-
Bug Fix
Window remains responsive during save operation
The Manage Custom Groups window no longer appears frozen when saving—you'll see progress updates and the window stays responsive.
-
Bug Fix
Special PSRule codes 'ME' and 'GI' remain filterable
Manual Entry ('ME') and Group Inconsistency ('GI') codes are stamped directly into the PSRule field and never have a numeric index. The new logic correctly handles these special cases, ensuring they remain filterable as expected.
-
Bug Fix
Rebuild now aborts early when POS table is missing
If the source pricing table is missing, you'll now see a clear error message instead of the system appearing to succeed while actually failing.
-
Bug Fix
Restore success message now accurately reports missing rules
After restoring a pricing strategy backup, the success message will now tell you if the backup file contained no pricing rules, so you know your strategies weren't actually restored.
-
Bug Fix
PSRule selection box now rebuilds after strategy execution
Fixed an issue where the PSRule selection box (used to filter by pricing rule names) would cache an empty state at startup and never rebuild, making PSRule-filtered strategy steps permanently unloadable. PSRule is now marked as a "volatile field" that is reset by every strategy run, so its selection box always re-scans to pick up newly stamped rule names rather than caching emptiness.
-
Bug Fix
Fixed duplicate "Not in Database" entries for valid SKUs
Custom group SKU lists no longer show duplicate or incorrect "Not in Database" entries for SKUs that exist in your system.
-
Bug Fix
Corrected Mi9 post-import record count validation
Import completion messages for Mi9 systems now correctly display the number of SKUs imported instead of always showing zero.
-
Bug Fix
Failed insert operations now logged as errors instead of successes
Changed logging behavior so that when ExecuteAsync returns -1 (indicating a caught SQL exception), it's logged as an error and post-processing is skipped, rather than reporting "Inserted -1 rows" as if the operation succeeded. This prevents the reconcile logic from counting a failed rebuild as successful and makes troubleshooting much clearer.
-
Bug Fix
Strategy execution now reports when no pricing steps exist
If you run a pricing strategy that has no pricing rules defined, you'll now see a clear warning that nothing was priced, instead of a "success" message.
-
Bug Fix
Active strategy fallback now logs when switching strategies
If the pricing strategy you had selected is missing (for example, after a restore), you'll now see a warning telling you which strategy the system switched to instead.
-
Bug Fix
MI9 impact calculation for single table mode
Modified MI9 impact calculation SQL generation to handle both processing modes. Single-table mode passes a singleTable flag that adjusts the SQL to work without the @GroupName parameter since one table covers all groups.
-
Cloud Sync
Margin Master database connection backup
Your Margin Master database connection is now automatically saved to the cloud after each import, just like your POS connection.
-
Cloud Sync
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.
-
Data Import
Mode restructure service
Added Mi9MainTableModeService to orchestrate switching between processing modes. The service drops existing main tables, rebuilds in the target mode by re-importing all store POS data (using forceSingleTable parameter), and only commits the setting after successful rebuild. Failed restructures leave the setting unchanged and prompt users to run a manual import.
-
User Interface
Context-aware empty messages for PS Rule selection box
When the PS Rule box is empty, you'll see a clear message explaining why—whether you need to run a strategy first, add rules to your strategy, or select a strategy.
-
User Interface
Context-aware empty state for PS Rule filter box
When the PS Rule filter box is empty, you'll now see helpful messages like "Execute the strategy to view affected items" or "No active strategy selected" instead of generic text, making it clearer what action to take.
-
User Interface
Improved strategy status messaging
The pricing strategy panel now accurately reflects whether a strategy can be executed, preventing wasted clicks on inactive strategies.
-
User Interface
Two-tab restore connection window
The restore window now has separate tabs for POS connections and Margin Master database connections, making it easier to find the connection you need.
-
User Interface
Two-tab restore dialog for POS and database connections
When restoring a connection, you'll now see separate tabs for your POS system and your Margin Master database.
-
User Interface
Added live progress reporting to Custom Groups loading
You can now see exactly how many groups have loaded and watch the progress bar advance instead of staring at a frozen screen.
-
User Interface
New MI9 options tab
A new MI9 tab in Settings lets you switch between team-level and store-level pricing modes.
-
User Interface
Progress indicator updates during long operations
The "Please Wait" spinner and status messages now update smoothly instead of appearing stuck.
-
User Interface
Updated display names for single-table across analysis screens
Analysis screens now show "All Stores" when viewing data from the Mi9 single table, making it clearer what data you're looking at.
-
User Interface
Warn users when restoring a backup with no pricing rules
The restore confirmation dialog now explicitly states when a backup file contained no pricing strategy rules, making it clear that settings and views were restored but no strategies were applied. Previously, the dialog reported plain success even when 100% of the store's pricing rules were missing from the backup.
-
User Interface
Enhanced error logging for group reordering
Added error logging to the Move Up and Move Down operations to help diagnose issues if group reordering fails.
-
Database
Enhanced step skip detection for pricing strategies
The system is now smarter about when to run or skip pricing steps when certain data values are temporarily missing, reducing unnecessary warnings while protecting against accidental over-pricing.
-
Database
Added backward compatibility for legacy PSRule data formats
The fix maintains compatibility with older databases that may still contain numeric step indexes in the PSRule column rather than step names. The filter resolution logic queries the active strategy configuration to translate between step names and their 1-based position indices, allowing filters to match data written by any version of the application. Special handling preserves manual entry ("ME") and group inconsistency ("GI") codes that are stamped directly without step indices.
-
Database
Optimized indexing for single-table query performance
Added store-number-specific indexes for single-table mode to handle the significantly larger dataset (verified at 2.8M rows across 131 stores vs. 279K rows in multi-table mode). Created a unique index on (StoreNumber, SKU) to enforce data grain integrity and a covering index on StoreNumber with frequently accessed columns (SKU, CurrentPrice, FuturePrice, Cost). Multi-table mode retains its existing AltSku-only index since StoreNumber is constant there.
-
Database
Connection identity includes role designation
Database connections are now tagged with a "ConnectionKind" field (either "POS" or "MMDatabase") that distinguishes point-of-sale data sources from the Margin Master application database. This allows both connection types to coexist in cloud storage for the same store and ensures each appears under the correct restore tab.
-
Database
Parameterized SQL injection risk in CustomGroupSkus delete
Changed the CustomGroupSkus DELETE statement from string interpolation to parameterized queries, eliminating a potential SQL injection vector where SKU values were embedded directly into SQL strings.
-
Database
Single main table indexing strategy
Created a curated index set for the single main table mode: a unique index on (StoreNumber, SKU) to guard the grain, a covering index on StoreNumber for per-store queries, and an AltSku index for impact calculations. DMV-based auto-indexing is disabled in single-table mode to prevent index proliferation on the larger table (~2.8M rows vs ~121K per team table).
-
Architecture
Configurable empty-state text for selection boxes
Selection boxes can now override their empty-state title and subtitle on a case-by-case basis, allowing context-specific guidance throughout the application rather than relying on a single generic message.
-
Architecture
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.
-
Architecture
Connection identity expanded to include ConnectionKind
The PosCredentialDescriptor model and all related DTOs (PosCredentialRequest, PosCredentialSummaryDto, PosCredentialSecretDto) now include a ConnectionKind property that defaults to "POS" but can be set to "MMDatabase" for the Margin Master database connection. This field is part of the server-side identity, allowing both connection types to coexist per store and be restored independently.
-
Performance
Eliminated database bottleneck causing multi-minute loads
Opening a pricing strategy with hundreds of custom groups now takes seconds instead of several minutes.
- Infrastructure Added comprehensive test coverage for filter skip logic
-
Infrastructure
Added unit tests for exclusion filter skip logic
Added comprehensive test coverage (ExcludeFilterSkipTests) to verify the asymmetric behavior between inclusion and exclusion filters when selection box values are absent, preventing future regressions of this pricing-critical logic.
-
Infrastructure
Added comprehensive test coverage for PSRule filter scenarios
Added 8 unit tests covering Include/Exclude behavior, resolution of both name and index formats, handling of unresolvable values (renamed or deactivated steps), SQL injection prevention through quote escaping, and special codes like "ME" and "GI". Tests verify against real customer database patterns where PSRule='439' returned 0 rows while PSRule='BenjaminMoore' returned 1,288 rows, confirming the mismatch.
-
Infrastructure
Added test coverage for inactive step summary behavior
New unit tests verify that inactive steps report correct timing, display the INACTIVE marker, and don't affect active step output. Tests prevent regression of the phantom-duration and missing-label issues.
-
Infrastructure
Added unit tests for inactive step summary behavior
New test coverage ensures inactive steps are closed immediately, report sub-second duration, display the INACTIVE marker, and that active steps do not incorrectly display the marker.
-
Infrastructure
Store selection routing policy
Implemented StoreRoutingFilterPolicy to correctly handle store selections in both processing modes. In multi-table mode, the store selection is consumed by routing to specific tables and must be removed from filters. In single-table mode, the selection must be preserved and passed to the WHERE clause to prevent single-store operations from affecting all stores. Includes comprehensive unit tests to guard against accidental cross-store pricing changes.
-
Infrastructure
Configurable empty-state messages for selection boxes
Added EmptyTitle and EmptySubtitle properties to SelectionBoxDetail, allowing individual selection boxes to override the default "No Items Found / Verify data has been imported" message with context-specific guidance appropriate to each box's purpose.
-
Infrastructure
Improved heartbeat animation reliability during long operations
The splash screen heartbeat now runs independently on the thread pool rather than competing with the operation it's meant to monitor, ensuring it continues to animate even when other initialization phases are processing.
-
Infrastructure
Removed unreachable legacy migration code
Removed MigratePricingStrategiesAsync and two helper methods (347 lines) that were never called from anywhere in the application. This code path read from tables that were never populated (the root cause of the empty backups) and contained a scheduled deletion of the live GlobalFileConfig strategy sections 30 days post-migration that would have destroyed every pricing strategy fleet-wide if it had ever executed.
Imports & POS
-
New Feature
Automatic cloud backup of validated POS connections
When you successfully test any POS connection in Settings, it's now automatically backed up to the cloud in the background. You won't notice any difference, but the connection will be available to restore later.
-
New Feature
Automatic cloud backup of validated POS connections
Your POS connection details are now automatically saved to the cloud every time you test a connection or import data—no extra steps required.
-
New Feature
MySQL Connection Troubleshooter
Click "Troubleshoot Connection" on the Epicor Options screen to run a full connection health check. The troubleshooter will check everything from network reachability to login credentials to link speed, show you exactly what passed or failed, and provide specific instructions for fixing each problem. Click "Copy Report" to paste the full results into a support ticket.
-
New Feature
MySQL connection troubleshooter with diagnostic report
When your MySQL connection won't work, click "Troubleshoot Connection" to see a detailed checklist showing exactly what's wrong (e.g., "✗ Connection path: Remote Desktop session detected" or "⚠ Link quality: High latency may cause import timeouts"). Each failed or warning check includes a specific fix. Click "Copy Report" to copy the full diagnostic to paste into a support ticket.
-
New Feature
Modern MySQL driver with beta toggle
A new "Use new MySQL connector (beta)" checkbox appears in Settings under Epicor MySQL Options. Check it, click Test & Save, and the app will use a newer database driver that may resolve connection problems. Uncheck it to return to the previous driver instantly.
-
New Feature
Store number conversion setting
A new setting lets you control whether POS store numbers are matched to vendor store numbers. When turned on, stores without a matching POS number will be automatically excluded from data imports.
-
New Feature
FTP connection troubleshooter with diagnostic report
When you test your Epicor FTP connection, you'll now see a detailed checklist showing exactly which steps passed or failed (DNS lookup, port open, login successful, etc.), with specific remedies for any problems. You can copy the entire report to send to support.
-
New Feature
FTP connection troubleshooter
Click "Troubleshoot Connection…" in the Epicor FTP panel to run a comprehensive connection test that shows exactly where a connection problem occurs—whether it's missing settings, a firewall blocking the port, wrong login credentials, or a slow network link.
-
New Feature
Interactive new-store mapping during Epicor import
When a new Epicor store is found during import, you'll see a prompt asking you to enter its Vendor Store Number. Enter the number to map it, or click Cancel to skip it for now. You can always edit store mappings later under Data → Store Manager.
- New Feature Activity badge with full lifecycle
-
New Feature
MI9 processing mode selection
When using MI9, a new MI9 tab in Settings lets you switch between team-level pricing (where all stores in a team share the same prices) and store-level pricing (where each store can have different prices for the same item). The default remains team-level pricing.
-
New Feature
Restore POS connections from cloud backup
Each POS Settings screen now has a "Restore from Cloud…" button. Click it to see all previously saved connections for that POS type, pick one, and have all the connection details (including password) filled in automatically — perfect for reinstalls or setting up a second machine.
-
New Feature
One-click connection restore from cloud
Click "Restore from Cloud…" on any POS settings screen to see all your previously saved connections and restore one with a single click—perfect for reinstalls or setting up a new machine.
-
New Feature
Network Topology Detection
The troubleshooter automatically detects whether you're connecting over a VPN, Remote Desktop session, or across the internet, and warns you when these connection types are causing slow imports or timeouts. The most reliable fix is to run Margin Master on a PC on the same local network as your Eagle server.
-
New Feature
Troubleshoot Connection button for Epicor FTP
The new "Troubleshoot Connection" button lets you test your FTP settings and get a diagnostic report without saving any changes to your configuration.
-
New Feature
Automatic import folder cleanup
Your import folder will automatically clean up old files after 7 days, so you don't have to manually delete old exports and backups anymore.
-
New Feature
Link Quality and Timeout Risk Assessment
The troubleshooter measures your connection speed to the MySQL server and warns you if it's slow enough to cause import timeouts, with specific suggestions on how to fix it.
-
New Feature
Network topology detection and VPN/remote session identification
The troubleshooter now detects if you're connecting over a VPN or Remote Desktop session and warns that this often causes connection timeouts. It recommends running Margin Master on a PC on the same network as the Eagle server for best performance.
-
New Feature
Refresh Stores button now works for all POS systems
You can now click "Refresh Stores" in Store Manager to automatically find new stores from your imported data, regardless of which POS system you use.
-
New Feature
Store number conversion setting for non-Epicor systems
Added a new "Use POS Store to Vendor Store Number Conversion" option in Store Manager for RockSolid, BisTrack, and NCR Counterpoint systems. This setting controls whether POS store numbers are converted to vendor store numbers during import matchup. Epicor systems always use character ordinal conversion and do not display this option.
- New Feature Troubleshoot Connection now verifies Eagle IN export file exists
-
New Feature
Link quality assessment and timeout risk prediction
The troubleshooter measures connection speed and warns when your link is slow enough to cause import timeouts, with specific advice (like enabling streaming import or running imports at night) to work around slow connections.
- Improvement Complete store list display in Store Manager
-
Improvement
Vendor store assignment for imported POS stores
When a new store appears after importing POS data, you can now assign it to the correct vendor store number even if it's marked as excluded. Simply edit the Vendor # field to match it up.
-
Improvement
Vendor assignment for excluded stores
If a store is marked as excluded in the Store Manager, you can now still edit its Vendor Store # to match it with the correct vendor or fix an incorrect assignment.
-
Improvement
Configurable Epicor bulk operation timeout
Added a new application setting "EpicorBulkOperationTimeoutSeconds" (default 600 seconds) that allows support staff to adjust the timeout for Epicor bulk database operations without requiring a software rebuild. This matches existing timeout configuration available for Mi9 and MySQL Compass systems.
-
Improvement
Automatic self-healing for missing store tables
If a store's pricing data goes missing, Margin Master will automatically restore it the next time you start the application.
-
Improvement
Consistent error handling across MySQL connection points
By consolidating on the existing ILocalNetworkService.TestMySqlConnectionAsync() method, MySQL connection testing now behaves consistently whether triggered from the import workflow or the settings screen, improving reliability and maintainability.
-
Improvement
Faster failure detection for unreachable MySQL servers
If your Epicor MySQL/Compass server is unreachable, you'll know within 3 seconds instead of waiting through a long timeout.
-
Improvement
Extend orphaned store cleanup to more import paths
Applied the existing orphan-prune logic (originally built for CounterWorks in MM-1166) to Ace Hardware Falcon imports and other single-store POS systems processed through the Super import path. The cleanup now runs automatically when the system detects exactly one store numbered "0" in the imported data, preventing phantom store entries across more vendor and POS combinations.
-
Improvement
Added automatic retry logic for transient database blocks
The Epicor bulk insert operation now includes retry logic to handle temporary database locks that occur when multiple store tables are being created or updated during import. This prevents import failures due to momentary resource contention.
-
Improvement
Enhanced logging for file import header validation failures
Added detailed warning logs when import files are rejected due to header validation failures, including the specific file name, import definition name, and how many columns matched versus how many were required. This helps with troubleshooting import issues.
-
Improvement
Optimized post-import index rebuilding
The "Finalizing" step after adding catalog items now completes much faster.
-
Improvement
Import errors now display in clear error dialogs
When an import fails, you'll now see a clear error message that stays on screen until you close it, instead of a brief flash that disappears.
-
Improvement
Prefer raw .txt over .csv for BisTrack/Ace store 1178
Store 1178: When both .txt and .csv files are in your import folder, Margin Master will automatically use the .txt file and ignore the .csv to prevent duplicate imports.
-
Improvement
Automatic import folder cleanup
Old import files and backups older than 7 days are now automatically removed from your import folder to keep it tidy.
-
Improvement
Enhanced network scanner with MySQL handshake verification
The "Scan for MySQL Servers" button now shows which discovered servers are actually MySQL (with version number) and whether your username/password work on each one, making it easier to pick the correct server when multiple hosts respond.
-
Improvement
Driver identification in diagnostics
The MySQL troubleshooter report now shows which database driver is active, making it easier for support to diagnose connection issues.
-
Improvement
Store Manager dialog accessible for non-Epicor POS systems
BisTrack, Falcon, Mi9, and TransAct users can now use the improved Store Manager screen to manage store settings, matching the experience already available to Epicor users.
-
Improvement
Auto-exclude unmatched stores
Stores that can't receive POS data (because they have no matching POS store number) are now automatically marked as excluded, preventing import errors.
-
Improvement
Auto-exclude unmatched stores from imports
Stores without matching POS store numbers are now automatically excluded from imports since they cannot receive data.
-
Improvement
Context-specific remediation guidance for MySQL login failures
Authentication denied messages now distinguish between three scenarios: blank password field (directs user to enter the password in settings), rejected password (indicates incorrect password or host not allowed), and generic access denied (provides GRANT command syntax for MySQL administrators). Each message includes the relevant username and local IP address for troubleshooting.
-
Improvement
Automatic retry for transient MySQL errors
If a MySQL query briefly times out due to network congestion, the application will automatically retry it instead of immediately failing.
-
Improvement
Clearer connection test error messages
Error messages during FTP/SFTP connection tests now provide clearer guidance about toggling the "Use Secure FTP" setting based on which protocol failed, helping users diagnose configuration issues more quickly.
- Improvement One-at-a-time pipeline guards
- Improvement Resilient column mapping prevents future import failures
- Improvement Import failures now show actual connection errors
-
Improvement
Enhanced splash screen lifecycle logging
Added detailed logging at critical points in the interactive pipeline (import and vendor update workflows) to track splash screen state during operations. Previously, successful operations logged nothing between closing dialogs and finishing, leaving a 57-second gap in store 2596's logs that made diagnosis impossible. The new logging brackets pipeline endings and records splash state, phase text, and elapsed time to quickly identify any future stall points.
-
Improvement
Enhanced error handling for Mi9 mode switching
If something goes wrong while changing Mi9 settings, you'll now see a clear error message instead of the application crashing.
-
Improvement
Better error handling for MI9 mode changes
If an error occurs while changing MI9 processing mode, you now see an error message instead of the application closing unexpectedly.
-
Improvement
Self-healing for missing store tables
If a store's pricing data becomes corrupted or missing, the system will automatically rebuild it at the next startup.
-
Improvement
Do-it Best mailbox connection reporting
The Do-it Best mailbox FTP connection now reports to the cloud backup system at the moment the actual FTP connection succeeds during data retrieval (in DIBMailboxService), in addition to the manual "Test Connection" button in Settings. This ensures real working mailbox connections are preserved even if the user never explicitly tests from the Settings screen.
-
Improvement
Reduced notification noise for existing unmapped stores
You'll only see the unmapped store warning once when a new store is first discovered, not every time you import data.
-
Improvement
Standardized error handling for BisTrack and DIB imports
BisTrack and Do-It-Best import errors now show helpful error messages explaining what went wrong and how to fix it.
-
Improvement
Better error handling for BisTrack Direct Connect
If BisTrack import fails, the error message now tells you exactly what went wrong and how to fix it.
-
Improvement
Store Manager handles unmatched stores
Stores that haven't been matched between your vendor catalog and POS system now appear in Store Manager so you can complete the setup.
-
Improvement
MySQL timeout telemetry reporting
The error classifier now explicitly recognizes and reports MySqlConnector command timeouts to telemetry, ensuring persistent slow-query issues reach the error dashboard. The Settings screen's Test & Save path escalates timeout failures from Warning to Error severity so they're visible in Manager telemetry, while other test failures (bad password, wrong host) remain warnings. This ensures actionable slow-link issues are remedied while keeping noise low.
-
Improvement
Added intermediate status message during table rebuild phase
You'll now see a message explaining that pricing tables are being rebuilt after store data is imported, instead of the screen appearing stuck.
-
Improvement
Copyable diagnostic report
After troubleshooting completes, you can copy the full diagnostic report (including all test results and error details) directly to your clipboard to send to support.
-
Improvement
Enhanced store reconciliation logging
The MySQL/Compass store reconciliation now logs whether new stores were mapped via the interactive prompt or inherited from an existing mapping, providing clearer audit information about how store matchups were established.
-
Improvement
Better troubleshooting guidance for secure FTP settings
When connection tests fail, you'll get clearer instructions on whether to enable or disable the "Use Secure FTP" setting.
-
Improvement
Better error handling for DIB price file imports
DIB price file import errors now show a complete error message that you can read and share with support.
-
Improvement
Enhanced MySQL Network Scan
When you scan your network for MySQL servers, the scan now checks multiple ports on each machine, confirms that discovered servers are actually running MySQL (not just any open port), tells you the MySQL version, and shows whether your username and password work on each server found.
-
Improvement
MySQL troubleshoot report shows active driver
The MySQL diagnostic report (accessed via Troubleshoot button or diagnostics menu) now includes a "Driver" line showing which MySQL provider is currently in use (e.g., "MySqlConnector 2.6.1" or "MySql.Data 6.10.9"), helping support confirm the toggle state when investigating connection issues.
-
Improvement
BisTrack cloud restore workflow
The "Restore from Cloud" button is now disabled until you enable Direct Connect, making the required order of steps clearer.
- Improvement Adaptive polling frequency
-
Improvement
FTP troubleshooter validation logic
The "Test & Save Connection" button now performs a more thorough validation before marking your FTP connection as verified, while the new "Troubleshoot Connection" button lets you diagnose issues without affecting your saved settings.
-
Improvement
Credential backup integrated into all POS connection flows
Every time you test a connection or import data, your connection is automatically backed up—no manual save required.
-
Bug Fix
Store selection missing valid stores after rebuild
All active stores with inventory data will now appear in the store selection dropdown, even after rebuilding the pricing database.
-
Bug Fix
Main tables now reconcile against Store Manager for Epicor configurations
If you exclude a store in Store Manager, it will no longer appear in the Main Table grid after the next rebuild or when you restart Margin Master.
-
Bug Fix
Fast-fail MySQL connection test with actionable guidance
If your Epicor MySQL connection fails, you'll now see a clear message explaining what to check (IP address, MySQL service status, or firewall settings) within a few seconds, making it much easier to troubleshoot connection problems.
-
Bug Fix
Clearer MySQL connection error messages during import
When the system can't connect to your Epicor MySQL/Compass database during import, you'll now get a quick response with clear instructions on what to check (IP address, server status, or firewall settings) instead of waiting through a long timeout.
-
Bug Fix
Store Number dropdown displays extended Epicor store designations correctly
If your store uses Epicor and has a special character designation (like ‡ or ™), it will now show up correctly in the Store Number dropdown instead of appearing blank.
-
Bug Fix
Store Number box now displays extended Epicor designation characters
If your store uses special symbols like ‡, ™, or • in Epicor designations, these will now show up correctly in the Store Number box instead of appearing blank.
-
Bug Fix
Remove stale warehouse data during Falcon imports
If your store previously had multiple warehouses but now operates as a single location on Falcon, old warehouse entries will no longer appear in your pricing grid.
-
Bug Fix
Increased timeout for Epicor bulk insert operations
Epicor imports that previously failed with timeout errors will now complete successfully, even when multiple stores are syncing data at the same time.
-
Bug Fix
Extended timeout for Epicor bulk data operations
Increased the batch timeout from default to 10 minutes (600 seconds) and disabled temporary table clustering to improve performance during large Epicor imports. Added automatic retry logic to handle transient database connection issues during the bulk insert process.
- Bug Fix Prime Vendor and Fineline now populate for Falcon Ace customers
-
Bug Fix
Falcon Prime Vendor and Fineline auto-population
When using Falcon POS, the Prime Vendor and Fineline filter dropdowns in the pricing grid now populate automatically from Ace catalog data, making it easier to filter and analyze your inventory.
-
Bug Fix
Propello import now shows error dialog instead of failing silently
If you accidentally export the wrong report from Propello, you'll now see an error message telling you exactly what's wrong and how to fix it (export the full inventory report with all columns), instead of seeing nothing happen.
-
Bug Fix
Propello import failures now show actionable error dialogs
When a Propello spreadsheet doesn't import correctly, you'll now see a dialog box that stays on screen explaining exactly what's wrong and how to fix it by running the full inventory export from Propello with all columns included.
-
Bug Fix
Auto-exclude unmapped Epicor stores at discovery
New Epicor stores without vendor assignments are now clearly marked as excluded in the store list, making it easier to see which stores need configuration.
-
Bug Fix
Eliminated index thrashing during catalog imports
Catalog imports that appeared frozen at "Finalizing" will now complete normally, especially on stores with many locations or large product databases.
-
Bug Fix
Import errors now show persistent error dialogs
When a data import fails, you'll now see a clear error message dialog instead of text that briefly flashes and disappears in the splash screen.
-
Bug Fix
NCR Counterpoint imports now automatically rebuild main tables
After importing from NCR Counterpoint, your pricing data now appears immediately in the main grid without needing to click the Rebuild button.
-
Bug Fix
BisTrack raw .txt export files now import directly
If you use BisTrack, you can now import the raw .txt file that BisTrack generates without opening it in Excel first. This prevents Excel from corrupting your data by removing trailing zeros or turning SKU numbers into scientific notation.
-
Bug Fix
Import raw BisTrack .txt files without Excel conversion
You can now drop the raw BisTrack export file (.txt) directly into the import folder without opening it in Excel first. The system will automatically use the .txt file and ignore any old .csv versions.
-
Bug Fix
Store number matchup edits now save correctly
Store number, zone, and RSC changes are now saved correctly when you edit them through the Settings menu.
-
Bug Fix
Store Manager displays complete store list for non-Epicor systems
If you use BisTrack, Falcon, Transact, or similar POS systems, the Store Manager will now show your complete store list instead of only one or two stores.
-
Bug Fix
Repair corrupted POS store numbers in StoreManagerInfo
If you have multiple store locations, the system will now correctly match each store to its pricing data, fixing problems where updates wouldn't apply to the right stores.
-
Bug Fix
Repaired POS store numbers corrupted by legacy migration
Store numbers now display correctly in Store Manager for RockSolid, BisTrack, and NCR Counterpoint systems.
-
Bug Fix
MySQL authentication errors now identify root cause
The MySQL connection test now tells you exactly what's wrong: "Password field is blank" if you forgot to enter a password, or "password was rejected" if the password is incorrect or your PC isn't allowed to connect.
-
Bug Fix
MySQL command timeout enforcement on slow connections
When testing your MySQL Compass connection in Settings or running an import over a slow network, queries will now be given enough time to complete instead of failing after 30 seconds.
-
Bug Fix
Import splash screen remains responsive during Epicor MySQL imports
The import progress screen now updates smoothly during Epicor imports instead of freezing on a stale frame.
-
Bug Fix
Prompt to remove excluded store data tables
When a MySQL Epicor store was imported and then later excluded in Store Manager or had its vendor store number cleared, its data table remained in the database. These orphaned tables never appeared in the Data Aging view but still fed store selection dropdowns, creating confusing phantom store entries. After each import rebuild, Margin Master now detects these leftover tables and prompts whether to remove each one. Clicking "Yes" drops the table and cleans up its related index and import history records; "No" leaves it untouched; "Cancel" stops prompting. This prompt never appears in automated/headless mode—removal requires explicit user confirmation.
-
Bug Fix
Prompt to clean up excluded store data tables
If you exclude a store in Store Manager, Margin Master will now ask if you want to remove its old pricing data. Click "Yes" to clean it up and prevent the store from showing in your store lists. Click "No" to keep the data (you'll be asked again next import). Click "Cancel" to stop being asked about any remaining excluded stores.
-
Bug Fix
Connection test now matches actual import protocol
If your store uses Epicor with "Use Secure FTP" enabled (most common for port 22), connection tests will no longer incorrectly report failures or take a minute to timeout.
-
Bug Fix
Connection test protocol mismatch resolved
When testing your Epicor FTP connection in Settings with "Use Secure FTP" checked, the test will now work properly instead of timing out or showing false errors.
- Bug Fix Propello import now handles Do it Best export format changes
-
Bug Fix
Propello DIB import now handles renamed classification columns
If your Do-It-Best Propello import recently stopped bringing in data, it will now work correctly. The system automatically detects whether you're using an old or new export file format.
- Bug Fix Epicor INFILE import now uses correct FTP server address
-
Bug Fix
Loading splash screen no longer freezes after imports
If you were experiencing freezes where the loading screen got stuck on "Finalizing…" and wouldn't go away, forcing you to close Margin Master from Task Manager, this is now fixed. The loading screen will automatically close even if something goes wrong internally.
-
Bug Fix
Paladin 'None' location normalized to blank
Items imported from Paladin that show 'None' as their location are now treated as having no location, so pricing rules that exclude or include items with blank locations will work correctly.
-
Bug Fix
Paladin 'None' location now treated as no-location marker
Items showing "None" as their location in Paladin will now be properly treated as having no location, so rules that exclude blank locations will work correctly.
-
Bug Fix
Mi9 Options tab crash when applying processing mode
The Settings screen will no longer crash when you change Mi9 processing mode options.
-
Bug Fix
MI9 Options tab crash when applying processing mode
Changing between MI9 single-table and multi-table modes in Settings no longer crashes the application.
-
Bug Fix
Automatic cleanup of orphaned store tables
Excluded or removed stores no longer leave behind empty data tables, keeping the database clean and improving startup performance.
-
Bug Fix
NCR Counterpoint imports now rebuild the main pricing grid
After importing NCR Counterpoint data, the main pricing grid now automatically updates with the new data — you no longer need to manually rebuild tables to see your imported items.
-
Bug Fix
Zone pricing lookup corrected for non-Epicor stores
Zone pricing now correctly applies each store's specific zone instead of defaulting to the first zone found.
- Bug Fix Zone assignment lookup now uses correct store identifier
-
Bug Fix
Chunked database writes prevent import failures
Epicor imports will complete successfully more often, especially during busy times when the database is under heavy load.
-
Bug Fix
Improved numeric field handling for Propello imports
Propello imports are now more reliable when price or quantity fields contain unexpected values—the system will use zero for any field it can't read rather than skipping the entire product.
-
Bug Fix
Strategy location filters display BLANK option when needed
Pricing strategies that filter by blank locations will now load and apply correctly even if blank locations aren't currently visible in the location list.
-
Bug Fix
Strategy filter honors 'BLANK' sentinel even when not in selection list
Pricing strategies that reference "BLANK" values will now work reliably, even when no blank items were previously visible in the selection list.
-
Bug Fix
Store Manager dialog opening from Settings
The "Open Store Manager" button in POS Settings now works reliably. Clicking it closes the Settings window and opens Store Manager from the main screen.
- Bug Fix Activity badge now appears when feature enabled mid-session
-
Bug Fix
Eliminated redundant splash screen re-display during finalization
Removed unnecessary splash screen re-activation during the post-import processing phase. When ImportPOSData called ProcessStepsAfterPopulateMainDataset with an empty queue, it would re-show the splash purely to display "Finalizing…" with no actual work to do. The method now returns early when there are no pending steps, preventing the display of an empty progress indicator while still maintaining the contract that all eight callers can rely on the splash being closed upon return.
-
Bug Fix
Fixed Store Manager dialog launch from Options screens
Opening Store Manager from POS Options screens now works reliably.
-
Bug Fix
Import block query timeout defaults
Import operations will no longer hang indefinitely if a MySQL query encounters an issue—they'll timeout after 10 minutes and report the problem.
-
Bug Fix
Persist settings before troubleshooting to diagnose actual configuration
The troubleshooter now calls PersistSettingsAsync() before running checks, ensuring it diagnoses exactly what the user entered on-screen rather than stale saved settings, matching the Test & Save behavior where settings are saved before the test runs.
-
Cloud Sync
Auto-populate stores during vendor sync
After syncing vendor pricing, your store list is automatically updated with all stores from your organization account.
- Cloud Sync Automatic store seeding during vendor sync
-
Cloud Sync
Manager API integration for POS credential storage
Implemented three new Manager API endpoints in ApiClientService: POST /api/pos/credentials (submit), GET /api/pos/credentials/{storeNumber} (list), and GET /api/pos/credentials/{id}/secret (fetch with password). The submit endpoint is called fire-and-forget after every successful POS connect; the list and secret endpoints are called on-demand during restore. All credential transport uses new DTOs (PosCredentialRequest, PosCredentialSubmitResponse, PosCredentialSummaryDto, PosCredentialSecretDto) defined in PosCredentialModels.cs. Passwords and extras are encrypted at rest server-side; descriptor fields (server, database, username, auth mode) are stored plain for listing/filtering.
-
Data Import
New-store vendor mapping prompt during Epicor import
When Margin Master finds a new Epicor store during import, you'll see a prompt asking for its Vendor Store Number. Enter the number to include it next time, or press Cancel to skip it for now. You can always change this later under Data → Store Manager.
-
Data Import
Improved error handling for Epicor data uploads
Wrapped the bulk insert operation with transient retry logic to automatically recover from temporary database connectivity issues, making the Epicor import process more resilient.
-
Data Import
File import validation failures now logged to application log
All import definitions (not just Propello) now write a warning to the application log when header validation fails, recording the file name, import definition name, number of matched columns, and required column count. This ensures every validation failure is recorded for troubleshooting, even if the UI feedback is missing.
-
Data Import
Auto-add POS stores during import
When you import POS data, any new store numbers are automatically added to your store list.
-
Data Import
Import Manager now cleans up before building store selection lists
The cleanup prompt runs immediately after rebuilding per-store main tables and before populating store selection dropdowns, ensuring excluded stores never appear as selectable options in the Import Manager or other screens.
-
Data Import
Clean up import history for removed stores
When an orphan store table is removed after user confirmation, the system now also cleans up related records in the ImportProcessing table (Data Aging view) and the ManagedIndexes registry. This ensures a complete cleanup with no stale metadata left behind.
-
Data Import
Provider-agnostic MySQL error handling
Introduced MySqlErrorHelper to inspect MySQL error codes from either driver's MySqlException type, replacing direct casts that would fail during migration. All connectivity retry logic, transient error detection, and diagnostic failure analysis now work regardless of which driver is active. Added MySqlConnectionFactory and MySqlErrorHelper unit tests to verify toggle behavior and error-code extraction.
-
Data Import
Improved Epicor import resilience
Both the standard insert and streaming merge operations in the Epicor FTP import process now benefit from the configurable timeout and chunked write improvements, making the entire import pipeline more robust against database performance issues.
-
Data Import
Auto-mapped stores now marked as included
When the Epicor import auto-maps a new store (single-store case or inherited from binary ordinal), it now clears the Excluded flag and persists the matchup to GlobalFileConfig immediately, ensuring RefreshStoreModels and the Store Manager UI resolve the mapping. Previously, some auto-mapped stores remained marked excluded until manually edited.
-
Data Import
Column definition expanded for new Propello DIB format
Added Category Code, Sub Category, Sub Category Code, Product Group, and Product Group Code to the Propello DIB staging definition. The staging table now captures all columns from both old and new DIB exports, though the finest Product Group tier is not yet mapped to a main-table field.
-
Data Import
Regression tests added for blank location handling
Added automated tests to verify that the BLANK location sentinel is properly recognized and handled in selection filters, preventing future regressions of this issue.
- Data Import Automatic POS store detection during import
-
User Interface
ECI VPN requirement documentation
The documentation explains why connection attempts might fail even with correct credentials—the VPN tunnel must be active first. It clarifies that file-based imports (like RockSolid MAX Data.txt files) do not require the VPN, only direct database connections do.
-
User Interface
New documentation page for ECI VPN requirement
Added a help page that explains the VPN requirement and walks you through what your IT team needs to set up the connection to ECI.
- User Interface Added "Open Store Manager" button to additional POS tabs
-
User Interface
Updated Spruce and RockSolid MAX import documentation
Import guides now clearly explain when you need the VPN tunnel and when you don't.
- User Interface PS Rule filter box now shows helpful hint when empty
-
User Interface
PS Rule filter empty-state hint
The PS Rule filter now shows a helpful message reminding you to run a pricing strategy first, instead of appearing blank and confusing.
-
User Interface
Clarified "New Stores Found" notification
The warning about new Epicor stores now explains more clearly that their data wasn't imported and won't appear repeatedly on future imports.
-
User Interface
Settings checkbox for driver selection
Added "Use new MySQL connector (beta)" checkbox to the Epicor settings tab with a tooltip explaining it switches between the modern MySqlConnector and legacy MySql.Data driver. The active driver is shown in the MySQL diagnostic/troubleshoot report under "Driver".
-
User Interface
Store Manager matching workflow clarification
Added a new CanEditMatchup property that controls editability based only on hard states (deleted/not-found), separate from the general CanEdit property that also considers exclusion status. This ensures vendor store assignments can always be corrected when needed while maintaining appropriate restrictions for deleted or invalid stores.
-
User Interface
Updated Store Manager grid permissions
Added a new CanEditMatchup permission that controls editability of the Vendor Store # field independently from the general CanEdit permission. This allows vendor re-matching operations even on excluded stores while maintaining appropriate read-only protection for deleted and not-found stores.
-
User Interface
Fixed progress bar alignment on splash screen
The progress bar on the import screen is now properly aligned below its status message.
-
User Interface
Diagnostic progress overlay
When testing or troubleshooting the FTP connection, you'll see a progress indicator showing which step is running and how far along the test is.
-
User Interface
Simplified Epicor settings screen
The Epicor settings screen is now simpler with one less option to configure, since all Epicor servers use the same type.
-
User Interface
Explicit apply button with destructive-action confirmation
Switching processing modes rebuilds your main tables from scratch and may take several minutes. The system warns you exactly which tables will be removed and reminds you that you'll need to re-run your pricing strategies afterward. A progress bar shows the rebuild status.
-
User Interface
New restore connection picker dialog
A new dialog shows all your saved cloud connections in a list—select one and click Restore to fill in your connection settings automatically.
-
User Interface
Progress overlay during FTP connection testing
When testing your FTP connection, you'll now see a progress bar and status messages showing exactly which check is currently running.
-
User Interface
Never auto-remove store data in headless mode
In automated fix-pipeline (headless) scenarios, the system will log detected orphan tables but skip the removal prompt entirely. This safety guard ensures store data is never automatically deleted without explicit human confirmation.
-
User Interface
Server Type option hidden on Epicor settings
The "Server Type" selector (SCO/Linux) has been hidden from the Epicor settings screen since all stores use Linux servers. The underlying code remains functional and defaults to Linux.
-
User Interface
Conditional tab visibility
The MI9 tab appears only when the POS type is set to MI9 in Store Information and disappears when switching to a different POS system. The tab is registered in all six required wiring points: dependency injection, ViewModel initialization, tab visibility map, XAML DataTemplate, view code-behind, and the UpdatePosTabVisibilityAsync live-switching logic.
-
User Interface
Improved new-store exclusion messaging
The INFILE import's auto-exclusion warning now directs operators to "Data → Store Manager" instead of the older "Manage Epicor POS/Vendor Store Info" button reference, and the splash screen is hidden before showing the new-store prompt so modal dialogs are never covered.
-
User Interface
Diagnostic Report Display
After running the troubleshooter, you'll see a checklist of every connection check with clear pass/warning/error icons and specific instructions for fixing any problems. Click "Copy Report" to copy the entire diagnostic to your clipboard for pasting into emails or support tickets.
-
User Interface
Diagnostic checklist display in Epicor settings
Added a collapsible "Connection Diagnostics" section to the Epicor settings tab that appears after running the troubleshooter, displaying an overall verdict line (color-coded green for pass, orange for warnings, red for failures) followed by an ItemsControl-bound checklist of diagnostic steps, each with a status glyph, step name, detail message, and (when relevant) a remedy in italic orange text. The section includes a "Copy Report" button to copy the plain-text diagnostic to the clipboard.
-
User Interface
Improved Store Manager column header styling
Fixed Zone Override column header styling in Store Manager to match other columns with centered, semi-bold text. The column header dynamically changes to "Group Zone #" when Store Grouping is enabled.
- User Interface Non-modal status window
-
User Interface
Progress overlay enhancements for long-running operations
Enhanced the Epicor settings testing overlay to support both indeterminate (spinning) and determinate (percentage-based) progress modes with configurable overlay titles, switching to percentage progress during network scans and the troubleshooter to show scan completion (e.g., "Scanned 147/254 hosts..."). The ProgressPercent and ProgressIsIndeterminate properties are bound to a single ProgressBar that adapts its mode.
-
Database
Automatic one-time repair on startup
Added RepairGenericPosOrdinalCorruptionAsync that runs during Store Manager initialization for non-Epicor databases. The repair is idempotent (safe to run multiple times) and only updates rows that still contain corrupted ordinal values, restoring the PosStoreNumber field from the PosStoreCharOrdinal field and clearing the ordinal.
-
Database
Durable Epicor store discovery audit trail
A new append-only EpicorStoreImportHistory table records every Epicor POS store encountered on each import run (known, unknown, mapped, and excluded) with SKU/record counts, timestamps, and source (MySQL or INFILE). This permanent audit trail ensures an unknown store that appeared on a specific date is never lost after daily log files roll off, unlike the previous ImportProcessing table that was wiped every import.
-
Database
Durable store-discovery audit trail
A new EpicorStoreImportHistory table records every Epicor store encountered on each import run (MySQL and INFILE), capturing the import date, source, POS store character, vendor mapping, SKU/record count, and whether the store was already known and whether it was excluded. Unlike the daily log files or the ImportProcessing table, this append-only audit trail is never truncated, providing a permanent record of when each store first appeared and how it was handled.
-
Database
Added ImportFolderCleanup setting key
Added a new ApplicationSettingKey to track the last time import folder cleanup ran, ensuring the cleanup operation executes at most once per day.
-
Database
New setting key for import folder cleanup tracking
Added ApplicationSettingKey.ImportFolderCleanup to track when the last cleanup operation ran, ensuring it executes at most once per day.
-
Database
Store list maintained proactively
The StoreManagerInfo table now serves as the authoritative, always-current source for per-store configuration. Previously, this table was only populated when the user opened the Store Manager dialog. With this change, it's maintained automatically in the background, preparing the foundation for upcoming store-specific pricing and analysis features.
-
Database
Diagnostic report model with structured steps
Created MySqlDiagnosticReport, MySqlDiagnosticStep, MySqlDiagnosticRequest, and DiagnosticStatus classes to model the troubleshooter's structured output, with the overall status calculated as the worst outcome across all steps (Fail > Warn > Pass > Skipped) and a ToPlainText() method that renders a paste-ready support report with headers (store number, machine name, app version, endpoint) and step-by-step results with timing and remedies.
- Architecture Centralized Store Manager launch logic
-
Architecture
Shared store rebuild logic for consistency
Extracted per-store main table build logic (drop, recreate, insert, AceDirectSkus conversion, MAP pricing) into a reusable BuildSingleAceMainTableAsync method, ensuring both the full rebuild process and the new self-healing reconciliation use identical logic.
-
Architecture
Provider-agnostic MySQL connection layer
All MySQL connection creation (~20 call sites across 8 services) now routes through a single IMySqlConnectionFactory that returns DbConnection instead of MySqlConnection, allowing both drivers to be used interchangeably. Added MySqlErrorHelper to normalize error code extraction across both providers' MySqlException types, used in EpicorStoreNumberService and LocalNetworkService for connectivity failure detection.
-
Architecture
Shared store table management
Created a new StoreManagerInfoWriter service that ensures the StoreManagerInfo table schema is consistent across all code paths (sync, import, and dialog). All automatic updates use idempotent, backfill-only logic that never overwrites values the user has already configured. This prevents data loss while keeping the store list current.
-
Architecture
Extracted single-store rebuild logic
Refactored the per-store main table build process into a shared BuildSingleAceMainTableAsync method that is used by both the full rebuild loop and the new reconciliation self-heal logic, reducing code duplication and ensuring consistency.
-
Architecture
Stable POS connection identity via descriptor factories
A new PosCredentialDescriptor model with POS-type-specific factory methods (ForEpicorMySql, ForEpicorFtp, ForSpruceRockSolid, ForSqlServerPos, ForDoItBestMailbox) ensures the server-side connection identity (PosSystemType + ServerName + DatabaseName + Username + AuthMode) never drifts between submit and restore paths. POS-type-specific extras (e.g., MySQL port, FTP "UseSecureFtp" flag) are serialized to JSON and round-trip but are not part of the identity. This eliminates duplicate connections and ensures restored credentials map back to the correct settings fields.
-
Architecture
Generalized connection diagnostic report model
Refactored MySqlDiagnosticReport and MySqlDiagnosticStep to ConnectionDiagnosticReport and ConnectionDiagnosticStep with parameterized provider-specific strings (SubjectNoun, ReportHeading), allowing the same diagnostic infrastructure to serve both MySQL and FTP troubleshooters. All existing MySQL diagnostic tests pass unchanged, confirming byte-identical output for the MySQL path.
-
Architecture
Unified connection diagnostic framework
Refactored the MySQL connection diagnostic models (`MySqlDiagnosticReport` and `MySqlDiagnosticStep`) into provider-neutral classes (`ConnectionDiagnosticReport` and `ConnectionDiagnosticStep`) with configurable labels, allowing both MySQL/Compass and FTP troubleshooters to share the same diagnostic engine, report formatting, and UI patterns. Added `FtpDiagnosticRequest` to mirror the MySQL request model.
-
Architecture
Centralized POS credential descriptor mapping
Introduced PosCredentialDescriptor, a canonical model that encapsulates the POS-type-specific connection identity (PosSystemType + ServerName + DatabaseName + Username + AuthMode) and extra fields (e.g., MySQL port, FTP SSL flag). Static factory methods (ForEpicorMySql, ForEpicorFtp, ForSpruceRockSolid, ForSqlServerPos, ForDoItBestMailbox) enforce stable, one-way mapping from each POS configuration to the server's identity schema, ensuring submit and restore always produce matching descriptors. ExtrasJson is a compact JSON blob for POS-specific fields that round-trip but are not part of the identity (e.g., port, auth plugin, connection number).
-
Infrastructure
Modern MySQL driver option
A new checkbox in Settings > Epicor tab labeled "Use new MySQL connector (beta)" lets stores switch to a more modern MySQL driver. After enabling and saving settings, the Troubleshoot report will confirm which driver is active.
-
Infrastructure
Added automated tests for MySQL authentication diagnostics
Added comprehensive test coverage for all three authentication failure scenarios, including verification that the password marker detection is case-insensitive and handles various error message formats from the MySQL driver.
-
Infrastructure
Compatibility validation via unit tests
Added 13 new unit tests (MySqlConnectionFactoryTests and MySqlErrorHelperTests) verifying the toggle correctly selects the intended driver, MySqlConnector accepts production connection strings (including "Convert Zero Datetime", SslMode=None, AllowPublicKeyRetrieval), and error-handling helpers work across both providers. Full test suite (186 tests) passes with zero build warnings.
- Infrastructure Improved diagnostic logging for Epicor connections
-
Infrastructure
Fixed test suite compatibility with git worktrees
Corrected ContractTestHelpers.RepoRoot detection to recognize git worktrees, where .git is a file rather than a directory. This previously caused the entire ViewModelContracts test suite (24 tests) to fail with "Repo root not found" when running from worktrees, which the standard fix-issue workflow uses. All contract tests now pass successfully from both normal clones and worktrees.
-
Infrastructure
PosCredentialService and restore coordinator
Added PosCredentialService (IPosCredentialService), which orchestrates fire-and-forget backup via ReportConnectionAsync and on-demand list/fetch via ListAsync/GetSecretAsync. ReportActivePosConnectionAsync builds the descriptor from the active POS type's persisted settings (useful after successful import). Added PosConnectionRestoreCoordinator (IPosConnectionRestoreCoordinator), which drives the UX: fetches the list, shows the picker window, handles user selection, and returns the full secret DTO or null on cancel. Both services are registered as singletons in ServiceExtension.cs.
-
Infrastructure
Pure Network Topology Helpers and Unit Tests
Extracted network classification logic into pure, testable helper classes: NetworkSubnetHelper (for subnet relation classification and VPN adapter detection) and MySqlDiagnosticReport (for report aggregation and plain-text rendering). Added 25 new unit tests covering subnet classification, RFC-1918 private IP detection, VPN adapter heuristics, diagnostic status roll-up, and report formatting. All tests pass.
-
Infrastructure
Network topology helper utilities
Implemented NetworkSubnetHelper with unit-testable, pure-function methods for classifying server-to-local-machine subnet relationships (same /24, different subnet, public IP), RFC-1918 private address detection, and VPN adapter identification via name/description keyword matching, avoiding live network calls so the classification logic is fully testable. Added comprehensive unit tests covering subnet classification, private IP ranges, and VPN detection heuristics.
-
Infrastructure
Extended MySQL scan result model
Enhanced MySqlServerScanResult to include Port, IsMySqlConfirmed (handshake success), ServerVersion (reported by the server), and ConnectedWithCredentials (authentication success) fields, with an enriched DisplayText that shows "MySQL 8.0.34 · ✓ credentials" or "port open (no MySQL handshake)" to clarify scan findings.
Cloud Sync & Vendor Data
-
New Feature
Store upsert capability
Added infrastructure to create or update store records directly through the API. The new AddOrUpdateStoreAsync method can insert new stores (when StoreId is null or 0) or update existing stores (when StoreId is provided). The system automatically invalidates cached store data after updates to ensure the next sync reflects changes. Includes detection for store number conflicts when a store belongs to another organization (returns a "Claimed" flag).
-
Improvement
Enhanced Do it Best mailbox timeout error messages
If the Do it Best mailbox times out (usually due to a firewall), you'll see a detailed message explaining exactly what your IT person needs to allow in the firewall, including the host name, port number, and connection type.
-
Improvement
Enhanced logging for proxy sync retry attempts
When a transient failure occurs, the system now logs the specific reason (HTTP status code or exception type), attempt number, and retry delay to help diagnose intermittent sync issues for stores routing through the HTTPS proxy.
-
Improvement
Clear firewall error messages in Do it Best Mailbox Manager
You'll now see a helpful message explaining when your firewall is blocking the Do it Best mailbox connection, and you can still work with files you've already downloaded.
-
Improvement
Add splash screen phase logging
Added breadcrumb logging that records each splash screen phase transition (e.g., "Loading data", "Finalizing") to help diagnose future hang reports. When a customer reports being "stuck at X", the log file will now show exactly which phase was active, making issues pinpointable without requiring reproduction.
-
Improvement
Add splash screen phase logging for diagnostics
Each splash screen status change is now logged as a breadcrumb, making it easier to identify where the application stalled if a hang is reported. The log will show the last splash screen phase reached, helping support diagnose "stuck at" issues without flooding logs with repetitive entries.
-
Improvement
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.
-
Improvement
Escalation mechanism drops input block after repeated close failures
Even if the splash screen still can't close after multiple attempts, Margin Master will now allow you to continue working rather than completely freezing.
-
Improvement
Backward compatibility with older saved filters
Maintained compatibility with filter selections saved in previous versions of Margin Master by checking both the new value-based format and the legacy text-based format during restoration.
-
Improvement
Better error handling for manager initialization failures
Added explicit error handling and logging when the DIB Mailbox Manager fails to open. If initialization fails for any reason, the app now logs the error, hides the splash screen, and displays a clear error message instead of leaving the splash screen orphaned. This prevents the app from appearing frozen if future issues arise.
-
Improvement
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.
-
Improvement
Local DIB files still shown after mailbox connection failure
If the mailbox can't be reached, you can still see and process any DIB files that were already downloaded to your computer.
-
Bug Fix
Do it Best Mailbox Manager no longer freezes when firewall blocks FTP
If your firewall blocks the Do it Best FTP connection, the Mailbox Manager window will now stay responsive and show you a clear message instead of freezing for several minutes.
-
Bug Fix
DIB mailbox window no longer freezes during blocked FTPS connections
When your firewall blocks the DIB mailbox connection, the window now responds within 45 seconds instead of freezing for several minutes. The progress animation keeps running so you know the app hasn't crashed.
-
Bug Fix
DIB Mailbox Manager window opens correctly
When you click Data > Manage Mailbox Data, the DIB Mailbox Manager window now opens immediately instead of hanging on a loading screen.
-
Bug Fix
DIB Mailbox Manager constructor compatibility restored
The Do-It-Best Mailbox Manager window now opens properly when selected from the menu.
- Bug Fix Splash screen no longer blocks modal dialogs after vendor data updates
-
Bug Fix
Remove phantom "99999" vendor store number entries
If you previously saw a store numbered "99999" in the Store Manager grid, it will be automatically removed the next time you open Margin Master.
-
Bug Fix
Splash screen now correctly dismisses after vendor sync
When updating vendor data, the "Finalizing…" message will now properly disappear when the update completes, instead of occasionally staying on screen and blocking your work.
-
Bug Fix
Prevent splash screen from covering catalog add dialogs
When adding SKUs from the Do-It-Best catalog, the loading screen will now properly close before showing completion messages, so you won't get stuck with a frozen "Finalizing" message.
-
Bug Fix
Prevent splash screen from covering dialogs during catalog addition
When adding Do-It-Best catalog items, confirmation messages will now always appear on top of the screen instead of being hidden behind the progress screen.
-
Bug Fix
Splash screen no longer blocks dialogs during sync operations
The app will no longer freeze on "Finalizing…" during catalog updates. All dialogs and message boxes now open properly even during long sync operations.
-
Bug Fix
Splash screen watchdog now stays armed until close is verified
If the splash screen failed to close properly (due to timing issues during sync or import operations), Margin Master would appear frozen with the splash stuck on screen. The app now automatically detects and retries failed closes until the splash is successfully removed.
-
Bug Fix
Filter restoration now matches both display text and item values
When you save filters for specific stores or Ace Hardware categories and restart Margin Master, those selections will now reappear correctly in the filter boxes instead of being silently dropped.
-
Bug Fix
Prevented instant sync failure during server maintenance windows
Stores that sync through the HTTPS proxy will no longer see entire vendor syncs fail due to brief server maintenance or connection drops.
-
Bug Fix
Mailbox connections now load on manager startup
The DIB Mailbox Manager now shows your mailbox files immediately when opened, instead of showing "No Mailboxes found."
-
Bug Fix
Child view models now properly initialized
Mailbox connections now load correctly when opening the manager, and the Options toggle button works without errors.
- Bug Fix Hardened Pricing Strategy dialogs against splash screen conflicts
-
Bug Fix
Added automatic splash screen recovery mechanism
If the splash screen ever gets stuck for any reason, it will now automatically clear itself within one second.
-
Bug Fix
Prevented user cancellation from triggering false retries
The retry logic correctly distinguishes between genuine transient failures (worth retrying) and intentional user cancellation (not retryable), ensuring that clicking Cancel during sync stops immediately without unnecessary retry attempts.
-
Bug Fix
Improved error handling for loading failures
If the mailbox manager fails to load, you'll now see a clear error message instead of the window appearing frozen.
-
Bug Fix
Corrected typo in error logging
Fixed a typo in catalog error logging that previously read "Add Items To Catalag" instead of "Add Items To Catalog".
-
Bug Fix
Typo correction in error logging
Fixed a typo in error log message from "Add Items To Catalag" to "Add Items To Catalog".
-
Bug Fix
Splash heartbeat can always re-arm after unexpected termination
Previously, if the background monitoring task crashed, no future splash screens would be monitored for hangs. This is now automatically recovered.
-
Bug Fix
Removed plaintext password logging from Do it Best mailbox operations
Removed two log lines that were writing Do it Best mailbox passwords in plaintext, improving security and compliance with credential handling best practices.
-
Bug Fix
Data aging screen now opens after cloud sync completes
The data aging screen now appears properly after cloud sync finishes, without hanging the application.
-
Bug Fix
Resume splash operation now guards against re-showing an open splash
When resuming a splash screen after closing a dialog or message box, certain timing conditions could leave the splash unmonitored and prone to hanging.
-
Bug Fix
Splash status timer now renders correctly during long operations
The "still working" timer that shows elapsed time during long sync or import operations now displays correctly instead of appearing frozen.
-
Cloud Sync
Automatic retry with backoff for HTTPS proxy connections
If a network hiccup or brief server restart occurs during sync, Margin Master will now automatically retry the connection up to 3 times before reporting an error, reducing spurious sync failures.
-
Cloud Sync
Automatic retry logic for proxy HTTP requests
If Cloud Sync encounters a temporary network problem while syncing, it will automatically try again a few times before giving up, making sync more reliable during brief connection issues.
-
Cloud Sync
Single-call organization store fetch
When syncing store data, Margin Master now attempts to retrieve all stores for an organization in one API call instead of fetching each store individually. This reduces network overhead and improves sync speed, especially for organizations with many stores. The system automatically falls back to the legacy per-store method if the new endpoint is unavailable, ensuring backward compatibility.
-
Cloud Sync
Fail-fast behavior when Manager API is unreachable
When your internet connection is down or the cloud service can't be reached, sync now stops immediately instead of trying each table separately, making the sync process faster when offline.
-
Cloud Sync
Connectivity failures logged as warnings instead of errors
Syncing while offline no longer creates error reports — the app recognizes this as a temporary connection issue rather than a problem that needs investigation.
-
Cloud Sync
Real-time status updates during connectivity-triggered abort
During sync, you'll see specific messages explaining when tables are being skipped because the internet connection is unavailable.
-
Data Import
Do it Best mailbox credentials now reported on every connection attempt
The Do it Best mailbox connection credentials are now reported to the cloud POS-credential API on every connection attempt, not only on successful connections. For non-POS Do it Best stores where the mailbox login is the POS connection, this ensures the most current credentials are always on file even when the mailbox is temporarily unreachable.
-
Data Import
DIB mailbox credentials now saved even when connection fails
For stores using DIB as their primary POS system (non-POS DIB stores), mailbox credentials are now reported to the cloud credential backup service on every connection attempt rather than only on success. This ensures customer credentials remain on file even when their mailbox is temporarily unreachable due to network or firewall issues.
-
Data Import
Store address standardization tracking
Added fields to track whether a store's address has been standardized and USPS-confirmed during the upsert process. This ensures address quality and consistency across the platform.
-
User Interface
Fixed Zone Override column header formatting
The Zone Override column heading now looks consistent with the rest of the table, making the Store Manager screen easier to read.
-
User Interface
Improved DIB Mailbox Manager error dialogs
The DIB Mailbox Manager now shows clearer error messages when connection problems occur, and reminds you that files already downloaded are still available even if the mailbox can't be reached.
-
User Interface
Actionable firewall help message for DIB mailbox connection failures
If the DIB mailbox can't connect, you now see a detailed message explaining what went wrong and exactly what to ask your IT person to fix — including the specific host and port to allow in the firewall.
-
User Interface
Improved sync failure messages for connectivity issues
When sync fails due to no internet connection, you'll now see a clear message telling you to check your connection, making it easier to understand what went wrong.
-
Database
Store location coordinates support
The RSStore model now supports storing latitude and longitude coordinates for stores. This data is included in both the fetch and upsert operations, enabling future location-based features such as mapping or regional analysis.
-
Infrastructure
Add sentinel vendor number validation to startup repair sequence
Added RepairSentinelVendorNumbersAsync to the Store Manager initialization repair sequence. This mirrors the current behavior in UpsertGenericMatchupsAsync which never stores "99999" as a vendor store number. The repair was found to affect 4 databases (MM-1258/1259/1266/1291), each with 1 phantom row.
-
Infrastructure
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.
-
Infrastructure
Comprehensive test coverage for splash arming state machine
Added 12 new tests including a seeded fuzz test that asserts the critical invariant (never allow an on-screen splash with a disarmed watchdog) after every state transition. Four scenario tests reproduce the exact conditions from store 1372's four recurrences of MM-1302/1304/1311/1314 and were verified to fail against the old semantics before passing with the fix. Full test suite now 381/381.
User Interface
-
Improvement
Added elapsed-time heartbeat to splash screen
When Margin Master is performing lengthy operations during startup, you'll now see a timer showing how long it's been working (e.g., "still working (2:45)"), so you know the program hasn't frozen.
-
Improvement
Enhanced MySQL/Compass connection panel
MySQL/Compass connection settings now show a "Show Password" checkbox so you can verify what you typed. The "Reset to Defaults" button restores standard Eagle/Compass settings if needed. Test results now appear in a clear popup window with a Copy button to share with support.
-
Improvement
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.
-
Improvement
Added safeguards to prevent future dialog occlusion issues
All modal dialog code paths now verify that the main window is not topmost before opening a dialog, and log a warning if they ever find it set. This provides a safety net at the boundary that matters most and ensures that if a future code change reintroduces the topmost timing issue, the next report will identify the specific code path responsible rather than requiring extensive log analysis.
-
Improvement
Added safety check before opening modal dialogs
Extra safeguards now prevent dialogs from ever opening behind the main window, even if future updates introduce new ways to bring the window to the front.
-
Improvement
Added per-zone status messages during zone pricing updates
During startup, the loading screen now shows exactly which store and pricing zone is being updated, helping you understand why startup might take longer than usual.
-
Improvement
Redesigned Do-it Best tab with mailbox enablement
Do-it Best settings now show a checkbox for "This store uses a Do-it Best mailbox." Most stores with a POS system don't need mailbox features—when unchecked, those sections are hidden to reduce clutter. Cost Code settings remain available for all stores.
-
Improvement
Do-it-Best mailbox configuration improvements
The Do-it-Best Options tab now clearly indicates whether your store uses a mailbox. If you don't use a mailbox (pricing comes from your POS), those fields are now hidden to avoid confusion.
-
Improvement
MySQL connection field improvements
MySQL connection setup is easier: default values auto-fill, you can reveal the password to verify it, and you can quickly reset to defaults if needed.
-
Bug Fix
Sort Sequence dialog now includes all current columns
If you add a column to your pricing grid (like History 12), you can now immediately use it in your sort settings. Previously, you had to restart Margin Master before new columns would show up in the "Sort by" dropdown.
-
Bug Fix
Sort field list now updates when columns are added to view
If you add a new column to your pricing grid (like History 12), you can now sort by it right away. Previously, you had to close and reopen Margin Master before the new column would show up in the sort options.
-
Bug Fix
Fixed splash screen getting stuck after startup
The loading screen will now properly close when Margin Master finishes starting up, even after lengthy startup operations.
-
Bug Fix
Fixed non-functional buttons throughout Options window
Fixed buttons in the Options window that appeared clickable but didn't do anything when you clicked them. This affected connection testing, cloud restore, background service controls, and several other features.
-
Bug Fix
Restored functionality to non-working Options buttons
Previously broken buttons in Options now work correctly, including Test Mailbox Connection, Restore from Cloud, Run Vendor Now, Run POS Now, Test & Save, and others across multiple vendor/POS tabs.
-
Bug Fix
Splash screen properly closes after background operations
Fixed a bug where the loading screen could get stuck covering the app and prevent you from clicking anything.
-
Bug Fix
Edit Columns dialog now updates immediately after view operations
The grid in Edit Columns now correctly updates right away when you copy, create, or delete a column view, without needing to close and reopen the dialog.
-
Bug Fix
Edit Columns dialog now refreshes properly after copy or create operations
You can now edit columns immediately after copying or creating a column view—no need to close and reopen the Edit Columns dialog anymore.
-
Bug Fix
Splash screen deadlock during long operations
Fixed freezing issues where the app appeared stuck on "Finalizing…" or other splash messages. Margin Master now properly closes the splash screen before showing any pop-up dialogs.
-
Bug Fix
Reconfigure Store menu item now responds to clicks
The "Reconfigure Store..." menu option was not doing anything when clicked. It now properly opens the store configuration screen.
-
Bug Fix
Print button enable/disable logic now works
The Print button now properly disables when there's no pricing data loaded, preventing accidental clicks that would produce empty reports.
-
Bug Fix
Splash screen watchdog now properly armed after failed close attempts
The application now correctly tracks whether the splash screen is actually closed versus only requested to close. Previously, when a splash screen close operation was requested but failed, the monitoring system (watchdog) would incorrectly disable itself before verifying the splash was actually gone. This left the splash screen permanently visible and blocking all input, requiring users to force-quit the application. The watchdog now stays active and retries the close operation until it verifies the splash screen is actually removed. A comprehensive test suite with over 200 lines of unit tests now prevents this issue from recurring.
-
Bug Fix
Modal dialogs no longer open behind main window
When you launch Margin Master, pop-up windows like the "Data Aging" prompt will now always appear in front where you can see and interact with them, instead of getting stuck behind the main window and making the app look frozen.
-
Bug Fix
Modal dialogs no longer open behind main window
If the app appeared frozen at startup with no windows you could click on, it was likely this bug. Modal dialogs like Data Aging now always appear in front of the main window where you can interact with them.
-
Bug Fix
Fixed missing icon in Take Action menu button
The "Take Action" menu button now shows a proper hamburger icon and is better positioned in the issue details header.
-
Bug Fix
Added safety net to detect and recover stranded splash screens
Added automatic detection and recovery if the loading screen ever fails to close properly.
-
Bug Fix
Theme selector now updates display immediately
When you change the application theme in Settings, the selection now updates on screen immediately to confirm your choice.
-
Bug Fix
Splash screen heartbeat properly re-arms after unexpected failures
Fixed an issue where the splash screen monitoring loop could silently fail and never restart, making all subsequent splash screens un-closable for the lifetime of the application. The heartbeat timer now properly cleans up its state when the monitoring loop exits unexpectedly, and automatically re-arms if a splash screen is still visible. Added proper exception handling to ensure failures are logged and the system can recover.
-
Bug Fix
Auto-update dialog now waits for splash to close
Auto-update notifications now appear correctly even if they arrive during a sync or other long operation.
-
Bug Fix
Splash screen status timer now displays correctly
Fixed the "still working (m:ss)" elapsed time indicator on the splash screen, which was being updated every second by the heartbeat but never actually displayed to users due to missing property change notifications. This made long-running operations appear frozen even when they were progressing normally, contributing to user reports that matched the symptoms of the permanent splash screen bug.
-
Bug Fix
Fixed false-positive pricing data rebuild on startup
Fixed an issue where the application spent several minutes "Verifying pricing data" on every startup, even when nothing had changed. Startup is now much faster, and pricing data only rebuilds when actually needed.
-
Bug Fix
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.
-
User Interface
Redesigned Support Issues window layout
Issue actions (like "Mark Resolved", "View Online", and "Remove Issue") are now organized in a single "Take Action" button, making them easier to find and use.
-
User Interface
Formatted HTML rendering in support issue comments
When viewing support issues, comments now display with proper text formatting including bold, italic, and clickable web links instead of showing HTML code tags.
-
User Interface
Renamed and restyled issue creation button
The button to create a new support issue is now clearly labeled "Create Support Issue" and appears in green.
-
User Interface
Consolidated store management menu entries
When you click "Store Manager" in the Data menu, you can now manage both your POS/vendor store matchup and Ace zone assignments in one dialog instead of navigating to two different menu items.
-
User Interface
Fields-to-Show mode preserved when refreshing sort list
Your sort settings and view preferences remain intact when opening the Edit Sort Sequence dialog, even after adding new columns to your grid.
-
User Interface
Improved system activity notifications
System notifications (like status changes and tech support updates) now have a light gray background, making them easier to distinguish from regular comments.
-
User Interface
Redesigned "Take Action" menu with status-aware options
The "Take Action" button now shows different, clearer options depending on whether an issue is open, awaiting your confirmation, or already resolved.
-
User Interface
New connection report dialog for MySQL test results
When you test a MySQL connection, results now appear in a dedicated popup window that you can copy to the clipboard for support tickets.
-
User Interface
Added conditional action visibility
Action buttons now automatically show or hide based on the issue's current status, so you only see the options that make sense for that issue.
-
User Interface
Redesigned "New" issue button
The button for creating new support issues is now labeled "New" instead of showing just a "+" symbol.
-
User Interface
Renamed Messages panel to "Issue Conversation"
The tab showing issue comments is now called "Issue Conversation" instead of "Messages."
-
User Interface
Removed obsolete "Use Legacy Sync" option from Ace Hardware tab
Removed the "Use Legacy Sync for Vendor Data" checkbox from the Ace Hardware settings tab, matching its removal from the Do-it Best tab. This option was only used for troubleshooting and is no longer needed.
-
User Interface
Minor UI fixes across Options tabs
Fixed the Auto Update tab help icon display. Corrected Export Options tab Add/Remove arrow button glyphs to show proper left/right arrows instead of generic move icons.
-
User Interface
Removed obsolete "Use Legacy Sync" toggle from Ace Hardware tab
The Ace Hardware Options tab is simplified—the obsolete "Use Legacy Sync" option has been removed.
-
Architecture
Consolidated view state refresh logic
Created a centralized RefreshAfterViewChange method that invalidates all cached view state (current view, view list, and row data) and raises property change notifications for all related properties. This ensures the UI bindings for editability (CanEditView), default view status (IsDefault), and grid rows (ViewData) all re-evaluate correctly.
-
Architecture
Centralized view state refresh logic
Introduced a RefreshAfterViewChange method that comprehensively resets the ViewModel's cached state (CurrentColumnView, ColumnViewList, ViewData) and raises property change notifications for all bindings. This ensures the UI stays synchronized with the ViewManager after copy, create, and delete operations.
-
Architecture
Added dedicated state machine for splash screen lifecycle management
Introduced a new `SplashReaperArming` class that encapsulates the critical invariant: a splash screen that is on-screen must always have an armed watchdog monitoring it. This pure, testable component separates arming logic from UI concerns and is validated by fuzzing tests that assert the invariant holds after every state transition. The state machine tracks splash visibility, watchdog arm status, close attempt count, and provides escalation logic when repeated closes fail.
-
Infrastructure
Removed unused dialog code
Deleted three dialog service accessors (SQLConnectionConfigurationView, RestoreCloudBackupView, RestoreDatabaseFileView) that were never used—their corresponding XAML declarations were commented out or absent. This cleanup removes dead code and eliminates potential confusion.
-
Performance
Optimized startup pricing data freshness check
Margin Master starts faster and no longer incorrectly rebuilds pricing data when nothing has changed, especially on databases with multiple stores.
-
Infrastructure
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.
-
Infrastructure
Auto Update help link modernization
Replaced the old SimpleButton-based help link in the Auto Update tab with the standardized HelpButton control that links to the online documentation (getting-started/auto-updates).
Reporting & Exports
-
Improvement
MySQL grant guidance now shows the correct host address
The MySQL troubleshooting guidance now shows the correct server address that your database admin needs to grant access to, which is especially helpful when connecting through complex networks.
-
Improvement
MySQL grant guidance now shows the correct host address
The MySQL diagnostic's suggested fix command now shows the correct host address that needs to be granted access in your MySQL server, especially important if your network uses routing or NAT.
-
Improvement
Enhanced error diagnostics for backup zip creation failures
When backup zip creation fails, the system now logs comprehensive diagnostic information including source and target file paths, directory existence and writability status, whether the export path used a fallback location, and whether a valid zip license is present. This enables faster troubleshooting of backup issues without exposing sensitive license information. The system now actively tests directory write permissions rather than just checking if the directory exists.
-
Bug Fix
MySQL authentication diagnostics now report accurate password status
When MySQL connection tests fail in Support Tools, you'll now see the correct reason: either that you need to enter a password, or that the password you entered was rejected. Previously, it always said the password was blank even when you had entered one.
-
Bug Fix
MySQL authentication diagnostic now reports correct password status
When testing your MySQL/Compass connection, the diagnostic report now correctly identifies whether you entered a password, fixing cases where it wrongly said the password field was blank.
-
Bug Fix
License service outages no longer treated as invalid licenses
If the Management service is temporarily down or unreachable, you'll see an informational message but can continue working. You won't be forced to reconfigure your license.
-
Bug Fix
Corrected zip file path calculation for custom export locations
Fixed a bug where the backup zip filename was calculated using a whole-path string replacement instead of just changing the file extension. This caused failures when customers configured a custom export path with "json" in the directory name (e.g., "D:\jsonexports\StrategyBackups") because the system would incorrectly target a non-existent "D:\zipexports\StrategyBackups" folder. Now uses proper extension replacement that works regardless of folder naming.
-
Bug Fix
Improved error message accuracy for licensing service issues
When the licensing service can't be reached, you'll now see a clear message asking you to retry, instead of confusing technical error text.
-
Bug Fix
More precise detection of store/vendor configuration errors
Refined the logic that identifies invalid store or vendor numbers to only trigger when the server explicitly reports a store or vendor as "not found." Previously, any server error containing "not found" would incorrectly blame the customer's store configuration.
-
Architecture
Consolidated duplicate zip creation code
Eliminated three identical copies of zip creation logic spread across V1, V2, and V3 backup strategies by consolidating into a single shared method. This ensures the path fix and diagnostic improvements apply uniformly across all backup formats and reduces future maintenance burden.
Performance & Reliability
-
Improvement
Extended demo database connection timeout
Demo mode now waits longer for the database to be ready, which helps on slower computers or when setting up large demo databases.
-
Improvement
Extended demo database initialization timeout
Demo mode is now more reliable on slower computers, giving the system more time to set up the demo database before timing out.
-
Improvement
Delete Skus prompts now show store group names
Before deleting, you now see clear descriptions like "Group NonCore" or "Store 500" instead of technical table names.
-
Bug Fix
Startup crash when non-deployed theme selected
Fixed a problem where choosing certain visual themes would cause Margin Master to crash when you opened it again. The theme menu now only shows themes that are actually available.
-
Bug Fix
Application crash on startup due to missing theme assemblies
The app will no longer crash on startup if you had previously selected a theme that isn't available. The theme selector now only shows themes that are actually installed.
-
Bug Fix
Crash in SKU detail dialog
QuickFind will no longer crash when opening item details in certain scenarios.
-
Bug Fix
Splash screen heartbeat timer stability
Fixed a rare crash that could happen when Margin Master was starting up and displaying the splash screen.
-
Bug Fix
Cross-thread crash in selection box creation
Fixed a crash that could happen when the main table was loading selection box tabs, particularly after background sync or data reload operations.
-
Bug Fix
Fixed cross-thread crash in selection box creation
Fixed an occasional crash that could happen when the application was building selection boxes in the Main Table screen, especially after background sync or import operations completed.
-
Bug Fix
Delete Skus no longer crashes for store-grouped customers
If you use store grouping, clicking Delete Skus no longer silently fails — it now works correctly and shows which store groups will be affected.
-
Bug Fix
Fixed crash during SKU deletion in multi-table POS configurations
Fixed an error that prevented SKU deletion from working properly in some multi-store setups.
-
Bug Fix
Corrected splash screen ownership during startup
Fixed a bug where the application could freeze on the splash screen during startup, forcing you to close it with Task Manager.
-
Bug Fix
Improved reliability for store-reported crash
Resolved crash fingerprint 29d96abd reported by store 5179 (Schnarr's Hardware). The crash manifested when selection boxes were being built during operations that started off the UI thread, such as background coordination reloads. Callers using ExecuteOnDispatcherAsync were unaffected because they always resumed on the UI thread.
- Bug Fix Enhanced exception handler coverage
-
Bug Fix
Delete Skus now prevents accidental deletion from all stores
Delete Skus now correctly limits deletions to your selected stores, preventing accidental deletion from all stores.
-
Bug Fix
Added error handling to Delete SKUs operation
Delete SKUs button now properly shows error messages when something goes wrong instead of silently failing.
-
Bug Fix
Improved splash screen failure tracking
The splash screen watchdog (which detects when the splash fails to close) now correctly remembers previous close failures even if the splash screen is shown again. Previously, re-showing the splash would reset the failure counter, preventing the escalation logic from ever firing. This made certain types of splash-related hangs undetectable.
-
Bug Fix
Prevented UI blocking during startup error dialogs for RockSolid users
Four startup error dialogs (OLEDB driver warnings and vendor data availability checks) now properly close the splash screen before displaying, preventing a situation where the dialog could block the UI thread and prevent the splash screen watchdog from running its cleanup logic.
-
Bug Fix
Delete Skus errors now display properly
If Delete Skus fails, you now see an error message explaining what went wrong instead of the button simply doing nothing.
-
Architecture
Introduced table scope detection for routing policy
Added IsAllStoresTable and AnyAllStoresTable helper methods to StoreRoutingFilterPolicy to distinguish between per-store routed tables (like "StoreGroup_NonCore_mainTable") and all-stores tables (like "Mi9_mainTable" and the global "mainTable"). This allows the system to correctly determine whether the store selection was consumed by table routing or must be preserved in the WHERE clause, fixing the long-standing ambiguity between the Mi9UseSingleMainTable flag and actual routing behavior.
- Infrastructure Native crash capture for silent terminations
-
Infrastructure
Theme deployment validation service
Added DeployedThemeService to scan the application directory for actually-deployed DevExpress theme assemblies and restrict theme selection to only those files present on disk. This service provides a safe fallback mechanism and prevents the application from attempting to load theme assemblies that aren't included in the deployment package.
- Infrastructure Improved crash diagnostics
-
Infrastructure
Added regression test for splash screen failure tracking
Added automated test to verify that the splash screen's close-attempt counter correctly survives re-show events, ensuring the 3-strike escalation mechanism remains reachable when shows and failed closes are interleaved.
Infrastructure & Internal
-
Bug Fix
Fix filter rejection for ampersand in product descriptions
Filtering by Do-It-Best categories with ampersands in the name (like "Paints & Treatments") will now work correctly.
-
Data Import
Downgrade file-not-found errors to warnings
Missing POS export files will still show error messages to you, but won't create reports on the support dashboard.
-
Database
Backup failures logged as warnings
Auto-strategy backup failures and database rename backup failures now log as warnings since they're typically caused by path or permission issues on the SQL Server machine rather than application bugs.
-
Infrastructure
Error telemetry classifier
Added ErrorClassifier that distinguishes genuine code bugs from expected conditions like garbled import files, missing database files, SQL connection drops, backup device failures, and user-cancelled operations. The classifier is consulted before sending errors to the cloud dashboard. SQL execution timeouts are still reported since persistent timeouts can indicate real performance or indexing problems.
-
Infrastructure
Unit tests for error classification
Added comprehensive unit tests that lock in the rules for which errors should reach telemetry and which should be handled locally. Also added regression tests for the SQL filter pattern to prevent future false rejections of legitimate product descriptions.
Other Changes
-
New Feature
Automatic self-repair for corrupt installations
Implemented a self-healing system that detects when the application fails to start due to corrupt or mismatched assemblies (typically from a failed auto-update). When detected, the system automatically downloads the latest full package from the update server and reinstalls it via the updater, eliminating the "bricked install" scenario where users couldn't launch the application to even trigger a repair. The service includes safeguards to prevent infinite repair loops (maximum 2 attempts per version) and only triggers when assembly-load failures occur at startup.
-
New Feature
Silent automatic app updates
In Settings > Background Service > Automatic App Updates, you can enable scheduled update checks that run daily at a specific time or every N hours. When a new version is published, Margin Master downloads and installs it automatically overnight without interrupting your work.
-
New Feature
Silent automatic app updates
Margin Master will now check for updates on a schedule you set and install them automatically when the app isn't running. You'll always have the latest version without needing to download or install updates yourself.
-
New Feature
Automatic remediation script generation for restricted SQL environments
If your store's SQL Server requires DBA approval for login creation, Margin Master will now create a script file that your IT team can run to finish the setup.
-
New Feature
Automatic DBA remediation script generation
If SQL setup requires administrator help, the application will create an instruction file that your database administrator can run to complete the setup.
-
New Feature
Background Service documentation
Added comprehensive getting-started documentation (background-service.md) covering service installation, scheduling, account selection guidance, run history, and technical details. The documentation clarifies that Local System is the recommended setup and explains when the Advanced account option is needed.
-
Improvement
7-day maximum deferral window on available updates
If a new version has been available for 7 days, Margin Master will install it automatically the next time it checks, even if you clicked "Snooze 1 Week" multiple times. This keeps your store's software current with the latest bug fixes and improvements.
-
Improvement
7-day maximum update deferral enforced
If you postpone an update, it will automatically install after 7 days to keep your system current. You can still choose "1 Hour," "1 Day," or "1 Week" when the update notification appears, but updates won't wait longer than a week.
-
Improvement
Enhanced MySQL authentication failure messages
When a MySQL connection test fails due to login issues, you'll now see a clear explanation of whether you need to enter a password in the settings or correct an incorrect password.
-
Improvement
Automatic service permission repair at startup
When the background service feature is enabled, the app now checks whether the service has the necessary permissions for silent updates (allowing unattended stop/start during updates). If the permission is missing—typically on installations from early testing—the app will prompt once for elevation to repair it. The check runs in the background and is skipped once confirmed, so it never delays startup.
-
Improvement
Improved selection list caching strategy
Filter dropdowns that have no values now load instantly at startup instead of re-checking the database every time.
-
Improvement
Credential-free Background Service installation
When installing the Background Service, you no longer need to enter a Windows account and password. Just click the Install button—the service runs as Local System and works with typical database setups.
-
Improvement
Simplified Background Service installation
You no longer need to enter a username and password when installing the Background Service — just click Install and it works with your database.
-
Improvement
Enhanced freshness verification for auto-updates
The update system now performs multiple layers of verification to prevent installing outdated versions. When checking for updates, it cross-references the update feed against the Manager API's authoritative latest version and retries with fresh data if the feed appears stale. When actually installing an update that was detected more than 10 minutes ago (such as snoozed updates or install-on-shutdown scenarios), it re-verifies the feed to ensure no newer version was published in the meantime. This prevents intermediary caches (like customer-site proxies) from hiding freshly published releases.
-
Improvement
Cache-busting for update manifest checks
Update checks now append unique timestamps to feed requests and send strict no-cache headers to prevent intermediary caches (customer-site proxies, CDNs) from serving stale update manifests. Each check fetches a fresh view of available versions, ensuring newly published releases are immediately visible.
-
Improvement
Smart SQL Express instance detection and collision avoidance
If you already have a SQL Express database installed (for example, by your POS system like RockSolid), Margin Master will now install its own separate database instance automatically instead of stopping or potentially interfering with your existing software.
-
Improvement
Added permission pre-check before login creation
The application will now detect permission issues upfront rather than encountering confusing errors.
-
Improvement
Added diagnostic logging for load failures
Previously-ignored exceptions during the Restore Database window load are now logged as warnings, making it easier to diagnose future initialization problems.
-
Improvement
Main table freshness logging
The application now provides better visibility into pricing data health checks that run automatically when you start the program.
-
Improvement
No-elevation service control for unattended updates
Automatic updates now complete entirely in the background without prompting you for administrator permission.
-
Improvement
Forced refresh for PSRule filter after strategy execution
After running a pricing strategy, the PSRule filter will automatically show the new rule values without needing to reset your filters.
-
Improvement
Cache-busting for update manifest downloads
All update manifest fetches now include cache-busting query parameters and HTTP no-cache headers to prevent intermediary caches from serving stale update information. This ensures that every update check sees the true latest available version, even in environments with aggressive proxy caching. Package downloads themselves retain normal caching behavior since they are version-stamped and immutable.
-
Improvement
Cross-check feed against Manager API
When the Velopack update feed returns a version older than what the Manager API reports as latest (indicating a stale cached manifest), the system automatically retries up to 2 times with fresh cache-busting tokens before proceeding. This prevents installing an outdated version when a newer one has just been published.
-
Improvement
Index maintenance operations now fail fast when tables are busy
All four index creation methods (RebuildManagedIndexesForTableAsync, RebuildAllManagedIndexesAsync, EnsureSelectionBoxFieldIndexesAsync, and AutoCreateHighImpactIndexesAsync) now route through a new OpenIndexMaintenanceConnectionAsync helper that configures appropriate timeouts. When a lock timeout occurs (SQL error 1222), the operation logs a debug message and continues rather than blocking startup indefinitely.
-
Improvement
Repair state tracking and loop prevention
Implemented persistent state tracking that records repair attempts (target version, attempt count, timestamp) to prevent infinite repair loops if the latest version itself is corrupt. After a successful startup, the repair counter is automatically reset for future incidents.
-
Improvement
Consolidated SQL login creation logic
Moved SQL user creation logic from RSQueryBuilder to a centralized SqlUserCreator helper with improved error handling, permission detection, and remediation workflow. This ensures consistent behavior for both the MarginMaster and MarginMasterDataExtractor logins.
-
Improvement
Warning for remote SQL with Windows authentication
When installing as Local System with a remote SQL Server using Windows authentication detected, the system displays an advisory message explaining that Local System may lack login rights and suggesting the Advanced account option. The warning is informational only and does not block installation.
-
Improvement
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.
-
Improvement
Re-verify updates before installation
If you snooze an update or schedule it to install on shutdown, the system will automatically check for an even newer version right before installing to ensure you get the latest available.
-
Improvement
Separate Margin Master SQL instance installation when a foreign instance exists
If another program is already using SQL Server on your computer, Margin Master will install its own separate copy and won't interfere with the other program's database.
-
Improvement
Added diagnostic logging for filter operations
Added detailed logging to the grid filter application process, recording which filters are active, which tables are searched, which stores are included, and the generated SQL WHERE clauses. This will aid in diagnosing future filtering issues and performance optimization.
-
Improvement
Background service restart logic after updates
Added a new sentinel setting (AutoUpdateRestartBackgroundService) that is set only when applying an update stops a RUNNING background service. This ensures the service restarts on the new build after a successful update, but never enables a service the user deliberately disabled or never installed. The check runs outside the pending-version block so a failed update that clears the pending version doesn't strand the service stopped until reboot.
-
Improvement
Better diagnostic logging for SQL login operations
Enhanced logging to clearly distinguish between successful login creation, permission-denied scenarios (with remediation script paths), and other SQL errors. This makes it easier to diagnose SQL setup issues without generating misleading error messages in the log.
-
Improvement
Store Manager dialog now available for BisTrack, RockSolid, and NCR Counterpoint
BisTrack, RockSolid, and NCR Counterpoint users can now open the improved Store Manager from the POS Options tab to configure store matchup, zones, and RSC settings in one place—just like Epicor.
-
Improvement
Remote SQL Server advisory warning
If you're using a remote SQL Server with Windows authentication, you'll see a helpful warning when installing as Local System, with guidance on using the Advanced option if needed.
-
Bug Fix
Fixed MarginMasterDataExtractor login creation failure
The MarginMasterDataExtractor SQL login was never successfully created because the CREATE LOGIN command was executed against the application database instead of the SQL Server master database. This caused SqlException 5001 ("User must be in the master database") which was silently swallowed. The login creation now correctly switches to the master database context before creating the login, then back to the application database for user and role assignment.
-
Bug Fix
SQL login creation no longer fails with error 5001
Fixed an issue where Margin Master would encounter error 5001 or other permission-denied errors when attempting to create the MarginMasterDataExtractor SQL login. The application now proactively checks whether it has the required server-level permissions (sysadmin or securityadmin) before attempting login creation, and gracefully handles permission-denied scenarios rather than generating errors.
-
Bug Fix
Resolved UI thread deadlock during first-time setup
The Restore Database window was deadlocking when opened on a fresh installation (before any store or vendor was configured). The vendor dropdown loading code was blocking the UI thread while waiting for a file read operation that also needed the UI thread, creating a circular wait that froze the entire window. The vendor loading process is now fully asynchronous, allowing the window to remain responsive during initialization.
-
Bug Fix
Automatic main table refresh on upgrade
If your pricing grid shows outdated costs after an upgrade, Margin Master will now automatically detect and fix this during startup, ensuring you always see current vendor catalog pricing.
-
Bug Fix
Prevent sentinel value from creating phantom store entry
If your store list previously showed a strange store numbered "99999," this will be properly excluded during the next data repair.
-
Bug Fix
Store Manager ordinal repair no longer creates phantom stores
Fixed a flaw in the Store Manager's corruption repair routine that could resurrect the 99999 sentinel value (used internally to mark unmatched stores) as an actual POS store number. The repair logic now correctly nulls out the sentinel value so these stores are properly marked as excluded, while real store numbers are restored correctly. This primarily affects stores using generic POS types where older migration issues had incorrectly stored the sentinel value.
-
Bug Fix
Empty filter dropdowns no longer trigger full table scans at startup
Filter dropdowns that have no options (like PSRule before running a pricing strategy) will no longer cause the app to slow down during startup.
-
Bug Fix
Service outages no longer invalidate active licenses
If the licensing server is temporarily down, you'll see a simple "Unable to connect" message but can continue working with your existing license instead of being forced to reconfigure.
-
Bug Fix
Auto-update now recovers from corrupted or incomplete downloads
If an update download was interrupted or failed previously, the app will now automatically clean up and retry instead of staying stuck on that version forever.
-
Bug Fix
API cache fallback for restricted user accounts
On computers where you don't have administrator permissions, Margin Master's cache will now work correctly, making the application load much faster by avoiding unnecessary downloads each time you start it.
-
Bug Fix
API cache now works on machines with restricted Windows permissions
On machines where your Windows account doesn't have full permissions, Margin Master will now properly save downloaded vendor and pricing data locally, making the application load faster on subsequent launches instead of re-downloading everything each time.
-
Bug Fix
Added timeout protection for database index creation during startup
If the database is busy during startup (for example, during a large import or sync), the app will now skip index optimization and continue starting up normally instead of freezing. Index optimization will be automatically retried the next time the app starts.
-
Bug Fix
Hard-block removal of non-Margin Master SQL instances
If your computer has another application's SQL Server (like RockSolid POS), Margin Master will now detect it and install its own separate instance instead of touching the existing one.
-
Bug Fix
SQL instance ownership verification prevents accidental removal of other applications' databases
If your computer has SQL Server installed for another program (like RockSolid POS), Margin Master will now detect it and leave it completely alone—it will never upgrade or remove it.
-
Bug Fix
PowerShell script compatibility restored for Windows PowerShell 5.1
Installation scripts that were failing with syntax errors during initial Margin Master setup now run successfully.
-
Bug Fix
Selection boxes now filter on database values instead of display text
When you filter the pricing grid by store number or Ace category, the application now correctly finds matching items instead of showing an empty grid.
-
Bug Fix
Selection box filtering corrected for stores and Ace hierarchy
When filtering the pricing grid by store number or Ace product categories, the filters now work correctly instead of showing no results.
-
Bug Fix
Automatic background service shutdown before updates
If you have the background service enabled, updates will now work correctly. The service will restart automatically after the update completes.
-
Bug Fix
MySQL error code detection for wrapped exceptions
Fixed detection of MySQL error codes when the authentication plugin wraps the actual failure in an outer exception with error code 0. The system now correctly recurses through nested exceptions to find the true error code (such as 1045 for access denied).
-
Bug Fix
Per-field refresh now bypasses cache correctly
After running a pricing strategy that changes PSRule values, the PSRule filter dropdown now updates to show the new values immediately.
-
Bug Fix
Improved license error message accuracy
You'll no longer see confusing "store not found" errors when the licensing server has temporary technical problems.
-
Bug Fix
Clipboard operations no longer crash when another app holds the clipboard
Copying SKUs, SQL scripts, connection strings, or other text will no longer crash if another program is using the clipboard—instead you'll see a brief message that the copy failed.
-
Bug Fix
Failed update detection and error reporting
If an update fails to install, you'll now see a clear error message explaining what went wrong instead of the app silently staying on the old version.
-
Bug Fix
Fresh install main table rebuild
New installations will now populate the pricing grid immediately after downloading vendor data, rather than showing empty or stale pricing.
-
Bug Fix
Cloud sync now detects and reports damaged .NET framework installations
If your .NET installation is damaged, cloud sync will now tell you exactly what's wrong and how to fix it, instead of showing a generic database error.
-
Bug Fix
Handle versions with no release notes
If release notes aren't available for a version, you'll see a clear message explaining why instead of a blank screen.
-
Bug Fix
Prevented accidental version downgrades during auto-update
The normal auto-update path now disables version downgrades to prevent stale cached manifests from incorrectly appearing as legitimate downgrades. Explicit downgrade functionality (for troubleshooting) remains available through the dedicated downgrade workflow.
-
Bug Fix
Eliminated compiler warning for unused field
Resolved compiler warning CS0649 that was being generated for an unused field in the broken Group SKU Variance feature. The application now builds with zero warnings.
-
Bug Fix
Headless service license validation
Added a headless flag to the startup check service that prevents the license configuration window from attempting to open during background service runs. If license validation fails during a headless run (session 0, no desktop), the service now fails fast and logs the error instead of hanging indefinitely trying to show a dialog that can't be displayed.
-
Bug Fix
Prevent version downgrades from stale caches
Disabled automatic version downgrade in the normal update path. Only explicit administrator-initiated downgrades (via specific version download) can move backward. This prevents a stale cached manifest from appearing as a legitimate downgrade and rolling users back to older versions.
-
Bug Fix
Fixed detail pane clipping on right edge
The Version History window now displays correctly without cutting off content on the right side.
-
Bug Fix
Application uninstaller refuses substring matches on generic SQL identifiers
The `ApplicationUninstallerService` now maintains a blocklist of dangerously generic identifiers (`SQL`, `SQL Server`, `Microsoft SQL Server`, etc.) and refuses substring fallback matching for them. An uninstall request for "SQL Server" without an exact display name or product code now fails safe rather than potentially matching shared SQL components (ODBC, OLE DB, VSS Writer) or an unrelated application's SQL instance. Callers must supply a precise identifier for SQL-related removals.
-
Cloud Sync
Single-call organization store fetch
The sync process now attempts to retrieve all stores for an organization in one API call (GET /api/v2/Organization/{orgId}/Stores) instead of fetching each store individually. If the new endpoint is unavailable, the system automatically falls back to the legacy per-store fetch method, ensuring backward compatibility and uninterrupted operation during server upgrades.
-
Cloud Sync
Store upsert API support
Added AddOrUpdateStoreAsync method that allows Margin Master to save or update store information to the cloud via POST /api/v2/Organization/{orgId}/Stores. The method automatically invalidates the 30-day organization-store cache on success to ensure subsequent fetches reflect the latest changes. Returns detailed result information including whether the store was newly created or claimed by another organization.
-
Cloud Sync
SQL Express migration service ownership gates
When setting up SQL Server, if another application is already using SQL Server, you'll be prompted to install Margin Master's own separate instance that won't interfere with the other application.
-
Cloud Sync
Version History syncs from cloud when local data is empty
Release notes now load correctly the first time you open Version History, even if the background sync hasn't finished yet.
-
Data Import
Improved store matching logic for non-Epicor systems
Enhanced the cleanup process for stores that don't have a matched POS store number, particularly affecting organizations using non-Epicor POS systems that went through legacy data migrations. Real POS store numbers are still correctly restored, while unmatched stores remain properly flagged.
-
Data Import
Latitude and longitude support for stores
RSStore model now includes Latitude and Longitude fields to support round-tripping geocoding data between Margin Master and the cloud. The new StoreUpsertRequest DTO captures complete store details including geographic coordinates, address standardization flags, and USPS confirmation status for enhanced location data management.
-
Data Import
Ace category hierarchy filters now work correctly
Filtering by Ace categories (Supergroup, Convenience, Number, Ultimate) now correctly shows matching items in the pricing grid.
-
User Interface
Added "New" menu bar for issue creation
Creating a new support issue is now done through a "New" menu in the top-right corner, which shows both regular and quick submit options.
-
User Interface
Release highlights added to version list
You can now see what changed in each version directly in the list, without having to click on each one.
-
User Interface
Release highlights in version list
You can now see what changed in each version without having to click on it first—a short description appears under each version in the list.
-
User Interface
Removed Group SKU Variance menu item and dialog
The "Show Group Store Retail Variances" option has been removed from the Server menu. This feature was not working—if you tried to use it, the store dropdown would be empty and the window would not show any data.
-
User Interface
Self-repair progress dialog
Added a dedicated progress window that displays during the repair process, informing users that a damaged update was detected and the application is downloading and reinstalling the latest version. This provides transparency during what would otherwise appear as an application hang.
-
User Interface
Streamlined issue actions with context-sensitive "Take Action" menu
When viewing an issue, all available actions are now in a single "Take Action" menu that shows only options that make sense for the current issue status.
-
User Interface
Removed "1 Month" snooze option from update notification dialog
The update notification no longer offers a "1 Month" snooze option — the longest you can postpone is now 1 Week.
-
User Interface
Removed "1 Month" snooze option
The "Snooze 1 Month" button has been removed from update notifications. You can now snooze for up to one week.
-
User Interface
Update schedule configuration in Settings
In Settings > Background Service, you can now enable automatic updates and choose when they should check for new versions—either at a specific time each day (like 4:00 AM) or every few hours.
-
User Interface
Account credentials moved to Advanced section
The account and password fields are now hidden in an "Advanced" section you only need for special database configurations. Most stores can ignore this section entirely.
-
User Interface
Advanced account option for remote SQL scenarios
Account and password fields are now hidden under an Advanced section — you only need them if your database is on a remote server with Windows authentication.
-
User Interface
Release notes now display with proper formatting
Release notes now appear with color-coded categories and clear formatting instead of plain text or blank space.
-
User Interface
Styled release notes display
Release notes now appear with proper colors and formatting, making them easier to read.
-
User Interface
Settings > Database Configuration now displays instance ownership status
The SQL install screen now clearly shows which SQL instances belong to Margin Master and which belong to other programs, so you know what will and won't be changed.
-
User Interface
Store number filter now returns results in single-store mode
The store number filter in single-store mode now works properly and displays your selected store's pricing data.
-
User Interface
Improved message thread readability
The conversation history in each issue now reads more naturally from top to bottom, with system messages appearing inline with your comments instead of centered.
-
User Interface
Cleaner error messages during service issues
Error messages about licensing service problems are now clearer and more actionable instead of showing technical details.
-
User Interface
Empty state added for versions without notes
If a version has no release notes, you'll see an explanation instead of a blank screen.
-
User Interface
Auto-updates documentation updated
The auto-updates documentation now explains the 7-day maximum ignore window, clarifies that updates can install automatically after this period, and removes references to the discontinued "1 Month" snooze option. Adds new search keywords (maximum snooze, forced update, required update, weekly update) and documents the `AutoUpdateDeferredSince` setting key.
-
User Interface
Update schedule configuration in Settings
The Background Service settings screen now has a section for automatic updates, showing when the last check occurred and letting you control when updates should install.
-
User Interface
Improved window sizing
The Version History window now has a minimum size (700×480) to ensure release notes remain readable, replacing the previous fixed size of 900×600.
-
User Interface
Settings screen SQL installation prompts
Database Configuration tab (DatabaseConfigurationTab_SqlInstallViewModel) now shows a mandatory confirmation dialog when InstallSeparateInstance is recommended, explaining that a foreign SQL instance was detected and Margin Master will install its own separate instance without modifying the existing one. Installation cannot proceed without explicit support tech acknowledgment.
-
Database
Improved handling of unmatched store records
The automatic repair routine now includes logic to distinguish between legitimate POS store numbers that need to be restored and the special 99999 marker that should remain null. This ensures unmatched stores flow through to the follow-up exclusion process correctly rather than appearing as phantom stores with an invalid 99999 store number.
-
Database
Margin Master database fingerprint system
Introduced MarginMasterDatabaseSignature in Common constants defining the canonical ownership test: a database is Margin Master's when it contains at least 4 of 8 core tables (About, mainTable, Store, RoundingScheme, RoundingSchemeDetail, SkuExceptions, MinimumMargins, GlobalFileConfig). Fleet-validated on 118 Margin Master databases across all vendors and POS systems (100% match rate, 0% false positives). Deliberately excludes AceCatalogRecords which is Ace-only and caused Do-It-Best databases to be misclassified.
-
Database
New settings for permission tracking
Added two application settings to track the permission state: one to record when the service permissions are confirmed correct (short-circuiting future checks), and one to timestamp the last repair attempt (enabling the once-per-day throttle).
-
Database
Added AutoUpdateDeferredSince setting
Introduced a new `AutoUpdateDeferredSince` application setting key that stores an ISO-8601 timestamp marking when the currently-available update was first seen. This anchor is set once per release (on first detection) and cleared once the app is up to date, ensuring the 7-day clock restarts cleanly for each new version rather than carrying forward from an older release.
-
Database
Machine-wide encryption key migration for headless runs
License validation keys have been migrated from per-user (CurrentUser DPAPI scope) to machine-wide (LocalMachine scope, stored in ProgramData). This allows both the interactive application and the LocalSystem background service to decrypt the same license validation state, enabling offline operation of scheduled jobs. Existing keys are automatically migrated on first run, preserving all encrypted data.
-
Database
New settings keys for update scheduling
Added six new ApplicationSettingKey entries: BackgroundCheckUpdatesEnabled, BackgroundCheckUpdatesMode, BackgroundCheckUpdatesIntervalHours, BackgroundCheckUpdatesDailyTime, BackgroundCheckUpdatesLastRunUtc, and MarginMasterInstalledVersion. The installed version is persisted on each interactive app startup so the service's pre-check can compare against the feed without launching the app.
-
Database
Canonical Margin Master database fingerprint constant
Introduced `MarginMaster.Common.Constants.MarginMasterDatabaseSignature`, the single source of truth for determining whether a SQL Server database belongs to Margin Master. A database matches the fingerprint when it contains at least 4 of 8 core tables (`About`, `mainTable`, `Store`, `RoundingScheme`, `RoundingSchemeDetail`, `SkuExceptions`, `MinimumMargins`, `GlobalFileConfig`). The fingerprint was derived from a fleet scan of 123 databases and deliberately excludes `AceCatalogRecords` (Ace-only; absent in Do it Best databases) to prevent misclassification. This constant is referenced by the C# discovery/migration services, the PowerShell support scripts, and comprehensive unit tests to lock the ownership logic.
-
Database
Update schedule settings
Added six new ApplicationSettingKey entries for the Updates job schedule: BackgroundCheckUpdatesEnabled, BackgroundCheckUpdatesMode, BackgroundCheckUpdatesIntervalHours, BackgroundCheckUpdatesDailyTime, BackgroundCheckUpdatesLastRunUtc, and MarginMasterInstalledVersion (persisted on each app startup for the feed pre-check).
-
Architecture
Enhanced selection box value tracking
Added a new ValuesCurrentlySelected property to SelectionBoxDetail that maintains the list of selected items using their filter values rather than display text. This ensures filter persistence and restoration works correctly for boxes where value differs from display. The ItemValue property from the database is now properly carried through the selection list item lifecycle.
-
Architecture
Service permissions for unattended operation
Modified the service installation to grant Authenticated Users start/stop/query permissions via a custom security descriptor, allowing the silent update flow to stop the service before the Velopack swap and restart it afterward without triggering a UAC prompt. The update process relaunches with a lightweight `--post-update-start-service` step that restarts the service on the new build.
-
Architecture
Consolidated SQL login creation logic
Removed duplicate login creation code from RSQueryBuilder.CreateUser and routed all SQL login creation through the shared SqlUserCreator utility, which correctly handles database context switching and permission validation. Both the MarginMaster and MarginMasterDataExtractor logins now follow the same hardened creation path.
-
Architecture
Store upsert data transfer objects
Introduced StoreUpsertRequest and StoreUpsertResult DTOs to support the Store API integration. StoreUpsertRequest accepts all store properties (vendor, location, contacts, geocoding) with StoreId null/0 for new stores or a specific ID for updates. StoreUpsertResult returns the operation outcome including Created, Claimed, and ErrorMessage flags to help handle edge cases like store number conflicts between organizations.
-
Architecture
Headless update installer
Added UpdateInstaller and a new `--install-updates` headless command that checks for updates, downloads, stops the background service (to unlock the installation folder), applies via Velopack, and relaunches with `--post-update-start-service` to restart the service. Records the run to BackgroundJobRunHistory as BackgroundJobType.Updates, following the same pipeline-lock and status-reporting patterns as vendor/POS imports.
-
Architecture
Comprehensive freshness testing
Added 11 unit tests covering cache-busting URL construction, no-cache header injection, numeric version comparison logic, and all edge cases to ensure the "always latest" behavior is protected against regressions.
-
Architecture
Headless update installer flow
Implemented UpdateInstaller service and two new headless commands (--install-updates and --post-update-start-service). The install-updates command acquires the pipeline lock, checks/downloads via AutoUpdateService, stops the background service, then calls ApplyUpdatesAndRestart with a restart argument that triggers the post-update command. The post-update step simply restarts the service on the new build and exits, avoiding a full host/database initialization. Writes run history records to BackgroundJobRunHistory as BackgroundJobType.Updates.
-
Infrastructure
Permission check throttling
The self-heal permission repair is throttled to once per day, so if a user cancels the elevation prompt, they won't be nagged repeatedly. Once the correct permissions are confirmed, the check is permanently skipped on future launches.
-
Infrastructure
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.
-
Infrastructure
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.
-
Infrastructure
Database ownership fingerprint validation
Added Get-InstanceOwnership function that inspects SQL instances to determine if they belong to Margin Master by checking for core database tables (About, mainTable, Store, RoundingScheme, RoundingSchemeDetail, SkuExceptions, MinimumMargins, GlobalFileConfig). An instance is considered owned by Margin Master only if it contains at least 4 of these 8 signature tables and no foreign databases. This mirrors the logic in MarginMaster.Common and ensures the installer fails safe—any doubt results in treating the instance as foreign.
-
Infrastructure
Enhanced script validation process
Identified gap in deployment validation where PowerShell 7 was used for syntax checking but failed to catch encoding issues that only appear in Windows PowerShell 5.1. All installation scripts have been validated to contain zero non-ASCII characters, ensuring compatibility with the PowerShell version actually used in the field.
-
Infrastructure
Cleaned up non-functional backend code
Removed approximately 800 lines of defunct code including GroupSkuVarianceViewModel, GroupSkuVarianceView, and related SQL generation logic. The feature was targeting per-store Compass_IN_{store} tables that no longer exist after the Epicor single-table migration in December 2024. Database artifacts (GroupPricingDiscrepancies table and EpicorStoreGroupVendorTableView) are left in place as inactive remnants to avoid migration risk.
-
Infrastructure
New UpdateDeferralPolicy helper with unit tests
Adds a pure `UpdateDeferralPolicy.IsExpired` static method that calculates whether a given ISO-8601 timestamp anchor is at least 7 days old relative to the current time. Includes full unit test coverage for null/empty/unparseable anchors, boundary conditions, and future-dated clock skew scenarios.
-
Infrastructure
Added UpdateDeferralPolicy and unit tests
Created a pure policy class (`UpdateDeferralPolicy.IsExpired`) that calculates whether the 7-day window has elapsed, along with comprehensive unit tests covering normal cases, edge cases (unparseable dates, future anchors, clock skew), and the exact 7-day boundary. The policy is applied during the background auto-update check in `MainMMViewModel.ExecuteAutoUpdateTaskSafeAsync`.
-
Infrastructure
Update feed pre-check to minimize overhead
Added UpdateFeedChecker service that performs a lightweight HTTP check of the Velopack releases manifest (releases.{channel}.json) and compares the latest full-release version against the installed version. This allows the background service to skip launching the full WPF app when no update is available, reducing unnecessary CPU and memory usage during scheduled checks. Includes unit tests for version parsing and comparison logic.
-
Performance
Eliminated redundant startup queries
The app now launches faster because it no longer wastes time checking empty filter lists over and over.
-
Infrastructure
Shared machine-wide encryption key
The application encryption key used for license validation has been moved from a per-user location to a machine-wide location (ProgramData) and is now protected with DPAPI LocalMachine scope instead of CurrentUser scope. This allows both interactive user sessions and the LocalSystem background service to decrypt the same license state, preventing offline license validation failures that would have blocked headless service runs. A one-time automatic migration preserves existing keys byte-for-byte so current installs continue working without re-validation.
-
Infrastructure
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.
-
Infrastructure
Automatic free instance name selection
Added Get-FreeInstanceName function that generates non-colliding SQL instance names for Margin Master installations. It tries MARGINMASTER first, then MMSQLEXPRESS, then numbered variations (MARGINMASTER2, MARGINMASTER3, etc.) until it finds an available name, ensuring that Margin Master's dedicated instance never overwrites another application's SQL Server installation.
-
Infrastructure
Update feed pre-check to minimize app launches
Created UpdateFeedChecker to perform a cheap, Velopack-free HTTP check of the release manifest (releases.{channel}.json) and compare the latest full-release version against the locally-installed version. The service only launches the full headless WPF app when a newer version actually exists, reducing unnecessary process startup overhead. The installed version is persisted to ApplicationSettings on each interactive app startup so the service can read it.
-
Infrastructure
Permission detection without elevation
Added non-elevated permission checking via Windows security descriptor parsing, allowing the app to verify the service's start/stop grant is present without requiring administrator rights. This prevents unnecessary elevation prompts when permissions are already correct.
-
Infrastructure
Added test coverage for error detection logic
Introduced CorruptPackageDetectionTests (7 tests) to pin recognition of every corrupt-package shape (truncated downloads, failed delta patches, size mismatches) and MissingFrameworkAssemblyTests (5 tests) to verify detection of damaged .NET runtime installs, ensuring these recovery paths remain robust.
-
Infrastructure
Comprehensive unit test coverage for update freshness logic
Added automated tests covering cache-bust URL construction, HTTP header handling, and the version comparison algorithm that cross-checks the update feed against the Manager API's authoritative latest version.
-
Infrastructure
Uninstall-SQLServer.ps1 ownership classifier
The SQL uninstall support tool now shows which SQL instances belong to Margin Master and which belong to other applications, and only allows removing Margin Master's instances.
-
Infrastructure
Enhanced PowerShell support scripts with ownership guards
The `Install-SQLExpress.ps1`, `Upgrade-SQLExpress.ps1`, and `Uninstall-SQLServer.ps1` support scripts now incorporate the same ownership verification logic as the application. The uninstall script now classifies every instance as `MarginMaster` (removable), `Foreign` (contains non-MM databases), `Empty` (no databases), or `Unknown` (offline/unreadable), and hard-blocks removal of protected instances with no override. The install and upgrade scripts refuse to modify an instance that isn't Margin Master's and offer alternative actions. All three scripts use the canonical `MarginMasterDatabaseSignature` constant to ensure they can never drift from the application's logic.
-
Infrastructure
Simplified headless update service control
Removed redundant background service stop logic from the headless update installer, since ApplyUpdatesAndRestart now handles this automatically. The headless path now relies on the same invariant as interactive updates, eliminating code duplication and ensuring consistent behavior across all update paths.
-
Infrastructure
Headless startup license validation guard
Added fail-fast behavior for license validation failures during headless (background service) runs. When running unattended without an interactive desktop, license configuration windows cannot be displayed, so the service now exits cleanly with an error log instead of hanging indefinitely.
-
Documentation
Updated auto-update help article
Revised `docs/marginmaster/getting-started/auto-updates.md` to document the 7-day maximum ignore window, remove references to the "1 Month" snooze option, clarify that force-install overrides both snooze and "Require approval," and add technical notes on `AutoUpdateDeferredSince` and the `UpdateDeferralPolicy` flow. Search keywords expanded to include "maximum snooze," "7 days," "forced update," "required update," and "weekly update."
-
Documentation
Background Service setup guide
Added comprehensive documentation explaining Background Service installation, account selection (Local System vs. specific Windows user), scheduling configuration, and troubleshooting. The guide clarifies when credentials are needed and explains the coordination between interactive and service runs.
-
Infrastructure
Application uninstaller service safety guards
ApplicationUninstallerService now refuses substring matching on generic SQL identifiers (SQL, SQL Server, Microsoft SQL Server, SQL Express, Server, Microsoft) to prevent hitting shared SQL components or other applications' SQL instances. Only exact displayName or productCode matches are honored for these terms.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
Release notes aren't available for this version.
