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/"], 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//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/"], 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}, )