generic contact form
This commit is contained in:
parent
eece05af74
commit
2cbcc4ba98
9 changed files with 280 additions and 48 deletions
|
@ -0,0 +1,39 @@
|
|||
# Generated by Django 5.1.5 on 2025-02-27 14:33
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("services", "0007_service_is_coming_soon"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="lead",
|
||||
name="company",
|
||||
field=models.CharField(blank=True, max_length=200, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="lead",
|
||||
name="message",
|
||||
field=models.TextField(blank=True, max_length=1000, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="lead",
|
||||
name="phone",
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="lead",
|
||||
name="service",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="services.service",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -276,18 +276,22 @@ class ExternalLink(models.Model):
|
|||
|
||||
|
||||
class Lead(models.Model):
|
||||
service = models.ForeignKey(Service, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=200)
|
||||
email = models.EmailField()
|
||||
company = models.CharField(max_length=200, null=True, blank=True)
|
||||
phone = models.CharField(max_length=50, null=True, blank=True)
|
||||
message = models.TextField(blank=True, null=True, max_length=1000)
|
||||
odoo_lead_id = models.IntegerField(null=True, blank=True)
|
||||
|
||||
service = models.ForeignKey(
|
||||
Service, on_delete=models.SET_NULL, null=True, blank=True
|
||||
)
|
||||
offering = models.ForeignKey(
|
||||
ServiceOffering, on_delete=models.SET_NULL, null=True, blank=True
|
||||
)
|
||||
plan = models.ForeignKey(Plan, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
name = models.CharField(max_length=200)
|
||||
company = models.CharField(max_length=200)
|
||||
email = models.EmailField()
|
||||
phone = models.CharField(max_length=50)
|
||||
message = models.TextField(blank=True, max_length=1000)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
odoo_lead_id = models.IntegerField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} - {self.company} ({self.service})"
|
||||
|
|
|
@ -56,36 +56,48 @@ class OdooAPI:
|
|||
def create_lead(self, lead, source="form"):
|
||||
"""Create a lead in Odoo"""
|
||||
try:
|
||||
logger.info(
|
||||
f"Attempting to create lead for {lead.name} from {lead.company}"
|
||||
)
|
||||
|
||||
# Get provider name from offering if it exists
|
||||
provider_name = ""
|
||||
if hasattr(lead, "offering") and lead.offering:
|
||||
provider_name = lead.offering.cloud_provider.name
|
||||
logger.info(f"Attempting to create lead for {lead.name}")
|
||||
|
||||
# Prepare service description
|
||||
service_details = []
|
||||
if lead.service:
|
||||
|
||||
if hasattr(lead, "service") and lead.service:
|
||||
service_details.append(f"Service: {lead.service.name}")
|
||||
if provider_name:
|
||||
service_details.append(f"Provider: {provider_name}")
|
||||
if lead.plan:
|
||||
service_details.append(f"Plan: {lead.plan.name}")
|
||||
|
||||
# Get provider name from offering if it exists
|
||||
if (
|
||||
hasattr(lead, "offering")
|
||||
and lead.offering
|
||||
and hasattr(lead.offering, "cloud_provider")
|
||||
):
|
||||
provider_name = lead.offering.cloud_provider.name
|
||||
service_details.append(f"Provider: {provider_name}")
|
||||
|
||||
if hasattr(lead, "plan") and lead.plan:
|
||||
service_details.append(f"Plan: {lead.plan.name}")
|
||||
|
||||
if source == "form":
|
||||
service_details.append(f"Source: Servala Website")
|
||||
elif source == "osbapi":
|
||||
service_details.append(f"Source: OSB API")
|
||||
elif source == "contact_form":
|
||||
service_details.append(f"Source: Contact Form")
|
||||
|
||||
# Prepare lead name based on whether it's a service lead or generic contact
|
||||
if hasattr(lead, "service") and lead.service:
|
||||
lead_name = f"Servala - Interest in {lead.service.name}"
|
||||
else:
|
||||
lead_name = "Servala - Website Contact"
|
||||
|
||||
# Prepare lead data
|
||||
lead_data = {
|
||||
"name": f"Servala - Interest in {lead.service.name}",
|
||||
"name": lead_name,
|
||||
"contact_name": lead.name,
|
||||
"partner_name": lead.company,
|
||||
"partner_name": (
|
||||
lead.company if hasattr(lead, "company") and lead.company else ""
|
||||
),
|
||||
"email_from": lead.email,
|
||||
"phone": lead.phone,
|
||||
"phone": lead.phone if hasattr(lead, "phone") and lead.phone else "",
|
||||
"description": (
|
||||
f"{lead.message}<br/><br/>" + "<br/>".join(service_details)
|
||||
if lead.message
|
||||
|
@ -111,29 +123,50 @@ class OdooAPI:
|
|||
logger.info(f"Successfully created lead in Odoo with ID: {odoo_lead_id}")
|
||||
|
||||
# Post message in chatter
|
||||
message_data = {
|
||||
"body": f"""
|
||||
<p>Thank you for your interest in the service <strong>{lead.service.name}</strong>.
|
||||
We recorded the following information and will get back to you soon.</p><br/>
|
||||
if hasattr(lead, "service") and lead.service:
|
||||
# For service-related leads
|
||||
message_data = {
|
||||
"body": f"""
|
||||
<p>Thank you for your interest in the service <strong>{lead.service.name}</strong>.
|
||||
We recorded the following information and will get back to you soon:</p><br/>
|
||||
|
||||
<p>Contact Details:</p>
|
||||
<ul>
|
||||
<li><strong>Name:</strong> {lead.name}</li>
|
||||
<li><strong>Company:</strong> {lead.company}</li>
|
||||
<li><strong>Email:</strong> {lead.email}</li>
|
||||
<li><strong>Phone:</strong> {lead.phone}</li>
|
||||
</ul>
|
||||
<p>Contact Details:</p>
|
||||
<ul>
|
||||
<li><strong>Name:</strong> {lead.name}</li>
|
||||
<li><strong>Company:</strong> {lead.company if hasattr(lead, "company") and lead.company else "N/A"}</li>
|
||||
<li><strong>Email:</strong> {lead.email}</li>
|
||||
<li><strong>Phone:</strong> {lead.phone if hasattr(lead, "phone") and lead.phone else "N/A"}</li>
|
||||
</ul>
|
||||
|
||||
<p>Service Details:<p>
|
||||
<ul>
|
||||
<li><strong>Service:</strong> {lead.service.name}</li>
|
||||
{f'<li><strong>Provider:</strong> {provider_name}</li>' if provider_name else ''}
|
||||
{f'<li><strong>Plan:</strong> {lead.plan.name}</li>' if lead.plan else ''}
|
||||
</ul>
|
||||
""",
|
||||
"message_type": "comment",
|
||||
"subtype_xmlid": "mail.mt_comment",
|
||||
}
|
||||
<p>Service Details:<p>
|
||||
<ul>
|
||||
<li><strong>Service:</strong> {lead.service.name}</li>
|
||||
{f'<li><strong>Provider:</strong> {provider_name}</li>' if provider_name else ''}
|
||||
{f'<li><strong>Plan:</strong> {lead.plan.name}</li>' if lead.plan else ''}
|
||||
</ul>
|
||||
""",
|
||||
"message_type": "comment",
|
||||
"subtype_xmlid": "mail.mt_comment",
|
||||
}
|
||||
else:
|
||||
# For contact form submissions
|
||||
message_data = {
|
||||
"body": f"""
|
||||
<p>Thank you for contacting Servala by VSHN.<br/>
|
||||
We recorded the following information and will get back to you soon:</p><br/>
|
||||
|
||||
<p>Contact Details:</p>
|
||||
<ul>
|
||||
<li><strong>Name:</strong> {lead.name}</li>
|
||||
<li><strong>Email:</strong> {lead.email}</li>
|
||||
{f'<li><strong>Phone:</strong> {lead.phone}</li>' if lead.phone else ''}
|
||||
{f'<li><strong>Company:</strong> {lead.company}</li>' if lead.company else ''}
|
||||
{f'<li><strong>Message:</strong> {lead.message}</li>' if lead.message else ''}
|
||||
</ul>
|
||||
""",
|
||||
"message_type": "comment",
|
||||
"subtype_xmlid": "mail.mt_comment",
|
||||
}
|
||||
|
||||
# Post the message
|
||||
self.odoo.env["crm.lead"].browse(odoo_lead_id).message_post(
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
<li class="menu__item"><a class="menu__item-link" href="{% url 'services:provider_list' %}">Cloud Providers</a></li>
|
||||
<li class="menu__item"><a class="menu__item-link" href="{% url 'services:partner_list' %}">Consulting Partners</a></li>
|
||||
</ul>
|
||||
<ul class="menu-cta mb-0">
|
||||
<li class="mr-17"><a class="btn btn-outline-light btn-outline-primary" href="{% url 'services:contact' %}" role="button">Contact</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="nav__toggle">
|
||||
|
|
82
hub/services/templates/services/contact_form.html
Normal file
82
hub/services/templates/services/contact_form.html
Normal file
|
@ -0,0 +1,82 @@
|
|||
{% extends 'services/base.html' %}
|
||||
{% load form_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<h2 class="mb-4">Contact Us</h2>
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.name.id_for_label }}" class="form-label">Your Name</label>
|
||||
{{ form.name }}
|
||||
{% if form.name.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.name.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.email.id_for_label }}" class="form-label">Your Email Address</label>
|
||||
{{ form.email }}
|
||||
{% if form.email.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.email.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.phone.id_for_label }}" class="form-label">Your Phone Number (Optional)</label>
|
||||
{{ form.phone }}
|
||||
{% if form.phone.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.phone.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.company.id_for_label }}" class="form-label">Your Company (Optional)</label>
|
||||
{{ form.company }}
|
||||
{% if form.company.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.company.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.message.id_for_label }}" class="form-label">Your Message (Optional)</label>
|
||||
{{ form.message }}
|
||||
{% if form.message.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.message.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-lg">Send Message</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
18
hub/services/templates/services/contact_thank_you.html
Normal file
18
hub/services/templates/services/contact_thank_you.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 text-center">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-5">
|
||||
<h2 class="mb-4">Thank You!</h2>
|
||||
<p class="lead">Your message has been sent successfully.</p>
|
||||
<p>We'll get back to you as soon as possible.</p>
|
||||
<a href="{% url 'services:homepage' %}" class="btn btn-primary mt-3">Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -35,7 +35,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mb-40">
|
||||
<label for="{{ form.phone.id_for_label }}" class="form-label text-purple">Your Phone Number</label>
|
||||
<label for="{{ form.phone.id_for_label }}" class="form-label text-purple">Your Phone Number (Optional)</label>
|
||||
{{ form.phone|addclass:"form-control" }}
|
||||
{% if form.phone.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
|
@ -45,7 +45,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mb-40">
|
||||
<label for="{{ form.company.id_for_label }}" class="form-label text-purple">Your Company</label>
|
||||
<label for="{{ form.company.id_for_label }}" class="form-label text-purple">Your Company (Optional)</label>
|
||||
{{ form.company|addclass:"form-control" }}
|
||||
{% if form.company.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
|
@ -55,7 +55,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mb-40">
|
||||
<label for="{{ form.message.id_for_label }}" class="form-label text-purple">Message (Optional)</label>
|
||||
<label for="{{ form.message.id_for_label }}" class="form-label text-purple">Your Message (Optional)</label>
|
||||
{{ form.message|addclass:"form-control" }}
|
||||
{% if form.message.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
|
|
|
@ -15,4 +15,6 @@ urlpatterns = [
|
|||
path("partner/<slug:slug>/", views.partner_detail, name="partner_detail"),
|
||||
path("service/<slug:slug>/interest/", views.create_lead, name="create_lead"),
|
||||
path("service/<slug:slug>/thank-you/", views.thank_you, name="thank_you"),
|
||||
path("contact/", views.leads.contact, name="contact"),
|
||||
path("contact/thank-you/", views.leads.contact_thank_you, name="contact_thank_you"),
|
||||
]
|
||||
|
|
|
@ -91,3 +91,54 @@ def create_lead(request, slug):
|
|||
def thank_you(request, slug):
|
||||
service = get_object_or_404(Service, slug=slug)
|
||||
return render(request, "services/thank_you.html", {"service": service})
|
||||
|
||||
|
||||
def contact(request):
|
||||
if request.method == "POST":
|
||||
form = LeadForm(request.POST)
|
||||
if form.is_valid():
|
||||
# Create a minimal Lead object
|
||||
from hub.services.models import Lead
|
||||
|
||||
lead = Lead(
|
||||
name=form.cleaned_data["name"],
|
||||
email=form.cleaned_data["email"],
|
||||
message=form.cleaned_data["message"],
|
||||
company=form.cleaned_data["company"],
|
||||
phone=form.cleaned_data["phone"],
|
||||
)
|
||||
|
||||
try:
|
||||
logger.info(f"Attempting to create contact lead from {lead.name}")
|
||||
odoo = OdooAPI()
|
||||
odoo_lead_id = odoo.create_lead(lead, source="contact_form")
|
||||
lead.odoo_lead_id = odoo_lead_id
|
||||
lead.save()
|
||||
|
||||
logger.info(
|
||||
f"Successfully created contact lead with Odoo ID: {odoo_lead_id}"
|
||||
)
|
||||
messages.success(
|
||||
request, "Thank you for your message. We'll get back to you soon!"
|
||||
)
|
||||
return redirect("services:contact_thank_you")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create contact lead: {str(e)}", exc_info=True)
|
||||
error_message = "Sorry, there was an error processing your request. Please try again later."
|
||||
|
||||
if settings.DEBUG:
|
||||
error_message += f" Error: {str(e)}"
|
||||
|
||||
messages.error(request, error_message)
|
||||
else:
|
||||
form = LeadForm()
|
||||
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
return render(request, "services/contact_form.html", context)
|
||||
|
||||
|
||||
def contact_thank_you(request):
|
||||
return render(request, "services/contact_thank_you.html")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue