# BW Barnet Connector

Connects this WooCommerce site to the BarnetPOS e-commerce API.

## Where to find it

WP Admin sidebar: **Barnet** → *Settings* and *Diagnostics*.

## Credentials

Two ways to supply them. Constants win if both are present.

**Option A, the settings screen.** Barnet → Settings. Stored in `wp_options`.
The password is never rendered back into the form; leaving it blank on save
keeps the stored value.

**Option B, hardened.** Define in `wp-config.php` so the secret never touches
the database:

```php
define( 'BARNET_API_KEY',  '...' );
define( 'BARNET_API_PASS', '...' );
```

Set via WP-CLI without the value entering shell history:

```bash
srv-gw wp --project corkandbarrel -- config set BARNET_API_KEY --prompt
```

When constants are in force the settings fields disable themselves and say so,
so the screen can never disagree with what is actually being used.

## HTTPS is enforced, deliberately

Barnet's documentation specifies `http://` for every endpoint. HTTPS works
(valid Let's Encrypt cert, TLS 1.2/1.3 only) but their server does **not**
redirect, so an http URL succeeds silently while sending Basic-auth credentials
and customer PII in cleartext.

`BW_Barnet_Client::enforce_https()` refuses to make the request at all in that
case, and `redirection => 0` prevents a redirect from downgrading mid-flight.
Do not relax either.

## Diagnostics

Barnet → Diagnostics walks the catalogue in batched AJAX calls and reports:

- Catalogue size, and how much is flagged `show_on_web`
- **Barcode quality**: what share of `pid` values are real GTINs. Decides how
  well Google Shopping can work, because an invalid GTIN submitted as a GTIN
  gets the product disapproved, whereas declaring `identifier_exists: false`
  merely costs comparison matching
- Products whose `pid` is the SKU repeated twice (a data-entry pattern, worth
  raising with Barnet)
- Barcodes recoverable by restoring a stripped leading zero
- **Image coverage**, since Merchant Center requires an image per product
- Population rates for producer / vendor / distributor (brand candidates) and
  country / varietal / alcohol / sweetness (storefront filter candidates)

Batching exists because there is no documented rate limit and a full catalogue
is many pages. There is a 250ms pause between pages. If Barnet ever returns
429 the client surfaces it as a distinct error.

## Known API constraints

- **No incremental product sync.** `store/products` accepts only `q`, `p`,
  `items_on_page` and `show_on_web`. There is no modified-since parameter, so
  every refresh is a full crawl. `shop/orders` does accept `date`.
  `last_received` exists in the PUT schema but is not returned on GET.
- **No webhooks** anywhere in the API.
- **Images are relative paths** (`custom/000000/0000000200-9378.jpg`). The base
  URL is not in the documentation and is still outstanding from Barnet.
- **Checkout is undocumented.** `POST /api/orders` expects an already-paid order
  (`status` 1 plus card brand and last four), which reads as record-the-sale
  rather than take-payment. Whether a hosted handoff exists is outstanding.

## Files

| File | Role |
|---|---|
| `bw-barnet-connector.php` | Bootstrap, constants, capability definition |
| `includes/class-bw-barnet-client.php` | API client, HTTPS guard, error mapping |
| `includes/class-bw-barnet-gtin.php` | Barcode validation and leading-zero repair |
| `includes/class-bw-barnet-settings.php` | Credentials screen |
| `includes/class-bw-barnet-diagnostics.php` | Batched catalogue scan and report |
