generated from westfarn/web_django_template
## Summary - Slim the public contact form to email, interest, and message. Name, phone, and address live on the customer profile instead. - Customers can register, sign in, save shipping details, and view order history. Logged-in checkout creates a Stripe Customer and saves cards on Stripe (`setup_future_usage`); we only store `stripe_customer_id`. - Shipment tracking: EasyPost tracker lookup + webhook, plus paste-in numbers from Pirate Ship/Shippo. Customers see carrier status on their orders; `dispatch_due` refreshes open shipments. - Product reviews (1–5) only after a paid/fulfilled purchase of that product. Fixes #7 ## Test plan - [ ] Contact form submits with only email + message; extra name/phone/address fields are ignored - [ ] Register, sign in, save profile (name/phone/shipping) - [ ] Guest checkout still works; after signup, prior orders with that email show in history - [ ] Logged-in checkout prefills shipping and does not collect card data locally - [ ] Portal: buy label or paste a Pirate Ship tracking number, confirm status/events; customer order page shows tracking - [ ] Product page: non-buyers cannot review; buyers can leave one 1–5 star review - [ ] Non-staff users hitting `/portal/` redirect to `/account/` Reviewed-on: #8
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Outbound notifications for public-site events."""
|
|
|
|
import logging
|
|
|
|
from django.conf import settings
|
|
from django.core.mail import EmailMultiAlternatives
|
|
from django.template.loader import get_template
|
|
from django.urls import reverse
|
|
|
|
from leads.models import Lead
|
|
from public.email_branding import email_brand_context
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def notify_admins_of_contact_form(lead: Lead) -> bool:
|
|
"""
|
|
Email CONTACT_EMAIL when someone submits the public contact form.
|
|
|
|
Returns True if a message was sent. Failures are logged; callers should
|
|
not block the visitor success path on delivery errors.
|
|
"""
|
|
to_email = (settings.CONTACT_EMAIL or "").strip()
|
|
if not to_email:
|
|
logger.warning("CONTACT_EMAIL unset; skipping contact-form notification")
|
|
return False
|
|
|
|
contact = lead.contact
|
|
email = contact.email or "(none)"
|
|
message = (lead.message or "").strip() or "(no message)"
|
|
|
|
site = (settings.PUBLIC_SITE_URL or "").rstrip("/")
|
|
portal_path = reverse("leads:detail", kwargs={"pk": lead.pk})
|
|
portal_url = f"{site}{portal_path}" if site else portal_path
|
|
|
|
ctx = email_brand_context(
|
|
email=email,
|
|
message=message,
|
|
portal_url=portal_url,
|
|
)
|
|
text_content = get_template("emails/contact_email.txt").render(ctx)
|
|
html_content = get_template("emails/contact_email.html").render(ctx)
|
|
|
|
mail = EmailMultiAlternatives(
|
|
subject=f"New contact form inquiry from {email}",
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[to_email],
|
|
reply_to=[contact.email] if contact.email else None,
|
|
)
|
|
mail.attach_alternative(html_content, "text/html")
|
|
try:
|
|
mail.send(fail_silently=False)
|
|
except Exception:
|
|
logger.exception("Failed to send contact-form notification to %s", to_email)
|
|
return False
|
|
return True
|