108 lines
4.0 KiB
Python
108 lines
4.0 KiB
Python
import csv
|
|
import io
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.db.models import Count, Sum
|
|
from django.utils import timezone
|
|
from django.contrib import messages
|
|
from .models import Property, Guest, Stay, Campaign
|
|
from .mail import send_campaign_email
|
|
|
|
def home(request):
|
|
"""Host Dashboard"""
|
|
total_guests = Guest.objects.count()
|
|
total_properties = Property.objects.count()
|
|
total_stays = Stay.objects.count()
|
|
|
|
recent_stays = Stay.objects.select_related('guest', 'property').order_by('-check_in')[:5]
|
|
recent_guests = Guest.objects.order_by('-created_at')[:5]
|
|
|
|
context = {
|
|
'total_guests': total_guests,
|
|
'total_properties': total_properties,
|
|
'total_stays': total_stays,
|
|
'recent_stays': recent_stays,
|
|
'recent_guests': recent_guests,
|
|
'project_name': 'Host Loyalty CRM'
|
|
}
|
|
return render(request, "core/index.html", context)
|
|
|
|
def guest_list(request):
|
|
"""List of all guests"""
|
|
guests = Guest.objects.annotate(stay_count=Count('stays')).order_by('-created_at')
|
|
return render(request, "core/guest_list.html", {'guests': guests})
|
|
|
|
def import_guests(request):
|
|
"""Import guests from a CSV file"""
|
|
if request.method == 'POST' and request.FILES.get('csv_file'):
|
|
csv_file = request.FILES['csv_file']
|
|
|
|
if not csv_file.name.endswith('.csv'):
|
|
messages.error(request, 'Please upload a CSV file.')
|
|
return redirect('import_guests')
|
|
|
|
try:
|
|
decoded_file = csv_file.read().decode('utf-8')
|
|
io_string = io.StringIO(decoded_file)
|
|
reader = csv.DictReader(io_string)
|
|
|
|
# Simple column mapping/validation
|
|
required_cols = {'first_name', 'last_name', 'email'}
|
|
if not required_cols.issubset(set(reader.fieldnames or [])):
|
|
messages.error(request, f'CSV must contain columns: {", ".join(required_cols)}')
|
|
return redirect('import_guests')
|
|
|
|
created_count = 0
|
|
updated_count = 0
|
|
for row in reader:
|
|
guest, created = Guest.objects.update_or_create(
|
|
email=row['email'].strip().lower(),
|
|
defaults={
|
|
'first_name': row['first_name'].strip(),
|
|
'last_name': row['last_name'].strip(),
|
|
'phone': row.get('phone', '').strip(),
|
|
}
|
|
)
|
|
if created:
|
|
created_count += 1
|
|
else:
|
|
updated_count += 1
|
|
|
|
messages.success(request, f'Successfully imported {created_count} new guests and updated {updated_count}.')
|
|
return redirect('guest_list')
|
|
|
|
except Exception as e:
|
|
messages.error(request, f'Error processing file: {str(e)}')
|
|
return redirect('import_guests')
|
|
|
|
return render(request, "core/import_guests.html")
|
|
|
|
def campaign_list(request):
|
|
"""List of email campaigns"""
|
|
campaigns = Campaign.objects.all().order_by('-created_at')
|
|
return render(request, "core/campaign_list.html", {'campaigns': campaigns})
|
|
|
|
def send_campaign(request, pk):
|
|
"""Send a campaign to all guests"""
|
|
campaign = get_object_or_404(Campaign, pk=pk)
|
|
|
|
if campaign.status == 'sent':
|
|
messages.warning(request, "This campaign has already been sent.")
|
|
return redirect('campaign_list')
|
|
|
|
guests = Guest.objects.all()
|
|
if not guests:
|
|
messages.error(request, "No guests found to send the campaign to.")
|
|
return redirect('campaign_list')
|
|
|
|
success_count, fail_count = send_campaign_email(campaign, guests)
|
|
|
|
campaign.status = 'sent'
|
|
campaign.sent_at = timezone.now()
|
|
campaign.save()
|
|
|
|
if success_count > 0:
|
|
messages.success(request, f"Campaign sent successfully to {success_count} guests.")
|
|
if fail_count > 0:
|
|
messages.error(request, f"Failed to send to {fail_count} guests.")
|
|
|
|
return redirect('campaign_list') |