Two fixes bundled together:
1. Shrink CATEGORY_PAGE_SIZE from 100 to 25. Each item in a category page
can trigger several sequential BC calls (location stock, price lists,
brand/category lookup) beyond the page fetch itself - at 100 items/page
this measured 150-250+ seconds on live data, exceeding PHP's execution
limit and leaving the Action Scheduler action stuck "in-progress"
forever instead of completing or failing visibly.
2. BC's Item Category table has no parent-category field - confirmed via
the actual published CategProd endpoint (Code, Description only) and
the standard itemCategories entity (id, code, displayName only). The
original ItemCategoryHierarchy AL snippet assumed a Parent Category
field that doesn't exist. Switched to the standard /itemCategories API
for the brand display name (no custom endpoint needed for that part),
and replaced the BC-side parent-category walk with a WordPress-side
manual map (wbc_category_parent_map: "CODE=Parent Name" per line) for
the WooCommerce product category grouping, since BC has nothing to
offer there.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
When wbc_category_filter is set, sync now pages through BC's /items
endpoint filtered server-side by itemCategoryCode (or-chained eq - BC's
classic OData rejects the `in` operator) and matches each returned item to
a WooCommerce product locally via wc_get_product_id_by_sku(), instead of
querying BC once per WooCommerce product only to discard most of them.
Confirmed against live data that BC's `in` filter isn't supported here but
chained `eq ... or ...` is.
Also reorders find_bc_item_by_sku() to try GTIN/number before Item
Reference (ReferenciasArticulo). Empirically, on this catalog Reference_No
is always identical to Item_No, so the reference lookup never matched
anything the GTIN/number checks didn't already find - it was costing an
extra BC round trip on every single product for no benefit. Kept as a
last-resort fallback both directions (SKU->item and item->SKU) in case
that doesn't hold for some future item.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
as_enqueue_async_action() spreads the args array into separate positional
parameters on the hooked callback, it does not pass one combined array.
process_batch() was registered with accepted_args=1 and tried to read
$args['run_id']/$args['product_ids'] off what was actually just the run_id
string - the run_id comparison then always failed and every batch returned
immediately without doing any work, while Action Scheduler still marked
each action complete (no exception was thrown). Found by tracing why 896
queued batches all reported "complete" within seconds with zero products
actually synced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Manual and scheduled sync previously processed every WooCommerce product
inline in a single PHP request/AJAX call, with several sequential BC API
calls per product. At real catalog sizes this exceeds PHP's
max_execution_time and the proxy's read timeout, surfacing as a 502 Bad
Gateway on "Sync Now".
Adds WBC_Batch_Sync, which queues the catalog in chunks of 25 via Action
Scheduler (bundled with WooCommerce) and processes them asynchronously.
The manual sync AJAX call now returns immediately after queuing, and the
admin UI polls for progress instead of waiting on one long request.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>