Template
Add shopper accounts, reviews, tracking, and seed_demo (#10)
## Summary - Closes #9. Port shop-gated buyer accounts (register/login/profile, password reset, order history), purchase-gated reviews, and Stripe customer ids. Cards stay on Stripe. - Slim public contact form to email + interest + message. Shipping tracking status, scan events, paste-in numbers, and EasyPost webhook when FEATURE_SHIPPING is on. - Add template-neutral `seed_demo` (generic SKUs, demo shoppers, guest orders, tracking stubs). Prod refused. `--reset` deletes tagged demo rows after invoices. ## Test plan - [ ] `cd site && uv run python manage.py test` (173 tests passed locally) - [ ] Shop on: `/account/register`, login, profile, password reset, claim guest orders by email - [ ] Shop off: `/account/` URLs absent; Sign in / Account links hidden - [ ] Checkout as logged-in buyer stores `Order.user` and Stripe customer id; product review only after paid purchase - [ ] Shipping on: portal paste-in tracking + EasyPost webhook updates status; shipping off: orders still work without tracking UI - [ ] `seed_demo` refused in prod; `--reset` rebuilds tagged catalog/shoppers without deleting staff invoices Reviewed-on: #10
This commit was merged in pull request #10.
This commit is contained in:
1 parent
9cdce7a897
commit
f3e34f5099
66 files changed
+3051
-285
No files matched your search
@@ -26,8 +26,6 @@ def notify_admins_of_contact_form(lead: Lead) -> bool:
|
||||
return False
|
||||
|
||||
contact = lead.contact
|
||||
name = contact.full_name or "(no name)"
|
||||
phone = contact.phone or "(none)"
|
||||
email = contact.email or "(none)"
|
||||
message = (lead.message or "").strip() or "(no message)"
|
||||
|
||||
@@ -35,27 +33,8 @@ def notify_admins_of_contact_form(lead: Lead) -> bool:
|
||||
portal_path = reverse("leads:detail", kwargs={"pk": lead.pk})
|
||||
portal_url = f"{site}{portal_path}" if site else portal_path
|
||||
|
||||
postal = contact.postal_address or {}
|
||||
address_bits = [
|
||||
postal.get("line1") or "",
|
||||
postal.get("line2") or "",
|
||||
", ".join(
|
||||
part
|
||||
for part in [
|
||||
postal.get("city") or "",
|
||||
postal.get("state") or "",
|
||||
postal.get("zip") or "",
|
||||
]
|
||||
if part
|
||||
),
|
||||
]
|
||||
address = "\n".join(bit for bit in address_bits if bit) or "(none)"
|
||||
|
||||
ctx = email_brand_context(
|
||||
name=name,
|
||||
email=email,
|
||||
phone=phone,
|
||||
address=address,
|
||||
message=message,
|
||||
portal_url=portal_url,
|
||||
)
|
||||
@@ -63,7 +42,7 @@ def notify_admins_of_contact_form(lead: Lead) -> bool:
|
||||
html_content = get_template("emails/contact_email.html").render(ctx)
|
||||
|
||||
mail = EmailMultiAlternatives(
|
||||
subject=f"New contact form inquiry from {name}",
|
||||
subject=f"New contact form inquiry from {email}",
|
||||
body=text_content,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
to=[to_email],
|
||||
|
||||
Reference in new issue
Block a user