fix: pricing_mode never saved — handler gated on absent "submit" param
Root cause found via prod debug log: the product edit form's onsubmit="submit.disabled = true" handler disables the submit button before the browser collects form data, so the "submit" key is never sent in the POST. The pricing_mode / allow_offers / auction-config block was gated on `if "submit" in request.params:` — always False — so it never ran. Hence no flash, no save. The standard handlers (title, description, price, visibility) don't have this gate; they check whether the field's value changed. The pricing_mode block now follows the same pattern: gated on `if "pricing_mode" in request.params:` (that radio only appears on the product-title-and-description edit form, so other forms on the page — uploads, inventory, bundle — don't trigger it). - pricing_mode: read request.params["pricing_mode"], apply if valid and changed; immediate flush; flash; auto-create draft auction when switching into auction mode - allow_offers: only processed when "allow_offers" in request.params (so a different form submitting won't reset the override) - auction config block: unchanged, still inside the pricing_mode gate - torrent_opt_in: also re-gated on "pricing_mode" in params instead of "submit" (was equally broken, just masked by the torrent kill switch) Removed all the temporary debug logging (ENTER line, /opt and /tmp file writes, journalctl warning). Tests pass (15 in pricing_mode + auction-config slices).
This commit is contained in:
parent
938fda3e4a
commit
ee4bd862ce
1 changed files with 25 additions and 85 deletions
|
|
@ -255,30 +255,6 @@ def product_edit(request):
|
||||||
product_modified = False
|
product_modified = False
|
||||||
product = request.product
|
product = request.product
|
||||||
|
|
||||||
# TEMPORARY DEBUG: log every product_edit hit so we can confirm the
|
|
||||||
# view is even being reached when fox attempts to save pricing_mode.
|
|
||||||
import os as _os_dbg
|
|
||||||
import time as _time_dbg
|
|
||||||
for _path_dbg in (
|
|
||||||
"/opt/make_post_sell/pricing-debug.log",
|
|
||||||
"/tmp/mps-pricing-debug.log",
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
with open(_path_dbg, "a") as _f_dbg:
|
|
||||||
_f_dbg.write(
|
|
||||||
f"{_time_dbg.time():.3f} pid={_os_dbg.getpid()} ENTER product_edit "
|
|
||||||
f"product={product.uuid_str} method={request.method} "
|
|
||||||
f"submit={'submit' in request.params} "
|
|
||||||
f"pricing_mode={request.params.get('pricing_mode')!r}\n"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
_os_dbg.chmod(_path_dbg, 0o644)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
break
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
title = request.params.get("title", product.title).strip()
|
title = request.params.get("title", product.title).strip()
|
||||||
description = request.params.get("description", product.description).strip()
|
description = request.params.get("description", product.description).strip()
|
||||||
price = request.params.get("price", product.price)
|
price = request.params.get("price", product.price)
|
||||||
|
|
@ -336,63 +312,20 @@ def product_edit(request):
|
||||||
request.session.flash(("You updated the product's price.", "success"))
|
request.session.flash(("You updated the product's price.", "success"))
|
||||||
|
|
||||||
# MPS-20 + MPS-21: pricing_mode + allow_offers (per-product overrides).
|
# MPS-20 + MPS-21: pricing_mode + allow_offers (per-product overrides).
|
||||||
if "submit" in request.params:
|
# Gated on the pricing_mode field being present — it only appears on
|
||||||
# TEMPORARY DEBUG: log raw POST params for pricing_mode investigation.
|
# the product-title-and-description edit form, so other forms on the
|
||||||
# Writes to /tmp/mps-pricing-debug.log so we can read without sudo.
|
# page (uploads, inventory, bundle) won't trigger this block.
|
||||||
# Remove once the save defect is diagnosed.
|
# NOTE: do NOT gate on "submit" in request.params — the edit form's
|
||||||
|
# onsubmit handler disables the submit button before the browser
|
||||||
|
# collects form data, so "submit" is never sent.
|
||||||
|
if "pricing_mode" in request.params:
|
||||||
try:
|
try:
|
||||||
import logging as _logging
|
new_mode = int(request.params["pricing_mode"])
|
||||||
_logging.getLogger(__name__).warning(
|
|
||||||
"PRICING_MODE_DEBUG product=%s current=%s pricing_mode_param=%r "
|
|
||||||
"all_pricing_mode=%r submit=%r",
|
|
||||||
product.uuid_str,
|
|
||||||
product.pricing_mode,
|
|
||||||
request.params.get("pricing_mode"),
|
|
||||||
request.params.getall("pricing_mode")
|
|
||||||
if hasattr(request.params, "getall") else "no-getall",
|
|
||||||
request.params.get("submit"),
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
# Write to a path under /opt/make_post_sell where uwsgi has
|
|
||||||
# write access; /tmp may be sandboxed under PrivateTmp on some
|
|
||||||
# systemd configurations. World-readable so fox can tail without sudo.
|
|
||||||
import os as _os
|
|
||||||
import time as _time
|
|
||||||
for _path in (
|
|
||||||
"/opt/make_post_sell/pricing-debug.log",
|
|
||||||
"/tmp/mps-pricing-debug.log",
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
with open(_path, "a") as _f:
|
|
||||||
_f.write(
|
|
||||||
f"{_time.time():.3f} pid={_os.getpid()} "
|
|
||||||
f"product={product.uuid_str} "
|
|
||||||
f"current={product.pricing_mode} "
|
|
||||||
f"pricing_mode={request.params.get('pricing_mode')!r} "
|
|
||||||
f"all_modes={list(request.params.getall('pricing_mode')) if hasattr(request.params, 'getall') else 'no-getall'} "
|
|
||||||
f"submit={request.params.get('submit')!r} "
|
|
||||||
f"all_keys={sorted(request.params.keys())}\n"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
_os.chmod(_path, 0o644)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
break
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
new_mode = int(request.params.get("pricing_mode", product.pricing_mode))
|
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
new_mode = product.pricing_mode
|
new_mode = product.pricing_mode
|
||||||
if new_mode in (0, 1, 2, 3, 4) and new_mode != product.pricing_mode:
|
if new_mode in (0, 1, 2, 3, 4) and new_mode != product.pricing_mode:
|
||||||
product_modified = True
|
product_modified = True
|
||||||
product.pricing_mode = new_mode
|
product.pricing_mode = new_mode
|
||||||
# Flush immediately so the change persists even if a later
|
|
||||||
# block in this view raises. Defense in depth — the trailing
|
|
||||||
# dbsession.add(product) at function end also flushes, but we
|
|
||||||
# want to commit the pricing_mode change as soon as it is
|
|
||||||
# validated.
|
|
||||||
request.dbsession.add(product)
|
request.dbsession.add(product)
|
||||||
request.dbsession.flush()
|
request.dbsession.flush()
|
||||||
mode_label = {
|
mode_label = {
|
||||||
|
|
@ -423,14 +356,15 @@ def product_edit(request):
|
||||||
"success",
|
"success",
|
||||||
))
|
))
|
||||||
|
|
||||||
# allow_offers — three-state radio: inherit / yes / no.
|
# allow_offers — three-state radio: inherit / yes / no. Only
|
||||||
allow_raw = request.params.get("allow_offers", "inherit")
|
# process when the radio is actually present in the form.
|
||||||
new_allow = {
|
if "allow_offers" in request.params:
|
||||||
"inherit": None, "yes": True, "no": False,
|
new_allow = {
|
||||||
}.get(allow_raw, None)
|
"inherit": None, "yes": True, "no": False,
|
||||||
if new_allow != product.allow_offers:
|
}.get(request.params["allow_offers"], None)
|
||||||
product_modified = True
|
if new_allow != product.allow_offers:
|
||||||
product.allow_offers = new_allow
|
product_modified = True
|
||||||
|
product.allow_offers = new_allow
|
||||||
|
|
||||||
# MPS-20: auction config — only meaningful when product has an
|
# MPS-20: auction config — only meaningful when product has an
|
||||||
# auction and the auction is still in DRAFT (locked once SCHEDULED).
|
# auction and the auction is still in DRAFT (locked once SCHEDULED).
|
||||||
|
|
@ -546,8 +480,14 @@ def product_edit(request):
|
||||||
request.dbsession.add(auction)
|
request.dbsession.add(auction)
|
||||||
|
|
||||||
# torrent_opt_in — explicit per-product seeding consent.
|
# torrent_opt_in — explicit per-product seeding consent.
|
||||||
# MPS-22: gated by global torrent kill switch.
|
# MPS-22: gated by global torrent kill switch. Gated on pricing_mode
|
||||||
if request.torrent_enabled and product.shop.torrent_enabled and "submit" in request.params:
|
# being present (signals the product-edit form, not uploads/inventory)
|
||||||
|
# rather than "submit" — see the pricing_mode block note above.
|
||||||
|
if (
|
||||||
|
request.torrent_enabled
|
||||||
|
and product.shop.torrent_enabled
|
||||||
|
and "pricing_mode" in request.params
|
||||||
|
):
|
||||||
new_opt_in = request.params.get("torrent_opt_in", "off") == "on"
|
new_opt_in = request.params.get("torrent_opt_in", "off") == "on"
|
||||||
if new_opt_in != product.torrent_opt_in:
|
if new_opt_in != product.torrent_opt_in:
|
||||||
product_modified = True
|
product_modified = True
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue