38340-vm/core/views.py
2026-02-10 19:21:45 +00:00

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')