== Dox POS changelog ==

Every version, newest first. The readme on WordPress.org shows only the recent ones.

= 0.57.0 =
* New: Varies by. Each category says what its products vary by: up to two of the store's attributes, whatever they are. Clothes by Size and Color, thermoses by Capacity and Color, phone cases by Model, rings by Size and Material, shoes by Shoe size. The product form in the register keeps its grid: the first option goes in the rows and the second in the columns, and the titles change on their own (Capacity instead of Sizes). An option that is a color keeps its swatches; any other shows text buttons, like sizes. Set it in Settings > Products > Varies by, or from the register: when a product is created, the chosen category shows "Thermoses varies by Capacity and Color · Change it". From there a new attribute can be created with its values (the register warns when it looks like one the store already has, like Sizes and Size), and Add to Capacity… creates a value that is missing (a 750 ml), already marked.
* New: a store can have several size attributes, for example letters for clothes (Talla) and numbers for shoes (Talla calzado). In Settings > Products > Sizes and colors, mark every attribute that holds sizes. Until you change it they are detected by name, also the ones whose name starts or ends with size (Talla calzado, Shoe size); turning them all off means the store does not use sizes.
* New: a product created without colors (or without its second option) can get them from the register. When the product is edited, its category's option shows up: the units it already has go to the first value chosen, and the rest are added as new variations. Its SKUs and history stay as they were.
* Change: creating and editing use the product's own attributes, and the search, the sale, the inventory, the labels and the SKUs read any attribute ("500 ml · Red"). Shared units between sizes and pieces by actual size stay for sizes. A product that varies by three things or more still sells from the register and is edited in WooCommerce.
* Change: nothing to set up when updating. Each category keeps what it used: its size attribute (the one its products use, or the one set by hand) as the first option and the color as the second. A store with only Size and Color works exactly as before.
* Change: color swatches work with any theme, not only XStore. The register reads the shade of each color from XStore or from the most used swatch plugins (Variation Swatches for WooCommerce by GetWooPlugins or by CartFlows, ThemeHigh and VillaTheme), and a color created from the register is saved where the store's theme or plugin looks for it, so the shop shows its swatch too (a color attribute created from the register is created as a color type when the swatch plugin offers it). The shade set in the swatch plugin wins over an older one, colors with a photo swatch keep their photo and are not asked for a shade, and VillaTheme colors (saved as rgba) are read too. Short size labels are also read from ThemeHigh.
* Change: a color always goes in the columns of the product form, even when it is chosen as the first option in Varies by, because photos and shared units go by color. Choosing above the option that was below swaps them instead of emptying the second one.
* Change: when colors (or the first option) are added to a product that already exists, the first value chosen can be tapped again to remove it until saving, and saving says which value its units go to and asks to confirm. A product that had Color only as information (for the store's filter) can also get colors.
* Change: on a phone, Settings > Products > Varies by shows each menu across the screen (with Automatic, only one); the bottom bar of the product form hides while typing so the keyboard does not cover the field; the links of the form are easier to tap; Sell shows the whole SKU of each variation; the Counter lists sizes in order; and a value created with one product shows up in the next one without reloading.
* Fix: a subcategory whose products have no sizes (thermoses that vary by Capacity) now takes its parent's Varies by when the store has several size attributes.
* Fix: the warning about a similar attribute no longer mixes up short different words (Olor and Color, Tela and Talla, Marca and Manga), and using the existing one says which values were added.
* Fix: with the color on Automatic, the attribute called exactly Color keeps being the color even if another one with color in its name (Color de hilo) has more products.
* Fix: a color that already existed keeps its swatch or its image when it is chosen again from the register.
* Fix: with the size attribute on Automatic, a store with an empty "Talla" and its shoes in "Talla calzado" got the empty one, and the product form offered sizes nobody uses. Among several, the one that the most products have now comes first.
* Change: a color without a shade (created with New attribute…, or in a store without swatches) can get one from the register. When a color attribute is created with its values, each value shows a box to pick its shade; and when a color without a shade is chosen in a product, the form offers to pick it (or Not now). A color that already has a shade or an image keeps it.
* Change: changing Varies by from the register says clearly that it affects the next products of the whole category (and of its subcategories without their own), with how many products it has today, which stay as they are. If none of them varies, it offers Make it not vary; after saving it says how many subcategories changed too.
* Change: faster with several size attributes. What the products of each category use is counted once and kept until a product, a variation or a category changes, instead of on every request; and Settings > Products > Varies by works it out once for all the categories instead of once per category.
* Fix: after saving changes to a product, only the Saved window shows. The Create another window of a new product came out on top of it.
* Fix: saving Settings no longer undoes a Varies by changed from the register while the settings page was open: only the categories changed on the page are saved.
* Fix: closing the "looks like an existing attribute" warning no longer creates the attribute; it has Use it, Create anyway and Cancel. Saving Varies by from the register keeps the values already marked if the rows did not change.
* Fix: when colors are added to an existing product, marking a value, typing its units, removing it and marking it again no longer overwrites the units the product already had. Retrying a save that failed halfway does not create the same variations twice.
* Technical: new option key cat_vary in dox_pos_products (category => up to two taxonomies, or array( '-' )). dox_pos_category_vary_map() resolves it walking up the parents: the first category with cat_vary wins; one with cat_size or detected sizes (0.56) gives [its size, color]; nothing gives [size_attr, color_attr]. dox_pos_vary_axes() puts the first option in rows and the second in columns (a lone color goes to columns); dox_pos_product_axes() reads a product's own variation attributes. dox_pos_product_model() keeps its signature and keys (sizes, colors, size_attr) and adds color_attr; edit data adds add_size_attr and add_color_attr, and saving accepts adopt_size or adopt_color (dox_pos_adopt_axis()). products/form adds attrs (every global attribute with its values) and vary per category. New REST routes products/attributes (wc_create_attribute, error dox_pos_parecido with similar and label) and products/category-vary; products/sizes takes any attribute and an optional hex. Varies by fixes: dox_pos_vary_color_last() keeps a color attribute second (used by dox_pos_vary_axes(), dox_pos_set_category_vary() and the settings sanitize); dox_pos_category_vary_map() keeps walking up past a category whose products have no size (found '') and only stops at a detected size; dox_pos_adopt_axis() turns a non-variation attribute into a variation one (wp_set_object_terms without append) and runs after name, price and categories are validated; dox_pos_attribute_likeness() needs the same first letter and 5+ letters for distance 1, 8+ for distance 2; dox_pos_attribute_taxonomy() prefers an exact name; dox_pos_color_attributes( true ) resets after creating an attribute; products/attributes returns added, cuts the slug by bytes, skips reserved slugs, checks the new id and caps name and values; products/sizes writes the hex only on a new term, ThemeHigh only on a color-type attribute and VillaTheme only when its term has no type or a color type and no colors yet; the product form transient is deleted on woocommerce_attribute_added/updated/deleted and created/edited/delete_term of product_cat and pa_ taxonomies; dox_pos_format_product() sorts variations by size inside each color. Swatches: dox_pos_term_hex( $term_id, $tax ) reads st-color-swatch, product_attribute_color, cfvsw_color, product_{tax}, vi_wpvs_terms_params[color] and color, in that order (outside XStore only values with #); dox_pos_set_term_hex() writes to every active system from dox_pos_swatch_systems() (XStore theme, WOO_VARIATION_SWATCHES_PLUGIN_FILE, CFVSW_VER, THWVSF_VERSION, VI_WOO_PRODUCT_VARIATIONS_SWATCHES_VERSION; none: st-color-swatch); dox_pos_term_label() reads st-label-swatch, then ThemeHigh's product_{tax}. SKU codes are learned from any attribute (first option, then color). Pool names and real-size cells read the column attribute of the variation (dox_pos_variation_column()). Catalog variations add fila (the first option) and put other attributes between the size and the color in the label. Review: new REST route products/swatch (dox_pos_set_value_hex(): attr, id, hex; only on a color attribute and only when the term has no shade, else kept: true). dox_pos_category_usage() replaces the per-request query of dox_pos_category_size_found(): it keeps found (size per category, with 2+ size attributes) and varied (products with variations per category, summed up the parents) in the transient dox_pos_category_usage for a day, deleted by dox_pos_forget_category_usage() on woocommerce_new/update/delete/trash_product(_variation), set_object_terms of product_cat, trashed_post, untrashed_post, deleted_post and created/edited/delete_term of product_cat. dox_pos_category_size_map() and dox_pos_category_vary_map() take $own = false to skip each category's own setting (Settings builds the Automatic labels with one map). products/form categories add varied and parent. The register's crearProducto() shows modalProductoGuardado() or modalProductoCreado(), not both. Pre-release review: dox_pos_term_hex() reads the active systems first, then the rest, and parses rgb()/rgba() (dox_pos_css_hex()); dox_pos_set_term_hex() leaves a VillaTheme term with colors untouched and falls back to st-color-swatch when no active system kept the shade; attribute terms and product model colors add img (dox_pos_term_has_image()) and the register does not ask a shade for them; dox_pos_new_attribute_type() creates color-named attributes as type color (or st-color-swatch) when registered; products/attributes strips a leading pa_ (WooCommerce strips it), takes the taxonomy from wc_get_attribute(), cuts with dox_pos_cut_bytes() (no mbstring needed) and prefers an exact name over a similar one; products/attributes, products/sizes and products/swatch also need manage_product_terms (dox_pos_rest_terms_permission()); new variations are deduped by color term id on create and update; create returns an error when size_attr or color_attr is not an attribute of the store; the settings sanitize only applies the Varies by categories whose selects changed (vary_orig) and drops deleted categories; request fields read with is_scalar(); uninstall deletes the dox_pos_product_form and dox_pos_category_usage transients.

= 0.55.0 =
* New: what is sold without a product (a made-to-order piece, a repair) can carry a photo. In Sell > Without a product, Photo (optional): on a phone it opens the camera or the gallery. It is saved as WebP like product photos and shows in the sale line, in the order detail and in the WooCommerce order, under the line's name. Deposits to store credit do not carry a photo.

= 0.54.1 =
* Fix: in the product form, under Pieces by actual size, a group with a single actual size showed a "?" in that size, as if something were missing. It now shows the units of the group, which are all of that size.

= 0.54.0 =
* New: labels to stick on the products, from Products > Labels. Each one carries the name, the SKU, the price, the sizes in stock when it is printed and the barcode of the SKU: scan it at the Counter, with a scanner or the phone camera, and its sizes show up. They print from the browser on the label sheets sold in stationery shops (Letter with 30, 20, 14 or 10 labels, Avery 5160 to 5163; A4 with 24, 21 or 14, Avery L7159, L7160 and L7163), or on a whole adhesive sheet with lines to cut; one per product or one per unit in stock, and a sheet already started can be used from any label.
* New: dark mode. In Settings > Brand, Appearance: Light (as always), Dark, or Like the device (it follows the dark mode of each phone or computer). The dark colors are made from the store's own: its main color, lightened until it reads, on an almost black background.
* Change: Reports in the Dox design: each figure with the dot of its color, channels and payment methods with their icon, and what is left to collect with its status and a link to the order. The register preview in Settings paints channels and payment methods like the register.
* New: the sign-in screen, redone. The store's bar color, logo and name on one side and the form on the other (on a phone, a strip with the logo). Password or code by email is now a two-option switch instead of a loose link, the password has an eye to see it while typing, errors and notices come in boxes with their icon, and below it says who to ask for a user.
* Change: the product form, redone on the Dox design system: each part in its own card, what is chosen (category, colors, sizes, package) in the store's tint instead of solid color, a green profit, and the save bar floating at the bottom with the total and the button side by side on a computer.
* Fix: letter sizes now come in their order (XS, S, M, L, XL) and not alphabetically; and the note "No colors" no longer shows when the product has colors.
* Fix: in Settings > Sales, the sample receipt did not show until saving when Settings was opened on another tab.
* Fix: sizes in the Mexican and Central American style (CH, M, G, EG or XG) and the Brazilian one (PP, P, M, G, GG, XG) also come in their order.
* Fix: after a wrong password, the sign-in keeps the username and puts the cursor on the password.
* Fix: in dark mode, the real-size pill, the "arrived" badge and the colored initials (Orders, the Pro PIN) were hard to read; and the phone's top bar follows the dark mode.
* Fix: after opening and closing the layaway window, every key typed in the next windows (Labels among them) threw an error in the background, and a new layaway could show the previous one's summary.
* Change: barcodes with numbers (a SKU like 7701234567890) take about a third less width, so they read better on small labels; a label of a product with nothing in stock lists its sizes instead of saying it is out of stock.
* Technical: modalEtiquetas() in caja.js draws the sheets with the Code 128 of ticket.js (now a dependency of the register too); seven sheet formats in HOJAS (Avery letter 5160-5163, A4 L7159, L7160, L7163), the default from the store country (cfg.paper) and then the one this device chose (localStorage). ticket-ajustes.js measures the receipt again when it comes into view. .mbtn.stick sticks at bottom:-24px so it no longer covers the last line of a long window. ticket.js codigo() uses Code 128 set C for runs of digits. Print frames are removed after printing (afterprint) or when the next print starts, not on a 60 s timer. New dark tokens --on-solid and --ini-mix.

= 0.53.0 =
* New: a new look for the register, built on the Dox design system. The top bar has icons and its counters in small bubbles; Sell shows products as cards and each size as a tile with its stock in a colored pill (green, amber when few are left, red when none); channels and payment methods carry their color and icon (also the payment methods a shop creates); Orders shows each status in a colored pill, the customer's initials and the channel with its icon; the Dashboard, the Assistant, the windows and the login are cleaner. The four colors in Settings (background, bar, primary, text) still dress the whole register.
* New: the order detail, redone. Three figures first (total, how it was paid and where the delivery is), the products on the left and the customer and the profit on the right, each in its card, the history folded at the end and the actions at the bottom. A deposit to store credit opens as a Deposit, with how much, how it was paid and the credit the customer has left. A layaway shows what is left to pay with a bar, its deposits and its deadline.
* Fix: on the iPhone, Safari no longer zooms the register in when a field is tapped (the register stayed bigger, cut off on the left and with the bottom bar under Safari's own bar), and the search no longer takes the focus on its own on a phone (it hid the bottom bar).
* Fix: right after adding a size of a group that shares units, its tiles counted one piece too many until the next search; and the line proposes the closest piece that is still free.
* Technical: the order detail is drawn by pintarDetalle() with the pd-* classes in caja.css; the detail endpoint adds credit_key and credit_balance. dox_pos_head() adds maximum-scale=1 to the viewport only on iPhone and iPad.
* Change: the button to take one size off the order sits in the corner of its tile, so the size name no longer wraps.
* Fix: a double tap (or Enter twice) on a window's main button no longer does it twice: one deposit on a layaway was recorded as two, and a line without a product could go in twice. Returning to store credit, in Orders and at the Counter, can no longer be saved twice while it is saving.
* Fix: if a sale's answer never arrives (a timeout, a dropped connection) and it is recorded again, the store returns the order it already made instead of making a second one.
* Fix: a cashier who opens an order paid with store credit no longer sees the link to the customer's movements (it is for managers), and something the user is not allowed to do now says so instead of closing the session and losing the sale in progress.
* Fix: the counter-only user can no longer download the inventory or the history in Excel.
* Change: cancelling an order that was already paid says that the money is not refunded from there; marking an order as delivered asks first; Enter in a window does its main button; missing fields say what is missing; on a phone the order detail has a Close button at the bottom; a layaway deposit reads "Deposit on layaway #72" instead of "Deposit: Deposit on layaway #72"; and in Orders, what was deposited and what is left go to a second line instead of widening the list.
* Technical: the modal ignores clicks while it closes (.modal.out); Enter on an input clicks #m-ok; the register and the Counter keep the sale's ref while its payload is the same (st.refVenta / m.refVenta); api() turns a 403 with a dox_pos_* or rest_forbidden code into an error message instead of an expired session; deposit lines carry layaway; ?descargar= refuses dox_pos_is_counter_only().

= 0.52.0 =
* New: pieces by actual size. In a group of sizes that share units, the product form says how many pieces carry each size on their tag (Pieces by actual size), checks that they add up to the units of the group, and warns when a group is not split yet or does not add up. Sell, Inventory and the Counter say "4 in the group · 2 with tag 12-18 months" instead of looking like 4 of each size.
* New: when a size of a group is sold or put on layaway, the order line proposes which piece leaves (the closest actual size with pieces; if two are equally close, the one with more) and it can be changed right there. That piece goes down, the order's "Actual size" says the one that left, and cancelling, releasing or returning puts it back. Website orders take the closest piece when they are paid. A stock entry asks which tag the pieces came with. The stock history says which piece each movement was.
* New: Settings, Products, "Offer a size only if there is a piece with an actual size close to it", with how close (1 to 4 sizes). Off by default. On, a size with no piece close enough shows as out of stock on the website and in the register, even if the group has units.
* Change: in Orders, a deposit to store credit says "Deposit" instead of "Delivered".
* Technical: the count of each actual size lives in the variation meta _dox_pos_real_qty (includes/real-sizes.php); a group with two or more actual sizes is split when all of them have it. The line meta _dox_pos_real_pick holds the planned pieces and _dox_pos_real_out the ones taken, moved on woocommerce_reduce_order_item_stock, woocommerce_restore_order_item_stock and woocommerce_refund_created. Order lines and stock entries take real (the variation of the chosen actual size). The products endpoint adds split to each variation; the form sends real_qty. Setting dox_pos_products[real_near]. tools/migrar-tallas-reales.php (not in the plugin zip) fills the counts from an inventory spreadsheet.

= 0.51.0 =
* New: layaways with their own deadline. When you put something on layaway you choose how long it is held (24 hours, 2, 7 or 30 days, any number of hours or days, or no deadline); it starts with the one in Settings, Layaways, which can now be set in hours or days or as "Layaways do not expire". The deadline can be extended, shortened or removed later from the order detail (Change deadline).
* New: deposits on a layaway. Take part of the money when putting something on layaway, with its payment method, and add more deposits later from the order detail (Add deposit), each one on its own day. Each deposit counts as a sale on the day the money comes in, and the layaway's total (and its payment link) becomes what is left to pay. A deposit that covers everything marks the layaway as paid.
* New: Charge the rest. Paying a layaway now asks how the rest was paid, and only what is left counts as a sale, on the day it is paid.
* New: releasing a layaway with deposits asks what happens with the money: it stays as the customer's store credit (the default) or it is given back, with the payment method you choose (it comes off Sales on the day it goes out). Only administrators and shop managers can give money back; the Cashier role leaves it as store credit.
* New: a layaway with deposits does not cancel itself when it expires: it shows up as expired until you extend it or release it. Layaways with no deposit still cancel themselves, as before.
* New: Dashboard, Layaways due soon: the ones that expire within 3 days and the expired ones with deposits, with what was deposited, what is left and the WhatsApp button.
* New: in Orders and in the order detail each layaway shows what it is worth, what has been deposited, what is left and when it expires.
* New: the layaway message has {due} (when that layaway expires), {deposit} and {remaining}; a sentence whose placeholder does not apply removes itself (the payment link always stays). {hours} is now the hours left on that layaway.
* Change: a layaway now counts as a sale on the day it is paid, not on the day it was put on layaway (only layaways created from this version on: past reports do not change).
* Change: the profit of a layaway counts everything it is worth on the day it is paid; its deposit orders count as sales but not as sales without a cost.
* Change: in stores whose prices exclude tax, the Put on layaway window says that tax is added when it is saved.
* Technical: a layaway carries the meta _dox_pos_layaway = 1, which stays when it is paid; _dox_pos_hold_until is its deadline or 0 for no deadline. dox_pos_layaway_info() gives what it is worth, the deposits, what is left, the deadline and whether it expired (includes/layaways.php). Each deposit is a store-credit deposit order linked with _dox_pos_layaway_of and hidden from the Orders list, used at once on the layaway as a credit fee (_dox_pos_fee = credit, with _dox_pos_dep_order, _dox_pos_dep_date, _dox_pos_dep_method, _dox_pos_dep_user), so cancelling gives it back to store credit with the existing credit code; giving the money back refunds the deposit orders (their status is kept) and writes a reversal row, skipping deposits already cancelled or refunded; it needs manage_woocommerce and a paid payment method. The deposit order ref is namespaced with the layaway id. paid, release and cancel on a layaway take the customer's credit lock. The deposits due query filters _dox_pos_hold_until in the database. dox_pos_history_orders() counts a paid layaway on its payment date (dox_pos_order_sale_date()). New order actions: deposit, deadline; paid takes payment; release and cancel take refund and refund_payment. Options dox_pos_hold_unit and dox_pos_hold_never.

= 0.50.0 =
* New: store credit. Money a customer leaves with the shop to use later, kept under their phone number. Take a deposit in Sell (Without a product, Deposit to store credit), for example 50% of a made-to-order piece: it counts as a sale on the day the money comes in, with its payment method.
* New: pay with store credit in Sell and at the Counter, all of it or part, together with another payment method or a split payment. That part does not count as a sale again, because it already counted when the money came in. The tax is still charged in full.
* New: return pieces to store credit instead of giving money back, from the order detail (Orders) or at the Counter (Return, To store credit). The pieces go back to stock and the shop can keep an exchange fee (Settings, Sales, Store credit; 0% by default, it can be changed on each return).
* New: Reports, Store credit: what the shop owes in store credit, each customer's balance and the history of every amount (where it came from and where it was used), adjustments with a reason and "Load a balance" for balances kept in a spreadsheet. The customer gets the balance by WhatsApp or text message, and the receipt shows the credit used and what is left.
* New: sell something that is not in the catalog (Sell, Without a product): a made-to-order piece or a repair, with its own price. It does not touch the stock.
* Fix: money given back at the Counter now comes off Sales, Daily cash and the Dashboard (it only came off the till closing). Returned units no longer count as sold, and their cost no longer counts in the profit.
* Technical: store credit lives in its own table, {prefix}dox_pos_credit (one row per movement, never deleted; the balance is their sum), keyed by the phone number with the country calling code. Paying with credit is a negative order fee with the meta _dox_pos_fee = credit and no tax (WooCommerce would spread a negative fee over the taxes and cap it at the subtotal); a deposit is a positive fee with _dox_pos_fee = deposit. A return to store credit is a WooCommerce refund of 0 that restocks the items. Cancelling or fully refunding an order gives its credit back and reverses its deposit (once). Lines sold without a product are line items with no product and the meta _dox_pos_free, and go to processing when paid.
* Technical: the stock movements of a Counter return now say "Refund #order" (they said "API").

= 0.49.1 =
* Fix: Edit this product did not save a product whose sizes have different prices. With the Price field empty (which leaves the price of each size as it is), the register sent a price of 0 and the store answered "The price has to be greater than zero", so nothing was saved. An empty Price goes again as "do not touch the prices"; creating a product still asks for a price.
* Fix: in that same case, the line under the cost said "The price is missing" (or "Enter a price and a cost"), as if a price had to be typed, and typing one replaces the price of every size. It now says that the sizes have different prices, from the lowest to the highest.

= 0.49.0 =
* Improved: in the product form (Edit this product, also when creating), the menu of each size says "Not offered" when the size does not share units and has none of its own, and "Own units" when it has some. Choosing "Not offered" on a size that shares takes it out of the group: it shows as sold out in the register and in the store, and the other sizes keep the units.
* New: under each group of sizes that share units, "Actual size" chooses the size on the label of the piece (the `_dox_pos_real_size` meta of 0.46.0), for products with one color and for colors with their own shared units. A group that already had several actual sizes keeps them until you pick one, and a size that stops sharing keeps its mark (it only shows while it shares). Saving from the Pro chat does not touch it.
* Fix: taking a size out of a group of shared units and putting another one in, in the same save, could copy the group's units to the size that left. The group now only syncs the sizes that are still in it.
* Fix: changing the number of shared units in the same save where a size joins the group now writes its row in the stock movements (it was left out).
* Fix: after saving a product opened from Inventory or Sell, the list showed it as it was before saving until you searched again.

= 0.48.1 =
* Fix: on the phone, tapping a product further down the Inventory or Sell list opened it but sent the list back to the top (Safari on iPhone), so you had to scroll down again to find it. Now it opens in place and the list stays where it was, also when you add a size.

= 0.48.0 =
* New: the Counter, for a physical store. Turn it on in WooCommerce > Dox POS > Sales and the register gets a Counter tab: scan barcodes with a USB or Bluetooth scanner or with the camera (ZXing on Safari), quick buttons for products without a barcode, keyboard shortcuts (F2 to F9), sales on hold and a discount.
* New: charge cash with suggested bills and the change in large type, by card, or split between several payment methods. Each sale is a WooCommerce order handed over at the counter, with the tax worked out from the store address.
* New: open the till with its float and close it counting the drawer. The closing shows the sales by payment method and whether the cash matches, is short or is over.
* New: receipts for 58 or 80 mm paper printed from the browser on any printer, with a basic editor in Settings > Sales (top, bottom, logo, what it shows) and a barcode that opens the return of that sale.
* New: returns at the Counter: scan the receipt, choose the pieces and give the money back in cash or by the same method. The pieces go back into stock.
* New: a Counter cashier role that only reaches the Counter, a maximum discount for whoever does not manage the shop (Settings > Sales > Discounts, 0% turns discounts off) and a blind till closing for them.

= 0.47.1 =
* Improved: with Colciudades on a store in Colombia, a city typed by hand in the register ("medellin", "MEDELLIN", "bogota") is saved with its name from the list ("Medellín", "Bogotá"), ignoring accents, capital letters and extra spaces. The register fixes it when you leave the field, and the server does it again when the order is saved. A place that is not on the list (a rural district, for instance) is saved as typed.

= 0.47.0 =
* Changed: on the phone, Sell and Inventory no longer have the two tabs at the top. When you add something, a bar appears at the bottom ("View the order" or "Review and save") that opens what you picked, with an arrow to keep searching and an "Empty all" button that asks first.
* New: a size that is already in the order (or in what arrived) shows how many with a "+2" and has a minus button next to it to remove one without going to review.
* Changed: on the phone, "Download Excel" and "Upload costs" sit under the Inventory search.
* Changed: Products opens with the list of products and a "New product" button. Each product opens in its own card with an arrow to go back (to the list, or to the tab you came from). If you leave with unsaved changes, the register asks whether to save, discard or keep editing.
* Changed: when the register opens on the Dashboard, the Dashboard goes first in the bottom bar on the phone.

= 0.46.0 =
* New: the actual size of a piece. When several sizes share the same units (a bodysuit labelled 18-24 months that also fits 12-18), mark the size on the label with the `_dox_pos_real_size` meta (`yes`) on that variation. The register then highlights it in the product sizes (Sell, Inventory and the product card), and the sizes that share it say "Also fits · it is the 18-24 months one".
* New: when the register or the website sells another size of that group, the order line says "Actual size: 18-24 months", so whoever packs knows which piece to take. It shows in the register orders, in the WooCommerce order and in the emails to the store, but not to the customer.
* Fixed: the units in stock on the Dashboard counted the sizes of hidden products.

= 0.45.0 =
* New: the register sign-in screen can offer "Sign in with a code by email" next to the password, when another plugin on the site provides one-time codes (through the `dox_pos_login_code_enabled`, `dox_pos_login_code_send` and `dox_pos_login_code_verify` filters). The cashier types the 6-digit code from their phone into the register, with no password. Codes are only sent to accounts that can use the register, and the register checks the session that was really opened before letting anyone in. Without such a plugin nothing changes: the register asks for username and password as always, and Dox POS sends no email of its own for this.

= 0.44.0 =
* New: on a phone, the register sections move to a bar at the bottom of the screen, like an app. The four used every day (Sell, Orders, Inventory and the Dashboard, or My day for the cashier) are always in view and within reach of the thumb; when there are more than five sections, "More" opens a sheet with the rest. Orders shows the number of orders waiting on its icon. On a tablet or a computer the tabs stay at the top as before.
* Improved: while typing on a phone, the bottom bar steps aside so the keyboard and the order total have room.

= 0.43.0 =
* New: Settings > Sales suggests the payment methods that are turned on in WooCommerce and the register does not have yet (Addi, Wompi, Mercado Pago...), as one button each under "Add payment method". One click adds it with its name, ready to rename. Nothing is added on its own: many of them only make sense on the website. A sale recorded with one counts as paid and keeps its own key, so WooCommerce never offers to refund it through that gateway.
* Fixed: with a light bar and a main color close to it (a lime green bar with the same green as main color), the tabs of the register disappeared: their text took the main color. Text on the bar, links and the "not paid yet" button now use the main color only when it reads well, and otherwise the soft color or the text color. The settings preview does the same.

= 0.42.0 =
* New: a **Help** link at the top of the settings, next to the version, opens the Dox POS guide in the Dox Studio help center (in Spanish on a site in Spanish). Administrators also find it as "Guide" in the gear menu of the register. It is a plain link: the plugin still calls no outside server.
* Fixed: the sample total in the settings preview and in the layaway message was a fixed 189,000, which reads well in Colombian pesos but showed "$189,000.00" in a store that sells in dollars. It is now a believable price in the currency of the store.
* Fixed: the size and color of the sample product in the settings preview ("M · Pink") was written in Spanish on sites in any language.

= 0.41.1 =
* Since WooCommerce 11.0, an order that goes to failed payment gives back the stock it had taken. The stock history now records that movement under its order ("Payment failed #1234"), among the returned ones, instead of as a change with no order and a guessed reason.
* The order history in the register leaves out the notes that WooCommerce 10.9 and later adds for every email it sends ("Email "Completed order" sent."), which pushed the shop's own notes out of the list. They are still in the order in WooCommerce.

= 0.41.0 =
* New: **shipping costs, set from the register.** The gear at the top of the screen (administrators and shop managers) opens Shipping costs: a fixed price, by weight, free from an amount or store pickup, for the whole country or for some of its regions. Nothing is kept apart: they are the WooCommerce shipping zones and methods, so the web checkout and the register charge the same. What the screen cannot edit (a price written as a formula, free shipping that asks for a coupon, the method of another plugin) is shown as it is and can only be turned on or off.
* New: **shipping by weight**, a WooCommerce shipping method with ranges ("up to 1 lb, 6; up to 5 lb, 10"), a price for heavier orders and an optional amount per extra unit of weight. It works in the web checkout too, with no table rate plugin.
* New: **weight and size of the product** in the Products tab, in the units of the store. The packages the store uses the most show up as buttons, so a shop that ships almost everything in the same bag sets them with one tap. They go to the product and its sizes inherit them; if someone gave a size its own weight in WooCommerce, the form leaves it alone unless you type a new one.
* New: **categories from the register.** The product form has a "New category…" button: a name and, if it goes inside another one, which. It is created on the spot and stays chosen. Categories with no products yet now show up too, behind "More categories", so a store that is just starting (no products at all) can create its first product from the register.
* Changed: when other Dox Studio plugins are installed, the settings of Dox POS move into the shared **Dox Plugins** menu (Dox Plugins > POS), next to the rest. Installed on its own from WordPress.org nothing changes: they stay in WooCommerce > Dox POS. The copy installed from GitHub carries that shared menu with it, so there the settings always live in Dox Plugins > POS. The address is the same either way, and shop managers still get in.
* New: the sale asks for the **postcode** in the countries that use one (ZIP Code in the United States), saves it in the order and uses it to find the shipping zone. A country that does not require it, such as Colombia, sees no change.
* When the store charges nothing for the place of a sale, the register now says so instead of asking for the city again, and the amount can still be typed by hand.
* Fixed: with WP_DEBUG on, a shipping cost written as a formula WooCommerce cannot evaluate ("[qty] > 2 ? 24000 : 12000") made WooCommerce print a notice into the answer, and the sale showed no shipping options at all. What a shipping method prints while it calculates no longer reaches the register.
* Fixed: a few texts of the register showed up in Spanish on a site in another language ("Editar este producto", "Buscando…", "Guardando…", the hint under the categories, the badge of the main photo and the page count of the product search, "1-20 de 134").
* Fixed (copy installed from GitHub): the updater took the first file attached to a release, whatever it was, and releases carried the WordPress.org zip first, which has no Spanish translation and no updater. It now asks for its own zip by name, and releases attach only that one.

= 0.40.0 =
* New: Dox POS now shows up in the shared **Dox Plugins** menu when other Dox Studio plugins are installed, with a link to its settings. The register itself does not move: it stays under WooCommerce > Dox POS, which is where anyone using it looks for it. On a site where Dox POS is the only Dox plugin, no extra menu is added at all.
* Fixed (copy installed from GitHub): a site set to a Spanish variant other than Spain, such as Spanish (Colombia) or Spanish (Mexico), showed the register in English, because the bundled translation is es_ES and WordPress does not fall back between variants on its own. Any Spanish variant now gets the Spanish translation, unless the site has its own translation for that variant.

= 0.39.0 =
* The totals and the headings of the register now use the font of the phone or the computer, the same one as the rest of the screen, instead of always falling back to Georgia. A shop that prefers a serif picks it in WooCommerce > Dox POS > Brand from a list of fonts every device already has (Georgia, Charter, Iowan Old Style, Palatino, Baskerville, Times New Roman): nothing is downloaded and nothing is requested from outside. With Google Fonts on, the one you pick here is what shows if Google does not answer.
* The register shows the site icon in the browser tab again, and carries it when you add the register to the home screen of a phone. It was missing on sites whose theme replaces the WordPress icon tags with its own, because the register is a page outside the theme; it now prints them itself, and falls back to the icon the theme stores if WordPress has none.

= 0.38.1 =
* Deleting the plugin no longer erases anything of yours. Until now, removing it from Plugins took the settings, the brand, the address of the register and the Cashier role with it, because that is what its uninstall file did. Now it keeps all of it, so installing it again picks up where you left off. WordPress asks nothing while it deletes a plugin, so a new switch in WooCommerce > Dox POS > Screen lets a shop say beforehand that it does want everything gone; with it on, the plugins list says so right next to the plugin. Orders, stock, the stock entries and the ledger were never touched and still are not.

= 0.38.0 =
* The register follows the store country (WooCommerce > Settings > General). Payment methods: Nequi only for a Colombian store, Zelle and Venmo for a US one, and card, cash, bank transfer and cash on delivery everywhere. Suggested carriers: Coordinadora, Servientrega, Interrapidísimo, TCC, Envía, Deprisa and 4-72 in Colombia; USPS, UPS, FedEx and DHL in the United States; Estafeta, Redpack, Paquetexpress and 99minutos in Mexico; Correos, SEUR, MRW, GLS and Nacex in Spain; the local ones in Argentina, Chile, Peru and Ecuador; DHL, UPS and FedEx anywhere else. A store that never saved its carriers now gets the ones of its country suggested when it marks an order as shipped. Default sales channels: Instagram, TikTok, Facebook and In person where WhatsApp is not the norm.
* Text messages where WhatsApp is not used (the United States, Canada, Australia, New Zealand, Japan, Korea, China): the layaway message, the shipping notice and every "write to them" button open the phone's Messages app with the text written, and the customer field says Phone. A new "Messages to the customer" setting in WooCommerce > Dox POS > Sales switches between the two for any store.
* "Use the site's one" for the logo now finds the logo of themes that keep it in their own settings (UiCore, Flatsome, WoodMart, Avada, Divi), not only the one from Appearance > Customize, and says so when there is none to use.
* The switches in the settings (costs, website orders, dashboard, shipping email, Google Fonts) are rows with a title and a line that says what they do, so the costs card no longer reads as a wall of text.
* The Pro tab says what the add-on is: an AI assistant that runs the shop with you, and what it does.

= 0.37.4 =
* Under the hood: the notes that translators read next to each text, and the three context labels that tell them what a word means, were written in Spanish. They are in English now, so the plugin can be translated into any language from translate.wordpress.org.

= 0.37.3 =
* The "Shipped" order status reads Shipped on an English site: the counter next to it in the orders list was written in Spanish in the code, and on a Spanish site the status itself showed as "Shipped" because its translator context was in Spanish too.

= 0.37.2 =
* The settings page is headed by the Dox POS logo instead of a letter in a box.
* The plugin page is now doxstudio.com/dox-pos.
* A "Pro" tab in the settings says what the paid add-on adds and links to the plans. It is not there if Dox POS Pro is already installed, and nothing else in the register changes.

= 0.37.1 =
* The Spanish translation is no longer bundled with the plugin: it comes from translate.wordpress.org, as the directory requires. The default address on a Spanish site (/caja) now follows the site language directly, so it does not depend on translation files.

= 0.37.0 =
* Google Fonts are off until the shop turns them on in WooCommerce > Dox POS > Brand: a fresh install uses the fonts of the phone or the computer and does not connect to any outside service. A shop that had already made its choice keeps it.
* Font names go into the register stylesheet as letters, digits, spaces and hyphens only, and the line that starts the register is added through the WordPress script system instead of being printed by the template.
* The register and the sign-in page declare the language of the site instead of a fixed one.
* The default address of the register follows the language of the site: /pos on an English site, /caja on a Spanish one. It is written to the settings when the plugin is installed, so it never moves afterwards, and shops that were already using /caja stay there. In English the screen is called POS instead of Register, which on a website reads like signing up.

= 0.36.0 =
* The lists of the register no longer leave half a line empty: a long one splits into two columns that still read top to bottom.
* Add-ons can now draw the same figure cards and strip cells the Dashboard uses, so every screen of the register counts in the same shapes.

= 0.35.0 =
* The Dashboard is laid out again: today's figures in three big cards, then one strip with the week, the month and whatever the add-ons contribute, and the lists in two columns. No more half-empty rows or cards stretched to fill a gap.
* The chart of the last days switches between 7, 14, 30 and 90 days, and remembers the choice on that device. Its total is now the headline of the card, saying what it covers and what it averages a day.
* Best sellers lists six products.

= 0.34.0 =
* Hardening after a full code review. A sale only takes the channels set in Sales, a discount larger than the products is rejected, and the sales, entries and shipping routes skip malformed lines instead of failing.
* The Cashier role can no longer confirm the payment of a website order, cancel an order that was already shipped or delivered, or void a stock entry from another day or another person: those are for administrators and shop managers.
* A stock entry refuses a product that does not track stock and a date that does not exist, and the units and the entry are saved together: if the entry cannot be saved, the stock is not touched.
* Sizes that share units by colour now move by the difference instead of copying the number, so two sales of different sizes of the same colour at the same instant both count.
* Amounts with decimals: the register reads and shows prices, costs, discounts and shipping with the store's decimal separator, and the phone keyboard offers the decimal key when the store uses decimals. Stores with whole amounts (COP) see no change.
* The Sales tab warns when WooCommerce has "Manage stock" turned off, because then nothing lowers the stock.
* Uninstalling no longer deletes the settings of Dox POS Pro and removes the plugin's scheduled tasks.
* Cost imports skip the "(no SKU)" rows in any language, the Excel files and the history get more memory and time for long periods, and the unit price in the order detail keeps the store's decimals.

= 0.33.3 =
* In Reports > Movements, filtering by a product now shows a coloured strip with the product's name and a "See them all" button, instead of a line of small text that was easy to miss.

= 0.33.2 =
* The Inventory list is titled just "All products", with the count.

= 0.33.1 =
* Inventory no longer starts empty either: before you search it lists the whole catalogue from A to Z, twenty products at a time, and loads more as you reach the bottom. Searching by name or SKU works as before, and the list refreshes after each entry so the stock is current.

= 0.33.0 =
* Several groups of sizes can share units within the same colour: 0-6 and 6-12 months from one pool, 2-3 and 3-4 years from another. The "Shares" box on each size is now a small menu (does not share, shares, or shares in another group), the colour card gets one "Shared units" box per group, and the register, the website checkout, the kardex and the Excel treat each group as its own pool. With one colour and one group everything stays exactly as before.

= 0.32.1 =
* The Units block of the product form is now one card per colour: its sizes in rows, each with its number and a small "Shares" box, and under them the colour's shared units with a line saying which sizes share them. Cards stack on a phone and sit in a grid on a wide screen, so a product with six colours no longer turns into a table that scrolls sideways. "All sizes share" in the card header ticks every size of that colour at once.

= 0.32.0 =
* Shared units by colour. In a product with several colours, "Shares units" now works per colour: the Coral sizes share Coral's units and the Rosa sizes share Rosa's, each with its own box under the table. Selling a size only lowers the units of its colour, the register warns with the colour's figure ("Romper Marian · Coral has 3 left for all its sizes together"), and the website checkout counts the whole colour while it holds stock during a payment, so two customers cannot take two sizes when one unit is left. The inventory Excel, the Dashboard, the product card and the cost average count each colour's units once. A product with one colour keeps the plain product total, as before.

= 0.31.2 =
* A Dashboard tab for administrators and shop managers, before Sell: sold today with yesterday next to it, today's profit, what is owed (cash on delivery on the way and layaways), the week and the month against the previous ones at the same point, the last fourteen days as bars, what came in today by payment method, the best sellers of the last thirty days, the orders to handle and the stock. Every card opens the tab it comes from. The register opens on it for whoever manages the shop (a switch in Settings > Register turns that off); salespeople keep landing on Sell.
* Sell no longer starts empty: before you type anything it lists the best sellers of the last thirty days, with their sizes and stock, ready to tap.
* The Units table of the product form is simpler: the "All to 1" and "All to 0" buttons are gone, and each size has a "Shares units" checkbox instead of the "from the total" and "its own" links. Ticking it takes that size out of its own box and onto the shared units, which get one box under the table together with the list of sizes that share them.

= 0.30.0 =
* Each size decides where its units come from. In the product form, creating or editing, every size (and colour) has a small link: "from the total" moves it onto the product's shared total, "its own" gives it separate units. The shared total gets its own box as soon as one size uses it, and "One total for all" switches every size at once. So a product can have, say, 2-3 and 3-4 years drawing from one pool while 6-12 months keeps its own count, without opening WooCommerce.

= 0.29.2 =
* A product where some sizes take their units from the product's total and others carry their own (the usual case in a shop that grew over time) now shows all its sizes when you edit it: the shared ones are marked "from the total" and the rest are typed in as always. Before, the whole table was hidden and those units could only be changed in WooCommerce.
* The three controls in the Units header no longer run into each other, and "One total for all" looks like the switch it is.

= 0.29.0 =
* The tab is called Reports, not History: what is in there (sales, the day's cash, stock movements and performance) are reports on how the shop is doing. The order detail keeps its own History with the order's notes.
* A new product can carry one total for all its sizes, the way many shops keep their stock: under Units, "One total for all". The store then discounts from that total whichever size is sold, and you can spread it by size later from Edit one.

= 0.28.1 =
* An add-on can choose which tab the register opens on when there is no address to follow (Dox POS Pro uses it to open on Today for whoever manages the shop). Everyone else keeps opening on Sell.

= 0.28.0 =
* Tap a product anywhere (the assistant, the history, the stock entries) and its card opens right there: photo, code, price, cost and what each unit leaves for those who manage the shop, units per size (or the shared total), category, and the buttons to edit it or see it in the store. Before, it jumped straight to the editor.
* The loss on an order stands out: a proper "Note a loss" button on the detail, a red tag with the amount once noted, and the same tag on the orders list and in the history. The profit comes out in colour: green when it reaches the shop's target margin, amber when it falls short, red when it is low.

= 0.27.0 =
* Losses. From the order detail, an administrator or shop manager can note what an order cost beyond the goods (a shipment that cost more than what was charged, a freight refunded, a repair), with the reason. It comes off the profit of that sale, shows in the history, the cash report and their Excel files, and the order keeps a note of who wrote it.
* Your own payment methods. Settings > Sales has "Add payment method": a second Nequi account, Daviplata, Addi, whatever the shop takes. They can be turned off, renamed and removed, and a sale recorded with one counts as paid.
* Sizes that share one stock total. When a product keeps one total for all its sizes (the parent manages the stock and the sizes inherit it), the register says so ("5 left for all sizes") instead of repeating the number on every size and adding them up, the order cannot take more than that total across sizes, and the message when it does not fit names the product and what is really left. Recording stock on one of those sizes says it goes to the shared total, and the product editor can spread that total by size so each one carries its own units from then on.

= 0.26.0 =
* The stock tab is called Inventory, and the latest entries show each garment with its photo, name and quantity; tapping one opens its product card.

= 0.25.4 =
* The "View" button of each check in the assistant's review no longer opens a "That order does not exist" window: the register only opens an order when there is a real order number.

= 0.25.3 =
* A refund in the shop left the Orders tab blank: the list asked for orders without saying which type and got the refunds too. And the settings cards no longer leave an empty column.

= 0.25.1 =
* Photos are reduced on the phone before uploading (to the size the shop keeps), so a 48-megapixel photo goes up as about 100 KB and works on any hosting.

= 0.25.0 =
* Photos from new phones (24 and 48 megapixels) no longer take minutes to convert: the memory given to ImageMagick fits the photo and the reduction happens in two steps.

= 0.24.8 =
* The sales card in the history said "Sales" in English on a Spanish site: the plural form was missing from the translation.

= 0.24.6 =
* The total, the figures in the history and the headings are set in Manrope instead of Libre Baskerville: the register reads as a tool, not as a book. If your shop already picked its own fonts in Settings, nothing changes.

= 0.24.5 =
* The "No logo: the name shows" notice on the settings page follows the color of the bar: with a dark bar it was black on black.

= 0.24.4 =
* The date on the order detail follows the language of the site: it was written in Spanish inside the code, so an English shop read "8 de September".

= 0.24.3 =
* Housekeeping: the code that updates the plugin outside the WordPress.org directory lives in its own file, and the directory build carries neither that file nor the line that loads it.

= 0.24.1 =
* The plugin page and the author page are now two different addresses, as WordPress.org requires.

= 0.24.0 =
* New factory colors: a warm white, a dark bar and an orange button. They are only the starting point; the five colors keep being yours to change in WooCommerce > Dox POS > Brand, and a shop that already saved its own colors does not change.
* The placeholders in the WhatsApp messages are now in English: {name}, {items}, {hours}, {order}, {store}, {carrier} and {tracking}. Messages and tracking links you had already written are translated on their own when the plugin updates.
* Under the hood: table names go through $wpdb->prepare, and the code passes the WordPress coding standard with no findings.

= 0.23.0 =
* The texts inside the register itself (the JavaScript) are now translated too, through the WordPress script translation system. The plugin is fully in English, with the Spanish translation included; nothing changes on a Spanish site.

= 0.22.0 =
* The plugin now ships in English, with the Spanish translation included. Nothing changes on a Spanish site.

= 0.21.1 =
* The WooCommerce cost field is no longer turned on when the plugin is installed: it is turned on when you save the settings with the costs switch on, and the card says so.
* New switch to stop loading the fonts from Google Fonts (WooCommerce > Dox POS > Brand): with it off, the plugin does not connect to any outside service.
* Under the hood: the register stylesheet and script are enqueued through WordPress, and the settings icons are printed through wp_kses.

= 0.21.0 =
* Costs and profit. Each product carries a cost per unit in the WooCommerce cost field: set it when you create or edit a product in the register, or all at once from the inventory Excel with the Cost column filled in. Every stock entry carries what each unit cost and recalculates the product's weighted average cost. Every sale freezes the cost in its order, so raising a cost later does not change history. The history shows the profit and the margin, the stock ledger shows the unit cost of each movement, and the Excel files carry the cost, profit and value at cost columns. Only administrators and shop managers see any of it.

= 0.20.0 =
* While the plugin is not on WordPress.org, it updates itself from the GitHub releases.

= 0.19.0 =
* The plugin is split in two: Dox POS (this one, the whole register) and Dox POS Pro (the assistant). The free one works fully without the Pro.

= 0.18.0 and earlier =
* The register itself: selling, layaways, stock entries, orders from the website, creating and editing products with photos, the history with sales, daily cash and the stock ledger, the Excel files, shipping with tracking, the settings for any brand, two registers at once and working with no signal.
