Require a complete PCM return address before placing orders.
Empty PCM_RETURN_ADDRESS was sending SITE_NAME as firstName with blank street fields, which PCM rejects with 400; validate early and wire PCM env through compose.
This commit is contained in:
@@ -193,38 +193,82 @@ def pcm_request(
|
||||
|
||||
|
||||
def return_address_from_settings() -> dict[str, str]:
|
||||
"""Build PCM returnAddress from PCM_RETURN_ADDRESS JSON or CONTACT_* vars."""
|
||||
"""Build PCM returnAddress from PCM_RETURN_ADDRESS JSON and/or PCM_RETURN_* vars.
|
||||
|
||||
PCM requires address/city/state (and zip) whenever firstName is set — an empty
|
||||
street with SITE_NAME-derived firstName causes a 400 from POST /order/postcard.
|
||||
"""
|
||||
data: dict[str, Any] = {}
|
||||
raw = (settings.PCM_RETURN_ADDRESS or "").strip()
|
||||
if raw:
|
||||
data = json.loads(raw)
|
||||
if not isinstance(data, dict):
|
||||
try:
|
||||
parsed = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise PcmApiError(
|
||||
"PCM_RETURN_ADDRESS must be valid JSON "
|
||||
'(e.g. {"firstName":"…","lastName":"…","address":"…",'
|
||||
'"city":"…","state":"IL","zipCode":"…"})'
|
||||
) from exc
|
||||
if not isinstance(parsed, dict):
|
||||
raise PcmApiError("PCM_RETURN_ADDRESS must be a JSON object")
|
||||
return {
|
||||
"company": str(data.get("company") or ""),
|
||||
"firstName": str(data.get("firstName") or data.get("first_name") or ""),
|
||||
"lastName": str(data.get("lastName") or data.get("last_name") or ""),
|
||||
"address": str(data.get("address") or data.get("line1") or ""),
|
||||
"address2": str(data.get("address2") or data.get("line2") or ""),
|
||||
"city": str(data.get("city") or ""),
|
||||
"state": str(data.get("state") or ""),
|
||||
"zipCode": str(data.get("zipCode") or data.get("zip") or ""),
|
||||
}
|
||||
data = parsed
|
||||
|
||||
name = (settings.SITE_NAME or "").strip()
|
||||
parts = name.split(None, 1)
|
||||
first = parts[0] if parts else "Monica"
|
||||
last = parts[1] if len(parts) > 1 else ""
|
||||
return {
|
||||
"company": "",
|
||||
"firstName": first,
|
||||
"lastName": last,
|
||||
"address": str(getattr(settings, "PCM_RETURN_LINE1", "") or ""),
|
||||
"address2": str(getattr(settings, "PCM_RETURN_LINE2", "") or ""),
|
||||
"city": str(getattr(settings, "PCM_RETURN_CITY", "") or ""),
|
||||
"state": str(getattr(settings, "PCM_RETURN_STATE", "") or ""),
|
||||
"zipCode": str(getattr(settings, "PCM_RETURN_ZIP", "") or ""),
|
||||
site_first = parts[0] if parts else ""
|
||||
site_last = parts[1] if len(parts) > 1 else ""
|
||||
|
||||
address = {
|
||||
"company": str(data.get("company") or "").strip(),
|
||||
"firstName": str(
|
||||
data.get("firstName") or data.get("first_name") or site_first or ""
|
||||
).strip(),
|
||||
"lastName": str(
|
||||
data.get("lastName") or data.get("last_name") or site_last or ""
|
||||
).strip(),
|
||||
"address": str(
|
||||
data.get("address")
|
||||
or data.get("line1")
|
||||
or getattr(settings, "PCM_RETURN_LINE1", "")
|
||||
or ""
|
||||
).strip(),
|
||||
# PCM treats blank address2 oddly; space matches recipient payload.
|
||||
"address2": str(
|
||||
data.get("address2")
|
||||
or data.get("line2")
|
||||
or getattr(settings, "PCM_RETURN_LINE2", "")
|
||||
or ""
|
||||
).strip()
|
||||
or " ",
|
||||
"city": str(
|
||||
data.get("city") or getattr(settings, "PCM_RETURN_CITY", "") or ""
|
||||
).strip(),
|
||||
"state": str(
|
||||
data.get("state") or getattr(settings, "PCM_RETURN_STATE", "") or ""
|
||||
).strip(),
|
||||
"zipCode": str(
|
||||
data.get("zipCode")
|
||||
or data.get("zip")
|
||||
or getattr(settings, "PCM_RETURN_ZIP", "")
|
||||
or ""
|
||||
).strip(),
|
||||
}
|
||||
|
||||
missing = [
|
||||
field
|
||||
for field in ("firstName", "address", "city", "state", "zipCode")
|
||||
if not address.get(field, "").strip()
|
||||
]
|
||||
if missing:
|
||||
raise PcmApiError(
|
||||
"PCM return address incomplete (missing "
|
||||
+ ", ".join(missing)
|
||||
+ "). Set PCM_RETURN_ADDRESS JSON with firstName, lastName, "
|
||||
"address, city, state, zipCode "
|
||||
"(or PCM_RETURN_LINE1 / CITY / STATE / ZIP)."
|
||||
)
|
||||
return address
|
||||
|
||||
|
||||
def contact_to_pcm_recipient(contact, *, ext_ref: str) -> dict[str, str]:
|
||||
address = contact.postal_address or {}
|
||||
|
||||
Reference in New Issue
Block a user