Tag
qa-2026-10-06· Created: 2026-10-06 · Last Updated: 2026-10-06
What shipped to QA in this release (changes since 2026-08-11), grouped by area. The Ref column is stable — cite it when reporting. Rows marked → How to test are expanded at the bottom.
This release covers almost two months. An intermediate build was published to QA on 2026-09-28 without release notes, so some of these changes may already have been visible; they are listed here because this is the first changelog since 2026-08-11.
| Type | What changed | Where to check | Ref |
|---|---|---|---|
| New | The Merchants list switches to a card per merchant on narrow screens, with a select-all checkbox and a Sort by control above the cards · other admin lists are unchanged. | Platform › Merchants · window at 375 px | #2589 |
| New | Quick search (Ctrl+K) finds merchants, partners and users as you type, listed under Merchants, Partners and Users · a partner admin sees only their own partner's merchants and users · a merchant result opens its detail page and a user result opens the Users list (there is no single-user page) · the old "merchant:", "partner:" and "user:" search tips, which never worked, are gone. | Admin portal › Quick search (Ctrl+K) | #2357 |
| Fixed | Renaming a database server to a name another server already uses is now refused instead of saving two servers with the same name · the drawer reports the refusal through the "Someone updated this server while you were editing" conflict dialog rather than a "name already exists" message, so that dialog is expected here. → How to test | Platform › Servers & DBs › open a server › Edit server | #2635 |
| Fixed | Status badges (Active, Inactive, Online, Suspended and the device states) read in English when the admin portal is in English · they used to show the Spanish text ("Activo", "Pendiente", "Sin conexión") whatever the language, and still read in Spanish after switching to ES. | Platform › Merchants · Partners · Devices · Servers · Merchant groups · AI prompts · a merchant's header, Overview and Devices tab · Partner › Merchants · Users | #2441 |
| Fixed | Inviting an email that already has an account is refused with "This email already belongs to an account" · a SystemAdmin is refused for any existing account, a partner admin only when the account already belongs to that partner or one of its merchants (outside that scope the invite is sent, so a partner cannot probe who has an account). → How to test | Platform › Users › Invite · Platform › Merchants › a merchant › Invite · Partner › Users › Invite · Partner › Merchants › a merchant › Invite | #2394 |
| Fixed | A second invitation to an email that already has a pending invitation for the same partner or merchant is refused with "This email already has a pending invitation" · the partner and merchant invite drawers used to send a duplicate. | Partner › Users › Invite · Partner › Merchants › a merchant › Invite · Platform › Merchants › a merchant › Invite | #2394 |
| Fixed | The Type filter on the device registry offers only POS and Kiosk · the retired "Connector RMH" and "Connector RMS" options, which could never match a device, are gone. | Platform › Devices › Type filter | #2320 |
| Fixed | Editing the master email layout shows it once in the live preview and in version history, with its {{Content}} slot between one header and one footer · before, the layout appeared nested inside itself, with the header and footer twice · other templates still preview inside the layout. |
Configuration › Templates › _master-layout |
#2197 |
| Fixed | On Windows, or any browser that shows classic scrollbars, the {{variable}} highlights in a template long enough to scroll stay on the text they mark instead of drifting off it · the catch: the editor now always keeps an empty strip (about 15px) at its right edge for the scrollbar, even when nothing scrolls. → How to test |
Configuration › Notification Templates › open a template | #2255 |
| Fixed | On a template longer than the editor box, the line numbers and highlighted text no longer run past the editor's bottom border, and they scroll with the text instead of staying put · known: where a line wraps, the line numbers below it can sit one row high (#2024, still open). → How to test | Configuration › Notification Templates › open a long template | #2051 |
| Fixed | {{variable}} highlights in the template editor sit exactly on their text instead of creeping right along a line (about 10px off by the third variable), and a long unbroken word wraps at the same point in the highlight as in the text · the highlight halo now shows on all four sides. |
Configuration › Notification Templates › open a template | #2018 |
| Fixed | Editing a platform user with a first or last name longer than 50 characters now shows a validation message instead of a server error · the form still lets you type up to 100, so the message appears when you save. → How to test | Platform › Platform Users › a user › Edit | #1930 |
| Type | What changed | Where to check | Ref |
|---|---|---|---|
| New | On the product editor, a tab with unsaved changes now shows a small dot that stays when you switch to another tab, so you can see which sections still have edits before saving. | Products › a product › Edit › change a field › switch tabs | #2633 |
| New | Clicking Save all with a value that cannot be saved now shows a "Fix before saving" list under the status panel, naming each section and field, with a button that jumps to it · nothing is sent until the list is clear, and it changes to "Nothing left to fix. Save again." once fixed. → How to test | Products › a product › Edit › Save all | #2633 |
| New | On a narrow screen (under 768px wide) the product editor replaces its row of tabs with a "Jump to section" dropdown that marks sections with unsaved changes with ●. → How to test | Products › a product › Edit · window under 768px wide | #2633 |
| New | The Products list switches to a card per product on narrow screens · each card shows the product name as a link with every other column as a label/value pair (SKU and barcode wrap instead of being cut off), plus a Sort by control above the cards · other lists still show a table at every width. → How to test | Products · window narrower than the tablet breakpoint (e.g. 375 px) | #2589 |
| New | Categories have an optional Code · the category drawer has a Code field after Name (letters, digits, - and _, up to 20), it is saved in upper case, and it shows in a new Code column on the category list and as a row on the category's detail page · categories saved before this release show "—" until a code is entered. |
Categories › New category (or a category › Edit) · Categories list › Code column · a category › General | #2535 |
| New | A category code already used by another category is refused on the Code field with "This code is already used by another category, including deleted ones." · a deleted category keeps its code forever, so a code freed by deleting a category still cannot be reused. → How to test | Categories › New category › Code | #2535 |
| New | Two categories under the same parent can no longer share a name · the drawer marks the Name field with "A category with this name already exists under the same parent." · the match ignores upper/lower case, and top-level categories count as siblings of each other. → How to test | Categories › New category (or a category › Edit) › Name | #2534 |
| New | Deleting a category that still has products or subcategories now offers to move them to another category first · Delete is no longer greyed out, and after confirming you pick a target and click "Move and delete", which warns first if the target is in a tax holiday that those products would join. → How to test | Categories › a category › Delete (list row or detail page) | #2531 |
| New | Categories can be nested at most 8 levels below a top-level category · creating a 10th level, or moving a category so that its deepest subcategory would land past that, is refused in the drawer with "Category tree depth limit exceeded" · the message stays in English when the portal is in Spanish. → How to test | Categories › New category › Parent category (or a category › Edit › Parent category) | #2530 |
| New | A customer tax profile is now edited on its own page instead of the side drawer · General (name, description, requires-certificate) and Mapping rules sit on separate tabs and save together with one Save all, an inactive profile opens read-only with no save bar, and the drawer now only creates new profiles. → How to test | Taxes › Customer tax profiles › open a profile › Edit | #2552 |
| New | The product edit page's General section has a Track inventory toggle ("Quantity on hand is tracked across locations") · it saves with the rest of General and appears in the "someone else changed this product" dialog. | Products › a product › Edit › General | #2504 |
| New | The Inventory section of the product edit page has an Inventory rules block (Allow fractional quantities, Track serial numbers) and a Weighing block (tare weight in lb and in %) · Weighing shows only when fractional quantities or Requires manual price is on, a tare over 100% or with too many decimals is refused under the field, and a blanked tare now clears it, which the old Quick edit drawer silently ignored. → How to test | Products › a product › Edit › Inventory | #2494 |
| New | The Pricing section of the product edit page has a "Sale" block · commission mode and value, the tag-along product and its quantity, and the four selling rules (Can be sold, EBT / SNAP eligible, Requires manual price at register, Lock quantity at register) save from there together with any other changed section, with one "Product updated" toast. → How to test | Products › a product › Edit › Pricing › Sale | #2482 |
| New | The product page editor's General section now edits the product's categories · the same picker and chips as Quick edit, the first category listed is the primary, and the change saves with Save all instead of only from the Quick edit drawer. | Products › a product › Edit › General | #2467 |
| New | Lookup code and Barcode on the product page editor's General section are editable inputs for a product with exactly one variant · a blank lookup code is not saved (the field can only be changed, not cleared), while a blank barcode clears it. | Products › a product with one variant › Edit › General | #2467 |
| New | A non-Admin who opens an employee's edit address directly lands on the Dashboard with "Only an Admin can manage employees." | Employees › an employee › add /edit to the address (as a Manager) | #2444 |
| New | Deactivating a payment method that has already been used asks for confirmation first and lists what still uses it (sale payments, order payments, shift counts, account ledgers) · Cancel returns to the drawer with your edits kept · an unused method still deactivates directly. → How to test | Settings › Payment methods › a payment method › Active off › Save | #2408 #2407 |
| New | The payment-type picker offers "Credit card", "Debit card" and "Charge to account" alongside the existing types. | Settings › Payment methods › New payment method › Payment type | #2408 |
| New | Edit on a customer opens a full edit page instead of a drawer, with a General section (one "Save all" and "Discard changes") and the customer's Addresses on the same page · if someone else changed the customer meanwhile, the save shows the conflict screen instead of overwriting · an inactive customer opens read-only. | Customers › a customer › Edit | #2367 |
| New | Each price-change row in a product's History tab has "Show details", which expands to show the stores it applies to ("All locations" for a global change) and each line's old → new price · details load only when you expand, with a retry if they fail. | Products › a product included in a price change › History | #2369 |
| New | Cost update method has an "Apply to" choice, so the method can be set for the entire merchant as well as per location · in the location view, "Use the merchant default" now states the current merchant value ("Current merchant value: …") instead of leaving you to guess. → How to test | Settings › Cost update method | #2334 |
| New | Edit on a supplier opens a full edit page instead of a drawer, with a General section (one "Save all" and "Discard changes") and the supplier's Contacts on the same page · if someone else changed the supplier meanwhile, the save shows the conflict screen instead of overwriting · an inactive supplier opens read-only · the drawer is now used only to create a supplier. | Suppliers › a supplier › Edit | #2323 |
| New | Quick search (Ctrl+K) now finds products by name, SKU or barcode alongside pages, and choosing one opens the product and adds it to Recents · Recents are now kept per merchant, so the list starts empty after this release and switching merchant shows only that merchant's entries. → How to test | Top bar › Quick search (Ctrl+K) | #2258 |
| New | Settings has a Cost update method page where an Admin chooses, per location, whether completing a purchase receipt leaves the item cost alone, sets it to the receipt's unit cost, or uses a weighted average · "Use the merchant default" follows the business-wide value, and with none set the cost is not updated. → How to test | Settings › Catalog & Inventory › Cost update method | #2134 |
| New | An Admin can Reverse a completed receipt: on-hand goes back down, a linked purchase order steps back, the cost is restored where this receipt set the latest one, and the receipt shows a Reversed badge with "Reversed on" and "Reversed by" · this cannot be undone, and Managers do not see the button. → How to test | Receipts › a completed receipt › Reverse | #2133 |
| New | Reversing a receipt is refused, with every reason listed and nothing changed, when on-hand is below what the receipt would take back, a distribution was made from it, or its purchase order is closed or cancelled. → How to test | Receipts › a completed receipt › Reverse | #2133 |
| New | The Receipts list has a Reversed status filter, and a reversed receipt shows the Reversed badge on the list and in its purchase order's receipts. | Receipts › Status filter · Purchase orders › a purchase order | #2133 |
| New | Receipts have a Supplier reference field for the supplier's invoice or delivery-note number, editable while Draft, shown on the receipt, and matched by the Receipts search box · receipts saved before this release have no reference. → How to test | Receipts › a new or draft receipt · Receipts › search | #2132 |
| New | A receipt's General tab shows Received by and Closed by · they read "—" when the signed-in user's email matches no active employee, which is the case for the seeded admin. | Receipts › a completed or cancelled receipt › General tab | #2131 |
| New | The full-page product editor shows a Product status panel at the top in every status, listing what is still missing before the product can be activated or confirming it is ready · it is a readout only, and activation still happens from the product page. | Products › a product › Edit | #1936 |
| New | A Manager who opens a product's editor address is sent back to the product page with the message "Only an Admin can edit this product. You can still view it." · the page has no Edit button for a Manager, so the address is the only way in. → How to test | /products/<id>/edit as a Manager |
#1896 #2382 |
| New | The product editor has a save bar that names the sections you changed and saves them together with Save all, or reverts them with Discard changes · it states "Sections that share this product's record save together, in one request." | Products › a product › Edit › change a field | #1896 |
| New | The product Images tab works, where it used to be a "coming soon" notice. You can upload PNG, JPEG, WebP or iPhone HEIC photos (up to 8 MB each, 10 per product) by clicking or dropping them. You can also drag to reorder, set the primary image, edit each image's description, delete with a confirmation, and click an image to zoom. → How to test | Products › a product › Images tab | #1302 #1173 |
| New | The Products list, and a category's Products tab, show each product's primary image as the row thumbnail · if the image cannot load, the row shows the placeholder icon instead of a broken-image box. | Products · Categories › a category › Products tab | #1302 #1173 |
| Improved | Deactivating a category that still has products, active subcategories or tax holidays is refused, and a "Cannot deactivate" window lists exactly what depends on it · before, deactivation went through and left its products in a hidden category. | Categories › a category › Deactivate | #2531 |
| Improved | The breadcrumbs on a product's edit page now move to the Products list or back to the product without reloading the whole page, the same way the supplier, customer and employee edit pages already did. | Products › a product › Edit › breadcrumbs | #2541 |
| Improved | The Quick edit button and its side drawer are gone from the product detail page · every field the drawer edited is now on the Edit page (General, Pricing › Sale, Inventory), so the General tab's buttons are just Edit, Activate or Deactivate, and Delete. | Products › a product › General tab | #2504 #2482 #2494 |
| Improved | Edit on an employee's detail page now opens a full page editor with General and Locations & roles sections instead of a side drawer · the employee code is read-only there and there is no PIN field, the drawer is now used only to add a new employee, and a save that collides with another user's opens the conflict dialog. | Employees › an employee › Edit | #2444 |
| Improved | Blanking the Selling unit or Stocking unit on the product edit page shows a note under the field that it "can't be cleared, only changed" and the saved value is kept · the field used to snap back to its old value after saving with no explanation. | Products › a product › Edit › General | #2419 |
| Improved | The "Go to Adjustments" link in the dialog that blocks a receipt reversal opens a new adjustment already set to the receipt's location · after you save its header, one line per short item is added for the exact shortfall and you land on the draft · if you change the location first, the lines are skipped with a warning. → How to test | Purchase receipts › a completed receipt › Reverse › Go to Adjustments | #2256 |
| Improved | The expand/collapse arrow on each category row is a full 44px target instead of about 20px, so it is easier to hit on a touch screen · it takes a little more room on each row. | Categories › category tree | #2266 |
| Improved | Edit on a product's General tab now opens the full-page product editor instead of the side drawer · Admin only, as before. | Products › a product › General tab › Edit | #2233 |
| Improved | Completing a purchase receipt now changes the item cost by the location's cost update method · catch: with nothing configured the cost is no longer touched, where before every completion overwrote it with the receipt's unit cost. → How to test | Receipts › complete a receipt · then Products › the product › Inventory tab | #2131 #2134 |
| Improved | The product page labels the identifier row Lookup code instead of "SKU", matching the editor and the New product drawer. | Products › a product with one variant › General tab | #1896 #1897 |
| Improved | In the New product drawer the Lookup code comes right after the name (it was third, below the category, and labelled "SKU"), and its hint says a blank one is generated from the product name and can be overwritten. | Products › New product | #1897 |
| Improved | When the barcode policy uses the barcode as the SKU, the New product drawer shows one Item lookup code / barcode field instead of a read-only SKU copy beside the barcode. | Settings › Barcode policy › Use the barcode as the SKU › then Products › New product | #1897 |
| Improved | The All · Prices · Costs filters on a product's History tab are now rounded filter chips with a count inside, instead of small primary and secondary buttons. | Products › a product › History tab | #1839 |
| Improved | On Reports catalog cards the Run button and Schedule link labels use the smaller 13px nav text size the design calls for instead of 16px · values in the product conflict dialog likewise drop from 16px to 15px. | Reports › catalog · conflict dialog | #1686 |
| Improved | Dragging tax rates to reorder them no longer animates the rows when the device's "reduce motion" setting is on. | Taxes › Tax groups › a tax group › rates table | #1302 |
| Improved | Closing a fully received purchase order while a draft receipt is open now shows a translated message telling you to complete or cancel that receipt, and the dialog closes · before, the Spanish UI showed an English server message, and the dialog stayed open. | Purchase orders › a fully received order › Close | #1202 |
| Fixed | When someone else changed a product while you were picking its default tax group, saving now opens the "Someone updated this product while you were editing" dialog showing both choices by name, instead of an error toast that threw your pick away · the old toast now appears only if the latest product cannot be loaded. → How to test | Products › a product › Taxes tab › Default tax group › Save | #2620 |
| Fixed | Saving a customer tax profile where you changed only the mapping rules now detects that someone else saved first and opens the conflict dialog · before, the second save silently replaced the other person's rules. → How to test | Taxes › Customer tax profiles › a profile › Edit › Mapping rules | #2569 |
| Fixed | Saving a draft receipt where you changed only its lines now detects that someone else saved first and shows "Another user modified this draft. Please reload and try again." · before, the second save silently overwrote the other person's lines. → How to test | Inventory › Receipts › a Draft receipt | #2569 |
| Fixed | Products can no longer be added to an inactive category · "Add existing" or "Create product" from an inactive category's page fails with "Category is inactive: cat_…" (the message names the category by its internal reference, not its name), while a product already in an inactive category still saves normally. → How to test | Categories › an inactive category › Products › Add existing | #2531 |
| Fixed | The category picker on New product and on a product's edit page lists an active subcategory whose parent is inactive · it now appears at the top level of the list instead of being missing, so it can be chosen. → How to test | Products › New product › Category · Products › a product › Edit › General › Category | #2530 |
| Fixed | The Customers list and a customer's detail page now load for a Manager · they answered with an access error because only Admin could read customers, while adding, editing and deleting customers stays Admin-only. → How to test | People › Customers › open a customer | #2511 |
| Fixed | The Suppliers list, a supplier's Products tab, and the supplier pickers (new purchase order, purchase receipt header, a product's supplier drawer) now load for a Manager instead of failing with an access error · creating, editing and deleting suppliers stays Admin-only. → How to test | Suppliers › open a supplier › Products · Purchase orders › new purchase order | #2511 |
| Fixed | Blanking MSRP on a product's edit page now clears it, and the "can't be cleared" note no longer appears for MSRP · a value that is not a plain number (12,50, $12, more than 2 decimals) shows "Enter a valid number" or a decimals message under the field and the save sends nothing. → How to test |
Products › a product › Edit › General › MSRP | #2512 |
| Fixed | When another user saved the same product first, the conflict dialog on the product page editor now lists Categories as a differing field · "Apply mine" on a categories-only change used to replace the other editor's categories without showing any difference. → How to test | Products › a product › Edit › General | #2467 |
| Fixed | A Manager who opens a customer's or supplier's edit address directly now sees why they were turned away · customers send them to the Dashboard with "Only an Admin can manage customers.", suppliers to the supplier's read page with "Only an Admin can edit this supplier. You can still view it." · the message used to vanish before it could be seen. → How to test | Customers › a customer › add /edit to the address · Suppliers › a supplier › add /edit to the address | #2458 |
| Fixed | Saving the product edit page with "Save all" shows a "Product updated" confirmation · a successful save used to give no feedback at all · a conflict or a failed save still shows no toast. | Products › a product › Edit › Save all | #2419 |
| Fixed | In Spanish the product screens say "Controlado" / "No controlado" / "Controlar inventario" / "Controla números de serie" instead of the mixed "Con track" / "Sin track" / "Track de inventario" / "Trackea seriales". | Products list (ES) › Inventario filter and stock column · a product › General | #2419 |
| Fixed | SKU, barcode, supplier SKU, terminal serial number and postal code refuse accented letters, emoji and other non-standard characters with "Use standard characters only (A-Z, 0-9, spaces and symbols) — no accents or emoji" · before, the save succeeded and those characters were stored as "?". → How to test | Products › New product · a product › Variants grid and barcode aliases · a product › Suppliers · Suppliers · Locations › a location · Terminals · Customers › Addresses | #2278 |
| Fixed | Editing an employee's existing role now shows Location and Role as read-only with the note "Location and Role cannot be changed. To rename or move, delete this role and add a new one." and Save is disabled · before, you could change them and save, and the change silently did not happen. | Employees › an employee › Locations & roles › edit a role | #2236 |
| Fixed | The product edit page's General section saves only the fields you changed, and a save from a tab that is out of date now opens the conflict screen even when you only changed categories · before, the second of two tabs could save over the first and silently drop the categories it had added. → How to test | Products › a product › Edit › General › Save all | #2390 |
| Fixed | Adding or removing variant option axes and values from a tab that is out of date now shows "This product was changed by someone else. Your edit was not saved — reload it and try again." · before, it could silently delete the axes another tab had just added · an axis edit also no longer rewrites the product's name. → How to test | Products › a product › Variants › options | #2384 |
| Fixed | In Spanish, money shows the US way ($35.85) everywhere, the same as in English · before, the product page mixed $35.85 on the Price tab with 35,85 US$ on the Inventory tab and in the header, which reads as a foreign currency · dates and plain numbers stay in Spanish format. |
Products › a product in ES › header · Price · Inventory · Suppliers · History | #2365 #2304 |
| Fixed | When reversing a purchase receipt is blocked because stock has already moved, the "Reverse receipt" button is disabled · it used to stay clickable and just repeat the same refusal. | Purchase receipts › a completed receipt › Reverse | #2256 |
| Fixed | When a purchase order is below the supplier's minimum and your merchant enforces supplier minimums, the second submit confirmation now disables Submit to supplier instead of offering a button whose only outcome was an error toast · Cancel still works and the order stays Draft. → How to test | Purchase orders › a draft order › Submit to supplier | #2209 |
| Fixed | After you save a product's default tax group, the inherited rows in the per-location grid below show the new group straight away · they used to keep the old group until the page refetched. → How to test | Products › a product › Taxes tab | #2275 |
| Fixed | The Taxes tab's Save button sits level with the default tax-group picker, with the hint underneath both · at phone width Save drops below the picker. | Products › a product › Taxes tab | #2275 |
| Fixed | The pin star on each Reports catalog card is now a 44px touch target instead of 28px · the star icon is unchanged, the area you can click or tap around it is larger. | Reports › catalog › any report card › star | #2249 |
| Fixed | A variant attribute name (Size, Color…) can now be up to 100 characters, the database's limit · names of 51 to 100 characters used to be refused. | Products › a product › Variants tab › Add attribute | #1927 |
| Fixed | A printed transfer confirmation keeps every shipped line after the product on a line is deleted · the line used to vanish from the printout. → How to test | Transfers › a transfer › Confirmations › Print | #1911 |
| Fixed | In the conflict dialog shown when someone else saved the product first, a long field name or user name is cut short with an ellipsis instead of running into the value or the radio button next to it. → How to test | Products › a product › Edit (two tabs) | #1897 |
| Fixed | The Run button on each Reports catalog card now meets the 44px minimum height · a style override had cancelled the minimum and left it shorter. | Reports › catalog › any report card | #1704 |
| Fixed | A product's description is kept when you save the Bundle tab or add or remove a variant attribute · both actions used to erase the description without warning. → How to test | Products › a product › Bundle tab · Variants tab › Variant attributes | #1556 #1572 |
| Fixed | The Reports page now lists the report catalog · before, it showed "Couldn't load reports" on every visit, because its requests never reached the API. | Reports | #1553 |
| Fixed | Pinning a report with "Pin for me" or "Pin for team", and unpinning it, now saves, and the pin shows under "My pins" or "Pinned by your team" · before, those calls failed the same way as the catalog. | Reports › a report card › pin menu | #1553 |
| Fixed | Opening a product's Alerts tab while offline shows "You are offline" instead of a loading skeleton that never ends. | Products › a product › Alerts tab | #1302 |
| Fixed | "Generate combinations" no longer reports plain success when it kept old variants because they still hold stock · it now shows a warning toast that names those SKUs and says to sell them down or adjust them to zero first. Before, the kept variants stayed in the grid with no explanation. → How to test | Products › a product › Variants tab › Generate combinations | #1275 #1274 |
| Fixed | Deleting a product that still holds stock, or has units on a transfer that has not been received, is refused with "Product still has stock on hand" (or "…in transit") · before, the product was archived and its stock silently dropped out of the location totals and stock value. → How to test | Products › a product › Delete | #1274 #1307 |
| Fixed | Removing a variant attribute or value whose variant still holds stock, or has stock in transit, is refused with "Option value still has stock on hand" (or "…in transit") · before, the variant was archived and its stock stopped being counted. | Products › a product › Variants tab › Variant attributes | #1274 #1307 |
| Fixed | Deleting a location now counts every record that depends on it · one held only by a purchase order, stock count, inventory adjustment, transfer or similar record is now refused, and the "Cannot delete" message shows those as "N other reference(s)". Before, the delete went through and those records disappeared from their lists. → How to test | Configuration › Locations › a location › Delete | #1240 |
| Fixed | A Manager opening a product sees only the tabs their role can use · the Inventory, Suppliers, Taxes, History and Pricing tabs are hidden, and opening a product no longer shows "forbidden" error toasts. → How to test | Products › a product (signed in as Manager) | #1246 |
| Fixed | For a Manager, the product Variants and Bundle tabs are read-only · Generate combinations is hidden, variant cells and barcode aliases cannot be edited, the attribute manager is disabled, and the Bundle Save row is hidden. Before, each of these was shown and then failed with an access error. | Products › a product › Variants tab · Bundle tab (signed in as Manager) | #1246 |
| Fixed | A Manager who reaches the Locations list by typing its address can no longer click a row into a location detail page the role is not allowed to open · rows no longer look clickable. | portal.qa.qiiub.com/settings/locations (signed in as Manager) | #1246 |
| Fixed | Cancelling a purchase order that has a draft receipt still open is now refused with "This order still has a draft receipt open. Complete or cancel that receipt before cancelling the order." · before, the cancel went through, and completing the receipt later posted stock and quietly reopened the cancelled order. → How to test | Purchase orders › a submitted order › Cancel | #1202 |
| Fixed | Stock by location now shows each item's cost and price, and a real "Value (at cost)" total, for items with no location-specific cost · before, those rows showed "-" and the value read 0. In QA's seeded data that was every row. | Inventory › Stock by location | #1207 |
| Fixed | Sorting Stock by location by Cost or Price now reorders the rows · before, both headers did nothing wherever no location-specific value was set. | Inventory › Stock by location › Cost / Price column headers | #1207 |
| Type | What changed | Where to check | Ref |
|---|---|---|---|
| New | Below 900 px window width the top bar's quick-search box becomes a magnifier icon button that opens the same quick-search palette · at desktop width the full search box with "Ctrl K" is unchanged. | Any page · window narrower than 900 px · top bar | #2585 |
| New | Clicking the sidebar item of the list you are already on now reloads that list's data and keeps your search, filters, sort and page · the click used to do nothing; on a record's detail page the same click still takes you back to the list, and the dashboard, hubs and the Categories tree are not affected. → How to test | Merchant portal › Products (or Suppliers, Customers, Employees, Purchase orders…) · Admin portal › Platform › Merchants (or Partners, Devices, Users…) | #2453 |
| Improved | The hamburger menu button in the top bar at narrow widths is now a 44×44 px target, matching the search button beside it, instead of a 32 px one. | Any page · window narrower than 900 px · top bar | #2595 |
| Fixed | Pressing [ while a dropdown has keyboard focus no longer collapses or expands the sidebar · the shortcut already ignored text fields and now ignores dropdowns too, so typing into a list's "Show … per page" picker leaves the layout alone. → How to test |
Any list with a "Show … per page" picker · press [ with the picker focused |
#2695 |
| Fixed | On a desktop-width window the app shell loads straight into the wide layout · the hamburger and search icon no longer flash for a frame and the content no longer slides sideways as the sidebar offset settles on page load. → How to test | Any page · hard refresh at desktop width | #2595 |
| Fixed | Closing the quick-search palette returns keyboard focus to the button that opened it, instead of dropping focus to the top of the page. → How to test | Any page · top bar › quick search | #2585 |
| Fixed | The success message after an action that takes you to another page now appears on that page · for example "Product created" after creating a product, "Product deleted" after deleting one from its page, "Merchant created successfully" in admin · these messages used to be cleared by the page change before you could see them. → How to test | Merchant portal › Products › New product · a product › Delete · Admin portal › Platform › Merchants › Create | #2450 |
| Fixed | On a narrow screen, a tab strip wider than the screen scrolls so the selected tab stays visible · selecting a tab past the edge used to leave it off-screen with nothing showing which tab was active. | Products › a product at 375px width · any tabbed page on a phone | #2410 |
| Fixed | When the browser cannot reach the server, error toasts and banners show the screen's own translated message (for example "Could not save supplier" · "No pudimos guardar el suplidor") instead of the browser's raw English text such as "Failed to fetch". → How to test | Any save with the network offline | #2139 |
| Type | What changed | Where to check | Ref |
|---|---|---|---|
| Improved | Revoking your own current session, or being signed out for inactivity, shows the explanation once, on the sign-in page · it no longer also pops a toast; revoking a different session still shows "Session revoked". | Profile › Sessions › revoke the current session | #2450 |
| Fixed | An invitation sent to someone who already has an account now adds the new partner or merchant access to that same account when they open the invitation link and sign in · an ordinary sign-in without the link adds nothing, and the invitation stays pending. → How to test | Invitation email › Accept › sign in | #2394 #2395 |
| Fixed | Invitation and sign-in emails now carry the 2026-08-11 template updates (QIIUB logo in Gmail and Outlook, and the Spanish footer "Desarrollado por") · those changes never reached the database, because the template updater was not switched on, so emails kept the old templates until this release. | Any emailed invitation or sign-in link · English and Spanish | #1217 |
| Fixed | The sign-in link email opens with "Hi!" (Spanish "¡Hola!") instead of "Hi ," with a blank name, and the invitation greeting drops its stray trailing comma. | Any portal › sign in with an emailed link · any emailed invitation | #1217 |
Only the items that need more than a glance. Click to expand.
Steps that sign in as manager@techzone.demo need a user with the Manager role on the TechZone merchant. If that account does not exist on QA, any Manager-role user on a merchant with products, customers and suppliers works the same way.
[ toggled the sidebar open or closed.[ does nothing to the sidebar while a dropdown has focus. It still toggles the sidebar when focus is on the page itself.[.[ again — the sidebar should collapse (and [ again expands it).5). The box changes to "Nothing left to fix. Save again."admin.qa.qiiub.com as SystemAdmin. You need at least two servers under Platform › Servers & DBs (create a second one if needed).md breakpoint (768 px) each row is a card; at desktop width the table is unchanged.portal.qa.qiiub.com as a merchant Admin (for example admin@techzone.demo).QA Code A, code qa-01, save. Open it — the detail page shows the code as QA-01.QA Code B, code QA-01. Save — expect the error under Code, and nothing saved.qa 01 (with a space) — expect "Use only letters, digits, - and _ (up to 20)." before anything is sent.QA Code A, then try QA-01 again on a new category — it is still refused.portal.qa.qiiub.com as a merchant Admin (for example admin@techzone.demo).Electronics → ELECTRONICS), no parent. Save — expect the Name field error.portal.qa.qiiub.com as a merchant Admin (for example admin@techzone.demo) and open the same customer tax profile's Edit page in two tabs.portal.qa.qiiub.com as a merchant Admin (for example admin@techzone.demo).portal.qa.qiiub.com as a merchant Admin (for example admin@techzone.demo).QA L1 with no parent, then QA L2 with parent QA L1, and so on down to QA L9 — all nine save.QA L10 with parent QA L9 — expect "Category tree depth limit exceeded" in the drawer, and nothing saved.QA X with a child QA X2. Edit QA X and set its parent to QA L8 — refused too, because QA X2 would land at level 10.QA Parent with a subcategory QA Child, neither with products.QA Child, then deactivate QA Parent, then reactivate QA Child.QA Child is in the list, unindented.QA Child is listed the same way./customer-tax-profiles/<id>/edit, a page with General and Mapping rules tabs and one commit bar ("General and Mapping rules save together, as one record.").admin@techzone.demo). Customer tax profiles are seeded for this merchant.manager@techzone.demo and open /customer-tax-profiles/<id>/edit directly. Expect to land on the dashboard with "Only an Admin can manage customer tax profiles."portal.qa.qiiub.com as manager@techzone.demo (TechZone, Manager role).12,50 in MSRP. Expect "Enter a valid number" under the field, and Save does nothing. Try 1.234 — expect "Maximum 2 decimal places".101 in Tare weight (%). Expect "Must be no more than 100", and saving is blocked. Enter 2.5 instead and save.1 and save.admin@techzone.demo) and open the same product's Edit page in two browser tabs./edit address was redirected with no message, because the redirect itself cleared the notice./customers/<id> and /suppliers/<id>).portal.qa.qiiub.com as a Manager (for example manager@techzone.demo)./customers/<id>/edit. Expect to land on the Dashboard with "Only an Admin can manage customers."/suppliers/<id>/edit. Expect the supplier's read page with "Only an Admin can edit this supplier. You can still view it."admin.qa.qiiub.com as SystemAdmin.admin@techzone.demo.ÑANDÚ-01 as a SKU (or an accented postal code, an emoji in a barcode) saved with no error, and the value came back as ?AND?-01.ÑANDÚ-01 and try to save.123é and commit the cell.00926ñ and a terminal serial number containing an emoji.? before this release stay that way until re-entered.admin@techzone.demo.Size).Color).Size is still there.admin@techzone.demo). Settings › Purchasing policy › turn on Enforce supplier minimum order amount and save.{{variable}} boxes drifted off the words they mark.{{variables}} near line ends.admin@techzone.demo. Settings › Catalog & Inventory › Cost update method.admin@techzone.demo, open the receipt › Reverse › confirm.manager@techzone.demo and open a completed receipt. There is no Reverse button./purchase-receipts/new).FAC-12345, add a line, Save draft.12345. The receipt appears.{{variable}} highlights came loose from it.{{variables}}, so the body is taller than the editor.admin.qa.qiiub.com as SystemAdmin./products/<id>/edit. Any other role is redirected to the read-only product page with an explanation.manager@techzone.demo./edit to the address and press Enter.admin@techzone.demo). Open Products › any product and use Edit to give it a description, then save.Size), and then remove it.admin@techzone.demo), find a product with quantity on hand at any location (Inventory › Stock by location).portal.qa.qiiub.com as manager@techzone.demo.admin@techzone.demo and open the same product. All tabs should be present.Referenced in development but with nothing to verify through the normal portal flow — listed so a referenced number never dead-ends.
| Ref | What | Why not testable |
|---|---|---|
| #2689 | A magic-link sign-in token can be redeemed only once even when the same link is submitted twice at the same instant · the second request now gets a 401 instead of also signing in | Needs two requests carrying the same token to reach the server concurrently · a browser double-click on the emailed link does not reliably produce that race, and a normal second click already failed before this change |
| #2685 | Stock counts gain line entry: lines can be added to, edited on, and removed from an in-progress count, a count may now start with no lines, and the stock-count list gains search, column sorting, per-status totals and a closed date | API-only · no portal screen calls these endpoints yet (the stock-count pages are later phases of the same work), so there is nothing to click in admin or the merchant portal |
| #2510 | Sync pull no longer sends the internal numeric Id and MerchantId on each record · devices key every pulled record on GlobalId only |
Sync-only (POST /sync/pull) · used by the POS app, which is not deployed to QA, and no admin or portal screen reads it |
| #2636 | A sale recorded while a concurrent merge or void retires its shift is now refused instead of attaching its totals to the merged or voided shift | Sales are recorded by the POS app (not deployed to QA), and the refusal only fires in a race between the sale's save and a concurrent shift merge/void · no portal trigger |
| #2587 | The product image upload hint and the browser-side size check now use the server's configured upload limit (ObjectStorage:MaxUploadBytes) instead of a hard-coded 8 MB |
QA runs the default 8 MB limit (appsettings.json, 8,388,608 bytes), so the hint and the refusal read "8 MB" before and after · only visible on a deployment configured with a different limit |
| #2531 (busy-tree part) | A category save, product save or tax-holiday category change that arrives while a delete-with-move or deactivation is running waits, and answers "Categories are being reorganized. Wait a moment and try again." if the wait runs out · a move that collides with a concurrent edit is refused with "The category changed while it was being deleted. Try again." | Needs two writes racing within the same instant · the portal offers no way to hold the category tree open long enough to trigger it |
| #2547 | The activity log service now finds a record by its public reference instead of its internal number, hides cost fields from roles that cannot see cost, and returns field-by-field changes · the purchase order's Activity log tab now queries it | Nothing records purchase-order activity, so the purchase order's Activity log tab shows the same empty state before and after · the field changes are written only for products, which show on the product History tab through a separate endpoint |
| #2530 (cycle part) | The server refuses a parent change that would make a category its own ancestor ("Circular parent reference"), and every category screen tolerates cycles already in the data instead of hanging or crashing the tab | The portal's parent picker never offers a category's own descendants, so a cycle cannot be requested from a screen · and the old-data case needs a cycle seeded directly in the database |
| #2546 | New read endpoint GET /products/{publicId}/history returning a product family's field-history trail (changes, action label, actor, source and cause, newest first, paged) · cost-valued fields are redacted for anyone but SystemAdmin and Admin |
API-only · neither portal calls it (the product History tab still reads the price-change and cost-change feeds), so there is no screen that shows this trail |
| #2545 | Removing a supplier from a product now marks the link deleted instead of erasing it, and re-adding the same supplier (by hand or by a receipt's auto-link) restores that link · status codes and what the screens show are unchanged | Storage-only · the Suppliers tab looks identical before and after (removed links are hidden, re-adds still answer 201), and the record it keeps is only readable through the API-only history endpoint (#2546) |
| #2544 | Field-history rows for a store price, cost or tax override now name what caused them · applying a price change records that price change, and an override edit that changes cost records a cost change | Writes trail metadata only · no portal screen reads the field-history trail (see #2546) |
| #2543 | Every save of a product, variant, barcode, tier price, supplier link or store override now writes a per-field change record (old and new value) in the same transaction, including variants soft-deleted when a matrix option is removed | No UI trigger to observe · the records land in the merchant audit table, which no portal or admin screen shows for products (the purchase-order activity timeline and the platform audit log read other data) |
| #2541 (field-row part) | The four edit pages (product, supplier, customer, employee) now share one field-row and page shell · product field labels became real <label> elements and field errors are announced as alerts |
Markup and screen-reader behaviour only · the rows look the same and accessible names did not change |
| #2512 (API part) | Both product PUT endpoints now take MSRP as { "value": … } and refuse a bare number with 400 · a null inside an option axis's values list is now also refused by the validator |
API-only · the portal already sends the new shape, and a null option value was already refused with 400 by the request boundary, so no portal action reaches either path |
| #2477 | New record sync identities (GlobalId) are now generated in the time-ordered UUIDv7 format, and the database no longer fills one in by default · existing rows keep their old ids | GlobalId is internal sync identity · it never appears in the portal, the API responses QA sees use PublicId, and the change has no screen or behaviour to observe |
| #2386 | The POS terminal's offline identity snapshot now expires after at most 7 days, and the API refuses to start with a longer configured lifetime | POS-only (Tauri app not deployed to QA) plus a startup config guard · no admin or portal surface |
| #2395 (race part) | Two simultaneous sign-ins from the same invitation no longer fail with a server error or provision the user twice · a failure part-way through leaves no half-created user | Needs two concurrent sign-ins racing on one invitation · the browser cannot force that interleave |
| #2421 | The full product update endpoint now always checks and advances the product's version token, so a stale category-only save gets a conflict instead of silently dropping categories another tab added | API-only at this release · the portal's Quick edit drawer that used this endpoint is retired (#2504), and the product edit page saves through the per-section endpoints, so no portal screen reaches it |
| #2324 | Creating a product with a blank or whitespace-only description stores no description (NULL) instead of an empty string, matching what an update already did · products created before keep "" (no backfill) |
API-only · the portal's new-product drawer has no description field, so nothing in the portal sends a blank one on create |
| #2330 | Creating a product whose variant barcode is blank stores no barcode instead of an empty string, so a second blank-barcode product no longer fails with a conflict | API-only · the portal's new-product drawer already omits a blank barcode, so the collision was only reachable by a direct API call |
| #2297 | Price changes can now be submitted for approval, rejected (with an optional reason) and cancelled, so the Pending approval, Rejected and Cancelled statuses finally have a writer | API-only at this release · the portal's Price changes screens are read-only and have no Submit, Reject or Cancel button yet |
| #2308 | Completing an adjustment, a purchase receipt, a distribution, a transfer receipt, initializing a location and applying a price change look up the tax group for new store-product rows in one batch instead of one database round trip per line | Performance-only with identical results · the saved round trips are not observable at QA data sizes |
| #2368 | The price-change and cost-change list responses now carry the name of the user who created each row | API-only · no portal screen displays the new field yet |
| #2375 | The sync acknowledgement endpoint identifies the device by its public id | POS/sync-only · the POS app is not deployed to QA and no portal screen calls it |
| #2327 | The product edit page keeps the editor and your draft on screen when a background reload fails, and a save conflict whose latest-version fetch fails now says so instead of merging against outdated data | Needs the network to drop exactly between a save and its follow-up reload · the portal does not reload on window focus, so a tester cannot trigger the background reload on demand |
| #2239 | The product Bundle tab saves through its own PUT /api/products/{id}/bundle and no longer sends the product name |
The tab looks and saves the same; the name it used to send was the product's own loaded name, so the overwrite it removes has no portal repro |
| #2220 | Two POS scan-feedback settings (on/off, volume) and a per-shift count of not-found scans | POS-only groundwork · the keys have no admin or portal screen and nothing reads them yet |
| #2262 | The Taxes tab saves the default tax group through its own PUT /api/products/{id}/tax-group and no longer resends six General-section fields |
The overwrite needed a save carrying a current version token with stale General values, which the portal's refetch-after-save does not produce · the tab looks and saves the same |
| #2190 | API request log lines record the route template instead of the raw path, so a token in a URL (such as an invitation link) is no longer written to the log · QA API console logs are now kept in blob storage for 7 days | Log content only · needs access to the App Service log storage, not a portal screen |
| #2136 | The Resend email webhook answers 429 after 300 requests a minute from one IP | Anonymous provider webhook with no UI · needs 301 scripted POSTs |
| #1964 | When two postings at the same moment both create a product's first stock row at a location, the loser now completes as an update instead of a server error · Bulk tax apply returns 409 instead of 500 in the same race | Needs two concurrent requests landing within milliseconds of each other |
| #1956 | "Updated at/by" is now stamped on four bulk updates: variants archived by removing an option value, the old default label template when a new default is set, and sales and cash movements moved by a shift merge | None of these records shows updated-by in admin or the portal |
| #1968 | Removing an option value re-checks stock inside the save and rolls everything back with the usual 409 if stock arrived in the meantime | Needs stock to land in the milliseconds between the save and the variant archive |
| #1934 | Recording a sale no longer fails after commit when a remapped tax rate is deleted during the request | POS sale path · the state cannot be staged even through the API (pinned by a source guard) |
| #1926 | The platform audit-log API accepts entity-type and action filters up to their column widths (100 and 50) | The admin filters are fixed dropdowns, so no value long enough to hit the old limits can be entered |
| #1905 | Email outbox: a send that throws now counts as a failed attempt for that one email and the rest of the batch keeps going, instead of the whole batch sitting stuck for about 5 minutes | Needs the mail provider to throw mid-batch · no portal trigger |
| #1314 | Shipping or receiving a transfer rejects a request that lists the same transfer line twice · that request used to double-receive the line, or drive the sending location's stock negative | API-only · the portal's ship and receive forms send each line once, so a duplicate needs a hand-built request |
| #1302 (Alerts refresh part) | If a refresh of the Alerts tab fails after a save, the rows stay on screen with a "Couldn't refresh this list" warning, instead of the whole list being replaced by an error | The refresh has to fail right after a successful write · the portal offers no way to force that |
| #1305 | A settings catalog (135 keys with platform defaults), a cached settings resolver, a new GET /settings/definitions endpoint, and a SettingChangeLog audit table. PUT /settings/{merchant,location,terminal} now rejects keys that are not in the catalog, and GET /settings/effective returns every key with its default |
API-only · no portal screen lists or edits settings in bulk. The one portal screen that writes a setting through this path is the supplier minimum-order toggle on purchase orders, and its key is registered, so it behaves as before |
| #1245 | Creating a user (merchant user, partner user, or a partner's merchant user) now answers 409 "already exists" in both race windows. Before, two simultaneous creates for the same email could return a server error | Needs two creates for the same email submitted at the same instant · a single form submission cannot trigger it |
| #1307 (transfer/receipt part) | Receiving a transfer, or completing a purchase receipt, that references an already-archived variant is refused with 409 instead of posting stock against it. A transfer line whose variant was archived stays visible on the transfer's detail page | Needs a variant archived before this release while it had units in transit or on a draft receipt · this release blocks creating that state, so it exists only in legacy data |
| #1272 | Requests whose arrays contain a null element are now rejected with 400 at the JSON boundary, instead of failing with 500 or being accepted silently. Applies across sales, transfers, POs, receipts, products, customers, employees and more (ADR-0129) |
API-only · the portal never sends a null element in a list, so this needs a hand-built request |
| #1269 | Processing a return for a sale whose variant was archived afterwards no longer reports failure after the return has already been saved. Before, a retry was then refused with "0 returnable" | Returns are made from the POS app, which is not deployed to QA · there is no portal trigger |
| #1256 | A sale, return, void or no-receipt return at a location with no location-specific cost now records the product's own cost on its inventory movement, instead of $0.00. Voids and returns reuse the cost the original sale recorded | Sales and returns are recorded by the POS app, which is not deployed to QA · sales already in QA keep their $0.00 cost |
| #1212 | 17 create endpoints (AR accounts and groups, custom fields, label sizes and templates, location-group members, loyalty enrol, partner and merchant users, payment methods, DB assignment, notification templates, coupons, reason codes, units of measure) now answer their own 409 when two simultaneous saves collide, instead of 500 | Needs two identical saves at the same instant · a duplicate entered normally was already caught with a 409 before this change |
| #1232 | Merging duplicate shifts now zeroes the absorbed shift's totals, so the shift close report no longer double-counts sales and tax after a merge. The whole merge retries as one unit on a concurrency conflict | POST /shifts/merge has no portal screen · duplicate shifts come from offline POS devices, which are not deployed to QA |
| #1202 (lock part) | Close, cancel, create receipt and complete receipt now lock the purchase order row in one order. Completing a receipt whose order is already closed or cancelled is refused | Concurrency between two users, or legacy order and receipt pairs created before this guard · not reproducible from a single portal session |
| #1237 | Customer tax profiles, price changes, start stock count, tax groups, tax holidays and process return now answer 400 instead of 500 when a list field is sent as null. Time-zone and PublicId rules were hardened as well |
API-only · the portal always sends a list, possibly empty, never null |
| #1195 | Enrolling a group-loyalty member with a phone number that another simultaneous enrolment is also using now answers 409 instead of 500 | Needs two enrolments with the same phone at the same instant · a duplicate entered normally was already caught |
| #1183 | Screen-reader labels for the filter-chip remove button, Alert and Toast close buttons, and the loading spinner follow the portal language. Before, they were always Spanish. The chip label also names the filter as shown on screen ("Status: Active") | Changes only the hidden aria-label text · needs a screen reader or the element inspector, nothing changes on screen |
| #1168 | Finalizing a stock count now records its variance adjustment at the product's cost and price (location override first, then the product's own value), instead of $0.00. Example: a 5-unit shrink at 474.26 is now booked as $2,371.30, not $0 | Stock counts are still a "Coming soon" card on the portal's Inventory page · counts are finalized outside the portal, so QA cannot produce one |