Browse Source

[ADD] appointment_event module

16.0
RemiFr82 4 months ago
parent
commit
1fc3673a3c
  1. 1
      appointment_event/__init__.py
  2. 9
      appointment_event/__manifest__.py
  3. 1
      appointment_event/controllers/__init__.py
  4. 132
      appointment_event/controllers/appointment.py
  5. 13
      appointment_event/data/mail_activity_type.xml
  6. 1
      appointment_event/models/__init__.py
  7. 13
      appointment_event/models/appointment_type.py
  8. BIN
      appointment_event/static/description/icon.png
  9. 93
      appointment_event/static/description/icon.svg
  10. 17
      appointment_event/views/appointment_type.xml

1
appointment_event/__init__.py

@ -1 +1,2 @@
from . import controllers
from . import models from . import models

9
appointment_event/__manifest__.py

@ -24,9 +24,14 @@
"excludes": [], "excludes": [],
"external_dependencies": [], "external_dependencies": [],
"depends": [ "depends": [
"",
"website_appointment",
"website_event",
"event_to_calendar",
],
"data": [
"data/mail_activity_type.xml",
"views/appointment_type.xml",
], ],
"data": [],
"css": [], "css": [],
"images": [], "images": [],
"js": [], "js": [],

1
appointment_event/controllers/__init__.py

@ -0,0 +1 @@
from . import appointment

132
appointment_event/controllers/appointment.py

@ -0,0 +1,132 @@
import pytz
from dateutil.relativedelta import relativedelta
from odoo import fields, _
from odoo.http import request, route
from odoo.addons.appointment.controllers.appointment import AppointmentController
from odoo.addons.base.models.ir_qweb import keep_query
from werkzeug.exceptions import NotFound
class AppointmentEventController(AppointmentController):
@route(
["/appointment/<int:appointment_type_id>/submit"],
type="http",
auth="public",
website=True,
methods=["POST"],
)
def appointment_form_submit(
self,
appointment_type_id,
datetime_str,
duration_str,
staff_user_id,
name,
phone,
email,
**kwargs
):
appointment_type = self._fetch_and_check_private_appointment_types(
kwargs.get("filter_appointment_type_ids"),
kwargs.get("filter_staff_user_ids"),
kwargs.get("invite_token"),
current_appointment_type_id=int(appointment_type_id),
)
if not appointment_type:
raise NotFound()
if not appointment_type.create_events:
return super().appointment_form_submit(
appointment_type_id,
datetime_str,
duration_str,
staff_user_id,
name,
phone,
email,
**kwargs
)
# new process i
# if booking a slot should create an event
timezone = request.session.get("timezone") or appointment_type.appointment_tz
tz_session = pytz.timezone(timezone)
date_start = (
tz_session.localize(fields.Datetime.from_string(datetime_str))
.astimezone(pytz.utc)
.replace(tzinfo=None)
)
duration = float(duration_str)
date_end = date_start + relativedelta(hours=duration)
invite_token = kwargs.get("invite_token")
# check availability of the selected user again (in case someone else booked while the client was entering the form)
staff_user = request.env["res.users"].sudo().browse(int(staff_user_id)).exists()
if staff_user not in appointment_type.sudo().staff_user_ids:
raise NotFound()
if staff_user and not staff_user.partner_id.calendar_verify_availability(
date_start, date_end
):
return request.redirect(
"/appointment/%s?%s"
% (appointment_type.id, keep_query("*", state="failed-staff-user"))
)
Partner = self._get_customer_partner() or request.env[
"res.partner"
].sudo().search([("email", "=like", email)], limit=1)
if Partner:
if not Partner.calendar_verify_availability(date_start, date_end):
return request.redirect(
"/appointment/%s?%s"
% (appointment_type.id, keep_query("*", state="failed-partner"))
)
if not Partner.mobile:
Partner.write({"mobile": phone})
if not Partner.email:
Partner.write({"email": email})
else:
Partner = Partner.create(
{
"name": name,
"mobile": Partner._phone_format(
phone, country=self._get_customer_country()
),
"email": email,
"lang": request.lang.code,
}
)
# partner_inputs dictionary structures all answer inputs received on the appointment submission: key is question id, value
# is answer id (as string) for choice questions, text input for text questions, array of ids for multiple choice questions.
partner_inputs = {}
event_type = appointment_type.event_type_id
event = (
request.env["event.event"]
.sudo()
.create(
{
"name": event_type.name,
"date_begin": date_start,
"date_end": date_end,
"date_tz": timezone,
"event_type_id": event_type.id,
"user_id": int(staff_user_id),
"address_id": appointment_type.location_id.id,
}
)
)
event = event.sudo()
event.sudo().with_user(int(staff_user_id)).add_to_agenda()
event.activity_schedule(
act_type_xmlid="appointment_event.mail_activity_type_validate_date",
summary=_("New booking to check"),
note=_(
"Check date availability and set automatic validation for next bookers."
),
user_id=staff_user_id,
)
event.write({"website_published": True})
return request.redirect(event.website_url)

13
appointment_event/data/mail_activity_type.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mail_activity_type_check_date" model="mail.activity.type">
<field name="name">Check date</field>
<field name="icon">fa-calendar-check-o</field>
<field name="delay_count">1</field>
<field name="decoration_type">warning</field>
<field name="sequence">0</field>
<field name="res_model">event.event</field>
</record>
</odoo>

1
appointment_event/models/__init__.py

@ -0,0 +1 @@
from . import appointment_type

13
appointment_event/models/appointment_type.py

@ -0,0 +1,13 @@
from odoo import models, fields, api
class AppointmentType(models.Model):
_inherit = "appointment.type"
create_events = fields.Boolean("Create events", defualt=False)
event_type_id = fields.Many2one("event.type", string="Event type")
@api.onchange("create_events")
def onchange_create_events(self):
if not self.create_events and self.event_type_id:
self.event_type_id = False

BIN
appointment_event/static/description/icon.png

After

Width: 1539  |  Height: 1771  |  Size: 182 KiB

93
appointment_event/static/description/icon.svg

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2000 2000" style="enable-background:new 0 0 2000 2000;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{opacity:0.288;fill:#5BB4B9;enable-background:new ;}
.st2{fill:#714B67;stroke:#FFFFFF;stroke-width:2.5312;stroke-linejoin:round;stroke-miterlimit:84.375;}
.st3{fill:#00A09D;stroke:#FFFFFF;stroke-width:2.5312;stroke-linejoin:round;stroke-miterlimit:84.375;}
</style>
<g id="Calque_1_00000161600930838337179250000013767234669113973950_">
<g>
<g>
<g transform="translate(13 10)">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-856.1276" y1="-992.6924" x2="-877.9248" y2="-975.3946" gradientTransform="matrix(43.9892 0 0 50.6251 39146.6719 50789.9492)">
<stop offset="0" style="stop-color:#81D9DD"/>
<stop offset="1" style="stop-color:#419CA1"/>
</linearGradient>
<path class="st0" d="M1747.1,540.7l-749.9-433c-6-3.4-13.3-3.4-19.3,0L228,540.7c-6,3.4-9.6,9.8-9.6,16.7v865.9
c0,6.9,3.7,13.3,9.6,16.7l749.9,433c3,1.7,6.3,2.6,9.6,2.6s6.6-0.8,9.6-2.6l749.9-433c6-3.4,9.6-9.8,9.6-16.7v-866
C1756.7,550.5,1753,544.1,1747.1,540.7z M256.8,1409V590.7l708.6,409.1l2.8,4.9V1823l-708.7-409.2L256.8,1409z M990.3,148.2
L1699,557.3L990.3,966.5h-5.6L276,557.3l708.7-409.1L990.3,148.2L990.3,148.2z M1006.8,1004.7l2.8-4.8l708.6-409.1V1409
l-2.8,4.8l-708.6,409.1L1006.8,1004.7L1006.8,1004.7z"/>
<rect x="970" y="870.2" class="st1" width="35" height="48.1"/>
<rect x="970" y="485.1" class="st1" width="35" height="48.1"/>
<rect x="970" y="774" class="st1" width="35" height="48.1"/>
<rect x="970" y="581.4" class="st1" width="35" height="48.1"/>
<rect x="970" y="196.3" class="st1" width="35" height="48.1"/>
<rect x="970" y="292.6" class="st1" width="35" height="48.1"/>
<rect x="970" y="388.9" class="st1" width="35" height="48.1"/>
<rect x="970" y="677.7" class="st1" width="35" height="48.1"/>
<rect x="703.4" y="1109.5" transform="matrix(0.8661 -0.4999 0.4999 0.8661 -465.9773 514.5881)" class="st1" width="48.1" height="35"/>
<rect x="620.2" y="1157.7" transform="matrix(0.8661 -0.4999 0.4999 0.8661 -501.1965 479.4498)" class="st1" width="48.1" height="35"/>
<rect x="536.7" y="1205.8" transform="matrix(0.8659 -0.5002 0.5002 0.8659 -536.6949 444.5481)" class="st1" width="48.2" height="35"/>
<rect x="870.1" y="1013.3" transform="matrix(0.8662 -0.4996 0.4996 0.8662 -395.3831 584.6333)" class="st1" width="48.1" height="35"/>
<rect x="786.8" y="1061.3" transform="matrix(0.8659 -0.5002 0.5002 0.8659 -430.897 550.2667)" class="st1" width="48.2" height="35"/>
<rect x="286.6" y="1350.2" transform="matrix(0.8659 -0.5002 0.5002 0.8659 -642.4768 338.7787)" class="st1" width="48.1" height="35"/>
<rect x="453.3" y="1253.8" transform="matrix(0.866 -0.5 0.5 0.866 -571.7071 408.9949)" class="st1" width="48.1" height="35"/>
<rect x="370.1" y="1302.1" transform="matrix(0.8661 -0.4999 0.4999 0.8661 -606.8809 373.7628)" class="st1" width="48.1" height="35"/>
<rect x="1307.6" y="1145.5" transform="matrix(0.5 -0.866 0.866 0.5 -350.2617 1732.3198)" class="st1" width="35" height="48.1"/>
<rect x="1141" y="1049.1" transform="matrix(0.5001 -0.866 0.866 0.5001 -350.2007 1539.6794)" class="st1" width="35" height="48.1"/>
<rect x="1224.4" y="1097.2" transform="matrix(0.4996 -0.8663 0.8663 0.4996 -349.8225 1636.8931)" class="st1" width="35" height="48.1"/>
<rect x="1638.3" y="1342.1" transform="matrix(0.5004 -0.8658 0.8658 0.5004 -349.8787 2112.7935)" class="st1" width="35" height="35"/>
<rect x="1057.5" y="1001" transform="matrix(0.5003 -0.8658 0.8658 0.5003 -350.4254 1443.0403)" class="st1" width="35" height="48.2"/>
<rect x="1474.3" y="1241.7" transform="matrix(0.5003 -0.8658 0.8658 0.5003 -350.5846 1924.1418)" class="st1" width="35" height="48.2"/>
<rect x="1557.8" y="1289.8" transform="matrix(0.5 -0.866 0.866 0.5 -350.1897 2021.1473)" class="st1" width="35" height="48.1"/>
<rect x="1391.1" y="1193.6" transform="matrix(0.4997 -0.8662 0.8662 0.4997 -349.9747 1829.327)" class="st1" width="35" height="48.1"/>
</g>
</g>
</g>
</g>
<g id="odoo">
<path class="st2" d="M993.2,439.3c-303.8,0-550,246.2-550,550s246.2,550,550,550s550-246.2,550-550S1297,439.3,993.2,439.3z
M993.2,659.3c182.3,0,330,147.7,330,330s-147.7,330-330,330s-330-147.7-330-330S811,659.3,993.2,659.3z"/>
</g>
<g id="kayak">
<path class="st3" d="M609.8,957.9c-0.4,14.4,11.8,59.8,23.4,86.8c33.6,75.8,69.2,108.4,220.1,201.6
c98.9,60.7,128.1,86.2,151.7,130.9c9.2,17,18.8,40,22,51.1l6,20.3v-44.8c0.8-103.6-28.8-138.3-193.3-229.7
c-39.6-21.8-88-51-107.3-64.7c-55.2-39.6-95.4-88.1-115.8-141c0,0-6.7-16.2-6.7-16.2L609.8,957.9z"/>
<path class="st3" d="M1179.5,540c-5.6,5.6-17.4,11.1-35.1,16.4c-15.4,4.6-35.2,9-59.3,13.2c-151.7,26.3-191.7,46.6-191.7,97.3
c0,13.3,6,27.7,29.6,71.8c16.4,30.3,32.4,65.1,36,77.3c10.4,37.7,12,87.3,4.8,149.8c-3.6,31.4-6.8,63.6-7.6,72.1l-0.8,14.8
l-56.8-27.7c-81.6-40.3-115.7-61.4-148.1-91.4c-54.8-50.7-76-114.7-64.8-197.5c8.8-68.1,35.2-132.8,70.8-173.1l18.4-21.1l-16,11.8
c-68,49.9-109.7,147.2-109.7,257.4c0,84.7,28.4,150.9,88,206c32.4,30,61.6,47.3,140.9,83.6c38,17.8,79.6,38.8,92.8,47
c44.8,29.2,84.4,82.5,98.1,132.4l7.2,26.3l4.8-58.4c2.8-32.5,6.8-67.3,8.8-77.3c2-10.4,7.2-40.3,11.2-66.6
c10.4-65.1,30.8-112.1,58.4-134.3c25.6-21.1,38.4-14.8,63.6,31.4c22,40.7,38,54.7,74.8,65.1c4.4,1.5,8,13.3,13.2,46.6
c6.4,39.9,6.8,50.7,2.4,96.5c-6,61.8-3.6,120.6,6,146.1c10.4,28.1,27.6,51,56.8,74.3l26,21.5l-2.4-38.8
c-6.4-85.1-18-150.2-38.4-208.2c-6.8-18.5-16.4-61-22.4-94.7c-15.6-92.1-51.6-255.2-67.6-306.3c-22.4-71.8-53.6-138.2-90.4-192.6
c-4.9-7.1-17.3-25.2-17.3-25.2s5.9-7.4,9.3-12.6c3.9-4.8,9.7-15.2,12.5-23.7c2.7-8.3,1.7-18,1.7-18S1183.5,535.9,1179.5,540z
M1177.1,619.2c36.4,59.2,61.2,128.3,86,240.8c19.2,88,31.2,150.2,29.2,152.4c-4.4,3.7-19.2-25.9-29.2-58.1
c-12.8-41.8-21.2-58.1-37.2-72.9c-18-17-37.6-23.7-88-30.7c-58.8-8.1-74-15.2-113.7-52.5c-42.4-39.9-59.6-64.7-62-88.4
c-3.6-33.7,9.6-43.6,81.2-62.5c48.4-12.9,71.6-23.3,96.1-42.5c8.8-7,17.8-13.8,17.8-13.8S1167.5,604,1177.1,619.2z"/>
<path class="st3" d="M1130.6,658.7c0,6.7-4.7,23.2-9.1,33.5c-6.4,14.8-8,27.4-8,61.4c0,34-1.6,45.1-6.8,53.6
c-4,5.9-13.2,14.4-13.2,14.4s22.4,3.7,44.4-6.7c52-24.4,55.6-74.3,9.6-139.8c-11-15.6-16.9-20.8-16.9-20.8
S1130.6,654.5,1130.6,658.7z"/>
</g>
</svg>

17
appointment_event/views/appointment_type.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="appointment_type_view_form_inherit_appointment" model="ir.ui.view">
<field name="name">appointment.type.view.form.inherit</field>
<field name="model">appointment.type</field>
<field name="inherit_id" ref="appointment.appointment_type_view_form" />
<field name="arch" type="xml">
<group name="right_details" position="inside">
<field name="create_events" />
<field name="event_type_id" options="{'no_create':1}"
attrs="{'invisible':[('create_events','=',False)],'required':[('create_events','=',True)]}" />
</group>
</field>
</record>
</odoo>
Loading…
Cancel
Save