4.2 KiB
4.2 KiB
Fusion WooCommerce — Odoo Module
What This Is
Bidirectional Odoo 19 ↔ WooCommerce sync module. The "brain" — all sync logic, product mapping, scheduling, conflict resolution, and dashboards live here. Pairs with the fusion-woodoo WordPress plugin (thin display layer).
Architecture
- Odoo calls WC via REST API v3 (consumer key/secret auth)
- WC calls Odoo via webhooks (HMAC signature auth) and the WP plugin calls custom endpoints (bearer token auth)
- Hybrid sync: real-time webhooks + scheduled cron fallback + manual "Sync Now"
Critical Odoo 19 Rules
- Views:
<list>NOT<tree>.view_modeuseslist,formNOTtree,form. - Search views: NO
<group expand="...">wrapper — use bare<filter>with<separator/>. - No
attrs: Use inlineinvisible="..."/readonly="..."/required="..."directly. - No
states: Useinvisible="state != 'draft'"instead. - HTTP routes:
type="jsonrpc"for internal.type="http"withcsrf=Falsefor WC webhooks (WC sends raw JSON, not JSON-RPC). - OWL: standalone
rpc()from@web/core/network/rpc.static props = []. No globals likeNumber()in templates — use component methods. - res.groups: NO
category_idfield. - API client in
lib/NOTmodels/— plain Python class, not an Odoo model.
Key Files
lib/woo_api_client.py — WC REST API wrapper (NOT an Odoo model)
models/woo_instance.py — Core: connection config, sync methods, cron entry points
models/woo_product_map.py — Product mapping + price sync methods
models/woo_order.py — Order tracking + status push methods
controllers/webhook.py — Receives WC webhooks (type="http", HMAC auth)
controllers/api.py — REST endpoints for WP plugin (type="jsonrpc", bearer auth)
controllers/product_search.py — AJAX search for OWL mapping UI
static/src/js/product_mapping.js — OWL product mapping client action
static/src/js/dashboard.js — OWL dashboard client action
static/src/js/theme_detect.js — Reads color_scheme cookie, sets data-woo-theme on <html>
static/src/css/woo_styles.css — Theme-aware CSS using var(--woo-*) custom properties
Dark Mode
- Odoo 19 stores dark mode in
color_schemecookie ("dark" or "bright") theme_detect.jsreads the cookie and setsdata-woo-theme="dark"on<html>- All CSS uses
var(--woo-*)custom properties with dark overrides underhtml[data-woo-theme="dark"] - NEVER use hardcoded colours in templates — use
woo-badge-*,woo-text-muted,woo-codeclasses - NEVER use Bootstrap colour classes (
bg-primary,text-dark, etc.) in OWL templates
WC Pricing Model
- WooCommerce has two prices:
regular_price(standard) andsale_price - Stored as
woo_regular_priceandwoo_sale_priceonwoo.product.map - Sync logic: if standard price is zero → sync sets regular_price. If standard exists → sync sets sale_price
- Standard price can never be less than sale price — validation enforced
Deployment
# Deploy to westin
ssh odoo-westin "rm -rf /opt/odoo/custom-addons/fusion_woocommerce"
scp -r fusion-woo-odoo/fusion_woocommerce odoo-westin:/opt/odoo/custom-addons/fusion_woocommerce
ssh odoo-westin "docker exec odoo-dev-app odoo -d westin-v19 -u fusion_woocommerce --stop-after-init --no-http"
# IMPORTANT: Clear asset cache after JS/CSS changes
ssh odoo-westin "docker exec odoo-dev-db psql -U odoo -d westin-v19 -c \"DELETE FROM ir_attachment WHERE name LIKE '%assets_backend%' OR url LIKE '%/web/assets%';\""
ssh odoo-westin "docker restart odoo-dev-app"
Gotchas
- Health check cron only logs — never changes instance state (Docker can't reach external URLs)
- Product map state stays
mappedeven on sync errors/conflicts — conflicts tracked separately inwoo.conflict - Search endpoints return
{"results": [...], "total": count}for pagination - Existing products are skipped during fetch (dedup by
woo_product_id+instance_id) - After adding new DB fields, must run
-u fusion_woocommercebefore backfilling data
Spec & Plan
- Design spec:
docs/superpowers/specs/2026-03-31-fusion-woo-odoo-design.md - Implementation plan:
docs/superpowers/plans/2026-03-31-fusion-woo-odoo-plan.md