2026-04-27 11:32:36 -04:00

130 lines
4.6 KiB
Python

from datetime import datetime, timedelta
import pytz
from odoo import fields, http
from odoo.http import request
class McsAppointmentController(http.Controller):
def _type_or_404(self, appointment_type_id):
appointment_type = (
request.env["mcs.appointment.type"]
.sudo()
.search(
[
("id", "=", appointment_type_id),
("active", "=", True),
("website_published", "=", True),
],
limit=1,
)
)
if not appointment_type:
return request.not_found()
return appointment_type
def _display_slots(self, appointment_type, day):
tz = appointment_type._timezone()
slots = []
for slot in appointment_type.get_available_slots(day):
start_utc = pytz.UTC.localize(slot["start"])
stop_utc = pytz.UTC.localize(slot["stop"])
slots.append(
{
"start": fields.Datetime.to_string(slot["start"]),
"stop": fields.Datetime.to_string(slot["stop"]),
"label": "%s - %s"
% (
start_utc.astimezone(tz).strftime("%I:%M %p"),
stop_utc.astimezone(tz).strftime("%I:%M %p"),
),
}
)
return slots
@http.route(["/appointments"], type="http", auth="public", website=True)
def appointments(self, **kwargs):
types = request.env["mcs.appointment.type"].sudo().search(
request.env["mcs.appointment.type"]._public_domain()
)
return request.render(
"mcs_appointment_booking.appointment_type_list",
{"appointment_types": types},
)
@http.route(
["/appointments/<int:appointment_type_id>"],
type="http",
auth="public",
website=True,
)
def appointment_type(self, appointment_type_id, date=None, **kwargs):
appointment_type = self._type_or_404(appointment_type_id)
if hasattr(appointment_type, "status_code"):
return appointment_type
today = fields.Date.context_today(request.env.user)
selected_day = fields.Date.to_date(date) if date else today
max_day = today + timedelta(days=appointment_type.max_schedule_days)
if selected_day < today:
selected_day = today
if selected_day > max_day:
selected_day = max_day
day_options = [today + timedelta(days=index) for index in range(appointment_type.max_schedule_days)]
return request.render(
"mcs_appointment_booking.appointment_type_page",
{
"appointment_type": appointment_type,
"selected_day": selected_day,
"day_options": day_options,
"slots": self._display_slots(appointment_type, selected_day),
},
)
@http.route(
["/appointments/<int:appointment_type_id>/book"],
type="http",
auth="public",
website=True,
methods=["POST"],
)
def appointment_book(self, appointment_type_id, **post):
appointment_type = self._type_or_404(appointment_type_id)
if hasattr(appointment_type, "status_code"):
return appointment_type
start = fields.Datetime.from_string(post.get("start"))
stop = fields.Datetime.from_string(post.get("stop"))
booking = request.env["mcs.appointment.booking"].sudo().create(
{
"appointment_type_id": appointment_type.id,
"customer_name": (post.get("customer_name") or "").strip(),
"customer_email": (post.get("customer_email") or "").strip(),
"customer_phone": (post.get("customer_phone") or "").strip(),
"start": start,
"stop": stop,
"notes": (post.get("notes") or "").strip(),
}
)
booking.action_confirm()
return request.redirect("/appointments/confirmed/%s" % booking.access_token)
@http.route(
["/appointments/confirmed/<string:token>"],
type="http",
auth="public",
website=True,
)
def appointment_confirmed(self, token, **kwargs):
booking = (
request.env["mcs.appointment.booking"]
.sudo()
.search([("access_token", "=", token)], limit=1)
)
if not booking:
return request.not_found()
return request.render(
"mcs_appointment_booking.appointment_confirmed",
{"booking": booking},
)