initial commit

This commit is contained in:
Данил Воробьев 2024-05-03 09:43:00 +00:00
commit fd1d573036
212 changed files with 203160 additions and 0 deletions

7
__init__.py Normal file
View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
from . import populate
from . import wizard

57
__manifest__.py Normal file
View File

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Calendar',
'version': '1.1',
'sequence': 165,
'depends': ['base', 'mail', 'onboarding'],
'summary': "Schedule employees' meetings",
'description': """
This is a full-featured calendar system.
========================================
It supports:
------------
- Calendar of events
- Recurring events
If you need to manage your meetings, you should install the CRM module.
""",
'category': 'Productivity/Calendar',
'demo': [
'data/calendar_demo.xml'
],
'data': [
'security/ir.model.access.csv',
'security/calendar_security.xml',
'data/calendar_cron.xml',
'data/mail_template_data.xml',
'data/calendar_data.xml',
'data/calendar_onboarding_data.xml',
'data/mail_activity_type_data.xml',
'data/mail_message_subtype_data.xml',
'views/mail_activity_views.xml',
'views/calendar_templates.xml',
'views/calendar_views.xml',
'views/res_config_settings_views.xml',
'views/res_partner_views.xml',
'wizard/calendar_provider_config.xml',
'wizard/calendar_popover_delete_wizard.xml',
'wizard/mail_activity_schedule_views.xml',
],
'installable': True,
'application': True,
'assets': {
'web.assets_backend': [
'calendar/static/src/**/*',
],
'web.qunit_suite_tests': [
'calendar/static/tests/**/*',
],
'web.assets_tests': [
'calendar/static/tests/tours/**/*',
],
},
'license': 'LGPL-3',
}

Binary file not shown.

4
controllers/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main

Binary file not shown.

Binary file not shown.

120
controllers/main.py Normal file
View File

@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo.http as http
from odoo.http import request
from odoo.tools.misc import get_lang
class CalendarController(http.Controller):
# YTI Note: Keep id and kwargs only for retrocompatibility purpose
@http.route('/calendar/meeting/accept', type='http', auth="calendar")
def accept_meeting(self, token, id, **kwargs):
attendee = request.env['calendar.attendee'].sudo().search([
('access_token', '=', token),
('state', '!=', 'accepted')])
attendee.do_accept()
return self.view_meeting(token, id)
@http.route('/calendar/recurrence/accept', type='http', auth="calendar")
def accept_recurrence(self, token, id, **kwargs):
attendee = request.env['calendar.attendee'].sudo().search([
('access_token', '=', token),
('state', '!=', 'accepted')])
if attendee:
attendees = request.env['calendar.attendee'].sudo().search([
('event_id', 'in', attendee.event_id.recurrence_id.calendar_event_ids.ids),
('partner_id', '=', attendee.partner_id.id),
('state', '!=', 'accepted'),
])
attendees.do_accept()
return self.view_meeting(token, id)
@http.route('/calendar/meeting/decline', type='http', auth="calendar")
def decline_meeting(self, token, id, **kwargs):
attendee = request.env['calendar.attendee'].sudo().search([
('access_token', '=', token),
('state', '!=', 'declined')])
attendee.do_decline()
return self.view_meeting(token, id)
@http.route('/calendar/recurrence/decline', type='http', auth="calendar")
def decline_recurrence(self, token, id, **kwargs):
attendee = request.env['calendar.attendee'].sudo().search([
('access_token', '=', token),
('state', '!=', 'declined')])
if attendee:
attendees = request.env['calendar.attendee'].sudo().search([
('event_id', 'in', attendee.event_id.recurrence_id.calendar_event_ids.ids),
('partner_id', '=', attendee.partner_id.id),
('state', '!=', 'declined'),
])
attendees.do_decline()
return self.view_meeting(token, id)
@http.route('/calendar/meeting/view', type='http', auth="calendar")
def view_meeting(self, token, id, **kwargs):
attendee = request.env['calendar.attendee'].sudo().search([
('access_token', '=', token),
('event_id', '=', int(id))])
if not attendee:
return request.not_found()
timezone = attendee.partner_id.tz
lang = attendee.partner_id.lang or get_lang(request.env).code
event = request.env['calendar.event'].with_context(tz=timezone, lang=lang).sudo().browse(int(id))
company = event.user_id and event.user_id.company_id or event.create_uid.company_id
# If user is internal and logged, redirect to form view of event
# otherwise, display the simplifyed web page with event informations
if request.session.uid and request.env['res.users'].browse(request.session.uid).user_has_groups('base.group_user'):
return request.redirect('/web?db=%s#id=%s&view_type=form&model=calendar.event' % (request.env.cr.dbname, id))
# NOTE : we don't use request.render() since:
# - we need a template rendering which is not lazy, to render before cursor closing
# - we need to display the template in the language of the user (not possible with
# request.render())
response_content = request.env['ir.ui.view'].with_context(lang=lang)._render_template(
'calendar.invitation_page_anonymous', {
'company': company,
'event': event,
'attendee': attendee,
})
return request.make_response(response_content, headers=[('Content-Type', 'text/html')])
@http.route('/calendar/meeting/join', type='http', auth="user", website=True)
def calendar_join_meeting(self, token, **kwargs):
event = request.env['calendar.event'].sudo().search([
('access_token', '=', token)])
if not event:
return request.not_found()
event.action_join_meeting(request.env.user.partner_id.id)
attendee = request.env['calendar.attendee'].sudo().search([('partner_id', '=', request.env.user.partner_id.id), ('event_id', '=', event.id)])
return request.redirect('/calendar/meeting/view?token=%s&id=%s' % (attendee.access_token, event.id))
# Function used, in RPC to check every 5 minutes, if notification to do for an event or not
@http.route('/calendar/notify', type='json', auth="user")
def notify(self):
return request.env['calendar.alarm_manager'].get_next_notif()
@http.route('/calendar/notify_ack', type='json', auth="user")
def notify_ack(self):
return request.env['res.partner'].sudo()._set_calendar_last_notif_ack()
@http.route('/calendar/join_videocall/<string:access_token>', type='http', auth='public')
def calendar_join_videocall(self, access_token):
event = request.env['calendar.event'].sudo().search([('access_token', '=', access_token)])
if not event:
return request.not_found()
# if channel doesn't exist
if not event.videocall_channel_id:
event._create_videocall_channel()
return request.redirect(event.videocall_channel_id.invitation_url)
@http.route('/calendar/check_credentials', type='json', auth='user')
def check_calendar_credentials(self):
# method should be overwritten by sync providers
return request.env['res.users'].check_calendar_credentials()

18
data/calendar_cron.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<!-- Scheduler for Event Alarm-->
<record forcecreate="True" id="ir_cron_scheduler_alarm" model="ir.cron">
<field name="name">Calendar: Event Reminder</field>
<field name="model_id" ref="model_calendar_alarm_manager"/>
<field name="state">code</field>
<field name="code">model._send_reminder()</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
</record>
</data>
</odoo>

49
data/calendar_data.xml Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<record id="alarm_notif_1" model="calendar.alarm">
<field name="name">Notification - 15 Minutes</field>
<field name="duration" eval="15" />
<field name="interval">minutes</field>
<field name="alarm_type">notification</field>
</record>
<record id="alarm_notif_2" model="calendar.alarm">
<field name="name">Notification - 30 Minutes</field>
<field name="duration" eval="30" />
<field name="interval">minutes</field>
<field name="alarm_type">notification</field>
</record>
<record id="alarm_notif_3" model="calendar.alarm">
<field name="name">Notification - 1 Hours</field>
<field name="duration" eval="1" />
<field name="interval">hours</field>
<field name="alarm_type">notification</field>
</record>
<record id="alarm_notif_4" model="calendar.alarm">
<field name="name">Notification - 2 Hours</field>
<field name="duration" eval="2" />
<field name="interval">hours</field>
<field name="alarm_type">notification</field>
</record>
<record id="alarm_notif_5" model="calendar.alarm">
<field name="name">Notification - 1 Days</field>
<field name="duration" eval="1" />
<field name="interval">days</field>
<field name="alarm_type">notification</field>
</record>
<record id="alarm_mail_1" model="calendar.alarm">
<field name="name">Email - 3 Hours</field>
<field name="duration" eval="3" />
<field name="interval">hours</field>
<field name="alarm_type">email</field>
<field name="mail_template_id" ref="calendar.calendar_template_meeting_reminder"/>
</record>
<record id="alarm_mail_2" model="calendar.alarm">
<field name="name">Email - 6 Hours</field>
<field name="duration" eval="6" />
<field name="interval">hours</field>
<field name="alarm_type">email</field>
<field name="mail_template_id" ref="calendar.calendar_template_meeting_reminder"/>
</record>
</data>
</odoo>

125
data/calendar_demo.xml Normal file
View File

@ -0,0 +1,125 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<record id="cal_contact_1" model="calendar.filters">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_admin"/>
<field name="partner_id" ref="base.res_partner_1"/>
</record>
<record id="cal_contact_2" model="calendar.filters">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_admin"/>
<field name="partner_id" ref="base.partner_demo"/>
</record>
<record id="categ_meet1" model="calendar.event.type">
<field name="name">Customer Meeting</field>
</record>
<record id="categ_meet2" model="calendar.event.type">
<field name="name">Internal Meeting</field>
</record>
<record id="categ_meet3" model="calendar.event.type">
<field name="name">Off-site Meeting</field>
</record>
<record id="categ_meet4" model="calendar.event.type">
<field name="name">Open Discussion</field>
</record>
<record id="categ_meet5" model="calendar.event.type">
<field name="name">Feedback Meeting</field>
</record>
<record id="calendar_event_1" model="calendar.event">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_admin"/>
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_1')])]"/>
<field name="name">Follow-up for Project proposal</field>
<field name="description">Meeting to discuss project plan and hash out the details of implementation.</field>
<field name="start" eval="time.strftime('%Y-%m-03 10:20:00')"/>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field name="stop" eval="time.strftime('%Y-%m-03 16:30:00')"/>
<field name="duration" eval="6.3"/>
<field name="allday" eval="False"/>
</record>
<record id="calendar_event_2" model="calendar.event">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_demo"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_4'),ref('base.res_partner_3')])]"/>
<field name="name">Initial discussion</field>
<field name="description">Discussion with partner for product.</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
<field name="start" eval="time.strftime('%Y-%m-05 12:00:00')"/>
<field name="stop" eval="time.strftime('%Y-%m-05 19:00:00')"/>
<field name="allday" eval="False"/>
<field name="duration" eval="7.0"/>
</record>
<record id="calendar_event_3" model="calendar.event">
<field name="active" eval="True"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_admin')])]"/>
<field name="user_id" ref="base.user_admin"/>
<field name="name">Pricing Discussion</field>
<field name="description">Internal meeting for discussion for new pricing for product and services.</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field name="start" eval="time.strftime('%Y-%m-12 15:55:05')"/>
<field name="stop" eval="time.strftime('%Y-%m-12 18:55:05')"/>
<field name="duration" eval="3.0"/>
<field name="allday" eval="False"/>
</record>
<record id="calendar_event_4" model="calendar.event">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_demo"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_1')])]"/>
<field name="name">Requirements review</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
<field name="start" eval="time.strftime('%Y-%m-20 08:00:00')"/>
<field name="stop" eval="time.strftime('%Y-%m-20 10:30:00')"/>
<field name="duration" eval="2.5"/>
<field name="allday" eval="False"/>
</record>
<record id="calendar_event_5" model="calendar.event">
<field name="active" eval="True"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_admin'),ref('base.res_partner_12')])]"/>
<field name="user_id" ref="base.user_admin"/>
<field name="name">Changes in Designing</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field name="start" eval="time.strftime('%Y-%m-22')"/>
<field name="stop" eval="time.strftime('%Y-%m-22')"/>
<field name="allday" eval="True"/>
</record>
<record id="calendar_event_6" model="calendar.event">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_demo"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_4'),ref('base.res_partner_1'),ref('base.res_partner_12')])]"/>
<field name="name">Presentation for new Services</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field name="start" eval="time.strftime('%Y-%m-18 02:00:00')"/>
<field name="stop" eval="time.strftime('%Y-%m-18 10:30:00')"/>
<field name="duration" eval="8.5"/>
<field name="allday" eval="False"/>
</record>
<record id="calendar_event_7" model="calendar.event">
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_demo"/>
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_4')])]"/>
<field name="name">Presentation of the new Calendar</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field name="start" eval="time.strftime('%Y-%m-16')"/>
<field name="stop" eval="time.strftime('%Y-%m-16')"/>
<field name="duration" eval="8.5"/>
<field name="allday" eval="True"/>
</record>
</data>
</odoo>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- ONBOARDING STEPS -->
<record id="onboarding_onboarding_step_setup_calendar_integration" model="onboarding.onboarding.step">
<field name="title">Connect your calendar</field>
<field name="description">With Outlook or Google</field>
<field name="button_text">Add</field>
<field name="done_text">Done!</field>
<field name="panel_step_open_action_name">action_view_start_calendar_sync</field>
<field name="step_image" type="base64" file="base/static/img/onboarding_calendar.png"></field>
<field name="step_image_filename">onboarding_calendar.png</field>
<field name="step_image_alt">Onboarding Calendar Synchronization</field>
<field name="sequence">1</field>
</record>
<record id="onboarding_onboarding_calendar" model="onboarding.onboarding">
<field name="name">Calendar Onboarding</field>
<field name="step_ids" eval="[(4, ref('calendar.onboarding_onboarding_step_setup_calendar_integration'))]"/>
<field name="panel_close_action_name">action_close_calendar_onboarding</field>
<field name="route_name">calendar</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<record id="mail.mail_activity_data_meeting" model="mail.activity.type">
<field name="category">meeting</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<record id="calendar.subtype_invitation" model="mail.message.subtype">
<field name="name">Invitation</field>
<field name="res_model">calendar.event</field>
<field name="description" eval="False"/>
<field name="default" eval="False"/>
</record>
</data>
</odoo>

451
data/mail_template_data.xml Normal file
View File

@ -0,0 +1,451 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<record id="calendar_template_meeting_invitation" model="mail.template">
<field name="name">Calendar: Meeting Invitation</field>
<field name="model_id" ref="calendar.model_calendar_attendee"/>
<field name="subject">Invitation to {{ object.event_id.name }}</field>
<field name="email_from">{{ (object.event_id.user_id.email_formatted or user.email_formatted or '') }}</field>
<field name="email_to">{{ ('' if object.partner_id.email and object.partner_id.email == object.email else object.email) }}</field>
<field name="partner_to">{{ object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False }}</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="description">Invitation email to new attendees</field>
<field name="body_html" type="html">
<div>
<t t-set="colors" t-value="{'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}"/>
<t t-set="customer" t-value=" object.event_id.find_partner_customer()"/>
<t t-set="target_responsible" t-value="object.partner_id == object.event_id.partner_id"/>
<t t-set="target_customer" t-value="object.partner_id == customer"/>
<t t-set="recurrent" t-value="object.recurrence_id and not ctx.get('calendar_template_ignore_recurrence')"/>
<p>
Hello <t t-out="object.common_name or ''">Wood Corner</t>,<br/><br/>
<t t-if="not target_responsible">
<t t-out="object.event_id.user_id.partner_id.name or ''">Colleen Diaz</t> invited you for the <strong t-out="object.event_id.name or ''">Follow-up for Project proposal</strong> meeting.
</t>
<t t-else="">
Your meeting <strong t-out="object.event_id.name or ''">Follow-up for Project proposal</strong> has been booked.
</t>
</p>
<div style="text-align: center; padding: 16px 0px 16px 0px;">
<a t-attf-href="/calendar/meeting/accept?token={{object.access_token}}&amp;id={{object.event_id.id}}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Accept</a>
<a t-attf-href="/calendar/meeting/decline?token={{object.access_token}}&amp;id={{object.event_id.id}}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Decline</a>
<a t-attf-href="/calendar/meeting/view?token={{object.access_token}}&amp;id={{object.event_id.id}}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px"
>View</a>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tr>
<td width="130px;" style="min-width: 130px;">
<div style="border-top-start-radius: 3px; border-top-end-radius: 3px; font-size: 12px; border-collapse: separate; text-align: center; font-weight: bold; color: #ffffff; min-height: 18px; background-color: #875A7B; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format='EEEE', lang_code=object.env.lang) or ''">Tuesday</t>
</div>
<div style="font-size: 48px; min-height: auto; font-weight: bold; text-align: center; color: #5F5F5F; background-color: #F8F8F8; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format='d', lang_code=object.env.lang) or ''">4</t>
</div>
<div style='font-size: 12px; text-align: center; font-weight: bold; color: #ffffff; background-color: #875A7B;'>
<t t-out="format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format='MMMM y', lang_code=object.env.lang) or ''">May 2021</t>
</div>
<div style="border-collapse: separate; color: #5F5F5F; text-align: center; font-size: 12px; border-bottom-end-radius: 3px; font-weight: bold ; border: 1px solid #875A7B; border-bottom-start-radius: 3px;">
<t t-if="not object.event_id.allday">
<div>
<t t-out="format_time(time=object.event_id.start, tz=object.mail_tz, time_format='short', lang_code=object.env.lang) or ''">11:00 AM</t>
</div>
<t t-if="object.mail_tz">
<div style="font-size: 10px; font-weight: normal">
(<t t-out="object.mail_tz or ''">Europe/Brussels</t>)
</div>
</t>
</t>
</div>
</td>
<td width="20px;"/>
<td style="padding-top: 5px;">
<p><strong>Details of the event</strong></p>
<ul>
<t t-if="object.event_id.location">
<li>Location: <t t-out="object.event_id.location or ''">Bruxelles</t>
(<a target="_blank" t-attf-href="http://maps.google.com/maps?oi=map&amp;q={{object.event_id.location}}">View Map</a>)
</li>
</t>
<t t-if="recurrent">
<li>When: <t t-out="object.recurrence_id.get_recurrence_name()">Every 1 Weeks, for 3 events</t></li>
</t>
<t t-if="not object.event_id.allday and object.event_id.duration">
<li>Duration: <t t-out="('%dH%02d' % (object.event_id.duration,round(object.event_id.duration*60)%60)) or ''">0H30</t></li>
</t>
<li>Attendees
<ul>
<li t-foreach="object.event_id.attendee_ids" t-as="attendee">
<div t-attf-style="display: inline-block; border-radius: 50%; width: 10px; height: 10px; background:{{ colors.get(attendee.state) or 'white' }};"> </div>
<t t-if="attendee.common_name != object.common_name">
<span style="margin-left:5px" t-out="attendee.common_name or ''">Mitchell Admin</span>
</t>
<t t-else="">
<span style="margin-left:5px">You</span>
</t>
</li>
</ul></li>
<t t-if="object.event_id.videocall_location">
<li>
How to Join:
<t t-if="object.get_base_url() in object.event_id.videocall_location"> Join with Odoo Discuss</t>
<t t-else=""> Join at</t><br/>
<a t-att-href="object.event_id.videocall_location" target="_blank" t-out="object.event_id.videocall_location or ''">www.mycompany.com/calendar/join_videocall/xyz</a>
</li>
</t>
<t t-if="not is_html_empty(object.event_id.description)">
<li>Description of the event:
<t t-out="object.event_id.description">Internal meeting for discussion for new pricing for product and services.</t></li>
</t>
</ul>
</td>
</tr></table>
<br/>
Thank you,
<t t-if="object.event_id.user_id.signature">
<br />
<t t-out="object.event_id.user_id.signature or ''">--<br/>Mitchell Admin</t>
</t>
</div>
</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="auto_delete" eval="True"/>
</record>
<record id="calendar_template_meeting_changedate" model="mail.template">
<field name="name">Calendar: Date Updated</field>
<field name="model_id" ref="calendar.model_calendar_attendee"/>
<field name="subject">{{ object.event_id.name }}: Date updated</field>
<field name="email_from">{{ (object.event_id.user_id.email_formatted or user.email_formatted or '') }}</field>
<field name="email_to">{{ ('' if object.partner_id.email and object.partner_id.email == object.email else object.email) }}</field>
<field name="partner_to">{{ object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False }}</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="description">Sent to all attendees if the schedule change</field>
<field name="body_html" type="html">
<div>
<t t-set="colors" t-value="{'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}"/>
<t t-set="is_online" t-value="'appointment_type_id' in object.event_id and object.event_id.appointment_type_id"/>
<t t-set="customer" t-value="object.event_id.find_partner_customer()"/>
<t t-set="target_responsible" t-value="object.partner_id == object.event_id.partner_id"/>
<t t-set="target_customer" t-value="object.partner_id == customer"/>
<t t-set="recurrent" t-value="object.recurrence_id and not ctx.get('calendar_template_ignore_recurrence')"/>
<p>
Hello <t t-out="object.common_name or ''">Ready Mat</t>,<br/><br/>
<t t-if="is_online and target_responsible">
<t t-if="customer">
The date of your appointment with <t t-out="customer.name or ''">Jesse Brown</t> has been updated.
</t>
<t t-else="">
Your appointment has been updated.
</t>
The appointment <strong t-out="object.event_id.appointment_type_id.name or ''">Schedule a Demo</strong> is now scheduled for
<t t-out="object.event_id.get_display_time_tz(tz=object.partner_id.tz) or ''">05/04/2021 at (11:00:00 To 11:30:00) (Europe/Brussels)</t>
</t>
<t t-elif="is_online and target_customer">
The date of your appointment with <t t-out="object.event_id.user_id.partner_id.name or ''">Colleen Diaz</t> has been updated.
The appointment <strong t-out="object.event_id.appointment_type_id.name or ''"></strong> is now scheduled for
<t t-out="object.event_id.get_display_time_tz(tz=object.partner_id.tz) or ''">05/04/2021 at (11:00:00 To 11:30:00) (Europe/Brussels)</t>.
</t>
<t t-else="">
The date of the meeting has been updated.
The meeting <strong t-out="object.event_id.name or ''">Follow-up for Project proposal</strong> created by <t t-out="object.event_id.user_id.partner_id.name or ''">Colleen Diaz</t> is now scheduled for
<t t-out="object.event_id.get_display_time_tz(tz=object.partner_id.tz) or ''">05/04/2021 at (11:00:00 To 11:30:00) (Europe/Brussels)</t>.
</t>
</p>
<div style="text-align: center; padding: 16px 0px 16px 0px;">
<a t-attf-href="/calendar/meeting/accept?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Accept</a>
<a t-attf-href="/calendar/meeting/decline?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Decline</a>
<a t-attf-href="/calendar/meeting/view?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
View</a>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tr>
<td width="130px;" style="min-width: 130px;">
<div style="border-top-start-radius: 3px; border-top-end-radius: 3px; font-size: 12px; border-collapse: separate; text-align: center; font-weight: bold; color: #ffffff; min-height: 18px; background-color: #875A7B; border: 1px solid #875A7B;">
<t t-out='format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format="EEEE", lang_code=object.env.lang) or ""'>Tuesday</t>
</div>
<div style="font-size: 48px; min-height: auto; font-weight: bold; text-align: center; color: #5F5F5F; background-color: #F8F8F8; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format='d', lang_code=object.env.lang) or ''">4</t>
</div>
<div style='font-size: 12px; text-align: center; font-weight: bold; color: #ffffff; background-color: #875A7B;'>
<t t-out='format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format="MMMM y", lang_code=object.env.lang) or ""'>May 2021</t>
</div>
<div style="border-collapse: separate; color: #5F5F5F; text-align: center; font-size: 12px; border-bottom-end-radius: 3px; font-weight: bold; border: 1px solid #875A7B; border-bottom-start-radius: 3px;">
<t t-if="not object.event_id.allday">
<div>
<t t-out='format_time(time=object.event_id.start, tz=object.mail_tz, time_format="short", lang_code=object.env.lang) or ""'>11:00 AM</t>
</div>
<t t-if="object.mail_tz">
<div style="font-size: 10px; font-weight: normal">
(<t t-out="object.mail_tz or ''">Europe/Brussels</t>)
</div>
</t>
</t>
</div>
</td>
<td width="20px;"/>
<td style="padding-top: 5px;">
<p><strong>Details of the event</strong></p>
<ul>
<t t-if="object.event_id.location">
<li>Location: <t t-out="object.event_id.location or ''">Bruxelles</t>
(<a target="_blank" t-attf-href="http://maps.google.com/maps?oi=map&amp;q={{ object.event_id.location }}">View Map</a>)
</li>
</t>
<t t-if="recurrent">
<li>When: <t t-out="object.recurrence_id.get_recurrence_name()">Every 1 Weeks, for 3 events</t></li>
</t>
<t t-if="not object.event_id.allday and object.event_id.duration">
<li>Duration: <t t-out="('%dH%02d' % (object.event_id.duration,round(object.event_id.duration*60)%60)) or ''">0H30</t></li>
</t>
<li>Attendees
<ul>
<li t-foreach="object.event_id.attendee_ids" t-as="attendee">
<div t-attf-style="display: inline-block; border-radius: 50%; width: 10px; height: 10px; background: {{ colors.get(attendee.state) or 'white' }};"> </div>
<t t-if="attendee.common_name != object.common_name">
<span style="margin-left:5px" t-out="attendee.common_name or ''">Mitchell Admin</span>
</t>
<t t-else="">
<span style="margin-left:5px">You</span>
</t>
</li>
</ul></li>
<t t-if="object.event_id.videocall_location">
<li>
How to Join:
<t t-if="object.get_base_url() in object.event_id.videocall_location"> Join with Odoo Discuss</t>
<t t-else=""> Join at</t><br/>
<a t-att-href="object.event_id.videocall_location" target="_blank" t-out="object.event_id.videocall_location or ''">www.mycompany.com/calendar/join_videocall/xyz</a>
</li>
</t>
<t t-if="not is_html_empty(object.event_id.description)">
<li>Description of the event:
<t t-out="object.event_id.description">Internal meeting for discussion for new pricing for product and services.</t></li>
</t>
</ul>
</td>
</tr></table>
<br/>
Thank you,
<t t-if="object.event_id.user_id.signature">
<br />
<t t-out="object.event_id.user_id.signature or ''">--<br/>Mitchell Admin</t>
</t>
</div>
</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="auto_delete" eval="True"/>
</record>
<record id="calendar_template_meeting_reminder" model="mail.template">
<field name="name">Calendar: Reminder</field>
<field name="model_id" ref="calendar.model_calendar_attendee"/>
<field name="subject">{{ object.event_id.name }} - Reminder</field>
<field name="email_from">{{ (object.event_id.user_id.email_formatted or user.email_formatted or '') }}</field>
<field name="email_to">{{ ('' if object.partner_id.email and object.partner_id.email == object.email else object.email) }}</field>
<field name="partner_to">{{ object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False }}</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="description">Sent to all attendees if a reminder is set</field>
<field name="body_html" type="html">
<div>
<t t-set="colors" t-value="{'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}" />
<t t-set="is_online" t-value="'appointment_type_id' in object.event_id and object.event_id.appointment_type_id" />
<t t-set="recurrent" t-value="object.recurrence_id and not ctx.get('calendar_template_ignore_recurrence')" />
<p>
Hello <t t-out="object.common_name or ''">Gemini Furniture</t>,<br/><br/>
This is a reminder for the below event:
</p>
<div style="text-align: center; padding: 16px 0px 16px 0px;">
<a t-attf-href="/calendar/{{ 'recurrence' if recurrent else 'meeting' }}/accept?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Accept</a>
<a t-attf-href="/calendar/{{ 'recurrence' if recurrent else 'meeting' }}/decline?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
Decline</a>
<a t-attf-href="/calendar/meeting/view?token={{ object.access_token }}&amp;id={{ object.event_id.id }}"
style="padding: 5px 10px; color: #FFFFFF; text-decoration: none; background-color: #875A7B; border: 1px solid #875A7B; border-radius: 3px">
View</a>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tr>
<td width="130px;" style="min-width: 130px;">
<div style="border-top-start-radius: 3px; border-top-end-radius: 3px; font-size: 12px; border-collapse: separate; text-align: center; font-weight: bold; color: #ffffff; min-height: 18px; background-color: #875A7B; border: 1px solid #875A7B;">
<t t-out='format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format="EEEE", lang_code=object.env.lang) or ""'>Tuesday</t>
</div>
<div style="font-size: 48px; min-height: auto; font-weight: bold; text-align: center; color: #5F5F5F; background-color: #F8F8F8; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format='d', lang_code=object.env.lang) or ''">4</t>
</div>
<div style='font-size: 12px; text-align: center; font-weight: bold; color: #ffffff; background-color: #875A7B;'>
<t t-out='format_datetime(dt=object.event_id.start, tz=object.mail_tz if not object.event_id.allday else None, dt_format="MMMM y", lang_code=object.env.lang) or ""'>May 2021</t>
</div>
<div style="border-collapse: separate; color: #5F5F5F; text-align: center; font-size: 12px; border-bottom-end-radius: 3px; font-weight: bold; border: 1px solid #875A7B; border-bottom-start-radius: 3px;">
<t t-if="not object.event_id.allday">
<div>
<t t-out='format_time(time=object.event_id.start, tz=object.mail_tz, time_format="short", lang_code=object.env.lang) or ""'>11:00 AM</t>
</div>
<t t-if="object.mail_tz">
<div style="font-size: 10px; font-weight: normal">
(<t t-out="object.mail_tz or ''">Europe/Brussels</t>)
</div>
</t>
</t>
</div>
</td>
<td width="20px;"/>
<td style="padding-top: 5px;">
<p><strong>Details of the event</strong></p>
<ul>
<t t-if="object.event_id.location">
<li>Location: <t t-out="object.event_id.location or ''">Bruxelles</t>
(<a target="_blank" t-attf-href="http://maps.google.com/maps?oi=map&amp;q={{ object.event_id.location }}">View Map</a>)
</li>
</t>
<t t-if="recurrent">
<li>When: <t t-out="object.recurrence_id.get_recurrence_name()">Every 1 Weeks, for 3 events</t></li>
</t>
<t t-if="not object.event_id.allday and object.event_id.duration">
<li>Duration: <t t-out="('%dH%02d' % (object.event_id.duration,round(object.event_id.duration*60)%60)) or ''">0H30</t></li>
</t>
<li>Attendees
<ul>
<li t-foreach="object.event_id.attendee_ids" t-as="attendee">
<div t-attf-style="display: inline-block; border-radius: 50%; width: 10px; height: 10px; background:{{ colors.get(attendee.state) or 'white' }};"> </div>
<t t-if="attendee.common_name != object.common_name">
<span style="margin-left:5px" t-out="attendee.common_name or ''">Mitchell Admin</span>
</t>
<t t-else="">
<span style="margin-left:5px">You</span>
</t>
</li>
</ul></li>
<t t-if="object.event_id.videocall_location">
<li>
How to Join:
<t t-if="object.get_base_url() in object.event_id.videocall_location"> Join with Odoo Discuss</t>
<t t-else=""> Join at</t><br/>
<a t-att-href="object.event_id.videocall_location" target="_blank" t-out="object.event_id.videocall_location or ''">www.mycompany.com/calendar/join_videocall/xyz</a>
</li>
</t>
<t t-if="not is_html_empty(object.event_id.description)">
<li>Description of the event:
<t t-out="object.event_id.description">Internal meeting for discussion for new pricing for product and services.</t></li>
</t>
</ul>
</td>
</tr></table>
<br/>
Thank you,
<t t-if="object.event_id.user_id.signature">
<br />
<t t-out="object.event_id.user_id.signature or ''">--<br/>Mitchell Admin</t>
</t>
</div>
</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="auto_delete" eval="True"/>
</record>
<record id="calendar_template_meeting_update" model="mail.template">
<field name="name">Calendar: Event Update</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="subject">{{object.name}}: Event update</field>
<field name="email_from">{{ (object.user_id.email_formatted or user.email_formatted or '') }}</field>
<field name="email_to">{{ object._get_attendee_emails() }}</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="description">Used to manually notifiy attendees</field>
<field name="body_html" type="html">
<div>
<t t-set="colors" t-value="{'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}" />
<t t-set="is_online" t-value="'appointment_type_id' in object and object.appointment_type_id" />
<t t-set="target_responsible" t-value="object.partner_id == object.partner_id" />
<t t-set="target_customer" t-value="object.partner_id == customer" />
<t t-set="recurrent" t-value="object.recurrence_id and not ctx.get('calendar_template_ignore_recurrence')" />
<t t-set="mail_tz" t-value="object._get_mail_tz() or ctx.get('mail_tz')" />
<div>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="130px;" style="min-width: 130px;">
<div style="border-top-start-radius: 3px; border-top-end-radius: 3px; font-size: 12px; border-collapse: separate; text-align: center; font-weight: bold; color: #ffffff; min-height: 18px; background-color: #875A7B; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.start, tz=mail_tz if not object.allday else None, dt_format='EEEE', lang_code=object.env.lang) ">Tuesday</t>
</div>
<div style="font-size: 48px; min-height: auto; font-weight: bold; text-align: center; color: #5F5F5F; background-color: #F8F8F8; border: 1px solid #875A7B;">
<t t-out="format_datetime(dt=object.start, tz=mail_tz if not object.allday else None, dt_format='d', lang_code=object.env.lang)">4</t>
</div>
<div style='font-size: 12px; text-align: center; font-weight: bold; color: #ffffff; background-color: #875A7B;'>
<t t-out="format_datetime(dt=object.start, tz=mail_tz if not object.allday else None, dt_format='MMMM y', lang_code=object.env.lang)">May 2021</t>
</div>
<div style="border-collapse: separate; color: #5F5F5F; text-align: center; font-size: 12px; border-bottom-end-radius: 3px; font-weight: bold; border: 1px solid #875A7B; border-bottom-start-radius: 3px;">
<t t-if="not object.allday">
<div>
<t t-out="format_time(time=object.start, tz=mail_tz, time_format='short', lang_code=object.env.lang)">11:00 AM</t>
</div>
<t t-if="mail_tz">
<div style="font-size: 10px; font-weight: normal">
(<t t-out="mail_tz"> Europe/Brussels</t>)
</div>
</t>
</t>
</div>
</td>
<td width="20px;"/>
<td style="padding-top: 5px;">
<p>
<strong>Details of the event</strong>
</p>
<ul>
<t t-if="not is_html_empty(object.description)">
<li>Description:
<t t-out="object.description">Internal meeting for discussion for new pricing for product and services.</t></li>
</t>
<t t-if="object.videocall_location">
<li>
How to Join:
<t t-if="object.get_base_url() in object.videocall_location"> Join with Odoo Discuss</t>
<t t-else=""> Join at</t><br/>
<a t-att-href="object.videocall_location" target="_blank" t-out="object.videocall_location or ''">www.mycompany.com/calendar/join_videocall/xyz</a>
</li>
</t>
<t t-if="object.location">
<li>Location: <t t-out="object.location or ''">Bruxelles</t>
(<a target="_blank"
t-attf-href="http://maps.google.com/maps?oi=map&amp;q={{object.location}}">View Map</a>)
</li>
</t>
<t t-if="recurrent">
<li>When: <t t-out="object.recurrence_id.get_recurrence_name()">Every 1 Weeks, for 3 events</t></li>
</t>
<t t-if="not object.allday and object.duration">
<li>Duration:
<t t-out="('%dH%02d' % (object.duration,round(object.duration*60)%60))">0H30</t>
</li>
</t>
</ul>
</td>
</tr>
</table>
</div>
<div class="user_input">
<hr/>
<p placeholder="Enter your message here"><br/></p>
</div>
<t t-if="object.user_id.signature">
<br />
<t t-out="object.user_id.signature or ''">--<br/>Mitchell Admin</t>
</t>
</div>
</field>
</record>
</data>
</odoo>

2367
i18n/af.po Normal file

File diff suppressed because it is too large Load Diff

2363
i18n/am.po Normal file

File diff suppressed because it is too large Load Diff

3045
i18n/ar.po Normal file

File diff suppressed because it is too large Load Diff

2371
i18n/az.po Normal file

File diff suppressed because it is too large Load Diff

2621
i18n/bg.po Normal file

File diff suppressed because it is too large Load Diff

2365
i18n/bn.po Normal file

File diff suppressed because it is too large Load Diff

2368
i18n/bs.po Normal file

File diff suppressed because it is too large Load Diff

2656
i18n/ca.po Normal file

File diff suppressed because it is too large Load Diff

2599
i18n/calendar.pot Normal file

File diff suppressed because it is too large Load Diff

2631
i18n/cs.po Normal file

File diff suppressed because it is too large Load Diff

3045
i18n/da.po Normal file

File diff suppressed because it is too large Load Diff

3059
i18n/de.po Normal file

File diff suppressed because it is too large Load Diff

2372
i18n/el.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/en_GB.po Normal file

File diff suppressed because it is too large Load Diff

3062
i18n/es.po Normal file

File diff suppressed because it is too large Load Diff

3066
i18n/es_419.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_BO.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_CL.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_CO.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_CR.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_DO.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_EC.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_PE.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_PY.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/es_VE.po Normal file

File diff suppressed because it is too large Load Diff

2637
i18n/et.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/eu.po Normal file

File diff suppressed because it is too large Load Diff

2629
i18n/fa.po Normal file

File diff suppressed because it is too large Load Diff

3066
i18n/fi.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/fo.po Normal file

File diff suppressed because it is too large Load Diff

3063
i18n/fr.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/fr_BE.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/fr_CA.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/gl.po Normal file

File diff suppressed because it is too large Load Diff

2367
i18n/gu.po Normal file

File diff suppressed because it is too large Load Diff

2634
i18n/he.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/hi.po Normal file

File diff suppressed because it is too large Load Diff

2384
i18n/hr.po Normal file

File diff suppressed because it is too large Load Diff

2624
i18n/hu.po Normal file

File diff suppressed because it is too large Load Diff

2599
i18n/hy.po Normal file

File diff suppressed because it is too large Load Diff

3051
i18n/id.po Normal file

File diff suppressed because it is too large Load Diff

2604
i18n/is.po Normal file

File diff suppressed because it is too large Load Diff

3055
i18n/it.po Normal file

File diff suppressed because it is too large Load Diff

3036
i18n/ja.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/ka.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/kab.po Normal file

File diff suppressed because it is too large Load Diff

2368
i18n/km.po Normal file

File diff suppressed because it is too large Load Diff

3035
i18n/ko.po Normal file

File diff suppressed because it is too large Load Diff

2363
i18n/lb.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/lo.po Normal file

File diff suppressed because it is too large Load Diff

2628
i18n/lt.po Normal file

File diff suppressed because it is too large Load Diff

2630
i18n/lv.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/mk.po Normal file

File diff suppressed because it is too large Load Diff

2383
i18n/mn.po Normal file

File diff suppressed because it is too large Load Diff

2374
i18n/nb.po Normal file

File diff suppressed because it is too large Load Diff

2363
i18n/ne.po Normal file

File diff suppressed because it is too large Load Diff

3061
i18n/nl.po Normal file

File diff suppressed because it is too large Load Diff

2636
i18n/pl.po Normal file

File diff suppressed because it is too large Load Diff

2623
i18n/pt.po Normal file

File diff suppressed because it is too large Load Diff

3053
i18n/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

2376
i18n/ro.po Normal file

File diff suppressed because it is too large Load Diff

3065
i18n/ru.po Normal file

File diff suppressed because it is too large Load Diff

2622
i18n/sk.po Normal file

File diff suppressed because it is too large Load Diff

2623
i18n/sl.po Normal file

File diff suppressed because it is too large Load Diff

2366
i18n/sq.po Normal file

File diff suppressed because it is too large Load Diff

2640
i18n/sr.po Normal file

File diff suppressed because it is too large Load Diff

2369
i18n/sr@latin.po Normal file

File diff suppressed because it is too large Load Diff

3066
i18n/sv.po Normal file

File diff suppressed because it is too large Load Diff

2627
i18n/th.po Normal file

File diff suppressed because it is too large Load Diff

2649
i18n/tr.po Normal file

File diff suppressed because it is too large Load Diff

3052
i18n/uk.po Normal file

File diff suppressed because it is too large Load Diff

3047
i18n/vi.po Normal file

File diff suppressed because it is too large Load Diff

3033
i18n/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

3033
i18n/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

18
models/__init__.py Normal file
View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import ir_http
from . import res_partner
from . import calendar_event
from . import calendar_alarm
from . import calendar_alarm_manager
from . import calendar_attendee
from . import calendar_filter
from . import calendar_event_type
from . import calendar_recurrence
from . import mail_activity
from . import mail_activity_mixin
from . import mail_activity_type
from . import res_users
from . import onboarding_onboarding
from . import onboarding_onboarding_step

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More