=== Australcode Facturación Electrónica SII & Stock for Bsale ===
Contributors: australcode
Tags: dte, facturacion electronica, sii, boleta, bsale
Requires at least: 6.1
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 3.8.6
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Facturación electrónica SII for WooCommerce via Bsale — boletas, facturas and credit notes, real-time webhook stock sync free, no per-document fees.

== Description ==

**Australcode Facturación Electrónica SII & Stock** makes SII-compliant facturación electrónica — boletas, facturas and credit notes (DTE) issued from your orders — for any WooCommerce store in Chile, with automatic emission and dispatch guides in Pro. Real-time sync of products, stock and prices from Bsale to WooCommerce. The Free version already includes real-time webhook stock updates, credit notes, and on-demand stock audit — with no per-document or per-boleta fees. Mature plugin in production since 2023, now part of the Australcode family.

It covers the full lifecycle of a Chilean e-commerce transaction: from product catalog sync to manual or automatic emission of the SII-compliant tax document required for each WooCommerce order.

*Australcode is an independent developer. This plugin is a third-party integration for Bsale and WooCommerce; it is not affiliated with, endorsed by, or sponsored by Bsale, Defontana SpA, or the WooCommerce/Automattic trademark holders.*

= Free version =

Everything you need to run a typical Chilean e-commerce store with WooCommerce + Bsale:

* **Product sync** — One-way synchronization from Bsale to WooCommerce. Imports product catalog including variants, SKUs, prices, and stock levels.
* **Single-office stock** — Stock from one configured Bsale office, with optional reserve buffer for in-person sales.
* **Real-time stock updates via webhooks** — Bsale stock changes propagate to WooCommerce in seconds.
* **Manual emission of boleta and factura** — Issue documents from the order admin screen. Document type auto-detected from customer billing data (RUT empresa → factura, otherwise boleta).
* **Credit notes (notas de crédito)** — Manual emission for refunds.
* **Chilean checkout fields** — Adds RUT field with module-11 validation. Compatible with both Block-based Checkout and Classic Checkout.
* **Order metabox** — Per-order Bsale status, PDF link, document type, and re-emit controls.
* **Email PDF to customer** — Automatic dispatch of the emitted document to the customer's email.
* **Stock audit (on-demand)** — Run-when-needed audit comparing WooCommerce and Bsale stock. Discrepancy detection and traceability, with an optional email summary of the discrepancies found.
* **Diagnostics** — Dashboard with API/webhook status, logs viewer with filters and retention policy, traceability ledger (read-only).
* **HPOS compatible** — Declares compatibility with WooCommerce High-Performance Order Storage and Cart/Checkout Blocks.

= Pro version =

Adds workflow automation, multi-warehouse support, and advanced B2B features:

* **Auto-emission post-payment** — Documents emitted automatically when WooCommerce orders reach configurable statuses (processing, completed, etc.). The killer time-saver.
* **Multi-office stock aggregation** — Sum stock across multiple Bsale offices.
* **Stock transfer modes** — Auto-move stock to main office via internal transfer or dispatch guide (guía de despacho) when an order requires stock from a secondary office.
* **Sales notes (nota de venta) + automatic credit notes from refunds** — Full B2B workflow automation.
* **Dispatch guides (guías de despacho)** — Inter-office stock transfers with electronic dispatch document.
* **Dynamic document attributes** — Custom attributes (e.g. WooCommerce order number) injected into each emitted document.
* **Scheduled audits** — Up to 3 daily automatic audit runs comparing WooCommerce ↔ Bsale stock, with optional auto-correction. Results go to the same notification email as on-demand audits.
* **Custom field mapping** — Map WooCommerce custom checkout fields (from third-party plugins) to Bsale invoice fields (rut_empresa, razón social, giro, dirección, comuna, ciudad).
* **Stock-per-office display on frontend** — Optional product page widget showing available stock per office.
* **Per-shipping-method office routing** — Emit documents from a specific Bsale office based on the WooCommerce shipping method (multi-warehouse).
* **Daily auto-link by SKU** — Cron job that auto-links unlinked WooCommerce products to Bsale variants by SKU match.

= Pricing =

Pro is sold as an annual subscription (or one-time lifetime license) with 1 site activation per license. A 5-site license is also available.

Learn more and purchase at https://bsale.australcode.io

= Requirements =

* WooCommerce 7.0 or later
* A Bsale account with API access
* WordPress 6.1 or later, PHP 7.4 or later

= Bsale =

Bsale is a Chilean SaaS platform for POS, inventory, and facturación electrónica (electronic tax document emission) compliant with SII (Servicio de Impuestos Internos, the Chilean tax authority). It is the de-facto choice for many Chilean small and medium e-commerce businesses to handle their day-to-day operations and tax compliance.

This plugin is an unaffiliated third-party integration. "Bsale" is a trademark of its respective owner.

== External services ==

This plugin connects to two third-party services. Both are used only for the features described, and only as a result of an action you take (entering your Bsale API token, or activating a Pro license). No data is sent on a fresh install before you configure these features.

= Bsale API (bsale.io / bsale.cl) =

What it is: Bsale is the Chilean POS and electronic invoicing platform this plugin integrates with. The plugin is an unaffiliated third-party integration.

Data sent and when:

* Your Bsale API access token is sent with every request, to authenticate.
* Product, variant, SKU, price and stock queries are sent when you sync your catalog or when Bsale stock webhooks arrive.
* When a tax document is emitted (boleta, factura, credit note, dispatch guide), the order data required by the SII (customer RUT, razón social, line items, amounts) is sent to Bsale so it can issue the legal document.

This happens because the plugin's purpose is to mirror your Bsale catalog into WooCommerce and to emit SII-compliant documents through Bsale. The connection is configured by you: you enter your own Bsale API token under "Bsale → Configuración".

* Terms of Service: https://www.bsale.cl/sheet/condiciones-uso
* Privacy Policy: https://www.bsale.cl/sheet/politica-privacidad

= Freemius (freemius.com) =

What it is: Freemius is the Merchant of Record and licensing provider used to manage the optional Pro license (checkout, activation, account, and updates).

Data sent and when:

* When you opt in (optional — you can skip it), your admin email and site URL are sent to Freemius so it can manage your account and license. The plugin is fully functional without opting in.
* Your license key and site URL are sent to Freemius when you activate, validate, or deactivate a Pro license through the native Freemius account screens, and periodically while a Pro license is active to re-check its status and deliver updates.
* The free version does not require an account and works without contacting Freemius.

* Terms of Service: https://freemius.com/terms/
* Privacy Policy: https://freemius.com/privacy/

== Installation ==

1. Install the plugin from **Plugins → Add New** in your WordPress admin, or upload its folder to `/wp-content/plugins/australcode-dte-stock-sync-bsale`.
2. Activate the plugin from the WordPress admin "Plugins" menu.
3. Navigate to **Bsale → Configuración** (the admin is in Spanish).
4. Enter your Bsale API access token (available in your Bsale account).
5. Select your default office (sucursal) and configure document type preferences.
6. Configure the Bsale webhook URL in your Bsale account to enable real-time stock updates.

To unlock Pro features, go to **Bsale → Mejorar a Pro** and complete checkout through Freemius. Your Pro license activates automatically after purchase. (The admin is in Spanish; once Pro is active the same screen is labelled **Licencia**.)

== Frequently Asked Questions ==

= Do I need a Bsale account? =

Yes, you need an active Bsale account with API access. The plugin connects to your existing Bsale account via API token.

= What's the difference between Free and Pro? =

Free covers everything a typical Chilean e-commerce store needs: product/stock sync, manual emission of boletas and facturas, RUT validation, single-office stock, on-demand audit, real-time webhook updates. Pro adds workflow automation (auto-emission post-payment, scheduled audits, daily SKU auto-link), multi-warehouse support (multi-office stock aggregation, stock transfer between offices, per-shipping-method routing), and advanced B2B features (custom field mapping, dynamic document attributes, sales notes, automatic credit notes from refunds). The Pro features are distributed as a separate plugin (from australcode.io) and are not included in this free version.

See the [Pro page](https://bsale.australcode.io) for the full comparison.

= Can I move from Free to Pro without losing my configuration? =

Yes. Your Bsale account connection and general settings (API connection, document types, tax options) are stored independently of the Pro features, so when you move to the Pro version your existing configuration carries over — no re-entry needed.

= What happens if I stop using Pro? =

The free version is fully functional on its own — it keeps handling product/stock sync and manual emission of boletas and facturas. The Pro features are provided by the separate Pro version and are not part of this free plugin.

= Is it compatible with the WooCommerce Block-based Checkout? =

Yes, the plugin is compatible with both the Block-based Checkout (WooCommerce 8.0+) and the Classic Checkout. Chilean tax fields (RUT, razón social, giro) are added to both.

= Can I emit boleta or factura selectively per order? =

Yes. The order metabox allows manual override of the document type per order, useful for B2B orders where the customer requests a factura instead of a boleta. This works in both Free and Pro.

= Does the plugin support multiple Bsale offices (sucursales)? =

Yes — in Pro. Free supports a single configured office. Pro adds multi-office stock aggregation (sum of available units across selected offices) plus stock transfer modes for inter-office logistics.

= What happens if a tax document emission fails? =

Failed emissions are logged with the error reason. The order metabox includes a "Re-emit" button to retry manually. The plugin also has an automatic retry mechanism (Pro feature, configurable, opt-in) for transient failures.

= Is the plugin HPOS compatible? =

Yes, the plugin declares compatibility with HPOS (High-Performance Order Storage) and uses the WooCommerce data abstraction layer for all order operations.

= Does the plugin work without Bsale (offline mode)? =

No. The plugin is a Bsale integration — it requires an active Bsale account and API access to function. The plugin's value is precisely the connection between WooCommerce and Bsale.

= How does Pro licensing work? =

Pro is sold as an annual subscription (or a one-time lifetime license) through Freemius (Merchant of Record). After checkout your Pro license activates automatically; you can manage, sync or deactivate it from the native Freemius account screen. Freemius re-validates the license periodically while it is active. If Freemius is temporarily unreachable, your Pro features keep working — only an explicit change (refund, revocation, expiration) deactivates them.

= Where can I find the plugin's documentation? =

Visit https://bsale.australcode.io for plugin documentation, support, and source code.

= What does the plugin cover besides issuing documents? =

* **Catalog sync** — products, variants, SKUs, prices and stock come from Bsale into WooCommerce, with real-time stock webhooks. Multi-office stock is a Pro feature.
* **Stock audit and traceability** — an on-demand audit compares WooCommerce and Bsale stock, and a read-only ledger records every stock movement.
* **No per-document fees** — the free version issues boletas, facturas and credit notes at no cost per document; Pro is a flat subscription or lifetime license.
* **Open source under GPLv2** — the full source of the free version is on WordPress.org. The plugin is in production since 2023.

= How much does Pro cost? =

Pro is sold as an annual subscription (or one-time lifetime license) with one site activation per license. A 5-site license is also available. Current pricing is on [bsale.australcode.io](https://bsale.australcode.io).

= Can I place the stock-by-branch widget somewhere else? =

The stock-by-branch widget is a Pro feature. By default it renders under the add-to-cart form, which only exists on the standard product page. For page builders or custom templates, use the shortcode:

`[acbsl_stock_by_office]`

Inside a product template it picks up the current product on its own. Elsewhere, name it explicitly:

`[acbsl_stock_by_office product_id="123"]`

= Can I change the widget from my own code? =

Yes, in Pro, through these filters and actions:

* `acbsl_should_render_stock_widget` (filter) — decide whether the widget renders. Receives the default verdict (the product has a Bsale mapping) and the product ID. Return false to hide it, true to force it.
* `acbsl_stock_by_office` (filter) — the branch rows before they are cached and sent to the browser. Each row is `office_name`, `available`, `in_stock`. Use it to hide branches that are not open to the public, reorder them, or rename them. Note it runs before the 5-minute cache, so a per-visitor callback would leak the first visitor's result to everyone.
* `acbsl_stock_widget_html` (filter) — the widget's final markup. Return an empty string to suppress it.
* `acbsl_before_stock_widget` / `acbsl_after_stock_widget` (actions) — run right before and after the widget is emitted. Both receive the product ID.

= Can I tune the webhook endpoint from my own code? =

Yes, through these filters. The defaults fit Bsale's traffic, so most stores never need them:

* `acbsl_webhook_max_payload_bytes` (filter) — largest request body the endpoint accepts, in bytes. Defaults to 1 MB; larger requests get HTTP 413.
* `acbsl_webhook_rate_limit_per_min` (filter) — requests per minute per IP that have not proven they come from your Bsale account (no matching `cpnId` or token). Defaults to 60. Return 0 to disable the limit.
* `acbsl_webhook_rate_limit_per_min_authenticated` (filter) — the same limit for requests that carry your account's `cpnId` or the webhook token. Defaults to 1200, well above a Bsale burst, because Bsale sends every notification from a few IPs.
* `acbsl_webhook_queue_time_budget` (filter) — seconds each queue run may spend processing webhooks one by one. Defaults to 60, or half of `max_execution_time` if that is lower.

= Can I restyle the widget with CSS? =

Yes (Pro). The widget inherits your theme's colours and fonts, so it usually needs no work. To adjust the "in stock" badge text colour, set this custom property on your theme's stylesheet:

* `--acbsl-badge-green-text` — text colour of the in-stock badge. Defaults to `#146c2e`.

Every other element uses standard classes you can target directly: `.acbsl-stock-by-office` (container), `.acbsl-stock-toggle` (button), `.acbsl-stock-results` (results panel).

== Screenshots ==

1. Plugin dashboard with sync status, stock health, and recent activity.
2. Configuration page with Bsale API connection, default office, and document type preferences.
3. Order metabox with Bsale document status, PDF link, and re-emit controls.
4. Stock audit interface showing discrepancies between WooCommerce and Bsale.
5. Upgrade page showing the Pro features (Bsale &rarr; Mejorar a Pro).

== Changelog ==

= 3.8.6 =

* **Fixed:** two translatable error messages about stock lost their note for translators in the published package, which WordPress.org's Plugin Check reports as an error. No change in how the plugin works.

= 3.8.5 =

* **Fixed:** the boleta or factura of an order that already had a sales note (nota de venta, issued by Pro; this also covers free sites that ran Pro before) failed with "no stock available" when stock was just enough: the check counted the units that the order's own sales note reserves in Bsale against it. Those units now count as available for that order, and orders stuck with this error can be issued again from the order screen with "Emitir Boleta" or "Reintentar".
* **Fixed:** the order's sales note is now voided in Bsale whichever way the boleta goes out, including when it is recovered after a timeout or issued after remapping variants. Before, it could stay active and keep its stock reserved.
* **Changed:** a sales note that was edited in Bsale stops the boleta with a clear message instead of leaving the edited copy active, and a real shortage no longer points to pending transfer guides.

= 3.8.4 =

* **Changed:** the free version no longer ships code from Pro features it cannot use: routing documents to an office by shipping method, the "hide shipping when the office is out of stock" option (it only works with that routing, so it now sits next to it in Pro), stock transfers between offices and the scheduling of Pro tasks. Settings saved while Pro was active are kept for when it comes back.
* **Fixed:** the free version could still issue a sales note or a dispatch guide if a setting saved while Pro was active, or a hand-made request, asked for one. It now issues boletas and facturas only, as documented.
* **Fixed:** the help under Document types said a type also needs an order status to be enabled. A Bsale document type is enough; order statuses only decide automatic emission in Pro.

Older entries ship with the plugin, in `changelog.txt`.

== Upgrade Notice ==

= 3.8.6 =
Fixes two translator notes flagged by Plugin Check. No change in behaviour; includes the 3.8.5 stock fix for orders with a sales note.

= 3.8.5 =
Boletas of orders with a sales note no longer fail with "no stock available" when stock is just enough, and the sales note is always voided once the boleta is issued. Recommended.

= 3.8.4 =
Free version: removes code from Pro-only features and issues boletas and facturas only, as documented. Pro: no change in behaviour. Recommended.

= 3.8.3 =
Pro: scheduled stock audits and SKU linking no longer skip a day when settings are saved or the license changes, and come back if they go missing. Webhooks are no longer delayed after saving settings. Recommended.

= 3.8.2 =
Pro: scheduled stock audits and daily SKU linking now start as soon as the license is activated. Recommended.

= 3.8.1 =
Updates the Freemius SDK to 2.13.4 (licensing). No change in how the plugin works; recommended.

= 3.8.0 =
Important fixes to tax documents (fees, block checkout choice, invoice receiver, stores sharing one Bsale account), stock sync and webhooks. Recommended for all sites. Review Settings after updating.

= 3.7.9 =
Cosmetic and performance fixes: the admin now shows the plugin's current name everywhere, the Pro field-mapping table works on phones, and the storefront stylesheet is 60% smaller. No action needed.

= 3.7.8 =
Fixes the "two copies active" notice added in 3.7.7, which never appeared. If you have two copies, deactivate the spare — do not delete it: deleting removes this store's Bsale data, which both copies share.

= 3.7.7 =
Pro users: fixes the Pro package installing into the wrong folder, which could leave two copies active. If Plugins lists two, deactivate the spare — do not delete it: deleting removes this store's Bsale data, shared by both.

= 3.7.6 =
Fixes a bug where the free version wiped six settings when saving Settings; two of them swapped city and comuna on the document sent to the SII. Recommended for all sites — review your checkout mapping after updating.

= 3.7.5 =
Stops the hourly Action Scheduler warnings in debug.log, puts the licensing screen and its menu entry in Spanish, and polishes the admin UI on phones. Safe update for all sites.

= 3.7.4 =
Fixes a bug where saving settings on the free version could erase Pro configuration stored from a previous license, plus mobile table and Settings styling fixes. Recommended for every site, especially if you ever ran Pro.

= 3.7.3 =
Security hardening: late output escaping in admin UI components and a defensive callback guard. No functional change. Safe update for all sites.

= 3.5.0 =
New: the Traceability screen opens with an at-a-glance stock-health verdict and a 24-hour reliability sparkline. Backward-compatible, no data changes. Safe update for all sites.

= 3.4.4 =
Compatibility fix: resolves a potential PHP 7.4 fatal in webhook handling (str_starts_with is PHP 8.0+). Recommended for any site on PHP 7.4.

= 3.4.3 =
Reliability fix: WP-CLI command registration is now null-safe against an unloaded licensing SDK. No functional changes. Safe update for all sites.

= 3.4.2 =
Spanish (Chile) polish in the Upgrade panel and status labels, mobile-friendly configuration tables, consistent brand color and motion, plus packaging hygiene. Presentation-only, no functional changes. Safe update for all sites.

= 3.4.1 =
Internal cleanup: transactional email styles are now centralized (no functional change; notification emails look the same, with one alert box tweaked to a consistent green). Safe update for all sites.

= 3.4.0 =
Fixes a data-loss edge case: saving Settings on a Free/lapsed license no longer clears saved Pro configuration. Also refreshes the Pro upsell on gated multi-control blocks. Recommended for all sites.

= 3.3.2 =
Visual consistency polish: residual admin styles now match the Admin Kit's neutrals, radii and motion. Presentation-only, no functional changes. Safe update for all sites.

= 3.3.1 =
Minor polish: Settings mapping tables are now mobile-friendly and transactional emails match the Australcode green branding. No functional changes. Safe update for all sites.

= 3.3.0 =
Admin UI refresh: all screens now share one consistent Australcode design system. No functional changes — same data, same actions, cleaner and more coherent look. Recommended for all sites.

= 3.2.0 =
Pro licensing moved to Freemius (Merchant of Record). Your active Pro license stays valid and all Free/Pro features are unchanged — activation, renewals and account management now use the native Freemius experience. No action required for existing customers.

= 3.1.4 =
Reliability release: the Repair-mappings tool preserves 1:N mappings, the Logs screen groups repeated events with a connection shortcut, stock audits resume after interruption, and API pagination gains a runaway safety cap. Recommended for all sites.

= 3.1.3 =
Compliance and admin UI polish: clears the WP 6.7 translation-timing notice and a checkout escaping warning, refreshes the admin design (unified headers, redesigned Stock Traceability) and removes decorative emoji. Recommended for all sites.

= 3.1.2 =
Product audit now badges private-status products in the unmapped list so they no longer read as problems. Presentation-only, audit coverage unchanged. Safe update for all sites.

= 3.1.1 =
Critical follow-up to 3.1.0: product sync no longer creates a spurious mapping to the wrong Bsale variant for simple products mapped to multi-variant items. Recommended for all sites on 3.1.0.

= 3.1.0 =
Critical sync fix: simple products mapped to multi-variant Bsale items no longer get the wrong variant stock or price. Also fixes Block-checkout RUT validation, silent transfer-guide failures, duplicate webhook mappings, and partial credit-note matching.

= 3.0.8 =
WP.org Plugin Check pass: release ZIP now ships clean (dev artifacts excluded), nonce annotations tightened on WooCommerce checkout reads, Upgrade Notices trimmed to fit display limit. No functional change.

= 3.0.7 =
Simplification: the 3.0.6 `sku_locked` flag is removed. WooCommerce SKU is permanently the matching key and is never overwritten by Bsale. Column dropped automatically. SKU-primary lookup and 1:N propagation preserved.

= 3.0.6 =
**Behavior change**: WooCommerce SKUs are no longer overwritten by Bsale during sync. Manual and scheduled product syncs now propagate to ALL WooCommerce products sharing a Bsale variant SKU (1:N), matching stock/price webhook behavior.

= 3.0.5 =
Polish release: dashboard activity table collapses to cards on mobile, completes brand-override cleanup, "Limpiar huérfanos" marked danger-outline, "Última auditoría" stat in monospace, ~40 inline styles extracted. No functional changes.

= 3.0.4 =
Polish release: WP.org Plugin Check now reports 0 errors, regenerated .pot, single primary CTA on Products, brand-colored buttons on Traceability, fixed mobile mid-word truncation, and one Spanish string moved to neutral conjugation. No functional changes, no manual steps.

= 3.0.3 =
Fixes the rebrand migration so a stored Pro license (and traceability history) is reconnected after upgrading; some sites reverted to free in 3.0.0–3.0.2. Idempotent, automatic, no manual steps.

= 3.0.2 =
Ensures the Bsale token and webhook secret are encrypted at rest even on a clean activation (in 3.0.1 this only happened on a version upgrade). Idempotent, no functional changes, no manual steps.

= 3.0.1 =
Security + robustness hardening (anti-SSRF on webhook fetch, encrypted Bsale credentials at rest, validated webhook bootstrap, no duplicate documents on retry, API circuit breaker, webhook de-duplication). No functional changes. Recommended before going live.

= 3.0.0 =
Rebrand to Australcode Bsale. Existing data migrates automatically and in place on upgrade; the Bsale webhook URL is unchanged, so stock sync keeps working. No manual steps required.

= 2.53.0 =

Fixes an emission lock collision so two orders emitting the same document type at the same time no longer block each other. Recommended for high-volume stores.

= 2.52.0 =

Introduces Free / Pro split. Free keeps all essentials; Pro adds auto-emission, multi-office and B2B features. If you used Pro-only features before, activate a license to keep them. Your configuration is preserved.

= 2.51.16 =

This is a stability and traceability improvement release. Recommended for all users.
