=== Cosmetic Wholesale Sync ===
Contributors: juniustech
Donate link: https://cosmeticwholesale.eu
Tags: woocommerce, dropshipping, catalog, wholesale, cosmetics
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
WC requires at least: 7.0
WC tested up to: 11.0
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Pulls Cosmetic Wholesale catalog (stock/price) into WooCommerce and sends paid orders to your Cosmetic Wholesale account.

== Description ==

Cosmetic Wholesale Sync connects a WooCommerce shop to a Cosmetic Wholesale dropshipping account.

This is the official integration for the Cosmetic Wholesale dropshipping service (https://cosmeticwholesale.eu), operated by Distraal B.V. in Rotterdam, Netherlands. It is published with their permission and developed by Juniustech. The plugin is free and fully functional; it does nothing until you paste the catalog feed URL and token issued to your approved Cosmetic Wholesale account, because it has no other service to talk to.

**Catalog**

* First import creates missing products (SKU = EAN). Images are not imported.
* Hourly job updates stock and sale price for existing SKUs only. It never wipes the catalog on feed failure.
* Price formula: `regular_price = round(cost × (1 + margin%/100) + fixed, 2)`.

**Orders**

* When a Woo order becomes `processing` (customer paid), the plugin queues a POST to Cosmetic Wholesale using the same catalog feed token (not during checkout HTML).
* Insufficient wallet → Woo stays `processing`; the plugin retries. It does not cancel the customer order.
* Tracking from Cosmetic Wholesale is written back; the Woo order can then be completed.

You need an approved Cosmetic Wholesale dropshipping account. Paste the catalog feed URL and token from your Account page. OMS / warehouse credentials are **not** stored in this plugin.

== Installation ==

1. Install and activate WooCommerce.
2. Upload the plugin zip (Plugins → Add New → Upload) or install from WordPress.org.
3. Open WooCommerce → Cosmetic Wholesale.
4. Paste Catalog feed URL (no token in the URL) and token from your Cosmetic Wholesale Account.
5. Set **Margin %** and **Margin fixed** (the same two numbers as the old 360 plugin). 0 / 0 = sell at B2B cost.
6. Save settings. Run First import (keep the tab open, or use `wp cw-sync import`).
7. Run Dry run until `updated > 0`. Leave hourly sync on.

== Frequently Asked Questions ==

= Do I put OMS or WMS passwords in the plugin? =

No. The plugin only talks to Cosmetic Wholesale. Warehouse dispatch is handled server-side.

= Why are there no product images? =

First import and hourly sync do not download images. That is intentional (large catalogs). Images can be added later as a separate, infrequent job.

= What happens if my Cosmetic Wholesale wallet is empty? =

The Woo order stays `processing`. The plugin retries about every 10 minutes after you top up. The customer is not cancelled.

= Does this replace the old 360 plugin? =

For catalog + order push to Cosmetic Wholesale, yes. Do not run 360 catalog cron and this plugin hourly job on the same SKUs without a cutover plan.

= What is Margin % / Margin fixed? =

They are your retail markup on the B2B feed cost (the same two numbers the 360 plugin used). 0 and 0 sells at cost.

= Paid orders never reach Cosmetic Wholesale =

Order push and the 10-minute wallet retry use WP-Cron. If `DISABLE_WP_CRON` is true and no system cron hits `wp-cron.php`, orders stay queued with no error. Check **Last order retry cron (UTC)** on WooCommerce → Cosmetic Wholesale.

== External services ==

This plugin connects to Cosmetic Wholesale (https://cosmeticwholesale.eu), the dropshipping service the merchant holds an account with. The host used is the one shown on the merchant’s Account page; no address is hard-coded in the plugin.

1. **Catalog feed (GET)** — the Feed URL the merchant pastes. Sends `Authorization: Bearer <token>`. Receives a CSV of EAN, title, stock, and cost. Used to create/update Woo products.
2. **Dropshipping orders (POST/GET)** — derived from the same host (`/api/v1/dropshipping/orders`). Sends the paid Woo shipping address (name, street, city, postcode, country, phone, email) and line EANs/quantities so Cosmetic Wholesale can fulfil the order. Returns order id and later tracking numbers.

No OMS or WMS passwords are stored or sent. The token is the merchant’s Cosmetic Wholesale catalog token. Data is sent only after the merchant saves settings and a customer pays. Nothing is sent while the Feed URL and token fields are empty.

The service is operated by Distraal B.V. (trading as Cosmetic Wholesale), Goudsesingel 103, 3031EE Rotterdam, Netherlands. KVK 95455078, VAT NL867137538B01.

* Terms and Conditions: https://cosmeticwholesale.eu/terms-and-conditions/
* Privacy Policy: https://cosmeticwholesale.eu/privacy-policy/
* Dropshipping policies: https://cosmeticwholesale.eu/dropshipping/policies-for-dropshipping/

== Screenshots ==

1. Settings: feed URL, token, margin, first import, hourly toggle.

== Changelog ==

= 1.0.1 =
* Stored meta keys use the full `_cw_sync_` prefix; keys written by pilot builds are still read.

= 1.0.0 =
* First WordPress.org directory release (catalog sync, hourly stock/price, paid-order push).
* Plugin slug, main file and text domain are `cosmetic-wholesale-sync`.
* First-import progress uses an enqueued admin script.

= 0.3.3 =
* Packaged for the WordPress.org directory: folder and main file renamed to `cosmetic-wholesale-sync`, text domain changed to `cosmetic-wholesale-sync` so language packs work.
* SKU lookup query documented and marked for the coding standards; behaviour unchanged.
* First-import progress uses an enqueued admin script (no inline JavaScript).

= 0.3.2 =
* Tested up to WordPress 7.1 and WooCommerce 11.0.
* Admin shows last order-retry cron time (UTC); WP-Cron note when it never runs.
* Product titles collapse newlines/whitespace to a single space.
* LICENSE is the full GPL-2.0 text.

= 0.3.1 =
* HPOS + cart/checkout blocks compatibility declared.
* Empty default feed URL (no staging host baked in).
* UTF-8-safe title clip; CSV parser uses fgetcsv (quoted newlines, PHP 8.4 escape).
* Order push queued off the checkout request; 401/403 not retried.
* Token field no longer echoes the secret into HTML.
* uninstall removes cw_sync_order_state.

= 0.3.0 =
* Order push on Woo `processing`.
* 402 wallet HOLD retry.
* Tracking poll → Woo completed.

= 0.2.2 =
* Catalog first import + hourly stock/price.

== Upgrade Notice ==

= 1.0.1 =
Stored meta keys were renamed to a longer prefix. Existing orders keep working; no action needed.

= 1.0.0 =
First directory release. If you installed an earlier zip as `cw-sync`, deactivate and delete it before installing this one; settings, products and orders are untouched.
