Improve outreach compose, contact merge, and email assets.
Deploy Beta / unit-tests (push) Successful in 10s
Deploy Beta / docker (push) Successful in 14s
Deploy Beta / deploy-beta (push) Successful in 1m40s

Add a Quill email editor with DB-backed image storage, selectable PCM designs, postcard defaults for addressed contacts, and merge-by-phone/address on the contact form.
This commit is contained in:
2026-08-09 10:42:22 -05:00
parent d3db6eed76
commit b3a6ee0cd0
19 changed files with 1158 additions and 129 deletions
+26 -11
View File
@@ -8,6 +8,7 @@ from django.views.decorators.http import require_GET, require_http_methods
from analytics.services import attribute_lead_from_request
from contacts.models import Channel, ConsentRecord, Contact
from contacts.services import upsert_contact
from leads.models import Lead
from messaging.services import (
channel_preferences,
@@ -91,12 +92,6 @@ def contact(request):
form = ContactForm(request.POST)
if form.is_valid():
data = form.cleaned_data
defaults = {
"first_name": data["first_name"],
"last_name": data.get("last_name") or "",
"phone": data.get("phone") or "",
"source": Contact.Source.CONTACT_FORM,
}
postal = Contact.make_postal_address(
line1=data.get("address_line1") or "",
line2=data.get("address_line2") or "",
@@ -104,11 +99,16 @@ def contact(request):
state=data.get("address_state") or "",
zip_code=data.get("address_zip") or "",
)
if Contact.postal_address_has_content(postal):
defaults["postal_address"] = postal
contact_obj, _ = Contact.objects.update_or_create(
email=data["email"].lower(),
defaults=defaults,
submitted_email = data["email"].lower()
contact_obj, _created, match_reason = upsert_contact(
email=submitted_email,
first_name=data["first_name"],
last_name=data.get("last_name") or "",
phone=data.get("phone") or "",
postal_address=postal
if Contact.postal_address_has_content(postal)
else None,
source=Contact.Source.CONTACT_FORM,
)
ConsentRecord.objects.update_or_create(
contact=contact_obj,
@@ -121,11 +121,26 @@ def contact(request):
channel=Channel.SMS,
defaults={"opted_in": True, "reason": "contact_form"},
)
if Contact.postal_address_has_content(postal):
ConsentRecord.objects.get_or_create(
contact=contact_obj,
channel=Channel.POSTCARD,
defaults={"opted_in": True, "reason": "contact_form"},
)
interest = data.get("interest") or ""
interest_label = dict(ContactForm.INTEREST_CHOICES).get(interest, interest)
body = data.get("message") or ""
if interest_label:
body = f"Interest: {interest_label}\n\n{body}".strip()
if (
match_reason in {"phone", "address"}
and (contact_obj.email or "").lower() != submitted_email
):
body = (
f"Submitted email: {submitted_email} "
f"(merged by {match_reason} with "
f"{contact_obj.email or 'existing contact'})\n\n{body}"
).strip()
lead = Lead.objects.create(
contact=contact_obj,
message=body,