=== WooCommerce RetailPoint Sync ===
Contributors: lewebsimple
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 8.1
Stable tag: 0.5.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Imports RetailPoint Plus XML exports into a local cache table and exposes them as a WP REST API.

== Description ==

Companion WordPress plugin for the retailpoint-sync webapp — the per-site **data plane**. It ingests
the RetailPoint Plus (RPP) XML export into a cache, exposes it over REST for the webapp to browse,
and keeps WooCommerce **stock and price** in sync on the products the webapp has linked. Everything
editorial — titles, descriptions, images, categories, variation structure — is owned by the webapp
(created and edited over the WooCommerce REST API); this plugin never creates products and never
touches those fields. The full architecture is documented in `CLAUDE.md`.

Responsibilities:

* Periodically import the RetailPoint Plus XML export from a configurable server path
  (Settings > RetailPoint Sync), using WooCommerce's Action Scheduler for background batching.
* Cache the parsed SKUs in a custom database table (`{prefix}retailpoint_sync`).
* Expose the cache as a read-only REST API (`/wp-json/retailpoint-sync/v1/`) with pagination,
  filtering and search.
* After each import, push the enabled stock/price fields onto linked WooCommerce products (matched
  by barcode), flag structural changes for the webapp to resolve, and apply the configured action to
  products whose reference has left the export.

Requires WooCommerce (for Action Scheduler).

== REST API ==

Top-level products (grouped by numref) with a `type` (`simple` / `variable`) and their
variations embedded:

* `GET /wp-json/retailpoint-sync/v1/products` — paginated, filterable, searchable product list;
  each variable product embeds its `variations[]`.
* `GET /wp-json/retailpoint-sync/v1/products/<numref>` — single product with variations.
* `GET /wp-json/retailpoint-sync/v1/skus/<codebar>` — single SKU (variation) by barcode.
* `GET /wp-json/retailpoint-sync/v1/status` — last sync status and cached row count.
* `GET /wp-json/retailpoint-sync/v1/facets` — distinct values per filter column (for dropdowns):
  `dept`, `subdept`, `brand`, `category`, `season`, `fournisseur`, `couleur`, `grandeur`.

Product list params: `page`, `per_page` (max 100), `search` (incl. barcode), `in_stock`,
`type` (`simple` / `variable`), `orderby` (`numref|product_desc|price|variation_count`), `order`,
and filters `numref`, `brand`, `dept`, `subdept`, `category`, `season`, `fournisseur`
(product-level) plus `couleur`, `grandeur` (product has a matching variation). `/products` also
reports link state (`linked`, `wc_product_id`, `last_synced_at`) and accepts a `linked` filter.

Authenticated endpoints (WordPress Application Password, `manage_woocommerce`) — used by the webapp:

* `GET /associations` — paginated numref ↔ WooCommerce product links.
* `POST | DELETE /products/<numref>/link` — register / remove a link (POST body: `product_id`).
* `POST /sync` — queue an operational stock/price resync (body: `{ numrefs?: string[] }`, default all linked).
* `GET /sync/status` — resync progress.
* `GET /flags` — outstanding structural-change flags; `DELETE /flags/<numref>` — mark one resolved.
* `GET | POST /settings` — read / update the operational-sync settings (field toggles, price sources, prune action, archived seasons).
* `GET /seasons` — per-season product / in-stock counts (for the "disable out-of-stock seasons" action).

== Changelog ==

= 0.5.0 =
* Multi-product associations: several RetailPoint references (numrefs) can back a single variable WooCommerce product (a "merge"). The link table already allowed it; the sync, prune and link registry now handle it correctly.
* The operational sync scopes each numref to its own variations (via the `_retailpoint_numref` variation meta written at creation/migration), so a merged product no longer raises spurious structural-change flags for its sibling references' variations.
* The removal action is product-aware: a reference leaving the export (or entering an archived season) no longer unpublishes a product other references still sell — its variations are flagged for manager-resolved removal instead. The product is only pruned once no linked reference remains.
* `_retailpoint_numref` product meta is now multi-valued (one row per numref) instead of being overwritten; unlink removes only its own value. New `RPS_Link::set_many()` and `RPS_Link::numrefs_for_product()`.
* `GET /associations` accepts a `product_id` filter, so a merged product's full reference set can be resolved in one call.
* New WP-CLI command `wp rps migrate-from-rpsync [--dry-run] [--rollback] [--product=<id>]`: re-links the WooCommerce products managed by the legacy `rpsync` plugin in place (stamps the `_retailpoint_codebar` / `_retailpoint_numref` join keys and registers the links, including merged products) without recreating products or touching editorial content.
* Uninstall now also drops the `retailpoint_sync_attr` table.

= 0.3.0 =
* Refocused the plugin as a pure data plane: operational stock/price sync only. Product/variation creation, field/category mapping and editorial writes are removed — they are now owned by the retailpoint-sync webapp, which creates and edits products over the WooCommerce REST API and links them here.
* Per-field sync toggles (`stock_quantity`, `regular_price`, `sale_price`) with selectable cache-column sources, under Settings > RetailPoint Sync > WooCommerce sync.
* Structural changes (barcode added/removed, simple↔variable) are flagged for the webapp to resolve instead of altering WooCommerce; exposed at `/flags`.
* Configurable action for products whose reference leaves the export: ignore | unpublish (default) | trash.
* Archived (disabled) seasons: linked products in a disabled season are pruned (per the removal action) and skipped by the sync, and the season is excluded from the read API (`/products`, `/facets`); managed from the webapp via `/settings` (`archived_seasons`).
* Authenticated `GET | POST /settings` exposes the operational-sync settings so the webapp can configure them without WP-admin (import mechanics stay WP-admin only).
* Removed endpoints `/mapping`, `/category-map`, `/departments`, `/products/<numref>/sync`, `/wc/products`, `/wc/categories`; removed class `RPS_Mapping`.

= 0.2.0 =
* Phase 2a: associate RetailPoint products with WooCommerce products and create/update them plugin-side.
* Department/sub-department → WooCommerce category mapping; XML field → WC field mapping; stock/price sync toggles.
* Authenticated (Application Password / manage_woocommerce) endpoints: /mapping, /category-map, /departments, /associations, /products/<numref>/link, /products/<numref>/sync, /sync, plus WC read proxies /wc/products and /wc/categories.
* `/products` now reports association state (linked, wc_product_id, last_synced_at) and accepts a `linked` filter.
* Update-only auto-resync of linked products after each scheduled import (never creates products).

= 0.1.2 =
* Add `type` (`simple` / `variable`) filter to the product list.
* Add `/facets` endpoint exposing distinct filter values (dept, brand, couleur, …) for dropdowns.

= 0.1.1 =
* Support both RetailPoint export layouts (attribute-based and child-element, quoted and unquoted values).
* Add niv1_en, niv1_fr and brand columns.
* Product-level REST API: /products returns top-level products (simple/variable) with embedded variations; barcode lookup moved to /skus/<codebar>.
* XML path is resolved relative to the site root (portable across host and container).

= 0.1.0 =
* Initial phase 1 release: XML import, cache table, read-only REST API.
