forked from Mapan/odoo17e
114 lines
6.4 KiB
Python
114 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import pytz
|
|
|
|
from babel.dates import format_datetime
|
|
from werkzeug.exceptions import NotFound
|
|
|
|
from odoo import Command, fields, http
|
|
from odoo.http import request
|
|
from odoo.addons.appointment.controllers.appointment import AppointmentController
|
|
from odoo.addons.base.models.ir_qweb import keep_query
|
|
from odoo.addons.payment import utils as payment_utils
|
|
from odoo.tools.misc import get_lang
|
|
|
|
|
|
class AppointmentAccountPayment(AppointmentController):
|
|
|
|
@http.route(['/calendar_booking/<string:booking_token>/cancel'], type='http', auth="public", website=True, sitemap=False)
|
|
def calendar_booking_cancel(self, booking_token):
|
|
""" Cancel the booking linked to booking_token if any, unlink it, and redirect
|
|
to the page of corresponding appointment to take another appointment """
|
|
booking_sudo = request.env['calendar.booking'].sudo().search([('booking_token', '=', booking_token)], limit=1)
|
|
if not booking_sudo or booking_sudo.calendar_event_id:
|
|
raise NotFound()
|
|
|
|
appointment_type = booking_sudo.appointment_type_id
|
|
invitation_params = booking_sudo.appointment_invite_id._get_invitation_url_parameters()
|
|
booking_sudo.unlink()
|
|
return request.redirect(f"/appointment/{appointment_type.id}?{keep_query(*invitation_params)}")
|
|
|
|
@http.route(['/calendar_booking/<string:booking_token>/view'], type='http', auth="public", website=True, sitemap=False)
|
|
def calendar_booking_view(self, booking_token):
|
|
""" View the booking summary. This is accessed at the end of the appointment flow when
|
|
the payment is pending or failed / was cancelled. Once paid, a calendar_event is created. If
|
|
it exists, redirect to that calendar event page instead. """
|
|
booking_sudo = request.env['calendar.booking'].sudo().search([('booking_token', '=', booking_token)], limit=1)
|
|
if not booking_sudo:
|
|
raise NotFound()
|
|
if booking_sudo.calendar_event_id:
|
|
return request.redirect(
|
|
"/calendar/view/{event_token}?partner_id={pid}&{args}".format(
|
|
event_token=booking_sudo.calendar_event_id.access_token,
|
|
pid=booking_sudo.partner_id.id,
|
|
args=keep_query(*booking_sudo.appointment_invite_id._get_invitation_url_parameters(), state='new')
|
|
))
|
|
|
|
timezone = (request.session.get('timezone') or
|
|
request.env.context.get('tz') or
|
|
booking_sudo.appointment_type_id.appointment_tz)
|
|
start_tz = fields.Datetime.from_string(booking_sudo.start).replace(tzinfo=pytz.utc).astimezone(pytz.timezone(timezone))
|
|
locale = get_lang(request.env).code
|
|
start_dt = f"{format_datetime(start_tz, 'EEE', locale=locale)} {format_datetime(start_tz, locale=locale)}"
|
|
|
|
return request.render("appointment_account_payment.calendar_booking_view", {
|
|
'attendees': (booking_sudo.partner_id | booking_sudo.staff_user_id.partner_id) if booking_sudo.staff_user_id else booking_sudo.partner_id,
|
|
'booking': booking_sudo,
|
|
'start_dt': start_dt,
|
|
'timezone': timezone,
|
|
})
|
|
|
|
def _handle_appointment_form_submission(
|
|
self, appointment_type,
|
|
date_start, date_end, duration,
|
|
description, answer_input_values, name, customer, appointment_invite, guests=None,
|
|
staff_user=None, asked_capacity=1, booking_line_values=None
|
|
):
|
|
""" Override: when a payment step is necessary, we create the calendar booking model to store all relevant information
|
|
instead of creating an calendar.event. This prevents synchronizing calendars with non-confirmed events. It will
|
|
be transformed to a calendar.event on payment (or confirmation). See _make_event_from_paid_booking on calendar.booking.
|
|
Redirects to payment if needed. See _redirect_to_payment"""
|
|
if appointment_type.has_payment_step and appointment_type.product_id.lst_price:
|
|
calendar_booking = request.env['calendar.booking'].sudo().create([{
|
|
'appointment_answer_input_ids': [Command.create(vals) for vals in answer_input_values],
|
|
'appointment_invite_id': appointment_invite.id,
|
|
'appointment_type_id': appointment_type.id,
|
|
'booking_line_ids': [Command.create(vals) for vals in booking_line_values],
|
|
'asked_capacity': asked_capacity,
|
|
'description': description,
|
|
'guest_ids': [Command.link(pid) for pid in guests.ids] if guests else [],
|
|
'name': name,
|
|
'partner_id': customer.id,
|
|
'product_id': appointment_type.product_id.id,
|
|
'staff_user_id': staff_user.id,
|
|
'start': date_start,
|
|
'stop': date_end,
|
|
}])
|
|
return self._redirect_to_payment(calendar_booking)
|
|
|
|
return super()._handle_appointment_form_submission(
|
|
appointment_type, date_start, date_end, duration, description, answer_input_values, name,
|
|
customer, appointment_invite, guests, staff_user, asked_capacity, booking_line_values
|
|
)
|
|
|
|
def _redirect_to_payment(self, calendar_booking):
|
|
""" Redirection method called from appointment form submission when the flow has a payment step.
|
|
This method does two things. First, it creates a draft invoice linked to the current booking.
|
|
A new invoice is created each time a booking is created after filling the form. Second, it
|
|
redirects to the /payment route of appointment, the payment page, allowing specific pre processing.
|
|
This method is overriden if eCommerce is installed to use use sale orders instead. """
|
|
invoice = calendar_booking.sudo()._make_invoice_from_booking()
|
|
if not invoice:
|
|
raise NotFound()
|
|
|
|
return request.redirect(
|
|
"/payment/pay?appointment_type_id={aid}&invoice_id={iid}&partner_id={pid}&amount={amount}&access_token={token}&{args}".format(
|
|
aid=calendar_booking.appointment_type_id.id,
|
|
iid=invoice.id,
|
|
pid=calendar_booking.partner_id.id,
|
|
amount=invoice.amount_total,
|
|
token=payment_utils.generate_access_token(invoice.partner_id.id, invoice.amount_total, invoice.currency_id.id),
|
|
args=keep_query('*')
|
|
))
|