=== WPNest Price History for WooCommerce ===
Contributors: wpnest
Tags: woocommerce, omnibus, price history, compliance, sale
Requires at least: 6.2
Tested up to: 6.9
Requires PHP: 7.4
Requires Plugins: woocommerce
Stable tag: 1.0.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

EU Omnibus directive compliance for WooCommerce — shows the lowest price from the last 30 days when a product is on sale.

== Description ==

WPNest Price History for WooCommerce gives WooCommerce stores automatic compliance with the EU Omnibus directive (Directive 2019/2161, in force across the EU since May 2022, in Poland from January 2023).

The plugin records every price change in your store with a timestamp and renders the legally required notice — "Najniższa cena z 30 dni przed obniżką: X" — under the price on every product page where a discount is announced.

= Key features (Free) =

* **Automatic price capture** — every change made via admin, REST API, WP-CLI, CSV import, or programmatic save is recorded with timestamp.
* **Daily snapshot failsafe** — a cron job ensures every published product has at least one history row per 24h, even when capture hooks miss.
* **30-day-low calculation** — uses the legally correct "Omnibus" method (lookback from the moment the current sale started). A "Rolling" alternative is available for stores that prefer it.
* **Configurable label** — the notice text is fully customizable per language.
* **Display options** — single product page (required), shop loop, cart line items.
* **Variable products** — per-variation tracking with frontend handler that updates the notice when a variation is selected.
* **Custom CSS** — paste your own styles for the notice without editing files.
* **Per-product mini-chart** in the admin product edit screen.
* **WP-CLI support** — `snapshot`, `cleanup`, `backfill`.
* **Backfill on activation** — seeds the history table with current prices so the 30-day window is never empty.
* **Cleanup cron** — automatically removes entries older than the retention window (default 90 days).
* **Cache** — transient-based (12h TTL) with automatic invalidation on every price change.
* **Compatible** with HPOS (WooCommerce custom order tables).

= Compliance basis =

This plugin implements requirements from:

* **EU Directive 2019/2161** ("Omnibus") — applicable across all EU member states.
* **Polish Ustawa o informowaniu o cenach towarów i usług, art. 4 ust. 2** — domestic transposition, in force since 1 January 2023.

UOKiK (the Polish Office of Competition and Consumer Protection) actively monitors compliance and may impose fines of up to 10% of annual revenue. The most commonly flagged violation is "price gymnastics" — artificially inflating the regular price shortly before a sale to make the discount appear larger.

= Pro version =

A Pro extension is available with additional features for shops that want to go beyond the legal minimum: public price history chart on product pages, Omnibus violation detector, compliance dashboard, webhooks (Slack/Discord), CSV export for audit, tamper-proof hash chain, white-label, and more. See https://wpnest.pl/sklep/prawo-i-formalnosci/wpnest-price-history-pro/ for details.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/` or install via the Plugins screen.
2. Activate the plugin through the "Plugins" screen in WordPress.
3. Go to **WooCommerce → Price History** to configure settings.
4. The plugin starts capturing prices immediately. The backfill process seeds existing products in the background — typically completes within minutes for shops up to 10k products.

== Frequently Asked Questions ==

= Does this plugin work with variable products? =

Yes. Each variation has its own price history. The notice on the single product page updates automatically when a customer selects a different variation.

= Does it work with theme overrides of single-product.php? =

Yes. The plugin uses the `woocommerce_get_price_html` filter as its primary integration point, which fires whenever any code calls `$product->get_price_html()`. This works in both standard themes and custom themes that bypass `woocommerce_single_product_summary`.

= What if my theme renders prices via wc_price() directly (not get_price_html())? =

In that rare case, you can call `do_action('woocommerce_single_product_summary')` from your theme template, or use the included `omnibus-notice.php` template override mechanism.

= Will my historical data be deleted when I uninstall the plugin? =

No, by default. The history table is treated as regulatory-grade data. To explicitly delete it on uninstall, enable "Delete data on uninstall" in the plugin settings.

= How does the daily cleanup cron decide what to delete? =

Entries older than the configured retention window (default 90 days) are deleted by `wpnest_ph_cleanup` cron. The retention window is configurable down to a minimum of 30 days.

= I see "Najniższa cena: X" but X equals the current sale price — is that wrong? =

This usually means you've recently activated the plugin and there's no historical data yet from before the current sale. The plugin falls back to the rolling window when no pre-sale snapshot exists. Once you accumulate ~31 days of history, the Omnibus method kicks in.

== Screenshots ==

1. Settings page — General (General) tab.
2. Settings page — Display (Display) tab with custom CSS.
3. Frontend notice on a single product page.
4. Per-product price history chart in the admin metabox.

== Third-Party Libraries ==

This plugin bundles the following libraries:

* Chart.js v4.5.1 — MIT License, https://www.chartjs.org/ — used to render the per-product price history chart in the admin product edit screen.
* chartjs-adapter-date-fns v3.0.0 (bundle including date-fns) — MIT License, https://github.com/chartjs/chartjs-adapter-date-fns — date adapter required by Chart.js v3+ for time-scale axes on the price history chart.

== Changelog ==

= 1.0.3 =
* Fixed: the per-product admin price history chart did not render after the Chart.js 4.x upgrade because Chart.js v3+ no longer bundles a date adapter. Added the `chartjs-adapter-date-fns` UMD bundle (MIT, includes date-fns inline) as a dependency of the chart script.
* Fixed: chart points were not drawn even when axes rendered, because `parsing: false` was paired with raw MySQL DATETIME strings as the `x` value. Pre-convert each row's `captured_at` (UTC) to a millisecond timestamp before pushing into the dataset.
* Disclosed the bundled `chartjs-adapter-date-fns` in the "Third-Party Libraries" section.

= 1.0.2 =
* Hardened custom CSS sanitization: `sanitize_textarea_field()` plus blacklist of CSS-level attack vectors (expression, javascript:, vbscript:, @import, behavior, -moz-binding).
* Refactored transient cache key construction to make the `wpnest_ph_low_` prefix unambiguous to static analyzers.
* Fixed: per-product cache invalidation now correctly clears transients for both calculation methods (previous version only cleared entries that no longer existed under that key).
* Hardened plugin action link: `esc_url()` and `esc_html__()` on the Settings link, matching the Pro link pattern.
* Documented why the Omnibus notice output is echoed without an outer `wp_kses_post()` wrap (would strip the `data-variation-lows` JSON attribute needed by the variation handler) — all values are still escaped internally.
* Synced Chart.js enqueue version string with the bundled file (4.5.1).
* Disclosed bundled Chart.js library in readme.txt.

= 1.0.1 =
* Renamed plugin slug to `wpnest-price-history-for-woocommerce` and display name to "WPNest Price History for WooCommerce" per WordPress.org review feedback.
* Added `Requires Plugins: woocommerce` header for WordPress 6.5+ dependency declaration.
* Hardened custom CSS output: `wp_strip_all_tags()` now applied at output in addition to sanitize-on-save.
* Updated bundled Chart.js to 4.5.1.

= 1.0.0 =
* Initial release.
* Automatic price capture via `woocommerce_update_product` and `woocommerce_update_product_variation` hooks.
* Daily snapshot failsafe cron.
* Omnibus and Rolling calculation methods.
* Configurable retention window with cleanup cron.
* Variable product support with per-variation tracking.
* Customizable notice label and position.
* Custom CSS field.
* Per-product mini-chart in admin.
* WP-CLI commands.
* HPOS compatible.

== Upgrade Notice ==

= 1.0.3 =
Restores the admin product price history chart, which silently failed to render after the Chart.js 4.x upgrade. Recommended.

= 1.0.2 =
Security hardening of custom CSS sanitization and fix for cache invalidation. Recommended.

= 1.0.1 =
Plugin slug renamed per WordPress.org review. Reinstall under the new slug; old instances should be deactivated and removed.

= 1.0.0 =
Initial public release.
