=== EmberPrice – Supplier Price List Import for WooCommerce ===
Contributors: emberprice
Tags: woocommerce, price import, supplier, bulk edit prices, csv import
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 8.2
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
WC requires at least: 8.0
WC tested up to: 10.9

Import a supplier price list (Excel or CSV), auto-match products, and bulk-update WooCommerce prices with rules, preview, and rollback.

== Description ==

EmberPrice imports supplier price lists (Excel XLSX/XLS or CSV) into WooCommerce, so you can update WooCommerce prices from Excel or run a bulk price update from CSV without editing products one by one. Upload the file and EmberPrice auto-detects the columns, matches each row to your real catalog (learned alias, SKU/GTIN, exact name, or fuzzy match), and applies a pricing rule (margin, VAT, rounding) you control. Every price update goes through a full preview, with old price, new price, and percent change, that you can export before anything touches your store, plus a snapshot-based rollback if you change your mind after applying it.

Try it before you trust it with real data: every install ships with a sample supplier price list, so you can run the whole wizard end to end in a couple of minutes with nothing at stake. And it scales past the demo: matching and pricing a real 5,000-row supplier list against a 10,000-product catalog, start to finish, takes under 4 minutes (see the Performance section below).

The full wizard:

1. **Upload** a supplier's XLSX, XLS, or CSV price list.
2. **Map columns**: code, description, price are auto-detected; confirm or correct once per supplier.
3. **Review matches**: a matching cascade (learned aliases → SKU/GTIN → exact name → fuzzy matching) resolves each row against your real catalog; anything uncertain is flagged for a quick manual confirm, reject, or assign.
4. **Set pricing rules**: margin (percentage or fixed), VAT handling, rounding (none, decimals, psychological `.99`/`.90` endings, or nearest multiple), existing sale-price policy, and per-category overrides.
5. **Preview the diff**: old price → new price, percent change, confidence, and guardrail flags, exportable to CSV before anything touches your store.
6. **Apply**: batched in the background via Action Scheduler, with a snapshot taken first so the whole import can be rolled back in one click.

= Why not just edit prices manually? =

Because supplier lists are messy: headers that aren't on row 1, merged cells, prices as `$ 1.234,56`, codes with leading zeros or no code column at all, section rows, discontinued items. EmberPrice's column detection and matching cascade are built around exactly these cases, and nothing is ever written to a product until you've seen the diff.

= Safety by design =

* A hard floor prevents any computed price from falling below the supplier's own list price (catches parsing errors before they reach your store).
* Guardrails flag any change beyond a configurable percentage for manual review, even when the product match itself is perfect.
* Every apply takes a snapshot first, so a rollback restores prices byte-for-byte.
* AI-assisted matching, planned as a future opt-in Pro feature (Anthropic or OpenAI, bring your own API key), is designed to only ever see the supplier's row text and your own catalog's product names/SKUs. It never sees customer, order, or other personal data.

= What's in this release =

This release covers the full wizard for CSV/XLSX imports on simple and variable products: manual column mapping, alias/SKU/exact-name/fuzzy matching with no row limit, learned-alias memory (so re-imports from the same supplier resolve instantly), a global margin rule, guardrails, preview/export, and full rollback history.

A paid Pro tier is planned for a future update and will add: AI-assisted matching and column mapping, PDF price lists, and per-category pricing rules and rounding.

== Installation ==

1. Make sure WooCommerce 8.0 or later is active.
2. Upload the plugin (or install from the WordPress plugin directory) and activate it.
3. Go to **WooCommerce → EmberPrice** to run the import wizard, or try it first with the bundled sample price list. History (past imports, rollback) is also under the WooCommerce menu.

== Frequently Asked Questions ==

= Does this change my product prices immediately when I upload a file? =

No. Nothing is written to any product until you reach the last step and explicitly apply the job. Every earlier step (mapping, matching, rules, preview) is read-only.

= What file formats are supported? =

XLSX, XLS, and CSV. PDF price lists (text-layer only, not scanned images) are planned for a future update.

= Does it work with price lists that don't have a SKU column? =

Yes. The matching cascade doesn't require a SKU: it also matches by learned alias (from your past confirmations), exact product name, and fuzzy name matching, so lists with only a description column still resolve.

= Do I need an AI/LLM API key to use this plugin? =

No. This release doesn't use one at all: the full wizard runs on local column detection and matching (alias, SKU/GTIN, exact name, fuzzy). AI-assisted matching and mapping is planned as a future opt-in, bring-your-own-key (BYOK) Pro feature; this plugin doesn't have or need its own AI backend.

= What data would be sent to the AI provider? =

Nothing today: this release doesn't include the AI-assisted matching code at all, so it never connects to Anthropic, OpenAI, or any other external service. When the feature ships in a future update, it will only run while explicitly enabled with your own API key, sending the supplier's own row text (names/codes) and matching candidates already in your store's catalog (product names, SKUs) only. Never customer, order, or other personal data.

= Does it work with variable products? =

Yes. The matching cascade resolves a supplier row directly to a variation (by its own SKU, name, or fuzzy match), and pricing rules apply to the matched variation.

= What happens if the matching gets something wrong? =

Any row the cascade isn't confident about is left for manual review: nothing auto-applies without a confirmed match. You can always search and manually assign a row to any product.

= Can I undo a price update? =

Yes. Every apply snapshots the previous prices first. Roll back any applied job from the History screen, not just the most recent one: snapshots are kept until the retention period expires.

= Does this touch stock, cost prices, or multiple currencies? =

Not in this version: EmberPrice is scoped to regular/sale price updates from a supplier list. Stock, cost fields, multi-currency, and scheduled/watched-folder imports are on the roadmap but not implemented yet.

== Screenshots ==

1. Step 1: upload a supplier file, or try the bundled sample price list.
2. Step 2: column mapping, auto-detected from the file.
3. Step 3: review matched, uncertain, and unmatched rows.
4. Step 4: pricing rules: margin, VAT, rounding, guardrails, category overrides.
5. Step 5: price diff preview, exportable to CSV.
6. Step 6: apply the import, with one-click rollback afterward.

== Changelog ==

= 1.0.2 =
* Admin: EmberPrice is now a single entry under WooCommerce instead of three separate submenus. Import, History, and Settings are tabs inside one screen with a shared header and navigation. Links and bookmarks to the previous screens redirect to the new ones, and resuming an import from History still works.
* Admin: more consistent, responsive, and accessible layout across the wizard, history, and settings.
* Renamed the plugin to "EmberPrice – Supplier Price List Import for WooCommerce" so the listing states what it does. The menu entry under WooCommerce is still just "EmberPrice".
* Fixed: the plugin description shown on the WordPress Plugins screen was in Spanish instead of English.
* No changes to importing, matching, pricing rules, applying, or rollback. Existing suppliers, aliases, jobs, and rollback history are preserved.

= 1.0.1 =
* Security: encrypt supplier uploads at rest and reject damaged, disguised, oversized, or unsafe workbooks.
* Reliability: resume interrupted jobs, detect and retry stalled background work, support WordPress Application Passwords, report partial failures, and block stale previews and duplicate product targets.
* Import quality: improve Spanish and Northwind column detection, enforce valid one-to-one mappings, and invalidate stale saved mappings.
* UX: give every WooCommerce submenu a distinct label, add useful paginated history with resume links, confirm rollbacks, and improve responsive and accessible controls.

= 1.0.0 =
* Initial public release: 6-step import wizard, matching cascade (alias/SKU/exact-name/fuzzy), pricing rules and guardrails, preview/export, batched apply with snapshot-based rollback, history screen, onboarding sample data.

== Upgrade Notice ==

= 1.0.2 =
The three EmberPrice submenus under WooCommerce are now one screen with tabs; old links redirect. Also a clearer plugin name. Imports, history, and rollbacks are unaffected.

= 1.0.1 =
Recommended security and reliability update. Existing suppliers, aliases, jobs, and rollback history are preserved.

= 1.0.0 =
Initial public release.

== Performance and tested limits ==

Measured against a real WooCommerce catalog of 10,000 products (9,700 simple + 300 variable products with 3,000 variations total) and a real 5,000-row supplier price-list import, driven through the actual REST endpoints (no mocks):

* Matching (full 4-stage cascade against the real catalog): ~71 seconds total (10 Action Scheduler batches of 500 rows, worst single batch 7.7s). Comfortably under 5 minutes.
* Apply: ~144 seconds total (38 batches of 100 rows, worst single batch 13.9s). Comfortably under a typical 30-second PHP execution limit on shared hosting.
* Seeder script and reproducible perf harness: `tests/seed-catalog.php` and `tests/run-perf-test.php` (WP-CLI only, not shipped in the distribution zip).

Hosting considerations found during this pass (environment characteristics, not plugin defects):

* On hosts with `innodb_flush_log_at_trx_commit=1` and slow disk I/O, every database write incurs a synchronous fsync; large batch operations (apply, rollback) will be slower than the numbers above. This is a MySQL/hosting configuration matter, outside the plugin's control.
* Action Scheduler's own claim query can degrade significantly once `wp_actionscheduler_actions`/`wp_actionscheduler_claims` accumulate a very large backlog (tens of thousands of rows) without periodic cleanup. If matching or apply appear stuck, run `wp action-scheduler clean` first before assuming a plugin bug.

Not yet covered by this QA pass: a full compatibility matrix across WooCommerce 8.x/9.x, PHP 8.2-8.3, and the Storefront/Astra themes. This pass validated against WooCommerce 10.9 / PHP 8.3 only.
