[MERGE] merge trunk into local branch

bzr revid: ged@openerp.com-20140116144326-8kwqab71zp8s7a8e
This commit is contained in:
Gery Debongnie 2014-01-16 15:43:26 +01:00
commit 00c6d55ac9
258 changed files with 5296 additions and 3129 deletions

View File

@ -1023,7 +1023,10 @@ class account_period(osv.osv):
if not result:
result = self.search(cr, uid, args, context=context)
if not result:
raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
model, action_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'account', 'action_account_fiscalyear')
msg = _('There is no period defined for this date: %s.\nPlease, go to Configuration/Periods and configure a fiscal year.') % dt
raise openerp.exceptions.RedirectWarning(msg, action_id, _('Go to the configuration panel'))
return result
def action_draft(self, cr, uid, ids, *args):

View File

@ -849,18 +849,17 @@ class account_move_line(osv.osv):
(tuple(ids), ))
r = cr.fetchall()
#TODO: move this check to a constraint in the account_move_reconcile object
if len(r) != 1:
raise osv.except_osv(_('Error'), _('Entries are not of the same account or already reconciled ! '))
if not unrec_lines:
raise osv.except_osv(_('Error!'), _('Entry is already reconciled.'))
account = account_obj.browse(cr, uid, account_id, context=context)
if not account.reconcile:
raise osv.except_osv(_('Error'), _('The account is not defined to be reconciled !'))
if r[0][1] != None:
raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.'))
if context.get('fy_closing'):
# We don't want to generate any write-off when being called from the
# wizard used to close a fiscal year (and it doesn't give us any
# writeoff_acc_id).
pass
elif (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \
if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \
(account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))):
if not writeoff_acc_id:
raise osv.except_osv(_('Warning!'), _('You have to provide an account for the write off/exchange difference entry.'))
@ -1199,7 +1198,7 @@ class account_move_line(osv.osv):
break
# Automatically convert in the account's secondary currency if there is one and
# the provided values were not already multi-currency
if account.currency_id and (vals.get('amount_currency', False) is False) and account.currency_id.id != account.company_id.currency_id.id:
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
vals['currency_id'] = account.currency_id.id
ctx = {}
if 'date' in vals:

View File

@ -224,14 +224,6 @@ class account_fiscalyear_close(osv.osv_memory):
query_2nd_part = ""
query_2nd_part_args = []
for account in obj_acc_account.browse(cr, uid, account_ids, context={'fiscalyear': fy_id}):
balance_in_currency = 0.0
if account.currency_id:
cr.execute('SELECT sum(COALESCE(amount_currency,0.0)) as balance_in_currency FROM account_move_line ' \
'WHERE account_id = %s ' \
'AND ' + query_line + ' ' \
'AND currency_id = %s', (account.id, account.currency_id.id))
balance_in_currency = cr.dictfetchone()['balance_in_currency']
company_currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id
if not currency_obj.is_zero(cr, uid, company_currency_id, abs(account.balance)):
if query_2nd_part:
@ -246,7 +238,7 @@ class account_fiscalyear_close(osv.osv_memory):
period.id,
account.id,
account.currency_id and account.currency_id.id or None,
balance_in_currency,
account.foreign_balance if account.currency_id else 0.0,
account.company_id.id,
'draft')
if query_2nd_part:

View File

@ -43,6 +43,7 @@
parent_id: account.cash
type: other
user_type: account.data_account_type_asset
reconcile: True
-
Configure Creditor Account Payable.
-
@ -52,6 +53,7 @@
parent_id: account.a_pay
type: other
user_type: account.data_account_type_payable
reconcile: True
-
Configure Debtor Account Receivable.
-
@ -61,6 +63,7 @@
parent_id: account.a_recv
type: other
user_type: account.data_account_type_receivable
reconcile: True
-
Configure Cost of Good sale Account.
-

View File

@ -43,6 +43,7 @@
parent_id: account.cash
type: other
user_type: account.data_account_type_asset
reconcile: True
-
Configure Creditor Account Payable.
-
@ -52,6 +53,7 @@
parent_id: account.a_pay
type: other
user_type: account.data_account_type_payable
reconcile: True
-
Configure Debtor Account Receivable.
-
@ -61,6 +63,7 @@
parent_id: account.a_recv
type: other
user_type: account.data_account_type_receivable
reconcile: True
-
Configure Cost of Good sale Account.
-

View File

@ -217,7 +217,7 @@ class account_voucher(osv.osv):
if context.get('type', 'sale') in ('purchase', 'payment'):
nodes = doc.xpath("//field[@name='partner_id']")
for node in nodes:
node.set('context', "{'search_default_supplier': 1}")
node.set('context', "{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}")
if context.get('invoice_type','') in ('in_invoice', 'in_refund'):
node.set('string', _("Supplier"))
res['arch'] = etree.tostring(doc)
@ -1329,7 +1329,7 @@ class account_voucher(osv.osv):
'date': voucher.date,
'credit': diff > 0 and diff or 0.0,
'debit': diff < 0 and -diff or 0.0,
'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or False,
'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or 0.0,
'currency_id': company_currency <> current_currency and current_currency or False,
'analytic_account_id': voucher.analytic_id and voucher.analytic_id.id or False,
}

View File

@ -194,7 +194,7 @@ class account_analytic_account(osv.osv):
'user_id': fields.many2one('res.users', 'Project Manager', track_visibility='onchange'),
'manager_id': fields.many2one('res.users', 'Account Manager', track_visibility='onchange'),
'date_start': fields.date('Start Date'),
'date': fields.date('End Date', select=True, track_visibility='onchange'),
'date': fields.date('Expiration Date', select=True, track_visibility='onchange'),
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'),('pending','To Renew'),('close','Closed'),('cancelled', 'Cancelled')], 'Status', required=True, track_visibility='onchange'),
'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company

File diff suppressed because it is too large Load Diff

View File

@ -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>

View File

@ -1,78 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!--
((((((((((( Demo Cases )))))))))))
-->
<!--For Meetings-->
<record id="crm_meeting_1" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_root"/>
<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"/>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="date_deadline"/>
<field eval="6.3" name="duration"/>
<field name="state">open</field>
</record>
<record id="crm_meeting_2" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_root"/>
<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>
</record>
<record id="crm_meeting_3" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_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')])]"/>
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="date"/>
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="date_deadline"/>
<field eval="3.0" name="duration"/>
<field name="state">open</field>
</record>
<record id="crm_meeting_4" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_demo"/>
<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"/>
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="date_deadline"/>
<field eval="2.5" name="duration"/>
<field name="state">open</field>
</record>
<record id="crm_meeting_5" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_demo"/>
<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"/>
<field eval="time.strftime('%Y-%m-22 16:05:00')" name="date_deadline"/>
<field eval="5" name="duration"/>
<field name="state">open</field>
</record>
<record id="crm_meeting_6" model="crm.meeting">
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_root"/>
<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>
</record>
</data>
</openerp>

View File

@ -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','&lt;', 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>

View File

@ -1,15 +0,0 @@
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_partner_manager,crm.meeting.partner.manager,model_crm_meeting,base.group_partner_manager,1,1,1,1
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_calendar_attendee calendar.attendee model_calendar_attendee 1 1 1 1
3 access_calendar_alarm calendar.alarm model_calendar_alarm base.group_user 1 1 1 1
4 access_res_alarm res.alarm model_res_alarm base.group_user 1 1 1 1
5 access_calendar_todo calendar.todo model_calendar_todo base.group_user 1 1 1 1
6 access_calendar_event calendar.event model_calendar_event base.group_user 1 1 1 1
7 access_calendar_attendee_survey_user calendar.attendee model_calendar_attendee base.group_survey_user 1 0 0 0
8 access_crm_meeting_manager crm.meeting.manager model_crm_meeting base.group_sale_manager 1 1 1 1
9 access_crm_meeting crm.meeting model_crm_meeting base.group_sale_salesman 1 1 1 0
10 access_crm_meeting_all crm.meeting_allll model_crm_meeting base.group_user 1 0 0 0
11 access_crm_meeting_partner_manager crm.meeting.partner.manager model_crm_meeting base.group_partner_manager 1 1 1 1
12 access_crm_meeting_type_sale_manager crm.meeting.type.manager model_crm_meeting_type base.group_sale_manager 1 1 1 0
13 access_crm_meeting_type_sale_user crm.meeting.type.user model_crm_meeting_type base.group_user 1 0 0 0
14 access_crm_meeting_type_sale_user crm.meeting.type.salesman model_crm_meeting_type base.group_sale_salesman 1 0 0 0
15 access_crm_meeting_type_manager crm.meeting.type.manager model_crm_meeting_type base.group_system 1 1 1 1

View File

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

View File

@ -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>

View File

@ -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

View File

@ -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_calendar_recurrent_event_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:

1622
addons/calendar/calendar.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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">calendar.event</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="calendar.event.type" id="categ_meet1">
<field name="name">Customer Meeting</field>
</record>
<record model="calendar.event.type" id="categ_meet2">
<field name="name">Internal Meeting</field>
</record>
<record model="calendar.event.type" id="categ_meet3">
<field name="name">Off-site Meeting</field>
</record>
<record model="calendar.event.type" id="categ_meet4">
<field name="name">Open Discussion</field>
</record>
<record model="calendar.event.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>

View File

@ -0,0 +1,131 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!--
((((((((((( Demo Cases )))))))))))
-->
<!--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="calendar_event_1" model="calendar.event">
<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"/>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="date_deadline"/>
<field eval="6.3" name="duration"/>
<field name="state">open</field>
</record>
<record id="calendar_event_2" model="calendar.event">
<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_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">draft</field>
</record>
<record id="calendar_event_3" model="calendar.event">
<field eval="1" name="active"/>
<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')])]"/>
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="date"/>
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="date_deadline"/>
<field eval="3.0" name="duration"/>
<field name="state">open</field>
</record>
<record id="calendar_event_4" model="calendar.event">
<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"/>
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="date_deadline"/>
<field eval="2.5" name="duration"/>
<field name="state">open</field>
</record>
<record id="calendar_event_5" model="calendar.event">
<field eval="1" name="active"/>
<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"/>
<field eval="time.strftime('%Y-%m-22 16:05:00')" name="date_deadline"/>
<field eval="5" name="duration"/>
<field name="state">open</field>
</record>
<record id="calendar_event_6" model="calendar.event">
<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_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">draft</field>
</record>
<record id="calendar_event_7" model="calendar.event">
<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="calendar_event_8" model="calendar.event">
<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>

View File

@ -0,0 +1,321 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Calendar Events Types Form View -->
<record id="view_calendar_event_type_tree" model="ir.ui.view">
<field name="name">Meeting Types Tree</field>
<field name="model">calendar.event.type</field>
<field name="arch" type="xml">
<tree string="Meeting Types" editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
<record id="action_calendar_event_type" model="ir.actions.act_window">
<field name="name">Meeting Types</field>
<field name="res_model">calendar.event.type</field>
<field name="view_type">form</field>
<field name="view_id" ref="view_calendar_event_type_tree"/>
</record>
<!-- Calendar Events Form View -->
<record model="ir.ui.view" id="view_calendar_event_form">
<field name="name">Calendar - Event Form</field>
<field name="model">calendar.event</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','&lt;', 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_calendar_event_form_popup">
<field name="name">Meetings Popup</field>
<field name="model">calendar.event</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_calendar_event_tree">
<field name="name">CRM - Meetings Tree</field>
<field name="model">calendar.event</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_calendar_event_calendar">
<field name="name">Meetings Calendar</field>
<field name="model">calendar.event</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_calendar_event_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_calendar_event_gantt" model="ir.ui.view">
<field name="name">CRM - Meetings Gantt</field>
<field name="model">calendar.event</field>
<field name="arch" type="xml">
<gantt date_delay="duration" date_start="date" string="Meetings"/>
</field>
</record>
<!-- CRM Meeting Search View -->
<record id="view_calendar_event_search" model="ir.ui.view">
<field name="name">CRM - Meetings Search</field>
<field name="model">calendar.event</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_calendar_event" model="ir.actions.act_window">
<field name="name">Meetings</field>
<field name="res_model">calendar.event</field>
<field name="view_mode">calendar,tree,form,gantt</field>
<field name="view_id" ref="view_calendar_event_calendar"/>
<field name="search_view_id" ref="view_calendar_event_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_calendar_event_calendar">
<field name="act_window_id" ref="action_calendar_event"/>
<field name="sequence" eval="1"/>
<field name="view_mode">calendar</field>
<field name="view_id" ref="view_calendar_event_calendar"/>
</record>
<record model="ir.actions.act_window.view" id="action_view_calendar_event_tree">
<field name="act_window_id" ref="action_calendar_event"/>
<field name="sequence" eval="2"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_calendar_event_tree"/>
</record>
<record model="ir.actions.act_window.view" id="action_view_calendar_event_form">
<field name="act_window_id" ref="action_calendar_event"/>
<field name="sequence" eval="3"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_calendar_event_form"/>
</record>
<record model="ir.actions.act_window.view" id="action_view_calendar_event_gantt">
<field name="act_window_id" ref="action_calendar_event"/>
<field name="sequence" eval="4"/>
<field name="view_mode">gantt</field>
<field name="view_id" ref="view_calendar_event_gantt"/>
</record>
<menuitem name="Calendar" id="mail_menu_calendar" parent="mail.mail_my_stuff" sequence="10" action="action_calendar_event"/>
<menuitem id="menu_calendar_configuration" name="Calendar" parent="base.menu_custom" groups="base.group_no_one"/>
<menuitem id="menu_calendar_event_type" parent="menu_calendar_configuration" action="action_calendar_event_type" groups="base.group_no_one"/>
<!-- called in js from '/js/base_calendar.js' -->
<record id="action_calendar_event_notify" model="ir.actions.act_window">
<field name="name">Meetings</field>
<field name="res_model">calendar.event</field>
<field name="view_mode">form,calendar,tree,gantt</field>
<field name="view_id" ref="action_view_calendar_event_form"/>
</record>
</data>
</openerp>

View File

@ -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,
}

View File

@ -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>

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -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('calendar.event')
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

View File

@ -5,5 +5,5 @@
<field name="name">Survey / User</field>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</data>
</data>
</openerp>

View File

@ -0,0 +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_calendar_attendee_survey_user,calendar.attendee,model_calendar_attendee,base.group_survey_user,1,0,0,0
access_calendar_event_manager,calendar.event.manager,model_calendar_event,base.group_sale_manager,1,1,1,1
access_calendar_event,calendar.event,model_calendar_event,base.group_sale_salesman,1,1,1,0
access_calendar_event_all,calendar.event_all,model_calendar_event,base.group_user,1,1,1,1
access_calendar_event_partner_manager,calendar.event.partner.manager,model_calendar_event,base.group_partner_manager,1,1,1,1
access_calendar_event_type_all,calendar.event.type.all,model_calendar_event_type,,1,0,0,0
access_calendar_event_type_sale_manager,calendar.event.type.manager,model_calendar_event_type,base.group_sale_manager,1,1,1,0
access_calendar_event_type_sale_user,calendar.event.type.user,model_calendar_event_type,base.group_user,1,0,0,0
access_calendar_event_type_sale_user,calendar.event.type.salesman,model_calendar_event_type,base.group_sale_salesman,1,0,0,0
access_calendar_event_type_manager,calendar.event.type.manager,model_calendar_event_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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_calendar_attendee calendar.attendee model_calendar_attendee 1 1 1 1
3 access_calendar_alarm calendar.alarm model_calendar_alarm base.group_user 1 1 1 1
4 access_calendar_attendee_survey_user calendar.attendee model_calendar_attendee base.group_survey_user 1 0 0 0
5 access_calendar_event_manager calendar.event.manager model_calendar_event base.group_sale_manager 1 1 1 1
6 access_calendar_event calendar.event model_calendar_event base.group_sale_salesman 1 1 1 0
7 access_calendar_event_all calendar.event_all model_calendar_event base.group_user 1 1 1 1
8 access_calendar_event_partner_manager calendar.event.partner.manager model_calendar_event base.group_partner_manager 1 1 1 1
9 access_calendar_event_type_all calendar.event.type.all model_calendar_event_type 1 0 0 0
10 access_calendar_event_type_sale_manager calendar.event.type.manager model_calendar_event_type base.group_sale_manager 1 1 1 0
11 access_calendar_event_type_sale_user calendar.event.type.user model_calendar_event_type base.group_user 1 0 0 0
12 access_calendar_event_type_sale_user calendar.event.type.salesman model_calendar_event_type base.group_sale_salesman 1 0 0 0
13 access_calendar_event_type_manager calendar.event.type.manager model_calendar_event_type base.group_system 1 1 1 1
14 access_calendar_alarm_manager access_calendar_alarm_manager model_calendar_alarm_manager 1 1 1 1
15 access_calendar_contacts_all access_calendar_contacts_all model_calendar_contacts 1 1 1 1
16 access_calendar_contacts access_calendar_contacts model_calendar_contacts base.group_system 1 1 1 1

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -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;
}

View File

@ -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_calendar_event_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=calendar.event', 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'));
});
}
};

View File

@ -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>

View File

@ -1,5 +1,5 @@
-
In Order to test base_calendar, I will first create One Simple Event with real data
In Order to test calendar, I will first create One Simple Event with real data
-
!record {model: calendar.event, id: calendar_event_technicalpresentation0}:
class: private
@ -27,6 +27,18 @@
!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 move a virtual event, to see that a real event is well created and depending from the native recurrence
-
!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} )
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
-
@ -41,14 +53,14 @@
-
In order to check reminder I will first create reminder
-
!record {model: res.alarm, id: res_alarm_daybeforeeventstarts0}:
!record {model: calendar.alarm, id: res_alarm_daybeforeeventstarts0}:
name: 1 Day before event starts
trigger_duration: 1
trigger_interval: days
trigger_occurs: before
trigger_related: start
duration: 1
interval: days
type: notification
-
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")})
self.write(cr, uid, [ref("calendar_event_alldaytestevent0")], {'alarm_ids': [(6,0,[ref("res_alarm_daybeforeeventstarts0")])]})

View File

@ -3,7 +3,7 @@
-
I create a recurrent meeting with daily recurrency and fixed amount of time.
-
!record {model: crm.meeting, id: crm_meeting_testmeeting0}:
!record {model: calendar.event, id: calendar_event_testmeeting0}:
count: 5
date: '2011-04-13 11:04:00'
date_deadline: '2011-04-13 12:04:00'
@ -13,17 +13,16 @@
recurrency: true
recurrent_id: 0.0
rrule_type: daily
sequence: 0.0
-
I search for all the recurrent meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_testmeeting0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_testmeeting0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 5, 'Recurrent daily meetings are not created !'
-
I create a weekly meeting till a particular end date.
-
!record {model: crm.meeting, id: crm_meeting_reviewcodewithprogrammer0}:
!record {model: calendar.event, id: calendar_event_reviewcodewithprogrammer0}:
date: '2011-04-18 11:47:00'
date_deadline: '2011-04-18 12:47:00'
day: 0.0
@ -39,17 +38,16 @@
recurrency: true
recurrent_id: 0.0
rrule_type: weekly
sequence: 0.0
-
I search for all the recurrent weekly meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_reviewcodewithprogrammer0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_reviewcodewithprogrammer0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 10, 'Recurrent weekly meetings are not created !'
-
I want to schedule a meeting every month for Sprint review.
-
!record {model: crm.meeting, id: crm_meeting_sprintreview0}:
!record {model: calendar.event, id: calendar_event_sprintreview0}:
count: 12
date: '2011-04-01 12:01:00'
date_deadline: '2011-04-01 13:01:00'
@ -59,39 +57,36 @@
recurrency: true
recurrent_id: 0.0
rrule_type: monthly
sequence: 0.0
-
I search for all the recurrent monthly meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 12, 'Recurrent monthly meetings are not created !'
-
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'})
!python {model: calendar.event}: |
idval = '%d-%s' % (ref('calendar_event_sprintreview0'), '20110901130100')
self.write(cr, uid, [idval], {'name': 'Sprint Review for google modules'})
-
I check whether all the records are edited or not.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
meetings = self.browse(cr, uid, meeting_ids, context)
for meeting in meetings:
assert meeting.name == 'Sprint Review for google modules', 'Name not changed for id: %s' %meeting.id
-
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.'})
!python {model: calendar.event}: |
idval = '%d-%s' % (ref('calendar_event_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)
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('recurrent_id', '=', ref('calendar_event_sprintreview0')), ('recurrent_id_date','=','2011-04-25 12:47:00')], context)
assert meeting_ids, 'Meeting is not edited !'

View File

@ -22,7 +22,7 @@
import crm
import crm_segmentation
import crm_lead
import crm_meeting
import calendar_event
import crm_phonecall
import report
import wizard

View File

@ -54,7 +54,7 @@ Dashboard for CRM will include:
'process',
'mail',
'email_template',
'base_calendar',
'calendar',
'resource',
'board',
'fetchmail',
@ -81,7 +81,7 @@ Dashboard for CRM will include:
'crm_lead_view.xml',
'crm_lead_menu.xml',
'crm_meeting_menu.xml',
'calendar_event_menu.xml',
'crm_phonecall_view.xml',
'crm_phonecall_menu.xml',

View File

@ -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)

View File

@ -24,18 +24,18 @@ import logging
_logger = logging.getLogger(__name__)
#
# crm.meeting is defined in module base_calendar
# calendar.event is defined in module calendar
#
class crm_meeting(osv.Model):
""" Model for CRM meetings """
_inherit = 'crm.meeting'
class calendar_event(osv.Model):
""" Model for Calendar Event """
_inherit = 'calendar.event'
_columns = {
'phonecall_id': fields.many2one ('crm.phonecall', 'Phonecall'),
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
}
def create(self, cr, uid, vals, context=None):
res = super(crm_meeting, self).create(cr, uid, vals, context=context)
res = super(calendar_event, self).create(cr, uid, vals, context=context)
obj = self.browse(cr, uid, res, context=context)
if obj.opportunity_id:
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.date, obj.duration, context=context)

View File

@ -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_calendar_event', context)
res['context'] = {
'default_opportunity_id': opportunity.id,
'default_partner_id': opportunity.partner_id and opportunity.partner_id.id or False,
@ -1049,11 +1049,13 @@ class crm_lead(format_address, osv.osv):
def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]
if action == 'log':
prefix = 'Logged'
message = _('Logged a call for %(date)s. %(description)s')
else:
prefix = 'Scheduled'
suffix = ' %s' % phonecall.description
message = _("%s a call for %s.%s") % (prefix, phonecall.date, suffix)
message = _('Scheduled a call for %(date)s. %(description)s')
phonecall_date = datetime.strptime(phonecall.date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
phonecall_usertime = fields.datetime.context_timestamp(cr, uid, phonecall_date, context=context).strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
html_time = "<time datetime='%s+00:00'>%s</time>" % (phonecall.date, phonecall_usertime)
message = message % dict(date=html_time, description=phonecall.description)
return self.message_post(cr, uid, ids, body=message, context=context)
def log_meeting(self, cr, uid, ids, meeting_subject, meeting_date, duration, context=None):

View File

@ -79,9 +79,9 @@
view_type="form"/>
<act_window
id="act_crm_opportunity_crm_meeting_new"
id="act_crm_opportunity_calendar_event_new"
name="Meetings"
res_model="crm.meeting"
res_model="calendar.event"
view_mode="tree,form,calendar"
context="{'default_duration': 4.0, 'default_opportunity_id': active_id}"
view_type="form"/>

View File

@ -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_calendar_event', context)
res['context'] = {
'default_phonecall_id': phonecall.id,
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,

View File

@ -5,9 +5,9 @@
<!-- TO CONFIRM: This is fine -->
<!-- act_window
id="act_crm_phonecall_crm_meeting_new"
id="act_crm_phonecall_calendar_event_new"
name="Meetings"
res_model="crm.meeting"
res_model="calendar.event"
src_model="crm.phonecall"
view_mode="tree,form,calendar"
context="{'default_duration': 4.0, 'default_phonecall_id': active_id}"

View File

@ -42,7 +42,7 @@ class res_partner(osv.osv):
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'opportunity_ids': fields.one2many('crm.lead', 'partner_id',\
'Leads and Opportunities', domain=[('probability', 'not in', ['0', '100'])]),
'meeting_ids': fields.many2many('crm.meeting', 'crm_meeting_partner_rel','partner_id', 'meeting_id',
'meeting_ids': fields.many2many('calendar.event', 'calendar_event_partner_rel','partner_id', 'meeting_id',
'Meetings'),
'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id',\
'Phonecalls'),

View File

@ -3,10 +3,10 @@
<data>
<!-- open meetings related to given partner -->
<record id="crm_meeting_partner" model="ir.actions.act_window">
<record id="calendar_event_partner" model="ir.actions.act_window">
<field name="name">Meetings</field>
<field name="src_model">res.partner</field>
<field name="res_model">crm.meeting</field>
<field name="res_model">calendar.event</field>
<field name="view_mode">calendar,tree,form,gantt</field>
<field name="context">{'default_partner_ids': [active_id]}</field>
</record>
@ -71,7 +71,7 @@
<a name="%(relate_partner_opportunities)d" type="action" t-if="record.opportunity_count.value>0">
<t t-esc="record.opportunity_count.value"/> Opportunities
</a>
<a name="%(crm_meeting_partner)d" type="action" t-if="record.meeting_count.value>0">
<a name="%(calendar_event_partner)d" type="action" t-if="record.meeting_count.value>0">
<t t-esc="record.meeting_count.value"/> Meetings
</a>
</xpath>
@ -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_calendar_event)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"

View File

@ -71,9 +71,9 @@
<field name="groups" eval="[(4, ref('base.group_sale_salesman_all_leads'))]"/>
</record>
<record id="crm_meeting_global" model="ir.rule">
<record id="calendar_event_global" model="ir.rule">
<field name="name">Hide Private Meetings</field>
<field ref="model_crm_meeting" name="model_id"/>
<field ref="model_calendar_event" name="model_id"/>
<field eval="1" name="global"/>
<field name="domain_force">['|',('user_id','=',user.id),('show_as','=','busy')]</field>
</record>

View File

@ -107,12 +107,12 @@
-
I confirm review needs meeting.
-
!python {model: crm.meeting}: |
context.update({'active_model': 'crm.meeting'})
self.write(cr, uid, [ref('base_calendar.crm_meeting_4')], {'state': 'open'})
!python {model: calendar.event}: |
context.update({'active_model': 'calendar.event'})
self.write(cr, uid, [ref('calendar.calendar_event_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])

View File

@ -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_calendar_event', context)
res['context'] = {
'default_phonecall_id': phonecall.id,
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,

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