{"id":346803,"date":"2026-08-01T09:39:48","date_gmt":"2026-08-01T09:39:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/expiry-tracking-and-discount-engine\/"},"modified":"2026-08-01T17:13:12","modified_gmt":"2026-08-01T17:13:12","slug":"tarkva-expiry-tracking-and-discount-engine","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/tarkva-expiry-tracking-and-discount-engine\/","author":23530791,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.8.5","stable_tag":"1.8.5","tested":"7.0.2","requires":"6.5","requires_php":"8.0","requires_plugins":null,"header_name":"Tarkva - Expiry Tracking and Discount Engine","header_author":"Tarkva","header_description":"Track batch\/expiry dates natively and apply automatic clearance pricing as products approach their best-before or use-by date. Admin UI, front-end notices, and product-feed support.","assets_banners_color":"b8d5e9","last_updated":"2026-08-01 17:13:12","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/tarkva.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":63,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.8.1":{"tag":"1.8.1","author":"tarkva","date":"2026-08-01 09:39:31"},"1.8.2":{"tag":"1.8.2","author":"tarkva","date":"2026-08-01 10:39:45"},"1.8.3":{"tag":"1.8.3","author":"tarkva","date":"2026-08-01 16:58:33"},"1.8.4":{"tag":"1.8.4","author":"tarkva","date":"2026-08-01 17:05:00"},"1.8.5":{"tag":"1.8.5","author":"tarkva","date":"2026-08-01 17:13:12"}},"upgrade_notice":{"1.8.5":"<p>Documentation only \u2014 the listing now states the WooCommerce requirement explicitly. No functional\nchange.<\/p>","1.8.4":"<p>Widens the expiry date picker in both directions, so historical dates can be entered as freely as\nfar-future ones. Existing batch data is unaffected.<\/p>","1.8.3":"<p>Fixes expiry dates beyond six years ahead being rejected by the date picker. Recommended if you\nstock long-dated goods. Existing batch data is unaffected.<\/p>","1.8.2":"<p>Corrects the feature list \u2014 instant recompute is a Pro feature; the free plugin runs on a schedule.\nNo functional change to pricing or reporting.<\/p>","1.8.1":"<p>Code-hardening release: output escaping and database query preparation throughout. No settings,\ndata, pricing, or reporting changes \u2014 safe to update without any action on your part.<\/p>","1.8.0":"<p>Removes every free-tier limit: unlimited tracked products, unlimited discount tiers, and the full\nRankings table. Nothing is taken away and no action is needed \u2014 if you were at a limit before, the\nrestriction is simply gone.<\/p>","1.7.0":"<p>Fixes waste\/sell-through reporting accuracy for batches whose grace window shifts them across a\nday or reporting-period boundary \u2014 your &quot;Unsold at expiry&quot; and sell-through figures may change\nafter updating to reflect this correction. No action needed.<\/p>","1.1.0":"<p>Adds CSV export on the Actions tab. No action needed to update.<\/p>","1.0.0":"<p>Initial public release.<\/p>"},"ratings":[],"assets_icons":{"icon-256x256.png":{"filename":"icon-256x256.png","revision":3630783,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3630783,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.8.1","1.8.2","1.8.3","1.8.4","1.8.5"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3630783,"resolution":"1","location":"assets","locale":"","width":1933,"height":1202},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3630783,"resolution":"2","location":"assets","locale":"","width":2097,"height":1227},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3630783,"resolution":"3","location":"assets","locale":"","width":900,"height":581},"screenshot-4.jpg":{"filename":"screenshot-4.jpg","revision":3630783,"resolution":"4","location":"assets","locale":"","width":1940,"height":1228},"screenshot-5.jpg":{"filename":"screenshot-5.jpg","revision":3630783,"resolution":"5","location":"assets","locale":"","width":2306,"height":720}},"screenshots":{"1":"The Reporting \u2192 Overview dashboard: sales, waste, and sell-through metrics with a toggleable\ntrend chart. Revenue, profit-margin figures, and Excel export require the Pro add-on.","2":"The Engine tab \u2014 sellable-day offsets, manual-sale handling, and discount tiers. Instant\nrecompute, cache clearing, cart price-split, and profit-margin cost source (badged PRO here)\nare part of the paid add-on.","3":"Product-level expiry batch entry on the Inventory tab.","4":"Configure how the expiry date and discount notices appear on the product page \u2014 labels,\ncolors, and timing are all customizable.","5":"The Actions tab \u2014 every product the engine is actively discounting for its approaching expiry\ndate, at a glance: days remaining, sell-through ratio, and the live discounted price."}},"plugin_section":[],"plugin_tags":[262205,6744,56513,6601,286],"plugin_category":[45],"plugin_contributors":[274129],"plugin_business_model":[],"class_list":["post-346803","plugin","type-plugin","status-publish","hentry","plugin_tags-clearance","plugin_tags-discounts","plugin_tags-expiry-date","plugin_tags-inventory","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-tarkva","plugin_committers-tarkva"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/icon-256x256.png?rev=3630783","icon_2x":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/icon-256x256.png?rev=3630783","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/screenshot-1.jpg?rev=3630783","caption":"The Reporting \u2192 Overview dashboard: sales, waste, and sell-through metrics with a toggleable\ntrend chart. Revenue, profit-margin figures, and Excel export require the Pro add-on."},{"src":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/screenshot-2.jpg?rev=3630783","caption":"The Engine tab \u2014 sellable-day offsets, manual-sale handling, and discount tiers. Instant\nrecompute, cache clearing, cart price-split, and profit-margin cost source (badged PRO here)\nare part of the paid add-on."},{"src":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/screenshot-3.jpg?rev=3630783","caption":"Product-level expiry batch entry on the Inventory tab."},{"src":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/screenshot-4.jpg?rev=3630783","caption":"Configure how the expiry date and discount notices appear on the product page \u2014 labels,\ncolors, and timing are all customizable."},{"src":"https:\/\/ps.w.org\/tarkva-expiry-tracking-and-discount-engine\/assets\/screenshot-5.jpg?rev=3630783","caption":"The Actions tab \u2014 every product the engine is actively discounting for its approaching expiry\ndate, at a glance: days remaining, sell-through ratio, and the live discounted price."}],"raw_content":"<!--section=description-->\n<p>Perishable and dated stock \u2014 food, supplements, cosmetics, anything with a best-before or use-by date \u2014 needs a different kind of pricing than the rest of your catalogue. Left alone, it either sits at full price until it's unsellable, or someone has to remember to mark it down manually, product by product, week after week.<\/p>\n\n<p><strong>Expiry Tracking and Discount Engine<\/strong> tracks expiry dates natively per product (or per variation), and automatically prices clearance discounts as each batch approaches its date \u2014 no spreadsheets, no manual sale-price editing, no forgotten stock.<\/p>\n\n<p><strong>This is a WooCommerce extension.<\/strong> WooCommerce must be installed and active; the plugin adds to your existing products rather than replacing any part of your store.<\/p>\n\n<h4>What it does (free)<\/h4>\n\n<ul>\n<li><strong>Native batch tracking<\/strong> \u2014 record one or more expiry dates and quantities per product, right on the product edit screen. Works with simple and variable products.<\/li>\n<li><strong>Best-before and use-by aware<\/strong> \u2014 the two date types behave differently (best-before stays sellable a little past its date; use-by is pulled before it), each with its own configurable grace window.<\/li>\n<li><strong>Automatic clearance pricing<\/strong> \u2014 a configurable table of discount tiers (\"7 days left \u2192 65% off\", \"30 days left \u2192 20% off\", and so on) prices each product automatically as its date approaches.<\/li>\n<li><strong>Runs on its own schedule<\/strong> \u2014 an automatic sweep recalculates every tracked product's price for you; pick twice daily, daily, weekly, semi-monthly or monthly to match how fast your stock moves.<\/li>\n<li><strong>Customers never buy expired stock<\/strong> \u2014 expired-but-retained stock stays visible to you for reference, but is automatically hidden from customers and excluded from product feeds (Google Shopping, Facebook, etc.) once it's no longer sellable.<\/li>\n<li><strong>A clear expiry notice on the product page<\/strong> \u2014 a configurable message shown to shoppers, with labels, colors, and placement you control so it fits your store's voice and design.<\/li>\n<li><strong>Your choice on manual sale prices<\/strong> \u2014 protect a price you've set by hand entirely, let the engine always manage it, or only override it when the engine's own discount is deeper: you decide which.<\/li>\n<li><strong>EU Omnibus-friendly pricing<\/strong> \u2014 your product's regular price is never altered or reset when a discount tier applies, so the reference (\"was\") price shown to customers is always your genuine original price, not an inflated or escalating one.<\/li>\n<li><strong>Unlimited tracked products and unlimited discount tiers<\/strong> \u2014 no caps of any kind. Track your whole catalogue and build as many discount tiers per date type as your pricing strategy needs.<\/li>\n<li><strong>Free Reporting dashboard<\/strong> \u2014 sales, waste, and sell-through metrics with a toggleable trend chart, a full Rankings table comparing every tracked product side by side, and a scheduled email summary, all included at no cost.<\/li>\n<li><strong>Backup and restore<\/strong> \u2014 snapshot all your batch and expiry data at any time, and restore from any saved snapshot.<\/li>\n<li><strong>WP-CLI support<\/strong> for previewing, applying, and inspecting discounts from the command line.<\/li>\n<\/ul>\n\n<h4>Why this is different<\/h4>\n\n<p>Most \"sale\" or \"dynamic pricing\" plugins schedule a fixed discount for a fixed period. This plugin instead reasons about <em>your actual expiry dates<\/em>: how close a batch is to its sellable deadline drives the price, automatically, continuously, without you touching it.<\/p>\n\n<h4>Want more?<\/h4>\n\n<p>The <strong>Pro<\/strong> add-on builds on the same engine for stores that want to go further:<\/p>\n\n<ul>\n<li>Stock &amp; velocity intelligence \u2014 slow-selling or overstocked batches discount earlier and harder; batches projected to sell out comfortably discount later or not at all, protecting margin<\/li>\n<li>Cart price-split \u2014 only the at-risk quantity gets the discounted price; extra units in the same order are charged full price<\/li>\n<li>Advanced notices \u2014 cart reminders, discounted-quantity display, custom CSS placement<\/li>\n<li>Scheduled, automated backups<\/li>\n<li>Bulk CSV import for batch and expiry data<\/li>\n<li>Deeper reporting \u2014 revenue and profit-margin figures, plus one-click Excel exports<\/li>\n<li>Instant price recompute plus automatic page-cache clearing (including Cloudflare)<\/li>\n<li>Priority customer support and configuration assistance<\/li>\n<\/ul>\n\n<p>Learn more at <a href=\"https:\/\/tarkva.com\">tarkva.com<\/a>.<\/p>\n\n<h4>Privacy and external services<\/h4>\n\n<p>This plugin does not send any data anywhere by default. See \"External services\" below for the one case where it does, and only when you explicitly opt into it.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to tarkva.com, the developer's own licensing server, to validate a Pro add-on license key and check for available Pro updates. This only happens if and when you enter a license key on the plugin's License tab \u2014 nothing is sent otherwise, and this free plugin works fully without ever triggering it. The data sent is the license key itself and this plugin's fixed product identifier; no other site data is transmitted. This service is provided by Tarkva: <a href=\"https:\/\/tarkva.com\/terms-of-service\/\">Terms of Service<\/a>, <a href=\"https:\/\/tarkva.com\/privacy-policy\/\">Privacy Policy<\/a>.<\/p>\n\n<p>The Engine tab's cache-clearing settings (a Pro-only feature) include a link to Cloudflare's own public documentation on creating an API token, for reference if you also install the separate Pro add-on. This free plugin never contacts Cloudflare itself, sends it no data, and does not require an account with it \u2014 the link is informational only, and the associated settings fields are read solely by that separate add-on's own code, never by this plugin.<\/p>\n\n<h3>License<\/h3>\n\n<p>This plugin is free software, licensed under the GPLv2 (or later) \u2014 see LICENSE.txt in this\nplugin's own folder for the full license text, or https:\/\/www.gnu.org\/licenses\/old-licenses\/gpl-2.0.html.\nIn plain terms: you're free to use, study, modify, and redistribute this plugin, including copies\nyou've modified yourself, for any purpose, commercial or otherwise. There is no warranty of any\nkind, including for any financial gain or loss resulting from the automatic pricing decisions this\nplugin makes on your store. As with any plugin that automatically modifies your store's data, keep\nyour own regular backups before and during use \u2014 standard practice for any such plugin, not a sign\nthat this one is unusually risky. This applies only to this free plugin \u2014 the separately-sold\n\"Expiry Tracking and Discount Engine PRO\" add-on is not distributed under the GPL and is not\ncovered by this section; see its own LICENSE.txt for the terms that apply to it.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Make sure <strong>WooCommerce<\/strong> is installed and active \u2014 this plugin extends it and will not activate without it.<\/li>\n<li>Upload the plugin files to <code>\/wp-content\/plugins\/tarkva-expiry-tracking-and-discount-engine<\/code>, or install directly through the WordPress plugins screen.<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress.<\/li>\n<li>Go to <strong>Products \u2192 Expiry &amp; Discounts<\/strong> to configure discount tiers and notices.<\/li>\n<li>On any product you want to track, open the <strong>Inventory<\/strong> tab and set its expiry type and batch dates.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20woocommerce%3F\"><h3>Do I need WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. This is a WooCommerce extension, not a standalone plugin \u2014 it reads your WooCommerce products, prices and orders, and WordPress will not let it activate unless WooCommerce is active. It works with any reasonably current WooCommerce version; there is nothing to configure on the WooCommerce side.<\/p><\/dd>\n<dt id=\"does%20this%20work%20with%20variable%20products%3F\"><h3>Does this work with variable products?<\/h3><\/dt>\n<dd><p>Yes. Each variation can have its own expiry batches; the expiry type (best-before\/use-by) is set once on the parent and inherited by all variations.<\/p><\/dd>\n<dt id=\"will%20customers%20ever%20be%20able%20to%20buy%20expired%20stock%3F\"><h3>Will customers ever be able to buy expired stock?<\/h3><\/dt>\n<dd><p>No. Once a batch is past its sellable window, it's automatically excluded from what customers can purchase and from product feeds, while remaining visible to you for reference.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20multilingual%2Ftranslation%20plugins%3F\"><h3>Does it work with multilingual\/translation plugins?<\/h3><\/dt>\n<dd><p>Yes. All customer-facing text (notices, labels) is a setting you configure, so your translation plugin translates it exactly like any other text on your site.<\/p><\/dd>\n<dt id=\"does%20it%20replace%20my%20existing%20expiry-tracking%20plugin%3F\"><h3>Does it replace my existing expiry-tracking plugin?<\/h3><\/dt>\n<dd><p>It can. The plugin includes a native batch\/expiry data model, so once your dates are entered here, you no longer need a separate expiry-tracking plugin.<\/p><\/dd>\n<dt id=\"can%20i%20set%20discounts%20without%20expiry%20dates%20involved%3F\"><h3>Can I set discounts without expiry dates involved?<\/h3><\/dt>\n<dd><p>Not at this time \u2014 this plugin is purpose-built for expiry-driven clearance. For general-purpose discount rules unrelated to expiry dates, pair it with a dedicated dynamic pricing plugin.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.8.5<\/h4>\n\n<p><strong>Changed<\/strong><\/p>\n\n<ul>\n<li>The listing now states plainly that this is a WooCommerce extension. WooCommerce was previously\nonly implied \u2014 named in the plugin's tags and enforced technically, but never actually said in\nthe description, the installation steps or the FAQ, so it was possible to install this expecting\nit to work on WordPress alone. Nothing about how the plugin behaves has changed.<\/li>\n<\/ul>\n\n<h4>1.8.4<\/h4>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>Widened the expiry date picker further, in both directions. 1.8.3 raised the ceiling but kept a\nnarrow floor, so entering or correcting an older date was still restricted. The picker now spans\nthirty years back to fifty years ahead, and the span remains filterable\n(<code>wcde_datepicker_year_range<\/code>). CSV import was never affected by any of this \u2014 it accepts any\nvalid date directly.<\/li>\n<\/ul>\n\n<h4>1.8.3<\/h4>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>Expiry dates more than six years ahead could not be entered. The date picker's year list stopped\nat the current year plus six, and a date typed by hand beyond that was silently pulled back into\nrange instead of being kept \u2014 a real problem for long-dated goods such as tinned food, spirits or\nsupplements. The picker now offers thirty years ahead, and the range is filterable\n(<code>wcde_datepicker_year_range<\/code>) if you need more. Nothing in the plugin or the database ever\nlimited the date itself; this was purely the picker.<\/li>\n<\/ul>\n\n<h4>1.8.2<\/h4>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>Corrected the feature list: instant price recompute is part of the Pro add-on, not the free\nplugin. The free plugin recalculates on its configurable schedule (twice daily through monthly).\nThe description previously implied both, and listed the feature under free and Pro at once.<\/li>\n<\/ul>\n\n<p><strong>New<\/strong><\/p>\n\n<ul>\n<li>An occasional, dismissible prompt asking for a WordPress.org review. It only appears after the\nplugin has been in use for two weeks and only if you actually have expiry-tracked products, can\nbe postponed or turned off permanently, and never blocks anything. There is also a quiet link\nunder License \u2192 Reviews if you would rather leave one on your own terms.<\/li>\n<\/ul>\n\n<h4>1.8.1<\/h4>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>If your Pro license is active but the Pro add-on plugin isn't installed on the site, the plugin\nnow says so. Previously the only mention was on the License tab, so every locked field showed a\nplain PRO badge \u2014 identical to what someone who had never bought Pro would see. There is now a\nnotice on the plugin's own screens and on the Plugins screen, and the PRO badge itself explains\non hover that the licence is fine and only the add-on is missing.<\/li>\n<\/ul>\n\n<p><strong>Security<\/strong><\/p>\n\n<ul>\n<li>Every value the plugin prints in the WordPress admin is now escaped at the point it is printed,\nrather than where it was built. The values were already escaped before, but escaping at the\noutput itself is what the WordPress coding standards require, and it keeps a future edit from\nquietly introducing a gap.<\/li>\n<li>All database queries now pass table and column names as prepared identifiers, and product-ID\nlists in <code>IN (...)<\/code> clauses are bound as individual placeholders instead of being assembled into\nthe query text.<\/li>\n<li>Data embedded into inline admin scripts is encoded at the point it is written into the page.<\/li>\n<\/ul>\n\n<p><strong>Changed<\/strong><\/p>\n\n<ul>\n<li>No settings, stored data, pricing behaviour, or reporting figures change in this release. It is\na code-hardening pass only.<\/li>\n<\/ul>\n\n<h4>1.8.0<\/h4>\n\n<p><strong>New<\/strong><\/p>\n\n<ul>\n<li>All free-tier limits removed. The plugin now tracks an unlimited number of products, supports an\nunlimited number of discount tiers per date type, and shows every row of the Rankings table. No\nfeature in this plugin is limited by quantity any more.<\/li>\n<\/ul>\n\n<p><strong>Changed<\/strong><\/p>\n\n<ul>\n<li>The Engine tab's discount-tier tables now show and let you edit every tier you have configured,\nwith no cap on adding more.<\/li>\n<li>The Rankings table and its CSV export now include every expiry-tracked product. Revenue and\nProfit margin remain columns supplied by the Pro add-on, which is what calculates those figures.<\/li>\n<li>Removed the product-limit notices from the product edit, product list, and plugin settings\nscreens, along with the \"limit reached\" message from backup restore, since there is no longer any\nlimit to report.<\/li>\n<\/ul>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>The scheduled summary email could permanently drift onto the wrong day of the week. WordPress only\nruns scheduled tasks when someone visits your site, so on a quieter store an email set for Monday\ncould actually go out on, say, Thursday \u2014 and from then on Thursday became the new send day, with\nevery further delay shifting it again. The schedule now always re-anchors to the day you chose, so\na late send corrects itself on the very next cycle.<\/li>\n<li>If duplicate summary emails ever ended up scheduled, every future email was sent that many times,\npermanently. Only one is ever scheduled now, and any existing duplicates clear themselves on the\nnext send.<\/li>\n<li>The Dashboard trend chart could keep drawing Pro-only metrics from previously cached report data\nafter a Pro license expired, even though those metrics were no longer selectable. Those series now\ndisappear as soon as the license does.<\/li>\n<\/ul>\n\n<p><strong>Security<\/strong><\/p>\n\n<ul>\n<li>Saving a report date range or a Rankings sort order as your remembered default now requires a\nvalid nonce and the manage_woocommerce capability. Viewing a report from a URL still works\nexactly as before, including bookmarked links \u2014 only storing that choice as your new default is\ngated.<\/li>\n<li>Product and category names embedded into admin JavaScript are now hex-escaped, so a name\ncontaining HTML can never break out of its surrounding script block.<\/li>\n<\/ul>\n\n<p><strong>Improved<\/strong><\/p>\n\n<ul>\n<li>The summary email now states the exact date range it covers (\"23.07.2026 to 30.07.2026\", in your\nsite's own date format) instead of only \"last 7 days\", so it is always clear which period the\nfigures belong to.<\/li>\n<li>Numbers now use your site's own decimal and thousands separators throughout the reporting screens\nand the summary email, instead of always using the English convention. A store set to Estonian,\nGerman or French now reads 1.234,56 rather than 1,234.56. Export filenames also use a neutral,\ncorrectly-sorting date format and your site's timezone.<\/li>\n<li>All inline JavaScript is now generated through output buffering with explicit escaping on every\ndynamic value, replacing heredoc syntax throughout, in line with WordPress.org's plugin coding\nrequirements.<\/li>\n<\/ul>\n\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>Fixed: \"Unsold at expiry,\" sell-through rate, Rankings, the scheduled email, and the Dashboard\ntrend chart could misreport waste for a batch whose actual sellable deadline (printed date plus\nits best-before\/use-by grace window) fell on a different day, or a different reporting period,\nthan its raw printed date \u2014 a best-before batch with real shelf life left could show as wasted\ntoo early, and a use-by batch pulled early could be missed entirely until its printed date\narrived. All of these now consistently use each batch's actual sellable deadline.<\/li>\n<li>Fixed: a permanently deleted product (or variation) that still had an expired, unsold batch\ncould lose that waste record entirely instead of it being counted. Deleting a product now gives\nany such batch one last chance to be recorded first.<\/li>\n<li>Fixed: the \"Remove\" button on a batch row (Inventory tab and Quick Edit) wasn't vertically\naligned with its Date\/Qty fields.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>New: \"Rankings\" (Dashboard \u2192 Reporting \u2192 Rankings) \u2014 a sortable, filterable table comparing every\nexpiry-tracked product side by side: current stock, days to sellable deadline, units wasted,\nwaste rate, units sold, and sell-through rate. Pro adds Revenue and Profit margin columns to the\nsame table.<\/li>\n<li>New: every discount notice (best-before, use-by) can now have its own background color, next to\nits own text field.<\/li>\n<li>New: best-before and use-by product-page dates can each optionally override their own text color.<\/li>\n<li>New: the product-page expiry date's position dropdown now also offers \"After add-to-cart button\"\nand \"Before product meta\" (previously 3 options, now 5 \u2014 the same choices already offered\nelsewhere).<\/li>\n<li>New: a \"cost includes VAT\" option next to the Engine tab's profit-margin cost source, and a\nDiscount timer option on the Display tab \u2014 both require Pro to take effect, same as other\nPro-gated settings already on these tabs.<\/li>\n<li>Improved: order lines now record a regular-price snapshot at the time of sale for every order,\nnot just discounted ones \u2014 improves the accuracy of Pro's revenue and profit-margin reporting.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>New: the Actions tab's \"Pending changes\" table now includes a \"Reason\" column explaining why\neach product is about to change (excluded, out of stock, no qualifying batch, days left, etc.).<\/li>\n<li>New: a free scheduled email summary (Dashboard \u2192 Reporting \u2192 Email summary) \u2014 pick weekly,\nevery-2-weeks, or monthly, plus your own day and time.<\/li>\n<li>New: \"Units sold without an expiry-driven discount\" is now shown for free alongside \"Units sold\nvia expiry-driven discounts,\" for comparison.<\/li>\n<li>New: the product-page expiry date's position dropdown now also offers \"After add-to-cart button\"\nand \"Before product meta\" (previously 3 options, now 5 \u2014 the same choices already offered\nelsewhere). Best-before and use-by dates can each optionally override their own text color.\nDiscount notices (best-before\/use-by) can also have their own background color now.<\/li>\n<li>Changed: the Dashboard's revenue\/comparison table is now free-tier rows first, with the Pro-only\nfigures grouped into a single section below rather than mixed in row by row.<\/li>\n<li>Changed: \"Sold before expiry\" now counts every sale, in your selected date range, of any product\ncurrently marked as expiry-tracked \u2014 discounted or not, and drawing on your store's full order\nhistory, not just what's been logged since this feature was installed. \"Unsold at expiry\" now\nreflects the date range you've selected instead of all-time, and keeps a permanent record as\neach batch expires so the count stays accurate even if you later clean up old batch entries.<\/li>\n<li>Changed: \"Manual sales\" is a 3-way choice again \u2014 protect entirely, always override, or override\nonly when the computed discount is cheaper than your manual price.<\/li>\n<li>New: the automatic-reconcile schedule dropdown now includes \"No schedule.\" Batch tracking and\nhiding expired stock from customers work the same regardless of what's set here.<\/li>\n<li>Changed: \"Update prices instantly when stock changes\" now requires an active Pro license \u2014 the\nautomatic schedule's new Hourly option keeps the practical gap small for everyone else. If you\nwere relying on this without Pro, switch the schedule to Hourly to stay close to instant.<\/li>\n<li>Changed: the wp-admin order screen now shows the actual best-before\/use-by date for each\nexpiry-tracked line item (using your own configured label wording), for every sale \u2014 not just\ndiscounted ones \u2014 instead of raw internal metadata.<\/li>\n<li>Fixed: the Dashboard's date-range buttons (Last 7 days, Last 30 days, etc.) now actually show\nwhich range is currently selected.<\/li>\n<li>Fixed: \"All time\" in Reporting was showing 0 for most figures.<\/li>\n<li>Fixed: \"Priority email support\" wording updated to \"Priority customer support and configuration\nassistance\" (Pro doesn't only offer email support).<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>New: the Dashboard now opens with a \"Revenue &amp; comparison\" report \u2014 units\/orders sold at a\ndiscount, average discount applied, and a batch sell-through\/waste metric all calculated for\nreal, no Pro required, with a 7\/30\/90-day\/all-time\/custom date range and a free CSV export.<\/li>\n<li>New: exclude specific products or categories from discount-engine management entirely (Engine tab).<\/li>\n<li>Changed: \"Manual sales\" is now a plain on\/off choice (protect entirely, or let the engine always\nmanage price) instead of a price-comparison condition.<\/li>\n<li>Changed: \"update prices instantly on stock change\" is now a visible, optional toggle (Engine tab).<\/li>\n<li>Changed: the automatic-reconcile schedule now also offers Hourly, Semi-monthly, and Monthly.<\/li>\n<li>Changed: the Dashboard's product table is now \"Actively managed discounts,\" with search\/scroll\npast 15 products.<\/li>\n<li>Fixed: the Engine tab's product\/category exclusion search now actually filters by what's typed.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>New: custom CSS-selector notice placement (product page) is now available to everyone \u2014 moved out\nof the Pro add-on, since it's plain positioning, not an automation feature.<\/li>\n<li>Changed: the Engine tab's Stock &amp; Velocity section now appears after the discount-tier tables.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Changed: the Engine tab's Stock &amp; Velocity fields are now grouped into one consolidated section\n(Pro feature \u2014 no change to plain date-based discounting for everyone else).<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New: CSV export of batch\/expiry data (Actions tab) \u2014 one row per batch, matched by SKU. Doubles\nas a spreadsheet-friendly backup and as the starting template for the Pro add-on's CSV import.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial public release.<\/li>\n<\/ul>","raw_excerpt":"Track batch expiry dates in WooCommerce and automatically discount products as they approach their best-before or use-by date.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/346803","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=346803"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/tarkva"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=346803"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=346803"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=346803"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=346803"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=346803"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=346803"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}