[FIX] website_sale_aplicoop: split cart and cycle stamp in localStorage
965c5c2stored the cart as {cutoff_date, items: {...}} in eskaera_<id>_cart. That broke every other reader of the same key: - checkout_labels.js iterates Object.keys() expecting product IDs and rendered "cutoff_date" / "items" as ghost rows → users on the checkout page saw their cart as empty. - home_delivery.js read/wrote the cart in place; the in-place mutation destroyed the wrapper. - _saveOrderDraft serialised the same object straight to the server, POSTing "cutoff_date" and "items" as productIds. Split the schema: eskaera_<id>_cart keeps the plain {productId: {...}} shape every other JS file already relies on; the cycle marker moves to eskaera_<id>_cart_cycle. _loadCart migrates browsers still holding the v18.0.1.10.0 wrapped value on the next read. Also make eviction strictly opt-in: drop the cart only when we know the current cycle AND the stored cycle disagrees. Missing data on either side (check-status didn't run, XHR failed) → preserve. This restores the checkout page where check-status isn't called. Version bump triggers the in-tab auto-reload added in6e6d1e5for clients already on that build. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
6e6d1e5256
commit
9484f8c349
2 changed files with 46 additions and 22 deletions
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
{ # noqa: B018
|
{ # noqa: B018
|
||||||
"name": "Website Sale - Aplicoop",
|
"name": "Website Sale - Aplicoop",
|
||||||
"version": "18.0.1.10.1",
|
"version": "18.0.1.10.2",
|
||||||
"category": "Website/Sale",
|
"category": "Website/Sale",
|
||||||
"summary": "Modern replacement of legacy Aplicoop - Collaborative consumption group orders",
|
"summary": "Modern replacement of legacy Aplicoop - Collaborative consumption group orders",
|
||||||
"author": "Odoo Community Association (OCA), Criptomart",
|
"author": "Odoo Community Association (OCA), Criptomart",
|
||||||
|
|
|
||||||
|
|
@ -442,7 +442,18 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadCart: function () {
|
_loadCart: function () {
|
||||||
|
// Storage layout:
|
||||||
|
// eskaera_<id>_cart → items as plain {productId: {...}}
|
||||||
|
// (keeps the contract used by
|
||||||
|
// checkout_labels.js, home_delivery.js
|
||||||
|
// and _saveOrderDraft).
|
||||||
|
// eskaera_<id>_cart_cycle → "YYYY-MM-DD" the cart was saved at.
|
||||||
|
// Eviction only fires when we KNOW the current cycle and it
|
||||||
|
// disagrees with the stored one. If either side is missing
|
||||||
|
// (e.g. checkout page that doesn't call check-status, or XHR
|
||||||
|
// failure), we preserve the user's cart.
|
||||||
var cartKey = "eskaera_" + this.orderId + "_cart";
|
var cartKey = "eskaera_" + this.orderId + "_cart";
|
||||||
|
var cycleKey = "eskaera_" + this.orderId + "_cart_cycle";
|
||||||
var raw = localStorage.getItem(cartKey);
|
var raw = localStorage.getItem(cartKey);
|
||||||
this.cart = {};
|
this.cart = {};
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
|
|
@ -455,27 +466,32 @@
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Cart load: invalid JSON in localStorage, dropping", e);
|
console.warn("Cart load: invalid JSON in localStorage, dropping", e);
|
||||||
localStorage.removeItem(cartKey);
|
localStorage.removeItem(cartKey);
|
||||||
|
localStorage.removeItem(cycleKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Legacy / corrupt shape (raw items object without cycle stamp) → drop.
|
if (!parsed || typeof parsed !== "object") {
|
||||||
if (
|
|
||||||
!parsed ||
|
|
||||||
typeof parsed !== "object" ||
|
|
||||||
!parsed.items ||
|
|
||||||
!("cutoff_date" in parsed)
|
|
||||||
) {
|
|
||||||
console.log(
|
|
||||||
"Cart load: legacy/unstamped value, dropping localStorage[" + cartKey + "]"
|
|
||||||
);
|
|
||||||
localStorage.removeItem(cartKey);
|
localStorage.removeItem(cartKey);
|
||||||
|
localStorage.removeItem(cycleKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Cycle mismatch (or no current cycle known) → drop. This is the
|
// Migration: v18.0.1.10.0 wrapped the cart as {cutoff_date, items}
|
||||||
// primary defence against stale carts surviving cycle rollover.
|
// in the same key, which broke checkout_labels.js / home_delivery.js
|
||||||
if (!this._currentCutoffDate || parsed.cutoff_date !== this._currentCutoffDate) {
|
// / _saveOrderDraft (they iterated Object.keys treating them as
|
||||||
|
// productIds). Unwrap once; subsequent saves use the canonical
|
||||||
|
// split-key layout below.
|
||||||
|
var items;
|
||||||
|
var storedCycle;
|
||||||
|
if (parsed.items && "cutoff_date" in parsed) {
|
||||||
|
items = parsed.items;
|
||||||
|
storedCycle = parsed.cutoff_date;
|
||||||
|
} else {
|
||||||
|
items = parsed;
|
||||||
|
storedCycle = localStorage.getItem(cycleKey);
|
||||||
|
}
|
||||||
|
if (this._currentCutoffDate && storedCycle && storedCycle !== this._currentCutoffDate) {
|
||||||
console.log(
|
console.log(
|
||||||
"Cart load: cycle mismatch (stored=" +
|
"Cart load: cycle mismatch (stored=" +
|
||||||
parsed.cutoff_date +
|
storedCycle +
|
||||||
", current=" +
|
", current=" +
|
||||||
this._currentCutoffDate +
|
this._currentCutoffDate +
|
||||||
"), dropping localStorage[" +
|
"), dropping localStorage[" +
|
||||||
|
|
@ -483,14 +499,20 @@
|
||||||
"]"
|
"]"
|
||||||
);
|
);
|
||||||
localStorage.removeItem(cartKey);
|
localStorage.removeItem(cartKey);
|
||||||
|
localStorage.removeItem(cycleKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.cart = parsed.items;
|
this.cart = items;
|
||||||
|
// Re-canonicalize storage so other readers see the plain shape.
|
||||||
|
localStorage.setItem(cartKey, JSON.stringify(items));
|
||||||
|
if (storedCycle) {
|
||||||
|
localStorage.setItem(cycleKey, storedCycle);
|
||||||
|
}
|
||||||
console.log(
|
console.log(
|
||||||
"Cart loaded from localStorage[" +
|
"Cart loaded from localStorage[" +
|
||||||
cartKey +
|
cartKey +
|
||||||
"] (cycle " +
|
"] (cycle " +
|
||||||
parsed.cutoff_date +
|
(storedCycle || "unknown") +
|
||||||
"):",
|
"):",
|
||||||
this.cart
|
this.cart
|
||||||
);
|
);
|
||||||
|
|
@ -498,11 +520,11 @@
|
||||||
|
|
||||||
_saveCart: function () {
|
_saveCart: function () {
|
||||||
var cartKey = "eskaera_" + this.orderId + "_cart";
|
var cartKey = "eskaera_" + this.orderId + "_cart";
|
||||||
var payload = JSON.stringify({
|
var cycleKey = "eskaera_" + this.orderId + "_cart_cycle";
|
||||||
cutoff_date: this._currentCutoffDate || null,
|
localStorage.setItem(cartKey, JSON.stringify(this.cart));
|
||||||
items: this.cart,
|
if (this._currentCutoffDate) {
|
||||||
});
|
localStorage.setItem(cycleKey, this._currentCutoffDate);
|
||||||
localStorage.setItem(cartKey, payload);
|
}
|
||||||
console.log(
|
console.log(
|
||||||
"Cart saved to localStorage[" +
|
"Cart saved to localStorage[" +
|
||||||
cartKey +
|
cartKey +
|
||||||
|
|
@ -515,7 +537,9 @@
|
||||||
|
|
||||||
_clearCurrentOrderCartSilently: function () {
|
_clearCurrentOrderCartSilently: function () {
|
||||||
var cartKey = "eskaera_" + this.orderId + "_cart";
|
var cartKey = "eskaera_" + this.orderId + "_cart";
|
||||||
|
var cycleKey = "eskaera_" + this.orderId + "_cart_cycle";
|
||||||
localStorage.removeItem(cartKey);
|
localStorage.removeItem(cartKey);
|
||||||
|
localStorage.removeItem(cycleKey);
|
||||||
this.cart = {};
|
this.cart = {};
|
||||||
console.log("[groupOrderShop] Cart cleared silently for order:", this.orderId);
|
console.log("[groupOrderShop] Cart cleared silently for order:", this.orderId);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue