[MERGE] Merge with trunk-cal-jke
New calendar : Component changed : dHtml into Jquery FullCalendar Manage recurrency Manage alarm with notif/mail oAuth google 'web app' Manage coworker / Favorite Use avatar for attendee and filter Manager calendar by partner and not user Your events are now event where you are attendees and not events that you have created Manage quick_create, Quick_view, ... Rename module google_base_account into google_account Rename module base_calendar into calendar New module Google Calendar bzr revid: jke@openerp.com-20140114155927-vu7x8egpcirommus
This commit is contained in:
commit
0848bc7c79
File diff suppressed because it is too large
Load Diff
|
@ -1,138 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record model="res.request.link" id="request_link_event">
|
||||
<field name="name">Event</field>
|
||||
<field name="object">calendar.event</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm1">
|
||||
<field name="name">1 minute before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="1" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm2">
|
||||
<field name="name">5 minutes before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="5" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm3">
|
||||
<field name="name">10 minutes before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="10" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm4">
|
||||
<field name="name">15 minutes before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="15" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm5">
|
||||
<field name="name">30 minutes before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="30" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm6">
|
||||
<field name="name">45 minutes before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="45" />
|
||||
<field name="trigger_interval">minutes</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm7">
|
||||
<field name="name">1 hour before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="1" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm8">
|
||||
<field name="name">2 hours before</field>
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="2" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm9">
|
||||
<field name="name">3 hours before</field>
|
||||
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="3" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm10">
|
||||
<field name="name">4 hours before</field>
|
||||
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="4" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm11">
|
||||
<field name="name">5 hours before</field>
|
||||
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="5" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
<record model="res.alarm" id="alarm12">
|
||||
<field name="name">18 hours before</field>
|
||||
|
||||
<field name="active" eval="1" />
|
||||
<field name="trigger_duration" eval="18" />
|
||||
<field name="trigger_interval">hours</field>
|
||||
<field name="trigger_occurs">before</field>
|
||||
<field name="trigger_related">start</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Scheduler for Event Alarm-->
|
||||
<record forcecreate="True" id="ir_cron_scheduler_alarm"
|
||||
model="ir.cron">
|
||||
<field name="name">Run Event Reminder</field>
|
||||
<field eval="True" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">5</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field eval="'calendar.alarm'" name="model" />
|
||||
<field eval="'do_run_scheduler'" name="function" />
|
||||
<field eval="'(False,)'" name="args" />
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,295 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<!-- CRM Meetings Types Form View -->
|
||||
|
||||
<record id="view_crm_meeting_type_tree" model="ir.ui.view">
|
||||
<field name="name">Meeting Types Tree</field>
|
||||
<field name="model">crm.meeting.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meeting Types" editable="bottom">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_crm_meeting_type" model="ir.actions.act_window">
|
||||
<field name="name">Meeting Types</field>
|
||||
<field name="res_model">crm.meeting.type</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_crm_meeting_type_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_crm_meeting_type" parent="base.menu_calendar_configuration" sequence="1"
|
||||
action="action_crm_meeting_type" groups="base.group_no_one"/>
|
||||
|
||||
<!-- CRM Meetings Form View -->
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_form">
|
||||
<field name="name">CRM - Meetings Form</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Meetings" version="7.0">
|
||||
<field name="state" invisible="True"/>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name"/>
|
||||
</div>
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
<label for="partner_ids" class="oe_edit_only"/>
|
||||
<h2>
|
||||
<field name="partner_ids" widget="many2many_tags"
|
||||
context="{'force_email':True}"
|
||||
on_change="onchange_partner_ids(partner_ids)"/>
|
||||
</h2>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Meeting Details">
|
||||
<group>
|
||||
<group>
|
||||
<field name="date" string="Starting at"
|
||||
on_change="onchange_dates(date, duration, False, allday)"/>
|
||||
<label for="duration"/>
|
||||
<div>
|
||||
<field name="duration" widget="float_time"
|
||||
on_change="onchange_dates(date,duration,False,allday)"
|
||||
class="oe_inline" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<label string="hours" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
(<field name="allday" on_change="onchange_dates(date,False,False,allday)" class="oe_inline"/>
|
||||
<label for="allday" string="All Day?"/>)
|
||||
</div>
|
||||
<field name="date_deadline" groups="base.group_no_one"
|
||||
attrs="{'invisible': ['|', ('allday','=',True), ('duration','<', 24)]}"
|
||||
on_change="onchange_dates(date,False,date_deadline)"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="user_id" groups="base.group_no_one" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="location"/>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
<label for="description"/>
|
||||
<field name="description"/>
|
||||
</page>
|
||||
<page string="Options">
|
||||
<group>
|
||||
<group col="1">
|
||||
<group>
|
||||
<field name="recurrency"/>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('recurrency','=',False)]}">
|
||||
<label for="interval"/>
|
||||
<div>
|
||||
<field name="interval" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="rrule_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
</div>
|
||||
<label string="Until" for="end_type"/>
|
||||
<div>
|
||||
<field name="end_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="count" attrs="{'invisible': [('end_type', '!=', 'count')], 'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="end_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
|
||||
</div>
|
||||
<label string="Select Weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}"/>
|
||||
<group col="2" colspan="1" name="weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}">
|
||||
<field name="mo"/>
|
||||
<field name="tu"/>
|
||||
<field name="we"/>
|
||||
<field name="th"/>
|
||||
<field name="fr"/>
|
||||
<field name="sa"/>
|
||||
<field name="su"/>
|
||||
</group>
|
||||
|
||||
<label string="Day of Month"
|
||||
attrs="{'invisible': [('rrule_type','!=','monthly')]}"/>
|
||||
|
||||
<div attrs="{'invisible': [('rrule_type','!=','monthly')]}">
|
||||
<field name="select1"/>
|
||||
<field name="day"
|
||||
attrs="{'required': [('select1','=','date'), ('rrule_type','=','monthly')],
|
||||
'invisible': [('select1','=','day')]}"/>
|
||||
<field name="byday" string="The"
|
||||
attrs="{'required': [('select1','=','day'), ('rrule_type','=','monthly')], 'invisible': [('select1','=','date')]}"/>
|
||||
<field name="week_list" nolabel="1"
|
||||
attrs="{'required': [('select1','=','day'), ('rrule_type','=','monthly')], 'invisible': [('select1','=','date')]}"/>
|
||||
</div>
|
||||
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="alarm_id" widget="selection" groups="base.group_no_one"/>
|
||||
<field name="class"/>
|
||||
<field name="show_as"/>
|
||||
<field name="rrule" invisible="1" readonly="1"/>
|
||||
<field name="recurrent_id_date" invisible="1"/>
|
||||
<field name="recurrent_id" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Invitations">
|
||||
<field name="attendee_ids" widget="one2many" mode="tree">
|
||||
<tree string="Invitation details" editable="top">
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="email" string="Mail To"/>
|
||||
<field name="state"/>
|
||||
<button name="do_tentative"
|
||||
states="needs-action,declined,accepted"
|
||||
string="Uncertain" type="object"
|
||||
icon="terp-crm"/>
|
||||
<button name="do_accept" string="Accept"
|
||||
states="needs-action,tentative,declined"
|
||||
type="object" icon="gtk-apply"/>
|
||||
<button name="do_decline" string="Decline"
|
||||
states="needs-action,tentative,accepted"
|
||||
type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
<form string="Invitation details" version="7.0">
|
||||
<header>
|
||||
<button name="do_tentative" type="object"
|
||||
states="needs-action,declined,accepted"
|
||||
string="Uncertain"/>
|
||||
<button name="do_accept" type="object"
|
||||
states="needs-action,tentative,declined"
|
||||
string="Accept"/>
|
||||
<button name="do_decline" type="object"
|
||||
states="needs-action,tentative,accepted"
|
||||
string="Decline"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,open,done"/>
|
||||
</header>
|
||||
<group>
|
||||
<group>
|
||||
<field name="email"/>
|
||||
<field name="rsvp"/>
|
||||
<field name="cutype"/>
|
||||
<field name="role"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="partner_id"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_tree">
|
||||
<field name="name">CRM - Meetings Tree</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meetings" fonts="bold:message_unread==True">
|
||||
<field name="name" string="Subject"/>
|
||||
<field name="user_id"/>
|
||||
<field name="date"/>
|
||||
<field name="state" invisible="True"/>
|
||||
<field name="duration"/>
|
||||
<field name="message_unread" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Calendar -->
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_calendar">
|
||||
<field name="name">CRM - Meetings Calendar</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Meetings" date_start="date" color="user_id" date_stop="date_deadline" date_delay="duration">
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Gantt -->
|
||||
|
||||
<record id="view_crm_meeting_gantt" model="ir.ui.view">
|
||||
<field name="name">CRM - Meetings Gantt</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<gantt date_delay="duration" date_start="date" string="Meetings"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Search View -->
|
||||
|
||||
<record id="view_crm_meeting_search" model="ir.ui.view">
|
||||
<field name="name">CRM - Meetings Search</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Meetings">
|
||||
<field name="name" string="Meeting" filter_domain="[('name','ilike',self)]"/>
|
||||
<field name="partner_ids"/>
|
||||
<field name="categ_ids"/>
|
||||
<field name="user_id"/>
|
||||
<separator/>
|
||||
<filter string="My Meetings" help="My Meetings" domain="[('user_id','=',uid)]"/>
|
||||
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meetings action and menu -->
|
||||
|
||||
<record id="action_crm_meeting" model="ir.actions.act_window">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="res_model">crm.meeting</field>
|
||||
<field name="view_mode">calendar,tree,form,gantt</field>
|
||||
<field name="view_id" ref="view_crm_meeting_calendar"/>
|
||||
<field name="search_view_id" ref="view_crm_meeting_search"/>
|
||||
<field name="context">{"calendar_default_user_id": uid}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to schedule a new meeting.
|
||||
</p><p>
|
||||
The calendar is shared between employees and fully integrated with
|
||||
other applications such as the employee holidays or the business
|
||||
opportunities.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_calendar">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="view_crm_meeting_calendar"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_tree">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_crm_meeting_tree"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_form">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_crm_meeting_form"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_gantt">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="view_mode">gantt</field>
|
||||
<field name="view_id" ref="view_crm_meeting_gantt"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Calendar"
|
||||
id="mail_menu_calendar" parent="mail.mail_my_stuff"
|
||||
sequence="10" action="action_crm_meeting"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,54 +0,0 @@
|
|||
-
|
||||
In Order to test base_calendar, I will first create One Simple Event with real data
|
||||
-
|
||||
!record {model: calendar.event, id: calendar_event_technicalpresentation0}:
|
||||
class: private
|
||||
date: '2011-04-30 16:00:00'
|
||||
date_deadline: '2011-04-30 18:30:00'
|
||||
description: The Technical Presentation will cover following topics:\n* Creating OpenERP
|
||||
class\n* Views\n* Wizards\n* Workflows
|
||||
duration: 2.5
|
||||
location: OpenERP S.A.
|
||||
name: Technical Presentation
|
||||
-
|
||||
Now I will set recurrence for this event to occur monday and friday of week
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00', 'recurrency' : True}
|
||||
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], data)
|
||||
-
|
||||
In order to check that recurrent events are views successfully in calendar view, I will open calendar view of events
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
self.fields_view_get(cr, uid, False, 'calendar', context)
|
||||
-
|
||||
In order to check that recurrent events are views successfully in calendar view, I will search for one of the recurrent event and count the number of events
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
assert len(ids) == 9, 'Wrong number of events found'
|
||||
-
|
||||
Now I will make All day event and test it
|
||||
-
|
||||
!record {model: calendar.event, id: calendar_event_alldaytestevent0}:
|
||||
allday: 1
|
||||
class: confidential
|
||||
date: '2011-04-30 00:00:00'
|
||||
date_deadline: '2011-04-30 00:00:00'
|
||||
description: 'All day technical test '
|
||||
location: School
|
||||
name: All day test event
|
||||
-
|
||||
In order to check reminder I will first create reminder
|
||||
-
|
||||
!record {model: res.alarm, id: res_alarm_daybeforeeventstarts0}:
|
||||
name: 1 Day before event starts
|
||||
trigger_duration: 1
|
||||
trigger_interval: days
|
||||
trigger_occurs: before
|
||||
trigger_related: start
|
||||
-
|
||||
Now I will assign this reminder to all day event
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
self.write(cr, uid, [ref("calendar_event_alldaytestevent0")], {'alarm_id': ref("res_alarm_daybeforeeventstarts0")})
|
|
@ -41,6 +41,8 @@ class base_config_settings(osv.osv_memory):
|
|||
'module_base_import': fields.boolean("Allow users to import data from CSV files"),
|
||||
'module_google_drive': fields.boolean('Attach Google documents to any record',
|
||||
help="""This installs the module google_docs."""),
|
||||
'module_google_calendar': fields.boolean('Allow the users to synchronize their calendar with Google Calendar',
|
||||
help="""This installs the module google_calendar."""),
|
||||
'font': fields.many2one('res.font', string="Report Font", help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<label for="id" string="Google Calendar"/>
|
||||
<div name="google_calendar">
|
||||
<div name="module_google_calendar">
|
||||
<field name="module_google_calendar" class="oe_inline"/>
|
||||
<label for="module_google_calendar"/>
|
||||
<div name="google_calendar_config_description" attrs="{'invisible': [('module_google_calendar','=',False)]}">
|
||||
<p>
|
||||
Once installed, you can configure your API credentials for "Google calendar"
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<label for="font" />
|
||||
<div>
|
||||
|
@ -188,6 +202,8 @@
|
|||
<field name="view_mode">form</field>
|
||||
<field name="target">inline</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -15,11 +15,10 @@
|
|||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import google_base_account
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
from . import calendar
|
||||
import controllers
|
||||
import contacts
|
|
@ -1,8 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name': 'Calendar',
|
||||
'version': '1.0',
|
||||
'depends': ['base', 'mail', 'base_action_rule'],
|
||||
'depends': ['base', 'mail', 'base_action_rule','web_calendar'],
|
||||
'summary': 'Personal & Shared Calendar',
|
||||
'description': """
|
||||
This is a full-featured calendar system.
|
||||
|
@ -38,20 +38,29 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'author': 'OpenERP SA',
|
||||
'category': 'Hidden/Dependency',
|
||||
'website': 'http://www.openerp.com',
|
||||
'demo': ['crm_meeting_demo.xml'],
|
||||
'demo': ['calendar_demo.xml'],
|
||||
'data': [
|
||||
'security/calendar_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'base_calendar_view.xml',
|
||||
'crm_meeting_view.xml',
|
||||
'base_calendar_data.xml',
|
||||
'crm_meeting_data.xml',
|
||||
'calendar_view.xml',
|
||||
'contacts_view.xml',
|
||||
'calendar_data.xml',
|
||||
],
|
||||
'test' : ['test/base_calendar_test.yml'],
|
||||
'js': [
|
||||
'static/src/js/*.js'
|
||||
],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'css': [
|
||||
'static/src/css/calendar.css'
|
||||
],
|
||||
'test' : [
|
||||
'test/calendar_test.yml',
|
||||
'test/test_crm_recurrent_meeting_case2.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/base_calendar1.jpeg','images/base_calendar2.jpeg','images/base_calendar3.jpeg','images/base_calendar4.jpeg',],
|
||||
'images': ['images/calendar1.jpeg','images/calendar2.jpeg','images/calendar3.jpeg','images/calendar4.jpeg'],
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,477 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Expense-related subtypes for messaging / Chatter -->
|
||||
<record id="calendar.subtype_invitation" model="mail.message.subtype">
|
||||
<field name="name">Invitation</field>
|
||||
<field name="res_model">crm.meeting</field>
|
||||
<field name="description">Warning, a mandatory field has been modified since the creation of this event</field>
|
||||
<field name="default" eval="False"/>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_notif_1">
|
||||
<field name="name">15 min notif</field>
|
||||
<field name="duration" eval="15" />
|
||||
<field name="interval">minutes</field>
|
||||
<field name="type">notification</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_notif_2">
|
||||
<field name="name">30 min notif</field>
|
||||
<field name="duration" eval="30" />
|
||||
<field name="interval">minutes</field>
|
||||
<field name="type">notification</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_notif_3">
|
||||
<field name="name">1 hour notif</field>
|
||||
<field name="duration" eval="1" />
|
||||
<field name="interval">hours</field>
|
||||
<field name="type">notification</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_notif_4">
|
||||
<field name="name">2 hours notif</field>
|
||||
<field name="duration" eval="2" />
|
||||
<field name="interval">hours</field>
|
||||
<field name="type">notification</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_notif_5">
|
||||
<field name="name">1 day notif</field>
|
||||
<field name="duration" eval="1" />
|
||||
<field name="interval">days</field>
|
||||
<field name="type">notification</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="calendar.alarm" id="alarm_mail_1">
|
||||
<field name="name">15 min mail</field>
|
||||
<field name="duration" eval="15" />
|
||||
<field name="interval">minutes</field>
|
||||
<field name="type">email</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_mail_2">
|
||||
<field name="name">30 min mail</field>
|
||||
<field name="duration" eval="30" />
|
||||
<field name="interval">minutes</field>
|
||||
<field name="type">email</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_mail_3">
|
||||
<field name="name">1 hour mail</field>
|
||||
<field name="duration" eval="1" />
|
||||
<field name="interval">hours</field>
|
||||
<field name="type">email</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_mail_4">
|
||||
<field name="name">2 hours mail</field>
|
||||
<field name="duration" eval="2" />
|
||||
<field name="interval">hours</field>
|
||||
<field name="type">email</field>
|
||||
</record>
|
||||
<record model="calendar.alarm" id="alarm_mail_5">
|
||||
<field name="name">1 day mail</field>
|
||||
<field name="duration" eval="1" />
|
||||
<field name="interval">days</field>
|
||||
<field name="type">email</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Scheduler for Event Alarm-->
|
||||
<record forcecreate="True" id="ir_cron_scheduler_alarm" model="ir.cron">
|
||||
<field name="name">Run Event Reminder</field>
|
||||
<field eval="True" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">30</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field eval="'calendar.alarm_manager'" name="model" />
|
||||
<field eval="'get_next_mail'" name="function" />
|
||||
<!--<field eval="'(False,)'" name="args" />-->
|
||||
</record>
|
||||
|
||||
<record model="crm.meeting.type" id="categ_meet1">
|
||||
<field name="name">Customer Meeting</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.meeting.type" id="categ_meet2">
|
||||
<field name="name">Internal Meeting</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.meeting.type" id="categ_meet3">
|
||||
<field name="name">Off-site Meeting</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.meeting.type" id="categ_meet4">
|
||||
<field name="name">Open Discussion</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.meeting.type" id="categ_meet5">
|
||||
<field name="name">Feedback Meeting</field>
|
||||
</record>
|
||||
|
||||
<record id="calendar_template_meeting_invitation" model="email.template">
|
||||
<field name="name">Meeting Invitation</field>
|
||||
<field name="email_from">${object.event_id.user_id.email or ''}</field>
|
||||
<field name="subject">${object.event_id.name}</field>
|
||||
<field name="model_id" ref="calendar.model_calendar_attendee"/>
|
||||
|
||||
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
|
||||
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
||||
<field name="body_html"><![CDATA[
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>${object.event_id.name}</title>
|
||||
<style>
|
||||
span.oe_mail_footer_access {
|
||||
display:block;
|
||||
text-align:center;
|
||||
color:grey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="border-radius: 2px; max-width: 1200px; height: auto;margin-left: auto;margin-right: auto;background-color:#f9f9f9;">
|
||||
<div style="height:auto;text-align: center;font-size : 30px;color: #8A89BA;">
|
||||
<strong>${object.event_id.name}</strong>
|
||||
</div>
|
||||
<div style="height: 50px;text-align: left;font-size : 14px;border-collapse: separate;margin-top:10px">
|
||||
<strong style="margin-left:12px">Hello ${object.cn}</strong> ,<br/><p style="margin-left:12px">${object.event_id.user_id.partner_id.name} invited you for the ${object.event_id.name} meeting of ${object.event_id.user_id.company_id.name}.</p>
|
||||
</div>
|
||||
<div style="height: auto;margin-left:12px;margin-top:30px;">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${object.event_id.get_interval(object.event_id.date, 'time')}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
% if object.event_id.location:
|
||||
<tr style=" height: 30px;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height: 25px; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Where
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="1" style="vertical-align:top;">
|
||||
<div style = "font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 14px" >
|
||||
: ${object.event_id.location}
|
||||
<span style= "color:#A9A9A9; ">(<a href="http://maps.google.com/maps?oi=map&q=${object.event_id.location}">View Map</a>)
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if object.event_id.description :
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
What
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${object.event_id.description}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if not object.event_id.allday and object.event_id.duration:
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Duration
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${('%dH%02d' % (object.event_id.duration,(object.event_id.duration*60)%60))}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
<tr style=" height: 30px;">
|
||||
<td style="height: 25px;width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
<div>
|
||||
Attendees
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
:
|
||||
% for attendee in object.event_id.attendee_ids:
|
||||
<div style='display:inline-block; border-radius: 50%; width:10px; height:10px;background:${ctx["color"][attendee.state]};'></div>
|
||||
% if attendee.cn != object.cn:
|
||||
<span style="margin-left:5px">${attendee.cn}</span>
|
||||
% else:
|
||||
<span style="margin-left:5px">You</span>
|
||||
% endif
|
||||
% endfor
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div style="height: auto;width:450px; margin:0 auto;padding-top:20px;padding-bottom:40px;">
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#8A89BA;margin : 0 15px 0 0;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/accept?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">Accept</a>
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#808080;margin : 0 15px 0 0;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/decline?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">Decline</a>
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#D8D8D8;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/view?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="calendar_template_meeting_changedate" model="email.template">
|
||||
<field name="name">Meeting Invitation</field>
|
||||
<field name="email_from">${object.event_id.user_id.email or ''}</field>
|
||||
<field name="subject">${object.event_id.name} - Date has been updated</field>
|
||||
<field name="model_id" ref="calendar.model_calendar_attendee"/>
|
||||
|
||||
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
|
||||
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
||||
<field name="body_html"><![CDATA[
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>${object.event_id.name}</title>
|
||||
<style>
|
||||
span.oe_mail_footer_access {
|
||||
display:block;
|
||||
text-align:center;
|
||||
color:grey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="border-radius: 2px; max-width: 1200px; height: auto;margin-left: auto;margin-right: auto;background-color:#f9f9f9;">
|
||||
<div style="height:auto;text-align: center;font-size : 30px;color: #8A89BA;">
|
||||
<strong>${object.event_id.name}</strong>
|
||||
</div>
|
||||
<div style="height: 50px;text-align: left;font-size : 14px;border-collapse: separate;margin-top:10px">
|
||||
<strong style="margin-left:12px">Hello ${object.cn}</strong> ,<br/>
|
||||
<p style="margin-left:12px">The date of the meeting has been changed...<br/>
|
||||
The meeting created by ${object.event_id.user_id.partner_id.name} is now scheduled for : ${object.event_id.date}.</p>
|
||||
</div>
|
||||
<div style="height: auto;margin-left:12px;margin-top:30px;">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${object.event_id.get_interval(object.event_id.date, 'time')}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
% if object.event_id.location:
|
||||
<tr style=" height: 30px;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height: 25px; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Where
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="1" style="vertical-align:top;">
|
||||
<div style = "font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 14px" >
|
||||
: ${object.event_id.location}
|
||||
<span style= "color:#A9A9A9; ">(<a href="http://maps.google.com/maps?oi=map&q=${object.event_id.location}">View Map</a>)
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if object.event_id.description :
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
What
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${object.event_id.description}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if not object.event_id.allday and object.event_id.duration:
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Duration
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${('%dH%02d' % (object.event_id.duration,(object.event_id.duration*60)%60))}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
<tr style=" height: 30px;">
|
||||
<td style="height: 25px;width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
<div>
|
||||
Attendees
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
:
|
||||
% for attendee in object.event_id.attendee_ids:
|
||||
<div style='display:inline-block; border-radius: 50%; width:10px; height:10px;background:${ctx["color"][attendee.state]};'></div>
|
||||
% if attendee.cn != object.cn:
|
||||
<span style="margin-left:5px">${attendee.cn}</span>
|
||||
% else:
|
||||
<span style="margin-left:5px">You</span>
|
||||
% endif
|
||||
% endfor
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div style="height: auto;width:450px; margin:0 auto;padding-top:20px;padding-bottom:40px;">
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#8A89BA;margin : 0 15px 0 0;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/accept?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">Accept</a>
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#808080;margin : 0 15px 0 0;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/decline?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">Decline</a>
|
||||
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#D8D8D8;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/calendar/meeting/view?db=${ctx['dbname']}&token=${object.access_token}&action=${ctx['action_id']}&id=${object.event_id.id}">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="calendar_template_meeting_reminder" model="email.template">
|
||||
<field name="name">Meeting Invitation</field>
|
||||
<field name="email_from">${object.event_id.user_id.email or ''}</field>
|
||||
<field name="subject">${object.event_id.name} - Reminder</field>
|
||||
<field name="model_id" ref="calendar.model_calendar_attendee"/>
|
||||
|
||||
<field name="email_to" >${('' if object.partner_id and object.partner_id.email and object.partner_id.email==object.email else object.email|safe)}</field>
|
||||
<field name="partner_to">${object.partner_id and object.partner_id.email and object.partner_id.email==object.email and object.partner_id.id or False }</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
||||
<field name="body_html"><![CDATA[
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>${object.event_id.name}</title>
|
||||
<style>
|
||||
span.oe_mail_footer_access {
|
||||
display:block;
|
||||
text-align:center;
|
||||
color:grey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="border-radius: 2px; max-width: 1200px; height: auto;margin-left: auto;margin-right: auto;background-color:#f9f9f9;">
|
||||
<div style="height:auto;text-align: center;font-size : 30px;color: #8A89BA;">
|
||||
<strong>${object.event_id.name}</strong>
|
||||
</div>
|
||||
<div style="height: 50px;text-align: left;font-size : 14px;border-collapse: separate;margin-top:10px">
|
||||
<strong style="margin-left:12px">Hello ${object.cn}</strong> ,<br/>
|
||||
<p style="margin-left:12px">this it a rmeinder for the event below : </p>
|
||||
</div>
|
||||
<div style="height: auto;margin-left:12px;margin-top:30px;">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${object.event_id.get_interval(object.event_id.date, 'time')}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
% if object.event_id.location:
|
||||
<tr style=" height: 30px;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height: 25px; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Where
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="1" style="vertical-align:top;">
|
||||
<div style = "font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 14px" >
|
||||
: ${object.event_id.location}
|
||||
<span style= "color:#A9A9A9; ">(<a href="http://maps.google.com/maps?oi=map&q=${object.event_id.location}">View Map</a>)
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if object.event_id.description :
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
What
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${object.event_id.description}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% if not object.event_id.allday and object.event_id.duration:
|
||||
<tr style=" height:auto;">
|
||||
<td style="vertical-align:top;">
|
||||
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
Duration
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3" style="vertical-align:text-top;">
|
||||
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
: ${('%dH%02d' % (object.event_id.duration,(object.event_id.duration*60)%60))}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
<tr style=" height: 30px;">
|
||||
<td style="height: 25px;width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
|
||||
<div>
|
||||
Attendees
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
:
|
||||
% for attendee in object.event_id.attendee_ids:
|
||||
<div style='display:inline-block; border-radius: 50%; width:10px; height:10px;background:${ctx["color"][attendee.state]};'></div>
|
||||
% if attendee.cn != object.cn:
|
||||
<span style="margin-left:5px">${attendee.cn}</span>
|
||||
% else:
|
||||
<span style="margin-left:5px">You</span>
|
||||
% endif
|
||||
% endfor
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -5,10 +5,35 @@
|
|||
((((((((((( Demo Cases )))))))))))
|
||||
-->
|
||||
|
||||
<!--For Meetings-->
|
||||
<!--For Meetings -->
|
||||
<record id="res_partner_another" model="res.partner">
|
||||
<field name="name">Arshaw</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="customer" eval="False"/>
|
||||
<field name="email">fullcalendar@example.com</field>
|
||||
</record>
|
||||
<record id="res_user_another" model="res.users">
|
||||
<field name="name" >Second Demo User</field>
|
||||
<field name="login" >Second Demo User</field>
|
||||
<field name="partner_id" ref="res_partner_another"/>
|
||||
<field name="company_id" ref="base.main_company" />
|
||||
</record>
|
||||
|
||||
<record id="cal_contact_1" model="calendar.contacts">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
</record>
|
||||
<record id="cal_contact_2" model="calendar.contacts">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.partner_demo"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_meeting_1" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_1'),ref('base.res_partner_6')])]"/>
|
||||
<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 eval="time.strftime('%Y-%m-03 10:20:00')" name="date"/>
|
||||
|
@ -20,19 +45,20 @@
|
|||
|
||||
<record id="crm_meeting_2" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<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_5')])]"/>
|
||||
<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 eval="time.strftime('%Y-%m-05 12:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="date_deadline"/>
|
||||
<field eval="7.0" name="duration"/>
|
||||
<field name="state">open</field>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_meeting_3" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root')])]"/>
|
||||
<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')])]"/>
|
||||
|
@ -45,6 +71,7 @@
|
|||
<record id="crm_meeting_4" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_6')])]"/>
|
||||
<field name="name">Requirements review</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-20 8:00:00')" name="date"/>
|
||||
|
@ -55,7 +82,7 @@
|
|||
|
||||
<record id="crm_meeting_5" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_8')])]"/>
|
||||
<field name="name">Changes in Designing</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-22 11:05:00')" name="date"/>
|
||||
|
@ -66,13 +93,39 @@
|
|||
|
||||
<record id="crm_meeting_6" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_1'),ref('base.res_partner_4'),ref('base.res_partner_6'),ref('base.res_partner_8')])]"/>
|
||||
<field name="name">Presentation for new Services</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-18 2:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="date_deadline"/>
|
||||
<field eval="8.5" name="duration"/>
|
||||
<field name="state">open</field>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_meeting_7" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="res_user_another"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('res_partner_another'),ref('base.res_partner_8')])]"/>
|
||||
<field name="name">Presentation of the new Calendar</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-16 6:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-16 18:30:00')" name="date_deadline"/>
|
||||
<field eval="8.5" name="duration"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_meeting_8" model="crm.meeting">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="res_user_another"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('res_partner_another'),ref('base.partner_root')])]"/>
|
||||
<field name="name">Discuss about the module : Calendar </field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-16 6:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-16 18:30:00')" name="date_deadline"/>
|
||||
<field eval="8.5" name="duration"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,321 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<!-- CRM Meetings Types Form View -->
|
||||
|
||||
<record id="view_crm_meeting_type_tree" model="ir.ui.view">
|
||||
<field name="name">Meeting Types Tree</field>
|
||||
<field name="model">crm.meeting.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meeting Types" editable="bottom">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_crm_meeting_type" model="ir.actions.act_window">
|
||||
<field name="name">Meeting Types</field>
|
||||
<field name="res_model">crm.meeting.type</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_crm_meeting_type_tree"/>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meetings Form View -->
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_form">
|
||||
<field name="name">CRM - Meetings Form</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="priority" eval="1"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Meetings" version="7.0">
|
||||
<sheet>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="is_attendee" invisible="1"/>
|
||||
<field name="attendee_status" invisible="1"/>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name"/>
|
||||
</div>
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
<label for="partner_ids" class="oe_edit_only"/>
|
||||
<h2>
|
||||
<field name="partner_ids" widget="many2manyattendee"
|
||||
context="{'force_email':True}"
|
||||
on_change="onchange_partner_ids(partner_ids)"
|
||||
class="oe_inline"/>
|
||||
</h2>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Meeting Details">
|
||||
<group>
|
||||
<group>
|
||||
<field name="date" string="Starting at" on_change="onchange_dates(date, duration, False, allday)"/>
|
||||
<label for="duration"/>
|
||||
<div>
|
||||
<field name="duration" widget="float_time"
|
||||
on_change="onchange_dates(date,duration,False,allday)"
|
||||
class="oe_inline" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<label string="hours" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
(<field name="allday" on_change="onchange_dates(date,False,False,allday)" class="oe_inline"/>
|
||||
<label for="allday" string="All Day?"/>)
|
||||
</div>
|
||||
<field name="date_deadline" groups="base.group_no_one"
|
||||
attrs="{'invisible': ['|', ('allday','=',True), ('duration','<', 24)]}"
|
||||
on_change="onchange_dates(date,False,date_deadline)"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="alarm_ids" widget="many2many_tags" />
|
||||
<field name="location"/>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
<label for="description"/>
|
||||
<field name="description"/>
|
||||
</page>
|
||||
<page string="Options">
|
||||
<group>
|
||||
<group col="1">
|
||||
<group>
|
||||
<field name="recurrency"/>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('recurrency','=',False)]}">
|
||||
<label for="interval"/>
|
||||
<div>
|
||||
<field name="interval" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="rrule_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
</div>
|
||||
<label string="Until" for="end_type"/>
|
||||
<div>
|
||||
<field name="end_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="count" attrs="{'invisible': [('end_type', '!=', 'count')], 'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="end_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
|
||||
</div>
|
||||
<label string="Select Weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}"/>
|
||||
<group col="2" colspan="1" name="weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}" >
|
||||
<field name="mo" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="tu" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="we" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="th" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="fr" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="sa" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="su" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
</group>
|
||||
|
||||
<label string="Day of Month"
|
||||
attrs="{'invisible': [('rrule_type','!=','monthly')]}"/>
|
||||
|
||||
<div attrs="{'invisible': [('rrule_type','!=','monthly')]}">
|
||||
<field name="month_by"/>
|
||||
<field name="day"
|
||||
attrs="{'required': [('month_by','=','date'), ('rrule_type','=','monthly')],
|
||||
'invisible': [('month_by','=','day')]}"/>
|
||||
<field name="byday" string="The"
|
||||
attrs="{'required': [('month_by','=','day'), ('rrule_type','=','monthly')], 'invisible': [('month_by','=','date')]}"/>
|
||||
<field name="week_list" nolabel="1"
|
||||
attrs="{'required': [('month_by','=','day'), ('rrule_type','=','monthly')], 'invisible': [('month_by','=','date')]}"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="class"/>
|
||||
<field name="show_as"/>
|
||||
<field name="rrule" invisible="1" readonly="0" />
|
||||
<field name="recurrent_id" invisible="1" />
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
|
||||
<page string="Invitations" groups="base.group_no_one">
|
||||
<button name="do_sendmail" type="object" string="Send mail" icon="terp-mail-message-new" class="oe_link"/>
|
||||
<field name="attendee_ids" widget="one2many" >
|
||||
<tree string="Invitation details" editable="top" create="false" delete="false">
|
||||
<field name="partner_id" />
|
||||
<field name="state" />
|
||||
<field name="email" widget="email"/>
|
||||
|
||||
<button name="do_tentative" states="needsAction,declined,accepted" string="Uncertain" type="object" icon="terp-crm" />
|
||||
<button name="do_accept" string="Accept" states="needsAction,tentative,declined" type="object" icon="gtk-apply"/>
|
||||
<button name="do_decline" string="Decline" states="needsAction,tentative,accepted" type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Misc" groups="base.group_no_one">
|
||||
<label string="Owner"/>
|
||||
<field name="user_id" />
|
||||
|
||||
</page>
|
||||
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread" />
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_form_popup">
|
||||
<field name="name">Meetings Popup</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Meetings" version="7.0">
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="is_attendee" invisible="1"/>
|
||||
<field name="attendee_status" invisible="1"/>
|
||||
<label for="name"/>
|
||||
<field name="name"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date" string="Start" />
|
||||
<field name="duration" string="Duration" widget="float_time" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<field name="allday" class="oe_inline" attrs="{'invisible': [('allday','=',False)]}"/>
|
||||
<field name="partner_ids" widget="many2manyattendee" string="Attendees"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="alarm_ids" widget="many2many_tags" />
|
||||
<field name="location"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="view_crm_meeting_tree">
|
||||
<field name="name">CRM - Meetings Tree</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meetings" fonts="bold:message_unread==True">
|
||||
<field name="name" string="Subject"/>
|
||||
<field name="date" string="Event Date"/>
|
||||
<field name="user_id"/>
|
||||
<field name="location"/>
|
||||
<field name="show_as"/>
|
||||
<field name="class" string="Privacy"/>
|
||||
<field name="state" invisible="True"/>
|
||||
<field name="duration"/>
|
||||
<field name="message_unread" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Calendar -->
|
||||
<record model="ir.ui.view" id="view_crm_meeting_calendar">
|
||||
<field name="name">Meetings Calendar</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Meetings" date_start="date" date_stop="date_deadline" date_delay="duration" all_day="allday"
|
||||
display="[name]" color="color_partner_id" attendee="partner_ids" avatar_model="res.partner"
|
||||
use_contacts="True" event_open_popup="%(calendar.view_crm_meeting_form_popup)s">
|
||||
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="color_partner_id"/>
|
||||
<field name="partner_ids"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Gantt -->
|
||||
|
||||
<record id="view_crm_meeting_gantt" model="ir.ui.view">
|
||||
<field name="name">CRM - Meetings Gantt</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<gantt date_delay="duration" date_start="date" string="Meetings"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Meeting Search View -->
|
||||
<record id="view_crm_meeting_search" model="ir.ui.view">
|
||||
<field name="name">CRM - Meetings Search</field>
|
||||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Meetings">
|
||||
<field name="name" string="Meeting" filter_domain="[('name','ilike',self)]"/>
|
||||
<field name="partner_ids"/>
|
||||
<field name="categ_ids"/>
|
||||
<field name="user_id"/>
|
||||
<field name="show_as"/>
|
||||
<field name="class" string="Privacy"/>
|
||||
<filter icon="terp-go-today" string="My Events" domain="[('user_id','=',uid)]" help="My Events"/>
|
||||
<filter string="My Meetings" help="My Meetings" name="mymeetings" context='{"mymeetings": 1}'/>
|
||||
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<separator/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Availability" icon="terp-camera_test" domain="[]" context="{'group_by':'show_as'}"/>
|
||||
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
|
||||
<filter string="Event Month" icon="terp-go-month" domain="[]" context="{'group_by':'date'}" help="Start Date of Event by Month"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_crm_meeting" model="ir.actions.act_window">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="res_model">crm.meeting</field>
|
||||
<field name="view_mode">calendar,tree,form,gantt</field>
|
||||
<field name="view_id" ref="view_crm_meeting_calendar"/>
|
||||
<field name="search_view_id" ref="view_crm_meeting_search"/>
|
||||
<field name="context">{"search_default_mymeetings": 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to schedule a new meeting.
|
||||
</p><p>
|
||||
The calendar is shared between employees and fully integrated with
|
||||
other applications such as the employee holidays or the business
|
||||
opportunities.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_calendar">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="view_crm_meeting_calendar"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_tree">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_crm_meeting_tree"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_form">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_crm_meeting_form"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_view_crm_meeting_gantt">
|
||||
<field name="act_window_id" ref="action_crm_meeting"/>
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="view_mode">gantt</field>
|
||||
<field name="view_id" ref="view_crm_meeting_gantt"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Calendar" id="mail_menu_calendar" parent="mail.mail_my_stuff" sequence="10" action="action_crm_meeting"/>
|
||||
<menuitem id="menu_calendar_configuration" name="Calendar" parent="base.menu_custom" groups="base.group_no_one"/>
|
||||
<menuitem id="menu_crm_meeting_type" parent="menu_calendar_configuration" action="action_crm_meeting_type" groups="base.group_no_one"/>
|
||||
|
||||
<!-- called in js from '/js/base_calendar.js' -->
|
||||
<record id="action_crm_meeting_notify" model="ir.actions.act_window">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="res_model">crm.meeting</field>
|
||||
<field name="view_mode">form,calendar,tree,gantt</field>
|
||||
<field name="view_id" ref="action_view_crm_meeting_form"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
class calendar_contacts(osv.osv):
|
||||
_name = 'calendar.contacts'
|
||||
|
||||
_columns = {
|
||||
'user_id': fields.many2one('res.users','Me'),
|
||||
'partner_id': fields.many2one('res.partner','Employee',required=True, domain=[('customer','=',True)]),
|
||||
'active':fields.boolean('active'),
|
||||
}
|
||||
_defaults = {
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'active' : True,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_calendar_contacts" model="ir.ui.view">
|
||||
<field name="name">My Coworkers</field>
|
||||
<field name="model">calendar.contacts</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="contacts" editable="bottom">
|
||||
<field name="partner_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_calendar_contacts" model="ir.actions.act_window">
|
||||
<field name="name">Calendar Contacts</field>
|
||||
<field name="res_model">calendar.contacts</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_calendar_contacts" />
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click on "<b>create</b>" to select colleagues you want to see meetings.
|
||||
</p><p>
|
||||
Your colleagues will appear in the right list to see them in the calendar view. You will easily manage collaboration and meeting with them.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,3 @@
|
|||
import main
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,72 @@
|
|||
import simplejson
|
||||
import urllib
|
||||
import openerp
|
||||
import openerp.addons.web.http as http
|
||||
from openerp.addons.web.http import request
|
||||
import openerp.addons.web.controllers.main as webmain
|
||||
import json
|
||||
from openerp.addons.web.http import SessionExpiredException
|
||||
from werkzeug.exceptions import BadRequest
|
||||
|
||||
class meeting_invitation(http.Controller):
|
||||
|
||||
@http.route('/calendar/meeting/accept', type='http', auth="calendar")
|
||||
def accept(self, db, token, action, id,**kwargs):
|
||||
registry = openerp.modules.registry.RegistryManager.get(db)
|
||||
attendee_pool = registry.get('calendar.attendee')
|
||||
with registry.cursor() as cr:
|
||||
attendee_id = attendee_pool.search(cr, openerp.SUPERUSER_ID, [('access_token','=',token),('state','!=', 'accepted')])
|
||||
if attendee_id:
|
||||
attendee_pool.do_accept(cr, openerp.SUPERUSER_ID, attendee_id)
|
||||
return self.view(db, token, action, id, view='form')
|
||||
|
||||
@http.route('/calendar/meeting/decline', type='http', auth="calendar")
|
||||
def declined(self, db, token, action, id):
|
||||
registry = openerp.modules.registry.RegistryManager.get(db)
|
||||
attendee_pool = registry.get('calendar.attendee')
|
||||
with registry.cursor() as cr:
|
||||
attendee_id = attendee_pool.search(cr, openerp.SUPERUSER_ID, [('access_token','=',token),('state','!=', 'declined')])
|
||||
if attendee_id:
|
||||
attendee_pool.do_decline(cr, openerp.SUPERUSER_ID, attendee_id)
|
||||
return self.view(db, token, action, id, view='form')
|
||||
|
||||
@http.route('/calendar/meeting/view', type='http', auth="calendar")
|
||||
def view(self, db, token, action, id, view='calendar'):
|
||||
registry = openerp.modules.registry.RegistryManager.get(db)
|
||||
meeting_pool = registry.get('crm.meeting')
|
||||
attendee_pool = registry.get('calendar.attendee')
|
||||
with registry.cursor() as cr:
|
||||
attendee_data = meeting_pool.get_attendee(cr, openerp.SUPERUSER_ID, id);
|
||||
attendee = attendee_pool.search_read(cr, openerp.SUPERUSER_ID, [('access_token','=',token)],[])
|
||||
|
||||
if attendee:
|
||||
attendee_data['current_attendee'] = attendee[0]
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in webmain.manifest_list('js', db=db))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in webmain.manifest_list('css',db=db))
|
||||
|
||||
return webmain.html_template % {
|
||||
'js': js,
|
||||
'css': css,
|
||||
'modules': simplejson.dumps(webmain.module_boot(db)),
|
||||
'init': "s.calendar.event('%s', '%s', '%s', '%s' , '%s');" % (db, action, id, 'form', json.dumps(attendee_data)),
|
||||
}
|
||||
|
||||
# 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="none")
|
||||
def notify(self):
|
||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
||||
uid = request.session.uid
|
||||
context = request.session.context
|
||||
with registry.cursor() as cr:
|
||||
res = registry.get("calendar.alarm_manager").get_next_notif(cr,uid,context=context)
|
||||
return res
|
||||
|
||||
@http.route('/calendar/notify_ack', type='json', auth="none")
|
||||
def notify_ack(self, type=''):
|
||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
||||
uid = request.session.uid
|
||||
context = request.session.context
|
||||
with registry.cursor() as cr:
|
||||
res = registry.get("res.partner").calendar_last_notif(cr,uid,context=context)
|
||||
return res
|
||||
|
|
@ -5,5 +5,5 @@
|
|||
<field name="name">Survey / User</field>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,15 +1,16 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_calendar_attendee,calendar.attendee,model_calendar_attendee,,1,1,1,1
|
||||
access_calendar_alarm,calendar.alarm,model_calendar_alarm,base.group_user,1,1,1,1
|
||||
access_res_alarm,res.alarm,model_res_alarm,base.group_user,1,1,1,1
|
||||
access_calendar_todo,calendar.todo,model_calendar_todo,base.group_user,1,1,1,1
|
||||
access_calendar_event,calendar.event,model_calendar_event,base.group_user,1,1,1,1
|
||||
access_calendar_attendee_survey_user,calendar.attendee,model_calendar_attendee,base.group_survey_user,1,0,0,0
|
||||
access_crm_meeting_manager,crm.meeting.manager,model_crm_meeting,base.group_sale_manager,1,1,1,1
|
||||
access_crm_meeting,crm.meeting,model_crm_meeting,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_meeting_all,crm.meeting_allll,model_crm_meeting,base.group_user,1,0,0,0
|
||||
access_crm_meeting_all,crm.meeting_all,model_crm_meeting,base.group_user,1,1,1,1
|
||||
access_crm_meeting_partner_manager,crm.meeting.partner.manager,model_crm_meeting,base.group_partner_manager,1,1,1,1
|
||||
access_crm_meeting_type_all,crm.meeting.type.all,model_crm_meeting_type,,1,0,0,0
|
||||
access_crm_meeting_type_sale_manager,crm.meeting.type.manager,model_crm_meeting_type,base.group_sale_manager,1,1,1,0
|
||||
access_crm_meeting_type_sale_user,crm.meeting.type.user,model_crm_meeting_type,base.group_user,1,0,0,0
|
||||
access_crm_meeting_type_sale_user,crm.meeting.type.salesman,model_crm_meeting_type,base.group_sale_salesman,1,0,0,0
|
||||
access_crm_meeting_type_manager,crm.meeting.type.manager,model_crm_meeting_type,base.group_system,1,1,1,1
|
||||
access_calendar_alarm_manager,access_calendar_alarm_manager,model_calendar_alarm_manager,,1,1,1,1
|
||||
access_calendar_contacts_all,access_calendar_contacts_all,model_calendar_contacts,,1,1,1,1
|
||||
access_calendar_contacts,access_calendar_contacts,model_calendar_contacts,base.group_system,1,1,1,1
|
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
@ -0,0 +1,74 @@
|
|||
.openerp .oe_invitation , .text-core .text-tag .oe_invitation{
|
||||
width : 13px;
|
||||
height : 13px;
|
||||
margin-bottom : -4px;
|
||||
display : inline-block;
|
||||
}
|
||||
.openerp .needsAction , .tentative,.text-core .text-tag .custom-edit, .text-core .text-tag .tentative {
|
||||
background : url(/web/static/src/img/icons/gtk-normal.png) no-repeat;
|
||||
background-size : 11px 11px;
|
||||
}
|
||||
.openerp .accepted , .text-core .text-tag .accepted {
|
||||
background : url(/web/static/src/img/icons/gtk-yes.png) no-repeat;
|
||||
background-size : 11px 11px;
|
||||
}
|
||||
.openerp .declined , .text-core .text-tag .declined {
|
||||
background : url(/web/static/src/img/icons/gtk-no.png) no-repeat;
|
||||
background-size : 11px 11px;
|
||||
}
|
||||
.openerp a.oe_invitation {
|
||||
cursor:default !important;
|
||||
}
|
||||
.cal_meeting {
|
||||
font-size : 24px;
|
||||
font-style: bold;
|
||||
text-align : justify;
|
||||
color : #8A89BA;
|
||||
}
|
||||
.cal_lable {
|
||||
width: 50px;
|
||||
color : #808080;
|
||||
}
|
||||
.invitation_block {
|
||||
padding : 50px 0 0 30px;
|
||||
font-size : 14px;
|
||||
background : #f9f9f9;
|
||||
}
|
||||
.attendee_accepted {
|
||||
background : url(/web/static/src/img/icons/gtk-apply.png) no-repeat;
|
||||
background-size : 15px 15px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.attendee_declined {
|
||||
background : url(/web/static/src/img/icons/gtk-cancel.png) no-repeat;
|
||||
background-size : 15px 15px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.event_status {
|
||||
border : 1px solid;
|
||||
height : 20px;
|
||||
width : auto;
|
||||
background: #808080;
|
||||
color : #FFFFFF;
|
||||
padding: 5px 10px;
|
||||
width: 400px;
|
||||
}
|
||||
.cal_inline {
|
||||
display: inline;
|
||||
}
|
||||
.cal_tag {
|
||||
padding-right : 10px;
|
||||
font-style : italic;
|
||||
font-size : 17px;
|
||||
vertical-align:bottom;
|
||||
}
|
||||
.cal_image {
|
||||
height: 30px;
|
||||
width : 100px;
|
||||
}
|
||||
span.no-wrap {
|
||||
white-space:nowrap
|
||||
}
|
||||
.cal_tab {
|
||||
margin: 20 0 20 0;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
openerp.calendar = function(instance) {
|
||||
var _t = instance.web._t;
|
||||
var QWeb = instance.web.qweb;
|
||||
instance.calendar = {}
|
||||
|
||||
|
||||
instance.web.WebClient = instance.web.WebClient.extend({
|
||||
get_notif_box: function(me) {
|
||||
return $(me).closest(".ui-notify-message-style");
|
||||
},
|
||||
get_next_notif: function() {
|
||||
var self= this;
|
||||
this.rpc("/calendar/notify")
|
||||
.then(
|
||||
function(result) {
|
||||
_.each(result, function(res) {
|
||||
setTimeout(function() {
|
||||
//If notification not already displayed, we add button and action on it
|
||||
if (!($.find(".eid_"+res.event_id)).length) {
|
||||
res.title = QWeb.render('notify_title', {'title': res.title, 'id' : res.event_id});
|
||||
res.message += QWeb.render("notify_footer");
|
||||
a = self.do_notify(res.title,res.message,true);
|
||||
|
||||
$(".link2event").on('click', function() {
|
||||
self.rpc("/web/action/load", {
|
||||
action_id: "calendar.action_crm_meeting_notify",
|
||||
}).then( function(r) {
|
||||
r.res_id = res.event_id;
|
||||
return self.action_manager.do_action(r);
|
||||
});
|
||||
});
|
||||
a.element.find(".link2recall").on('click',function() {
|
||||
self.get_notif_box(this).find('.ui-notify-close').trigger("click");
|
||||
});
|
||||
a.element.find(".link2showed").on('click',function() {
|
||||
self.get_notif_box(this).find('.ui-notify-close').trigger("click");
|
||||
self.rpc("/calendar/notify_ack");
|
||||
});
|
||||
}
|
||||
//If notification already displayed in the past, we remove the css attribute which hide this notification
|
||||
else if (self.get_notif_box($.find(".eid_"+res.event_id)).attr("style") !== ""){
|
||||
self.get_notif_box($.find(".eid_"+res.event_id)).attr("style","");
|
||||
}
|
||||
},res.timer * 1000);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
check_notifications: function() {
|
||||
var self= this;
|
||||
self.get_next_notif();
|
||||
setInterval(function(){
|
||||
self.get_next_notif();
|
||||
}, 5 * 60 * 1000 );
|
||||
},
|
||||
|
||||
//Override the show_application of addons/web/static/src/js/chrome.js
|
||||
show_application: function() {
|
||||
this._super();
|
||||
this.check_notifications();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
instance.calendar.invitation = instance.web.Widget.extend({
|
||||
|
||||
init: function(parent, db, action, id, view, attendee_data) {
|
||||
this._super(parent); // ? parent ?
|
||||
this.db = db;
|
||||
this.action = action;
|
||||
this.id = id;
|
||||
this.view = view;
|
||||
this.attendee_data = attendee_data;
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
if(instance.session.session_is_valid(self.db) && instance.session.username != "anonymous") {
|
||||
self.redirect_meeting_view(self.db,self.action,self.id,self.view);
|
||||
} else {
|
||||
alert('in anonymous or null ');
|
||||
self.open_invitation_form(self.attendee_data);
|
||||
}
|
||||
},
|
||||
open_invitation_form : function(invitation){
|
||||
this.$el.html(QWeb.render('invitation_view', {'invitation': JSON.parse(invitation)}));
|
||||
},
|
||||
redirect_meeting_view : function(db, action, meeting_id, view){
|
||||
var self = this;
|
||||
var action_url = '';
|
||||
|
||||
action_url = _.str.sprintf('/?db=%s#id=%s&view_type=form&model=crm.meeting', db, meeting_id);
|
||||
|
||||
var reload_page = function(){
|
||||
return location.replace(action_url);
|
||||
}
|
||||
reload_page();
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.form.Many2ManyAttendee = instance.web.form.FieldMany2ManyTags.extend({
|
||||
tag_template: "many2manyattendee",
|
||||
initialize_texttext: function() {
|
||||
return _.extend(this._super(),{
|
||||
html : {
|
||||
tag: QWeb.render('m2mattendee_tag')
|
||||
}
|
||||
});
|
||||
},
|
||||
map_tag: function(value){
|
||||
return _.map(value, function(el) {return {name: el[1], id:el[0], state: el[2]};})
|
||||
},
|
||||
get_render_data: function(ids){
|
||||
var self = this;
|
||||
var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context());
|
||||
return dataset.call('get_attendee_detail',[ids, self.getParent().datarecord.id || false]);
|
||||
},
|
||||
render_tag: function(data){
|
||||
this._super(data);
|
||||
var self = this;
|
||||
if (! self.get("effective_readonly")) {
|
||||
var tag_element = self.tags.tagElements();
|
||||
_.each(data,function(value, key){
|
||||
$(tag_element[key]).find(".custom-edit").addClass(data[key][2])
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
instance.web.form.widgets = instance.web.form.widgets.extend({
|
||||
'many2manyattendee' : 'instance.web.form.Many2ManyAttendee',
|
||||
});
|
||||
|
||||
instance.calendar.event = function (db, action, id, view, attendee_data) {
|
||||
instance.session.session_bind(instance.session.origin).done(function () {
|
||||
new instance.calendar.invitation(null,db,action,id,view,attendee_data).appendTo($("body").addClass('openerp'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
<t t-name="many2manyattendee">
|
||||
<t t-set="i" t-value="0"/>
|
||||
<t t-foreach="elements" t-as="el">
|
||||
<span class="oe_tag no-wrap" t-att-data-index="i">
|
||||
<a t-attf-class="oe_invitation #{el[2]}"/>
|
||||
<t t-esc="el[1]"/>
|
||||
</span>
|
||||
<t t-set="i" t-value="i + 1"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-name='notify_title'>
|
||||
<span t-attf-class="'link2event eid_' + id" class='link2event eid_" + res.event_id + "'>
|
||||
<t t-esc="title"/>
|
||||
</span>
|
||||
</t>
|
||||
<t t-name='notify_footer'>
|
||||
<br/><br/>
|
||||
<button class='link2showed oe_highlight oe_form oe_button '><span>OK</span></button>
|
||||
<button class='link2event '>Details</button>
|
||||
<button class='link2recall '>Snooze</button>
|
||||
</t>
|
||||
<t t-name='m2mattendee_tag'>
|
||||
<div class="text-tag">
|
||||
<div class="text-button">
|
||||
<a class="oe_invitation custom-edit"/>
|
||||
<span class="text-label"/>
|
||||
<a class="text-remove"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="invitation_view">
|
||||
<div class='invitation_block well' style='width:50%; margin:auto; margin-top : 30px;'>
|
||||
<div class="oe_right"><b><t t-esc="invitation['current_attendee'].cn"/> (<t t-esc="invitation['current_attendee'].email"/>)</b></div>
|
||||
<div class="oe_left">
|
||||
<img class="cal_inline cal_image" src='/web/binary/company_logo' />
|
||||
</div>
|
||||
<div>
|
||||
<div class="invitation_block cal_meeting">
|
||||
<h2 class="cal_inline">Calendar Invitation</h2>
|
||||
<t t-if="invitation['current_attendee'].state != 'needsAction'">
|
||||
<a t-attf-class="attendee_#{invitation['current_attendee'].state}">
|
||||
<b t-if="invitation['current_attendee'].state == 'accepted'">Yes I'm going.</b>
|
||||
<b t-if="invitation['current_attendee'].state == 'declined'">No I'm not going.</b>
|
||||
</a>
|
||||
</t>
|
||||
<br/><br/>
|
||||
<div class="cal_meeting"><t t-esc="invitation['meeting'].event"/></div>
|
||||
<br/>
|
||||
<table class="">
|
||||
<tr>
|
||||
<td class="cal_lable">When</td>
|
||||
<td> <t t-esc="invitation['meeting'].when"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cal_lable">Where</td>
|
||||
<td> <t t-esc="invitation['meeting'].where or '-'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cal_lable">Who</td>
|
||||
<td>
|
||||
<t t-foreach="invitation['attendee']" t-as="att">
|
||||
<br/>
|
||||
<span class="cal_status"><a t-attf-class="oe_invitation #{att.status}"/><t t-esc="att.name"/></span>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
|
@ -0,0 +1,66 @@
|
|||
-
|
||||
In Order to test calendar, I will first create One Simple Event with real data
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_technicalpresentation0}:
|
||||
class: private
|
||||
date: '2011-04-30 16:00:00'
|
||||
date_deadline: '2011-04-30 18:30:00'
|
||||
description: The Technical Presentation will cover following topics:\n* Creating OpenERP
|
||||
class\n* Views\n* Wizards\n* Workflows
|
||||
duration: 2.5
|
||||
location: OpenERP S.A.
|
||||
name: Technical Presentation
|
||||
-
|
||||
Now I will set recurrence for this event to occur monday and friday of week
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00', 'recurrency' : True}
|
||||
self.write(cr, uid, [ref("crm_meeting_technicalpresentation0")], data)
|
||||
-
|
||||
In order to check that recurrent events are views successfully in calendar view, I will open calendar view of events
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.fields_view_get(cr, uid, False, 'calendar', context)
|
||||
-
|
||||
In order to check that recurrent events are views successfully in calendar view, I will search for one of the recurrent event and count the number of events
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
assert len(ids) == 9, 'Wrong number of events found'
|
||||
-
|
||||
Now I move a virtual event, to see that a real event is well created and depending from the native recurrence
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
before = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
self.write(cr, uid,[ids[1]], {'name':'New Name','recurrency' : True}, context={'virtual_id': True})
|
||||
after = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
assert len(after) == len(before)+1, 'Wrong number of events found, after to have moved a virtual event'
|
||||
new_id = list(set(after)-set(before))[0]
|
||||
new_event = self.browse(cr,uid,new_id,context=context)
|
||||
assert new_event.recurrent_id == before[0], 'Recurrent_id not correctly passed to the new event'
|
||||
-
|
||||
Now I will make All day event and test it
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_alldaytestevent0}:
|
||||
allday: 1
|
||||
class: confidential
|
||||
date: '2011-04-30 00:00:00'
|
||||
date_deadline: '2011-04-30 00:00:00'
|
||||
description: 'All day technical test '
|
||||
location: School
|
||||
name: All day test event
|
||||
-
|
||||
In order to check reminder I will first create reminder
|
||||
-
|
||||
!record {model: calendar.alarm, id: res_alarm_daybeforeeventstarts0}:
|
||||
name: 1 Day before event starts
|
||||
duration: 1
|
||||
interval: days
|
||||
type: notification
|
||||
|
||||
-
|
||||
Now I will assign this reminder to all day event
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.write(cr, uid, [ref("crm_meeting_alldaytestevent0")], {'alarm_ids': [(6,0,[ref("res_alarm_daybeforeeventstarts0")])]})
|
|
@ -70,9 +70,8 @@
|
|||
I change name of my monthly Sprint Review meeting.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
from base_calendar import base_calendar
|
||||
base_cal_id = base_calendar.real_id2base_calendar_id(ref('crm_meeting_sprintreview0'), '2011-09-01 13:01:00')
|
||||
self.write(cr, uid, [base_cal_id], {'name': 'Sprint Review for google modules'})
|
||||
idval = '%d-%s' % (ref('crm_meeting_sprintreview0'), '20110901130100')
|
||||
self.write(cr, uid, [idval], {'name': 'Sprint Review for google modules'})
|
||||
-
|
||||
I check whether all the records are edited or not.
|
||||
-
|
||||
|
@ -85,13 +84,12 @@
|
|||
I change description of my weekly meeting Review code with programmer.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
from base_calendar import base_calendar
|
||||
base_cal_id = base_calendar.real_id2base_calendar_id(ref('crm_meeting_reviewcodewithprogrammer0'), '2011-04-25 12:47:00')
|
||||
self.write(cr, uid, [base_cal_id], {'description': 'Review code of the module: sync_google_calendar.'})
|
||||
idval = '%d-%s' % (ref('crm_meeting_sprintreview0'), '20110425124700')
|
||||
self.write(cr, uid, [idval], {'description': 'Review code of the module: sync_google_calendar.'})
|
||||
-
|
||||
I check whether the record is edited perfectly or not.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
meeting_ids = self.search(cr, uid, [('recurrent_id', '=', ref('crm_meeting_reviewcodewithprogrammer0')), ('recurrent_id_date','=','2011-04-25 12:47:00')], context)
|
||||
meeting_ids = self.search(cr, uid, [('recurrent_id', '=', ref('crm_meeting_sprintreview0')), ('recurrent_id_date','=','2011-04-25 12:47:00')], context)
|
||||
assert meeting_ids, 'Meeting is not edited !'
|
||||
|
|
@ -54,7 +54,7 @@ Dashboard for CRM will include:
|
|||
'process',
|
||||
'mail',
|
||||
'email_template',
|
||||
'base_calendar',
|
||||
'calendar',
|
||||
'resource',
|
||||
'board',
|
||||
'fetchmail',
|
||||
|
|
|
@ -223,7 +223,7 @@ class MergePartnerAutomatic(osv.TransientModel):
|
|||
update_records = functools.partial(update_records, context=context)
|
||||
|
||||
for partner in src_partners:
|
||||
update_records('base.calendar', src=partner, field_model='model_id.model')
|
||||
update_records('calendar', src=partner, field_model='model_id.model')
|
||||
update_records('ir.attachment', src=partner, field_model='res_model')
|
||||
update_records('mail.followers', src=partner, field_model='res_model')
|
||||
update_records('mail.message', src=partner)
|
||||
|
|
|
@ -914,7 +914,7 @@ class crm_lead(format_address, osv.osv):
|
|||
:return dict: dictionary value for created Meeting view
|
||||
"""
|
||||
opportunity = self.browse(cr, uid, ids[0], context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_crm_meeting', context)
|
||||
res['context'] = {
|
||||
'default_opportunity_id': opportunity.id,
|
||||
'default_partner_id': opportunity.partner_id and opportunity.partner_id.id or False,
|
||||
|
|
|
@ -24,7 +24,7 @@ import logging
|
|||
_logger = logging.getLogger(__name__)
|
||||
|
||||
#
|
||||
# crm.meeting is defined in module base_calendar
|
||||
# crm.meeting is defined in module calendar
|
||||
#
|
||||
class crm_meeting(osv.Model):
|
||||
""" Model for CRM meetings """
|
||||
|
|
|
@ -265,7 +265,7 @@ class crm_phonecall(osv.osv):
|
|||
:return dict: dictionary value for created meeting view
|
||||
"""
|
||||
phonecall = self.browse(cr, uid, ids[0], context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_crm_meeting', context)
|
||||
res['context'] = {
|
||||
'default_phonecall_id': phonecall.id,
|
||||
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
context="{'search_default_partner_id': active_id}"/>
|
||||
<button class="oe_inline" type="action"
|
||||
string="Meetings"
|
||||
name="%(base_calendar.action_crm_meeting)d"
|
||||
name="%(calendar.action_crm_meeting)d"
|
||||
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
|
||||
<button class="oe_inline" type="action" string="Calls"
|
||||
name="%(crm.crm_case_categ_phone_incoming0)d"
|
||||
|
|
|
@ -109,10 +109,10 @@
|
|||
-
|
||||
!python {model: crm.meeting}: |
|
||||
context.update({'active_model': 'crm.meeting'})
|
||||
self.write(cr, uid, [ref('base_calendar.crm_meeting_4')], {'state': 'open'})
|
||||
self.write(cr, uid, [ref('calendar.crm_meeting_4')], {'state': 'open'})
|
||||
-
|
||||
I invite a user for meeting.
|
||||
-
|
||||
!python {model: calendar.attendee}: |
|
||||
meeting_id = self.create(cr, uid, {'user_id': ref('base.user_root'), 'email': 'user@meeting.com' })
|
||||
meeting_id = self.create(cr, uid, {'partner_id': ref('base.partner_root'), 'email': 'user@meeting.com' })
|
||||
self.do_accept(cr, uid, [meeting_id])
|
||||
|
|
|
@ -48,7 +48,7 @@ class crm_phonecall2meeting(osv.osv_memory):
|
|||
phonecall_id = context and context.get('active_id', False) or False
|
||||
if phonecall_id:
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, phonecall_id, context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_crm_meeting', context)
|
||||
res['context'] = {
|
||||
'default_phonecall_id': phonecall.id,
|
||||
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
|
||||
|
|
|
@ -32,6 +32,7 @@ from openerp import tools
|
|||
from openerp.tools.translate import _
|
||||
from urllib import urlencode, quote as quote
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import base_calendar
|
||||
import crm_meeting
|
||||
import google_account
|
||||
import controllers
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -32,7 +32,7 @@ The module adds google user in res user.
|
|||
'website': 'http://www.openerp.com',
|
||||
'depends': ['base_setup'],
|
||||
'data': [
|
||||
'google_base_account_data.xml',
|
||||
'google_account_data.xml',
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
|
@ -0,0 +1 @@
|
|||
import main
|
|
@ -0,0 +1,32 @@
|
|||
import simplejson
|
||||
import urllib
|
||||
import openerp
|
||||
import openerp.addons.web.http as http
|
||||
from openerp.addons.web.http import request
|
||||
import openerp.addons.web.controllers.main as webmain
|
||||
from openerp.addons.web.http import SessionExpiredException
|
||||
from werkzeug.exceptions import BadRequest
|
||||
import werkzeug.utils
|
||||
|
||||
class google_auth(http.Controller):
|
||||
|
||||
@http.route('/google_account/authentication', type='http', auth="none")
|
||||
def oauth2callback(self, **kw):
|
||||
""" This route/function is called by Google when user Accept/Refuse the consent of Google """
|
||||
|
||||
state = simplejson.loads(kw['state'])
|
||||
dbname = state.get('d')
|
||||
service = state.get('s')
|
||||
url_return = state.get('f')
|
||||
|
||||
registry = openerp.modules.registry.RegistryManager.get(dbname)
|
||||
with registry.cursor() as cr:
|
||||
if kw.get('code',False):
|
||||
registry.get('google.%s' % service).set_all_tokens(cr,request.session.uid,kw['code'])
|
||||
return werkzeug.utils.redirect(url_return)
|
||||
elif kw.get('error'):
|
||||
return werkzeug.utils.redirect("%s%s%s" % (url_return ,"?error=" , kw.get('error')))
|
||||
else:
|
||||
return werkzeug.utils.redirect("%s%s%s" % (url_return ,"?error=Unknown_error"))
|
||||
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.tools.translate import _
|
||||
from openerp.addons.web.http import request
|
||||
|
||||
import urllib
|
||||
import urllib2
|
||||
import simplejson
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class google_service(osv.osv_memory):
|
||||
_name = 'google.service'
|
||||
|
||||
def generate_refresh_token(self, cr, uid, service, authorization_code, context=None):
|
||||
ir_config = self.pool['ir.config_parameter']
|
||||
client_id = ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service)
|
||||
client_secret = ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_secret' % service)
|
||||
redirect_uri = ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri')
|
||||
|
||||
#Get the Refresh Token From Google And store it in ir.config_parameter
|
||||
headers = {"Content-type": "application/x-www-form-urlencoded"}
|
||||
data = dict(code=authorization_code, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, grant_type="authorization_code")
|
||||
data = urllib.urlencode(data)
|
||||
try:
|
||||
req = urllib2.Request("https://accounts.google.com/o/oauth2/token", data, headers)
|
||||
content = urllib2.urlopen(req).read()
|
||||
except urllib2.HTTPError:
|
||||
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"), context=context)
|
||||
|
||||
content = simplejson.loads(content)
|
||||
return content.get('refresh_token')
|
||||
|
||||
def _get_google_token_uri(self, cr, uid, service, scope, context=None):
|
||||
ir_config = self.pool['ir.config_parameter']
|
||||
params = {
|
||||
'scope': scope,
|
||||
'redirect_uri': ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri'),
|
||||
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
|
||||
'response_type': 'code',
|
||||
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
|
||||
}
|
||||
uri = 'https://accounts.google.com/o/oauth2/auth?%s' % urllib.urlencode(params)
|
||||
return uri
|
||||
|
||||
#If no scope is passed, we use service by default to get a default scope
|
||||
def _get_authorize_uri(self, cr, uid, from_url, service, scope = False, context=None):
|
||||
""" This method return the url needed to allow this instance of OpenErp to access to the scope of gmail specified as parameters """
|
||||
state_obj = dict(d=cr.dbname, s=service, f=from_url)
|
||||
|
||||
base_url = self.get_base_url(cr, uid, context)
|
||||
client_id = self.get_client_id(cr, uid, service, context)
|
||||
|
||||
params = {
|
||||
'response_type': 'code',
|
||||
'client_id': client_id,
|
||||
'state' : simplejson.dumps(state_obj),
|
||||
'scope': scope or 'https://www.googleapis.com/auth/%s' % (service,),
|
||||
'redirect_uri': base_url + '/google_account/authentication',
|
||||
'approval_prompt':'force',
|
||||
'access_type':'offline'
|
||||
}
|
||||
|
||||
uri = self.get_uri_oauth(a='auth') + "?%s" % urllib.urlencode(params)
|
||||
return uri
|
||||
|
||||
def _get_google_token_json(self, cr, uid, authorize_code, service, context=None):
|
||||
res = False
|
||||
base_url = self.get_base_url(cr, uid, context)
|
||||
client_id = self.get_client_id(cr, uid, service, context)
|
||||
client_secret = self.get_client_secret(cr, uid, service, context)
|
||||
|
||||
params = {
|
||||
'code': authorize_code,
|
||||
'client_id': client_id,
|
||||
'client_secret': client_secret,
|
||||
'grant_type' : 'authorization_code',
|
||||
'redirect_uri': base_url + '/google_account/authentication'
|
||||
}
|
||||
|
||||
headers = {"content-type": "application/x-www-form-urlencoded"}
|
||||
|
||||
try:
|
||||
data = urllib.urlencode(params)
|
||||
req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers)
|
||||
|
||||
content = urllib2.urlopen(req).read()
|
||||
res = simplejson.loads(content)
|
||||
except urllib2.HTTPError,e:
|
||||
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid"), context=context)
|
||||
return res
|
||||
|
||||
def _refresh_google_token_json(self, cr, uid, refresh_token, service, context=None): #exchange_AUTHORIZATION vs Token (service = calendar)
|
||||
res = False
|
||||
base_url = self.get_base_url(cr, uid, context)
|
||||
client_id = self.get_client_id(cr, uid, service, context)
|
||||
client_secret = self.get_client_secret(cr, uid, service, context)
|
||||
|
||||
params = {
|
||||
'refresh_token': refresh_token,
|
||||
'client_id': client_id,
|
||||
'client_secret': client_secret,
|
||||
'grant_type' : 'refresh_token'
|
||||
}
|
||||
|
||||
headers = {"content-type": "application/x-www-form-urlencoded"}
|
||||
|
||||
try:
|
||||
data = urllib.urlencode(params)
|
||||
req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers)
|
||||
content = urllib2.urlopen(req).read()
|
||||
res = simplejson.loads(content)
|
||||
except urllib2.HTTPError:
|
||||
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"), context=context)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def _do_request(self,cr,uid,uri,params={},headers={},type='POST', context=None):
|
||||
_logger.debug("Uri: %s - Type : %s - Headers: %s - Params : %s !" % (uri,type,headers,urllib.urlencode(params) if type =='GET' else params))
|
||||
res = False
|
||||
|
||||
try:
|
||||
if type.upper() == 'GET' or type.upper() == 'DELETE':
|
||||
data = urllib.urlencode(params)
|
||||
req = urllib2.Request(self.get_uri_api() + uri + "?" + data)
|
||||
elif type.upper() == 'POST' or type.upper() == 'PATCH' or type.upper() == 'PUT':
|
||||
req = urllib2.Request(self.get_uri_api() + uri, params, headers)
|
||||
else:
|
||||
raise ('Method not supported [%s] not in [GET, POST, PUT, PATCH or DELETE]!' % (type))
|
||||
req.get_method = lambda: type.upper()
|
||||
|
||||
request = urllib2.urlopen(req)
|
||||
|
||||
if request.getcode() == 204: #No content returned, (ex: POST calendar/event/clear)
|
||||
res = True
|
||||
elif request.getcode() == 404: #Page not found
|
||||
res = False
|
||||
else:
|
||||
content=request.read()
|
||||
res = simplejson.loads(content)
|
||||
except urllib2.HTTPError,e:
|
||||
_logger.exception("Bad google request : %s !" % e.read())
|
||||
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong with your request to google"), context=context)
|
||||
return res
|
||||
|
||||
def get_base_url(self, cr, uid, context=None):
|
||||
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url',default='http://www.openerp.com?NoBaseUrl',context=context)
|
||||
|
||||
def get_client_id(self, cr, uid, service, context=None):
|
||||
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_id' % (service,),default=False,context=context)
|
||||
|
||||
def get_client_secret(self, cr, uid, service, context=None):
|
||||
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_secret' % (service,),default=False,context=context)
|
||||
|
||||
def get_uri_oauth(self,a=''): #a = optional action
|
||||
return "https://accounts.google.com/o/oauth2/%s" % (a,)
|
||||
|
||||
def get_uri_api(self):
|
||||
return 'https://www.googleapis.com'
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="config_google_redirect_uri" model="ir.config_parameter">
|
||||
<field name="key">google_redirect_uri</field>
|
||||
<field name="value">urn:ietf:wg:oauth:2.0:oob</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue