You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
8.5 KiB
246 lines
8.5 KiB
# views.py
|
|
from django.views.generic import FormView, ListView, DetailView, CreateView, UpdateView
|
|
from django.views.generic.edit import FormView, BaseUpdateView
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.contrib.auth.decorators import permission_required
|
|
from django.contrib import messages
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.urls import reverse_lazy
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
from django.views import View
|
|
from django.utils import timezone
|
|
from django.contrib.sites.shortcuts import get_current_site
|
|
from django.template.loader import render_to_string
|
|
from django.core.mail import send_mail
|
|
from django.conf import settings
|
|
from django.db import IntegrityError
|
|
|
|
from .models import Event, Prospect, EmailTracker, EmailCampaign, EventType
|
|
from .filters import ProspectFilter
|
|
from .forms import CSVImportForm, BulkEmailForm, EventForm
|
|
|
|
from .mixins import CRMAccessMixin
|
|
|
|
import csv
|
|
from io import TextIOWrapper
|
|
from datetime import datetime
|
|
|
|
@permission_required('crm.view_crm', raise_exception=True)
|
|
def add_prospect(request):
|
|
if request.method == 'POST':
|
|
entity_name = request.POST.get('entity_name')
|
|
first_name = request.POST.get('first_name')
|
|
last_name = request.POST.get('last_name')
|
|
email = request.POST.get('email')
|
|
phone = request.POST.get('phone')
|
|
address = request.POST.get('address')
|
|
zip_code = request.POST.get('zip_code')
|
|
city = request.POST.get('city')
|
|
# region = request.POST.get('region')
|
|
|
|
try:
|
|
prospect = Prospect.objects.create(
|
|
entity_name=entity_name,
|
|
first_name=first_name,
|
|
last_name=last_name,
|
|
email=email,
|
|
phone=phone,
|
|
address=address,
|
|
zip_code=zip_code,
|
|
city=city,
|
|
# region=region,
|
|
created_by=request.user,
|
|
modified_by=request.user
|
|
)
|
|
messages.success(request, f'Prospect {name} has been added successfully!')
|
|
return redirect('crm:events') # or wherever you want to redirect after success
|
|
except Exception as e:
|
|
messages.error(request, f'Error adding prospect: {str(e)}')
|
|
|
|
return render(request, 'crm/add_prospect.html')
|
|
|
|
class EventCreateView(CRMAccessMixin, CreateView):
|
|
model = Event
|
|
form_class = EventForm
|
|
template_name = 'crm/event_form.html'
|
|
success_url = reverse_lazy('crm:planned_events')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.created_by = self.request.user
|
|
form.instance.modified_by = self.request.user
|
|
return super().form_valid(form)
|
|
|
|
class EditEventView(CRMAccessMixin, UpdateView):
|
|
model = Event
|
|
form_class = EventForm
|
|
template_name = 'crm/event_form.html'
|
|
success_url = reverse_lazy('crm:planned_events')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.modified_by = self.request.user
|
|
response = super().form_valid(form)
|
|
messages.success(self.request, 'Event updated successfully!')
|
|
return response
|
|
|
|
class StartEventView(CRMAccessMixin, BaseUpdateView):
|
|
model = Event
|
|
http_method_names = ['post', 'get']
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
return self.post(request, *args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
event = get_object_or_404(Event, pk=kwargs['pk'], status='PLANNED')
|
|
event.status = 'ACTIVE'
|
|
event.save()
|
|
|
|
if event.type == 'MAIL':
|
|
return HttpResponseRedirect(
|
|
reverse_lazy('crm:setup_email_campaign', kwargs={'event_id': event.id})
|
|
)
|
|
elif event.type == 'SMS':
|
|
return HttpResponseRedirect(
|
|
reverse_lazy('crm:setup_sms_campaign', kwargs={'event_id': event.id})
|
|
)
|
|
elif event.type == 'PRESS':
|
|
return HttpResponseRedirect(
|
|
reverse_lazy('crm:setup_press_release', kwargs={'event_id': event.id})
|
|
)
|
|
|
|
messages.success(request, 'Event started successfully!')
|
|
return HttpResponseRedirect(reverse_lazy('crm:planned_events'))
|
|
|
|
class EventListView(CRMAccessMixin, ListView):
|
|
model = Event
|
|
template_name = 'crm/events.html'
|
|
context_object_name = 'events' # We won't use this since we're providing custom context
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['planned_events'] = Event.objects.filter(
|
|
status='PLANNED'
|
|
).order_by('date')
|
|
context['completed_events'] = Event.objects.filter(
|
|
status='COMPLETED'
|
|
).order_by('-date')
|
|
return context
|
|
|
|
class ProspectListView(CRMAccessMixin, ListView):
|
|
model = Prospect
|
|
template_name = 'crm/prospect_list.html'
|
|
context_object_name = 'prospects'
|
|
filterset_class = ProspectFilter
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['filter'] = self.filterset_class(
|
|
self.request.GET,
|
|
queryset=self.get_queryset()
|
|
)
|
|
return context
|
|
|
|
|
|
class CSVImportView(CRMAccessMixin, FormView):
|
|
template_name = 'crm/csv_import.html'
|
|
form_class = CSVImportForm
|
|
success_url = reverse_lazy('prospect-list')
|
|
|
|
def form_valid(self, form):
|
|
csv_file = TextIOWrapper(
|
|
form.cleaned_data['csv_file'].file,
|
|
encoding='utf-8-sig' # Handle potential BOM in CSV
|
|
)
|
|
reader = csv.reader(csv_file, delimiter=';') # Using semicolon delimiter
|
|
|
|
# Skip header if exists
|
|
next(reader, None)
|
|
|
|
created_count = 0
|
|
updated_count = 0
|
|
error_count = 0
|
|
|
|
for row in reader:
|
|
try:
|
|
if len(row) < 10: # Ensure we have enough columns
|
|
continue
|
|
|
|
# Extract data from correct columns
|
|
entity_name = row[0].strip()
|
|
last_name = row[1].strip()
|
|
first_name = row[2].strip()
|
|
email = row[3].strip()
|
|
phone = row[4].strip()
|
|
zip_code = row[8].strip()
|
|
city = row[9].strip()
|
|
|
|
# Try to update existing prospect or create new one
|
|
prospect, created = Prospect.objects.update_or_create(
|
|
email=email, # Use email as unique identifier
|
|
defaults={
|
|
'entity_name': entity_name,
|
|
'first_name': first_name,
|
|
'last_name': last_name,
|
|
'phone': phone,
|
|
'zip_code': zip_code,
|
|
'city': city,
|
|
'modified_by': self.request.user,
|
|
}
|
|
)
|
|
|
|
if created:
|
|
prospect.created_by = self.request.user
|
|
prospect.save()
|
|
created_count += 1
|
|
else:
|
|
updated_count += 1
|
|
|
|
except Exception as e:
|
|
error_count += 1
|
|
messages.error(
|
|
self.request,
|
|
f"Error processing row with email {email}: {str(e)}"
|
|
)
|
|
|
|
# Add success message
|
|
messages.success(
|
|
self.request,
|
|
f"Import completed: {created_count} created, {updated_count} updated, {error_count} errors"
|
|
)
|
|
|
|
return super().form_valid(form)
|
|
|
|
class SendBulkEmailView(CRMAccessMixin, FormView):
|
|
template_name = 'crm/send_bulk_email.html'
|
|
form_class = BulkEmailForm
|
|
success_url = reverse_lazy('crm:prospect-list')
|
|
|
|
def form_valid(self, form):
|
|
prospects = form.cleaned_data['prospects']
|
|
subject = form.cleaned_data['subject']
|
|
content = form.cleaned_data['content']
|
|
|
|
# Create Event for this email campaign
|
|
event = Event.objects.create(
|
|
date=datetime.now(),
|
|
type=EventType.MAILING,
|
|
description=f"Bulk email: {subject}",
|
|
status='COMPLETED',
|
|
created_by=self.request.user,
|
|
modified_by=self.request.user
|
|
)
|
|
event.prospects.set(prospects)
|
|
|
|
# Send emails
|
|
success_count, error_count = send_bulk_email(
|
|
subject=subject,
|
|
content=content,
|
|
prospects=prospects
|
|
)
|
|
|
|
# Show result message
|
|
messages.success(
|
|
self.request,
|
|
f"Sent {success_count} emails successfully. {error_count} failed."
|
|
)
|
|
|
|
return super().form_valid(form)
|
|
|