=== Caravel GPSR for WooCommerce ===
Contributors: caravelsuite
Tags: gpsr, product safety, manufacturer, responsible person, woocommerce
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Requires Plugins: woocommerce
Stable tag: 1.0.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Store and show EU product safety information (GPSR) on WooCommerce product pages, and see which products still miss it.

== Description ==

Regulation (EU) 2023/988 on general product safety (GPSR) applies since 13 December 2024. For products offered online to consumers in the EU, article 19 lists what the product page has to show:

* the manufacturer’s name, trade name or trademark, postal address and electronic address (email or website);
* when the manufacturer is not established in the EU, the same details of the responsible person in the EU;
* information that identifies the product (type, model, batch or serial number) and a picture;
* warnings or safety information in a language consumers can easily understand.

Caravel GPSR keeps this information in one place, shows it on your product pages and tells you which products still miss something. It helps you store and display information. It is not legal advice and it does not decide which rules apply to your products.

= Contacts directory =

Add each manufacturer and responsible person once — name, trade name, postal address, country, email, website and an optional phone number — and reuse them on any number of products. The contact form checks what it can: a valid country, a valid email, a public http(s) website, an EU country for an EU responsible person and the United Kingdom for a UK responsible person. A contact that is still used by products, brands or the store defaults cannot be deleted by mistake.

= Product safety tab in the product editor =

A “Product safety” tab is added next to Inventory and Shipping. Pick the manufacturer and the responsible person, add identifiers and write warnings in every language you sell in (one box per language you choose). Variations can have their own identifiers. The SKU and GTIN can count as identifiers. The tab says at once what is still missing.

= Less typing =

* **Brands:** set a manufacturer and responsible person on a WooCommerce brand and all its products use them.
* **Store defaults:** used when neither the product nor its brand has a contact.
* **Assign in bulk:** choose products by category, brand or tag, see how many match, and assign contacts. Large catalogs are processed in the background with the Action Scheduler included in WooCommerce.
* **WooCommerce bulk edit:** the contacts can also be changed from the products list.
* **CSV:** download one line per product, fill in the safety columns in a spreadsheet and upload the file. You see every change before anything is saved. The same columns are available in the standard WooCommerce product importer and exporter.

= Coverage overview =

WooCommerce → Product safety shows how many published products are complete, incomplete or out of scope, and a list of the products with exactly what is missing: manufacturer, responsible person, identifier, picture, warnings, or an email/website that is hidden on the product page. Filter by category or brand and search by name or SKU. The products list gets a “Safety” column and filter. Statuses are stored per product, so the overview stays fast on large catalogs.

= On the product page =

* A “Product safety” tab, or a section below the add to cart button, or only where you place the “Product safety information” block or the `[caravel_gpsr]` shortcode (`[caravel_gpsr id="123"]` for a given product).
* Manufacturer, responsible person(s), identifiers (also per variation), SKU, GTIN and warnings in the visitor’s language, with the other languages in collapsible sections if you want.
* Plain, accessible HTML with no JavaScript and a small stylesheet that follows your theme. Email addresses are protected against harvesting. You choose whether emails, websites and phone numbers are shown.

= Out of scope products =

Virtual and downloadable products, whole categories (for example food or medicines, which have their own rules) or single products can be left out of the checks.

= United Kingdom (optional) =

Turn on the UK market to add a UK responsible person to contacts, products and the product page. It is off by default.

= Also included =

* The resolved safety data is added to the WooCommerce REST API product response (`caravel_gpsr`), for feeds and marketplaces.
* Compatible with High-Performance Order Storage (HPOS) and the cart and checkout blocks.
* Available in English, Portuguese (Portugal), Spanish, French, German and Italian.
* No external requests, no tracking, no advertising. All data stays in your WordPress database.

= For developers =

Other code can extend the plugin without changing it. All hooks are prefixed with `caravel_gpsr_`.

Actions:

* `caravel_gpsr_init` — the plugin is loaded (after WooCommerce).
* `caravel_gpsr_product_panel_after` (`WC_Product $product`) — end of the Product safety tab in the product editor; add your own fields here.
* `caravel_gpsr_product_saved` (`WC_Product $product`) — the Product safety tab was saved by an authorized user, before the product is stored.
* `caravel_gpsr_frontend_after` (`WC_Product $product`) — end of the product safety section on the product page; echo extra HTML.
* `caravel_gpsr_contact_saved` (`int $contact_id`) — a contact was saved.
* `caravel_gpsr_status_updated` (`int $product_id, array $result, string $previous`) — the status of a product (`complete`, `incomplete` or `exempt`, with the missing codes) was computed and stored.
* `caravel_gpsr_settings_saved` (`array $settings`) — the settings were saved by an authorized user.
* `caravel_gpsr_admin_tab_{tab}` (`string $tab`) — renders a tab added with `caravel_gpsr_admin_tabs`.

Filters:

* `caravel_gpsr_completeness` (`array $result, WC_Product $product`) — change the status and missing codes of a product.
* `caravel_gpsr_public_data` (`array $data, WC_Product $product`) — the safety data shown on the product page and in the REST API.
* `caravel_gpsr_settings_fields` (`array $fields`) — fields of the settings tab (WooCommerce settings API format); added fields are saved with the same form, nonce and capability checks.
* `caravel_gpsr_admin_tabs` (`array $tabs`) — tabs of the Product safety screens (key => [label, URL]).
* `caravel_gpsr_languages` (`array $languages`) — languages offered for warnings (locale => name).

More at [caravelsuite.com](https://caravelsuite.com/).

== Installation ==

1. Install and activate WooCommerce 8.0 or later on WordPress 6.4 or later with PHP 7.4 or later.
2. Install the plugin from Plugins → Add New, or upload the ZIP file, and activate it.
3. Go to WooCommerce → Product safety and follow “Get started”: add your manufacturers, link them to your products, and choose what to show on product pages.
4. All products are checked in the background after activation. The counts fill in as it runs.

== Frequently Asked Questions ==

= Does it tell me whether my products comply with the GPSR? =

No. It shows which of the pieces of information listed in article 19 are stored and shown for each product. Whether a product is safe and compliant depends on much more than its product page. If you are unsure which rules apply to you, ask a professional adviser.

= My manufacturer is in the EU. Do I need an EU responsible person? =

The plugin only asks for one when the manufacturer is outside the EU or when you choose to require one for every product in the settings.

= Can I use the SKU or the GTIN as the identifier? =

Yes, this is on by default. You can turn it off in the settings, and you can add a type, model, batch or serial number per product or per variation.

= How do I show warnings in several languages? =

Choose the main language and the other languages in WooCommerce → Settings → Product safety. Each product then gets one warnings box per language. The product page shows the visitor’s language, and can also list the others.

= Does it work with WPML or Polylang? =

The plugin has not been tested with multilingual plugins. Product safety data is stored as product meta, so a translated copy of a product has its own fields if your multilingual plugin keeps them separate. Without a multilingual plugin, you can keep warnings in several languages on one product.

= What does the CSV import change? =

Only the columns present in the file, and only for the products found by ID or SKU. Before anything is saved you see a preview with every change and every line that could not be used. Cells that start like a spreadsheet formula are protected in the downloaded file.

= Where is the data stored? Is anything sent elsewhere? =

Everything stays in your WordPress database: contacts as a private post type, product data as product meta, brand contacts as term meta. The plugin makes no external requests.

= What happens when I deactivate or delete the plugin? =

Deactivating stops the background jobs and keeps your data. Deleting the plugin keeps your data too, unless you tick “Also delete contacts, product safety data and settings” in the settings first.

== Screenshots ==

1. Coverage overview: complete and incomplete products, and what each product is missing.
2. The Product safety tab in the product editor.
3. The Product safety tab on the product page.
4. The contacts directory.
5. Assign contacts in bulk by category, brand or tag.
6. CSV import with a preview of every change.
7. Settings under WooCommerce → Settings → Product safety.

== Changelog ==

= 1.0.0 =
* First release: contacts directory, Product safety tab for products, brands and variations, store defaults, coverage overview, bulk assignment, CSV import and export, product page tab, block and shortcode, optional UK responsible person, REST API data and six languages.

