diff --git a/addons/account/invoice.py b/addons/account/invoice.py
index 3442e914634..a3146d9456d 100644
--- a/addons/account/invoice.py
+++ b/addons/account/invoice.py
@@ -236,7 +236,7 @@ class account_invoice(osv.osv):
'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."),
'reference_type': fields.selection(_get_reference_type, 'Reference Type',
required=True),
- 'comment': fields.text('Additional Information'),
+ 'comment': fields.text('Additional Information', translate=True),
'state': fields.selection([
('draft','Draft'),
@@ -1093,7 +1093,7 @@ class account_invoice_line(osv.osv):
'quantity': fields.float('Quantity', required=True),
'discount': fields.float('Discount (%)', digits=(16, int(config['price_accuracy']))),
'invoice_line_tax_id': fields.many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id','=',False)]),
- 'note': fields.text('Notes'),
+ 'note': fields.text('Notes', translate=True),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company',store=True)
}
diff --git a/addons/caldav/caldav_view.xml b/addons/caldav/caldav_view.xml
index 3dc58a6a765..eb92c487d58 100644
--- a/addons/caldav/caldav_view.xml
+++ b/addons/caldav/caldav_view.xml
@@ -9,17 +9,35 @@
caldav.invite.attendee
form
-
@@ -39,24 +57,32 @@
form
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index 503a02768d8..1eee04d9db6 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -61,7 +61,7 @@ def map_data(cr, uid, obj):
continue
if field_type == 'many2one':
id = None
- if not map_val:
+ if not map_val or not isinstance(map_val, dict):
vals[field] = id
continue
model = obj.__attribute__[map_dict].get('object', False)
@@ -128,12 +128,16 @@ class CalDAV(object):
continue
uidval = common.openobjectid2uid(cr, data[map_field], model)
vevent.add('uid').value = uidval
- elif field == 'attendee' and data[map_field]:
- attendee_obj = self.pool.get('basic.calendar.attendee')
- vevent = attendee_obj.export_ical(cr, uid, data[map_field], vevent, context=context)
- elif field == 'valarm' and data[map_field]:
- alarm_obj = self.pool.get('basic.calendar.alarm')
- vevent = alarm_obj.export_ical(cr, uid, data[map_field][0], vevent, context=context)
+ elif field == 'attendee' and data[map_field]:
+ #vevent.add('attendee').value = data[map_field]
+ #TODO : To export attendee
+ pass
+
+ elif field == 'valarm' and data[map_field]:
+ # vevent.add('valarm').value = data[map_field]
+ #TODO : To export valarm
+ pass
+
elif data[map_field]:
if map_type == "text":
vevent.add(field).value = str(data[map_field])
@@ -144,10 +148,12 @@ class CalDAV(object):
vevent.add(field).value = parser.parse(data[map_field])
elif map_type == "timedelta":
vevent.add(field).value = timedelta(hours=data[map_field])
+ elif map_type == "many2one":
+ vevent.add(field).value = [data.get(map_field)[1]]
if self.__attribute__.get(field).has_key('mapping'):
for key1, val1 in self.ical_get(field, 'mapping').items():
if val1 == data[map_field]:
- vevent.add(field).value = key1
+ vevent.add(field).value = key1
return ical
def import_ical(self, cr, uid, ical_data):
@@ -156,16 +162,16 @@ class CalDAV(object):
res = []
for child in parsedCal.getChildren():
for cal_data in child.getChildren():
- if cal_data.name.lower() == 'attendee':
- attendee = self.pool.get('basic.calendar.attendee')
- att_data.append(attendee.import_ical(cr, uid, cal_data))
- self.ical_set(cal_data.name.lower(), att_data, 'value')
- continue
- if cal_data.name.lower() == 'valarm':
- alarm = self.pool.get('basic.calendar.alarm')
- vals = alarm.import_ical(cr, uid, cal_data)
- self.ical_set(cal_data.name.lower(), vals, 'value')
- continue
+ #if cal_data.name.lower() == 'attendee':
+ # attendee = self.pool.get('basic.calendar.attendee')
+ # att_data.append(attendee.import_ical(cr, uid, cal_data))
+ # self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
+ # continue
+ #if cal_data.name.lower() == 'valarm':
+ # alarm = self.pool.get('basic.calendar.alarm')
+ # vals = alarm.import_ical(cr, uid, cal_data)
+ # self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
+ # continue
if cal_data.name.lower() in self.__attribute__:
self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
if child.name.lower() in ('vevent', 'vtodo'):
@@ -329,33 +335,37 @@ class Alarm(CalDAV, osv.osv_memory):
'x-prop': None,
}
- def export_ical(self, cr, uid, alarm_id, vevent, context={}):
- valarm = vevent.add('valarm')
- alarm_object = self.pool.get('calendar.alarm')
- alarm_data = alarm_object.read(cr, uid, alarm_id, [])
+ def export_ical(self, cr, uid, alarm_datas, context={}):
+ ical = vobject.iCalendar()
+ vevent = ical.add('vevent')
+ valarms = []
+ for alarm_data in alarm_datas:
+ valarm = vevent.add('valarm')
+
+ # Compute trigger data
+ interval = alarm_data['trigger_interval']
+ occurs = alarm_data['trigger_occurs']
+ duration = (occurs == 'after' and alarm_data['trigger_duration']) \
+ or -(alarm_data['trigger_duration'])
+ related = alarm_data['trigger_related']
+ trigger = valarm.add('trigger')
+ trigger.params['related'] = [related.upper()]
+ if interval == 'days':
+ delta = timedelta(days=duration)
+ if interval == 'hours':
+ delta = timedelta(hours=duration)
+ if interval == 'minutes':
+ delta = timedelta(minutes=duration)
+ trigger.value = delta
- # Compute trigger data
- interval = alarm_data['trigger_interval']
- occurs = alarm_data['trigger_occurs']
- duration = (occurs == 'after' and alarm_data['trigger_duration']) \
- or -(alarm_data['trigger_duration'])
- related = alarm_data['trigger_related']
- trigger = valarm.add('trigger')
- trigger.params['related'] = [related.upper()]
- if interval == 'days':
- delta = timedelta(days=duration)
- if interval == 'hours':
- delta = timedelta(hours=duration)
- if interval == 'minutes':
- delta = timedelta(minutes=duration)
- trigger.value = delta
-
- # Compute other details
- valarm.add('description').value = alarm_data['name']
- valarm.add('action').value = alarm_data['action']
- return vevent
+ # Compute other details
+ valarm.add('description').value = alarm_data['name']
+ valarm.add('action').value = alarm_data['action']
+
+ valarms.append(valarm)
+ return valarms
- def import_ical(self, cr, uid, ical_data):
+ def import_ical(self, cr, uid, ical_data):
for child in ical_data.getChildren():
if child.name.lower() == 'trigger':
seconds = child.value.seconds
@@ -403,7 +413,7 @@ class Attendee(CalDAV, osv.osv_memory):
'language': None, # Use: 0-1 Specify the language for text values in a property or property parameter.
}
- def import_ical(self, cr, uid, ical_data):
+ def import_ical(self, cr, uid, ical_data):
for para in ical_data.params:
if para.lower() == 'cn':
self.ical_set(para.lower(), ical_data.params[para][0]+':'+ ical_data.value, 'value')
@@ -414,17 +424,20 @@ class Attendee(CalDAV, osv.osv_memory):
vals = map_data(cr, uid, self)
return vals
- def export_ical(self, cr, uid, attendee_id, vevent, context={}):
- attendee_object = self.pool.get('calendar.attendee')
- for attendee in attendee_object.read(cr, uid, attendee_id, []):
+ def export_ical(self, cr, uid, attendee_data, context={}):
+ ical = vobject.iCalendar()
+ attendees = []
+ vevent = ical.add('vevent')
+ for attendee in attendee_data:
attendee_add = vevent.add('attendee')
- for a_key, a_val in attendee_object.__attribute__.items():
+ for a_key, a_val in self.__attribute__.items():
if attendee[a_val['field']]:
if a_val['type'] == 'text':
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
elif a_val['type'] == 'boolean':
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
- return vevent
+ attendees.append(attendee_add)
+ return attendees
Attendee()
diff --git a/addons/caldav/common.py b/addons/caldav/common.py
index afc7a6cb8c9..73dfc09f41d 100644
--- a/addons/caldav/common.py
+++ b/addons/caldav/common.py
@@ -43,7 +43,7 @@ def caldav_id2real_id(caldav_id = None, with_date=False):
return int(real_id)
return caldav_id and int(caldav_id) or caldav_id
-def real_id2caldav_id(real_id, recurrent_date):
+def real_id2caldav_id(real_id, recurrent_date):
if real_id and recurrent_date:
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
@@ -64,11 +64,17 @@ def uid2openobjectid(cr, uidval, oomodel):
if id in ids:
return id
return False
-
+
def openobjectid2uid(cr, uidval, oomodel):
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
return value
+def _links_get(self, cr, uid, context={}):
+ obj = self.pool.get('res.request.link')
+ ids = obj.search(cr, uid, [])
+ res = obj.read(cr, uid, ids, ['object', 'name'], context)
+ return [(r['object'], r['name']) for r in res]
+
class calendar_attendee(osv.osv):
_name = 'calendar.attendee'
_description = 'Attendee information'
@@ -87,12 +93,40 @@ class calendar_attendee(osv.osv):
'dir': {'field':'dir', 'type':'text'},
'language': {'field':'language', 'type':'text'},
}
-
+ def export_cal(self, cr, uid, ids, context={}):
+ basic_attendee_obj = self.pool.get('basic.calendar.attendee')
+ basic_attendee_obj.__attribute__.update(self.__attribute__)
+ data = self.read(cr, uid, ids)
+ attendees = basic_attendee_obj.export_ical(cr, uid, data, {'model': self._name})
+ cal_val = ''
+ for attendee in attendees:
+ cal_val += attendee.serialize()
+ return cal_val
+
+ def import_cal(self, cr, uid, data, context={}):
+ file_content = base64.decodestring(data)
+ basic_attendee_obj = self.pool.get('basic.calendar.attendee')
+ basic_attendee_obj.__attribute__.update(self.__attribute__)
+
+ vals = basic_attendee_obj.import_ical(cr, uid, file_content)
+ ids = []
+ for val in vals:
+ is_exists = uid2openobjectid(cr, val['id'], self._name)
+ if val.has_key('create_date'): val.pop('create_date')
+ val.pop('id')
+ if is_exists:
+ self.write(cr, uid, [is_exists], val)
+ ids.append(is_exists)
+ else:
+ attendee_id = self.create(cr, uid, val)
+ ids.append(attendee_id)
+ return ids
+
def _get_address(self, name=None, email=None):
if name and email:
name += ':'
return (name or '') + (email and ('MAILTO:' + email) or '')
-
+
def _compute_data(self, cr, uid, ids, name, arg, context):
name = name[0]
result = {}
@@ -101,16 +135,16 @@ class calendar_attendee(osv.osv):
email = user.address_id and user.address_id.email or ''
return self._get_address(user.name, email)
- for id in ids:
- result[id] = {}
- attdata = self.browse(cr, uid, id, context=context)
+ for attdata in self.browse(cr, uid, ids, context=context):
+ id = attdata.id
+ result[id] = {}
if name == 'sent_by':
if not attdata.sent_by_uid:
result[id][name] = ''
continue
else:
result[id][name] = self._get_address(attdata.sent_by_uid.name, \
- attdata.sent_by_uid.address_id.email)
+ attdata.sent_by_uid.address_id.email)
if name == 'cn':
result[id][name] = self._get_address(attdata.user_id.name, attdata.email)
if name == 'delegated_to':
@@ -122,31 +156,64 @@ class calendar_attendee(osv.osv):
user_obj = self.pool.get('res.users')
fromdata = map(get_delegate_data, attdata.del_from_user_ids)
result[id][name] = ', '.join(fromdata)
- return result
-
+ if name == 'event_date':
+ if attdata.ref:
+ model, res_id = tuple(attdata.ref.split(','))
+ model_obj = self.pool.get(model)
+ obj = model_obj.read(cr, uid, res_id, ['date'])[0]
+ result[id][name] = obj['date']
+ if name == 'event_end_date':
+ if attdata.ref:
+ model, res_id = tuple(attdata.ref.split(','))
+ model_obj = self.pool.get(model)
+ obj = model_obj.read(cr, uid, res_id, ['date_deadline'])[0]
+ result[id][name] = obj['date_deadline']
+
+ if name == 'sent_by_uid':
+ if attdata.ref:
+ model, res_id = tuple(attdata.ref.split(','))
+ model_obj = self.pool.get(model)
+ obj = model_obj.read(cr, uid, res_id, ['user_id'])[0]
+ result[id][name] = obj['user_id']
+ return result
+
+ def _links_get(self, cr, uid, context={}):
+ obj = self.pool.get('res.request.link')
+ ids = obj.search(cr, uid, [])
+ res = obj.read(cr, uid, ids, ['object', 'name'], context)
+ return [(r['object'], r['name']) for r in res]
+
+ def _lang_get(self, cr, uid, context={}):
+ obj = self.pool.get('res.lang')
+ ids = obj.search(cr, uid, [])
+ res = obj.read(cr, uid, ids, ['code', 'name'], context)
+ res = [((r['code']).replace('_', '-'), r['name']) for r in res]
+ return res
+
_columns = {
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
('room', 'Room'), ('unknown', 'Unknown') ], \
'User Type', help="Specify the type of calendar user"),
- 'member': fields.char('Member', size=124, help="Indicate the groups \
-that the attendee belongs to"),
- 'role': fields.selection([ ('req-participant', 'req-participant'), \
- ('chair', 'chair'), ('opt-participant', 'opt-participant'), \
- ('non-participant', 'non-participant')], 'User\'s Role', \
- help='Participation role for the calendar user'),
+ 'member': fields.char('Member', size=124,
+ help="Indicate the groups that the attendee belongs to"),
+ 'role': fields.selection([('req-participant', 'Participation required'), \
+ ('chair', 'Chair Person'), \
+ ('opt-participant', 'Optional Participation'), \
+ ('non-participant', 'For information Purpose')], 'Role', \
+ help='Participation role for the calendar user'),
'state': fields.selection([('tentative', 'Tentative'),
('needs-action', 'Needs Action'),
('accepted', 'Accepted'),
('declined', 'Declined'),
- ('delegated', 'Delegated')], 'Status', readonly=True,
+ ('delegated', 'Delegated')], 'State', readonly=True,
help="Status of the attendee's participation"),
- 'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
-favor of a reply is requested"),
+ 'rsvp': fields.boolean('Required Reply?',
+ help="Indicats whether the favor of a reply is requested"),
'delegated_to': fields.function(_compute_data, method=True, \
string='Delegated To', type="char", size=124, store=True, \
multi='delegated_to', help="The users that the original request \
-was delegated to"),
+ was delegated to"),
'del_to_user_ids': fields.many2many('res.users', 'att_del_to_user_rel',
'attendee_id', 'user_id', 'Users'),
'delegated_from': fields.function(_compute_data, method=True, string=\
@@ -154,22 +221,28 @@ was delegated to"),
'del_from_user_ids': fields.many2many('res.users', 'att_del_from_user_rel', \
'attendee_id', 'user_id', 'Users'),
'sent_by': fields.function(_compute_data, method=True, string='Sent By', type="char", multi='sent_by', store=True, size=124, help="Specify the user that is acting on behalf of the calendar user"),
- 'sent_by_uid': fields.many2one('res.users', 'Sent by User'),
+ 'sent_by_uid': fields.function(_compute_data, method=True, string='Sent by', type="many2one", obj='res.users', multi='sent_by_uid'),
'cn': fields.function(_compute_data, method=True, string='Common name', type="char", size=124, multi='cn', store=True),
'dir': fields.char('URI Reference', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
- 'language': fields.char('Language', size=124, help="To specify the language for text values in a property or property parameter."),
- 'user_id': fields.many2one('res.users', 'User'),
+ 'language': fields.selection(_lang_get, 'Language',
+ help="To specify the language for text values in a property or property parameter."),
+ 'user_id': fields.many2one('res.users', 'User', required=True),
'email': fields.char('Email', size=124),
- }
+ 'event_date' : fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
+ 'event_end_date' : fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
+ 'ref':fields.reference('Document Ref', selection=_links_get, size=128),
+ 'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
+ }
_defaults = {
- 'state': lambda *x: 'needs-action',
- }
+ 'state': lambda *x: 'needs-action',
+ }
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
return {'value': {'email': ''}}
- user = self.pool.get('res.users').browse(cr, uid, user_id, *args)
- return {'value': {'email': user.address_id.email}}
+ usr_obj = self.pool.get('res.users')
+ user = usr_obj.browse(cr, uid, user_id, *args)
+ return {'value': {'email': user.address_id.email, 'availability':user.availability}}
def do_tentative(self, cr, uid, ids, context=None, *args):
self.write(cr, uid, ids, {'state': 'tentative'}, context)
@@ -185,8 +258,8 @@ calendar_attendee()
class res_alarm(osv.osv):
_name = 'res.alarm'
_description = 'basic alarm information'
- _columns = {
- 'name':fields.char('Name', size=256, required=True),
+ _columns = {
+ 'name':fields.char('Name', size=256, required=True),
'trigger_occurs': fields.selection([('before', 'Before'), ('after', 'After')], \
'Trigger time', required=True),
'trigger_interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), \
@@ -196,12 +269,12 @@ class res_alarm(osv.osv):
'The event ends')], 'Trigger Occures at', required=True),
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
are both optional, but if one occurs, so MUST the other"""),
- 'repeat': fields.integer('Repeat'),
+ 'repeat': fields.integer('Repeat'),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
-
-
+
+
}
- _defaults = {
+ _defaults = {
'trigger_interval': lambda *x: 'minutes',
'trigger_duration': lambda *x: 5,
'trigger_occurs': lambda *x: 'before',
@@ -227,10 +300,10 @@ class calendar_alarm(osv.osv):
'duration': {'field': 'duration', 'type': 'text'},
'repeat': {'field': 'repeat', 'type': 'text'},
'attach': {'field': 'attach', 'type': 'text'},
- }
+ }
- _columns = {
- 'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
+ _columns = {
+ 'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
'name': fields.char('Summary', size=124, help="""Contains the text to be used as the message subject for email
or contains the text to be used for display"""),
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
@@ -238,27 +311,57 @@ or contains the text to be used for display"""),
required=True, help="Defines the action to be invoked when an alarm is triggered"),
'description': fields.text('Description', help='Provides a more complete description of the calendar component, than that provided by the "SUMMARY" property'),
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
- 'alarm_id', 'attendee_id', 'Attendees', readonly=True),
- 'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
+ 'alarm_id', 'attendee_id', 'Attendees', readonly=True),
+ 'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
* File which is intended to be sent as message attachments for email,
* Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""),
'res_id' : fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date' : fields.datetime('Event Date'),
+ 'event_end_date' : fields.datetime('Event End Date'),
'trigger_date' : fields.datetime('Trigger Date', readonly="True"),
'state':fields.selection([
- ('draft','Draft'),
- ('run','Run'),
- ('stop','Stop'),
- ('done','Done'),
- ],'State', select=True, readonly=True),
+ ('draft', 'Draft'),
+ ('run', 'Run'),
+ ('stop', 'Stop'),
+ ('done', 'Done'),
+ ], 'State', select=True, readonly=True),
}
_defaults = {
'action': lambda *x: 'email',
- 'state' : lambda *x: 'run',
- }
+ 'state' : lambda *x: 'run',
+ }
+
+ def export_cal(self, cr, uid, ids, context={}):
+ basic_alarm_obj = self.pool.get('basic.calendar.alarm')
+ basic_alarm_obj.__attribute__.update(self.__attribute__)
+ data = self.read(cr, uid, ids)
+ alarms = basic_alarm_obj.export_ical(cr, uid, data, {'model': self._name})
+ cal_val = ''
+ for alarm in alarms:
+ cal_val += alarm.serialize()
+ return cal_val
+
+ def import_cal(self, cr, uid, data, context={}):
+ file_content = base64.decodestring(data)
+ basic_alarm_obj = self.pool.get('basic.calendar.alarm')
+ basic_alarm_obj.__attribute__.update(self.__attribute__)
+
+ vals = basic_alarm_obj.import_ical(cr, uid, file_content)
+ ids = []
+ for val in vals:
+ is_exists = uid2openobjectid(cr, val['id'], self._name)
+ if val.has_key('create_date'): val.pop('create_date')
+ val.pop('id')
+ if is_exists:
+ self.write(cr, uid, [is_exists], val)
+ ids.append(is_exists)
+ else:
+ alarm_id = self.create(cr, uid, val)
+ ids.append(alarm_id)
+ return ids
def create(self, cr, uid, vals, context={}):
event_date = vals.get('event_date', False)
@@ -272,7 +375,7 @@ or contains the text to be used for display"""),
delta = datetime.timedelta(minutes=vals['trigger_duration'])
trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta)
vals['trigger_date'] = trigger_date
- res = super(calendar_alarm, self).create(cr, uid, vals, context)
+ res = super(calendar_alarm, self).create(cr, uid, vals, context)
return res
def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
@@ -283,31 +386,31 @@ or contains the text to be used for display"""),
cr.execute("select alarm.id as id \
from calendar_alarm alarm \
where alarm.state = %s and alarm.trigger_date <= %s", ('run', current_datetime))
- res = cr.dictfetchall()
- alarm_ids = map(lambda x: x['id'], res)
+ res = cr.dictfetchall()
+ alarm_ids = map(lambda x: x['id'], res)
attendee_obj = self.pool.get('calendar.attendee')
request_obj = self.pool.get('res.request')
mail_to = []
- for alarm in self.browse(cr, uid, alarm_ids):
+ for alarm in self.browse(cr, uid, alarm_ids):
if alarm.action == 'display':
- value = {
- 'name': alarm.name,
- 'act_from': alarm.user_id.id,
- 'act_to': alarm.user_id.id,
+ value = {
+ 'name': alarm.name,
+ 'act_from': alarm.user_id.id,
+ 'act_to': alarm.user_id.id,
'body': alarm.description,
'trigger_date': alarm.trigger_date,
- 'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
+ 'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
}
request_id = request_obj.create(cr, uid, value)
request_ids = [request_id]
- for attendee in alarm.attendee_ids:
- value['act_to'] = attendee.act_to.id
+ for attendee in alarm.attendee_ids:
+ value['act_to'] = attendee.user_id.id
request_id = request_obj.create(cr, uid, value)
request_ids.append(request_id)
request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
- sub = '[Openobject Remainder] %s' %(alarm.name)
+ sub = '[Openobject Remainder] %s' %(alarm.name)
body = """
Name : %s
Date : %s
@@ -316,12 +419,12 @@ or contains the text to be used for display"""),
From :
%s
%s
-
+
""" %(alarm.name, alarm.trigger_date, alarm.description, alarm.user_id.name, alarm.user_id.sign)
mail_to = [alarm.user_id.address_id.email]
- for att in alarm.attendee_ids:
- mail_to.append(att.act_to.address_id.email)
-
+ for att in alarm.attendee_ids:
+ mail_to.append(att.user_id.address_id.email)
+
tools.email_send(
tools.confirm['from_mail'],
mail_to,
@@ -349,8 +452,8 @@ class ir_attachment(osv.osv):
for i, arg in enumerate(new_args):
if arg[0] == 'res_id':
new_args[i] = (arg[0], arg[1], caldav_id2real_id(arg[2]))
- return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
- limit=limit, order=order,
+ return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
+ limit=limit, order=order,
context=context, count=False)
ir_attachment()
@@ -392,7 +495,7 @@ class ir_model(osv.osv):
for val in data:
val['id'] = caldav_id2real_id(val['id'])
return data
-
+
ir_model()
class virtual_report_spool(web_services.report_spool):
@@ -466,7 +569,7 @@ class set_rrule_wizard(osv.osv_memory):
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
- if byday:
+ if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
@@ -497,14 +600,14 @@ class set_rrule_wizard(osv.osv_memory):
rrule_string = 'FREQ=' + freq + weekstring + ';INTERVAL=' + \
str(datas.get('interval')) + enddate + monthstring + yearstring
-# End logic
+# End logic
return rrule_string
def do_add(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if datas.get('interval') <= 0:
raise osv.except_osv(_('Error!'), ("Please select proper Interval"))
-
+
if not context or not context.get('model'):
return {}
@@ -512,48 +615,95 @@ class set_rrule_wizard(osv.osv_memory):
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
-
+
rrule_string = self.compute_rule_string(cr, uid, datas)
obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string})
return {}
set_rrule_wizard()
+class res_users(osv.osv):
+ _inherit = 'res.users'
+
+ def _get_user_avail(self, cr, uid, ids, context=None):
+ current_datetime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+ res = {}
+ attendee_obj = self.pool.get('calendar.attendee')
+ attendee_ids = attendee_obj.search(cr, uid, [
+ ('event_date','<=',current_datetime), ('event_end_date','<=',current_datetime),
+ ('state','=','accepted'), ('user_id','in',ids)
+ ])
+
+ result = cr.dictfetchall()
+ for attendee_data in attendee_obj.read(cr, uid, attendee_ids, ['user_id']):
+ user_id = attendee_data['user_id']
+ status = 'busy'
+ res.update({user_id:status})
+
+ #TOCHECK : Delegrated Event
+ #cr.execute("SELECT user_id,'busy' FROM att_del_to_user_rel where user_id = ANY(%s)", (ids,))
+ #res.update(cr.dictfetchall())
+ for user_id in ids:
+ if user_id not in res:
+ res[user_id] = 'free'
+
+ return res
+
+ def _get_user_avail_fun(self, cr, uid, ids, name, args, context=None):
+ return self._get_user_avail(cr, uid, ids, context=context)
+
+ _columns = {
+ 'availability': fields.function(_get_user_avail_fun, type='selection', \
+ selection=[('free', 'Free'), ('busy', 'Busy')], \
+ string='Free/Busy', method=True),
+ }
+res_users()
+
class invite_attendee_wizard(osv.osv_memory):
_name = "caldav.invite.attendee"
_description = "Invite Attendees"
- _columns = {
- 'user_id': fields.many2one('res.users', 'User'),
- 'email': fields.char('Email', size=124),
- 'role': fields.selection([ ('REQ-PARTICIPANT', 'REQ-PARTICIPANT'), \
- ('CHAIR', 'CHAIR'), ('OPT-PARTICIPANT', 'OPT-PARTICIPANT'), \
- ('NON-PARTICIPANT', 'NON-PARTICIPANT')], 'User\'s Role', \
- help='Participation role for the calendar user'),
- 'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
-favor of a reply is requested"),
- }
+ _columns = {
+ 'attendee_ids': fields.many2many('calendar.attendee', 'invite_attendee_rel', 'invite_id', 'attendee_id', 'Attendees Detail'),
+ }
- def do_invite(self, cr, uid, ids, context={}):
- datas = self.read(cr, uid, ids)[0]
- if not context or not context.get('model') or not datas.get('user_id'):
- return {}
- else:
- model = context.get('model')
- obj = self.pool.get(model)
- res_obj = obj.browse(cr, uid, context['active_id'])
- user_obj = self.pool.get('res.users')
+ def create(self, cr, uid, vals, context={}):
+ attendee_ids = vals.get('attendee_ids',False)
+ model = context.get('model', False)
+ res_id = context.get('active_id', False)
+ state = context.get('state', False)
attendee_obj = self.pool.get('calendar.attendee')
- for user_id in datas.get('users', []):
- user = user_obj.browse(cr, uid, user_id)
- if not user.address_id.email:
- raise osv.except_osv(_('Error!'), \
- ("User does not have an email Address"))
- attendee_id = attendee_obj.create(cr, uid, {'user_id': user_id,\
- 'cn': user.name + ':MAILTO:' + user.address_id.email})
- obj.write(cr, uid, res_obj.id, {'attendee_ids': [(6, 0, [attendee_id])]})
+
+ if attendee_ids and model and res_id:
+ attend = False
+ if model == 'calendar.attendee' and state == 'delegated':
+ attend = attendee_obj.read(cr, uid, res_id, ['ref','user_id','del_to_user_ids'])
+
+ for v1, v2, attendee in attendee_ids:
+ vals = {}
+ ref = '%s,%d'%(model, res_id)
+ if attend:
+ ref = attend['ref']
+ del_from_user_ids = [attend['user_id'][0]]
+ del_to_user_ids = attend['del_to_user_ids']
+ del_to_user_ids.append(attendee['user_id'])
+ vals.update({
+ 'del_from_user_ids' : [(6, 0, del_from_user_ids)]
+ })
+ attendee_obj.write(cr, uid, [res_id], {'state':'delegated','del_to_user_ids' : [(6, 0, del_to_user_ids)]})
+
+ vals.update({
+ 'ref': ref,
+ })
+ attendee.update(vals)
+ attendee_obj.create(cr, uid, attendee)
+
+ res = super(invite_attendee_wizard, self).create(cr, uid, {}, context=context)
+ return res
+
+ def do_invite(self, cr, uid, ids, context={}):
return {}
-
+
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index 172e150740d..a58a50028a5 100755
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -73,7 +73,7 @@ class crm_case_section(osv.osv):
'user_id': fields.many2one('res.users', 'Responsible User'),
'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by Open ERP about cases in this section"),
'parent_id': fields.many2one('crm.case.section', 'Parent Section'),
- 'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Sections'),
+ 'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Sections'),
'calendar' : fields.boolean('Calendar', help='Allows to show calendar'),
}
_defaults = {
@@ -408,6 +408,11 @@ class crm_case(osv.osv):
if context.get('portal', False):
return False
return uid
+
+ def _get_section(self, cr, uid, context):
+ user = self.pool.get('res.users').browse(cr, uid, uid)
+ return user.section_id.id
+
_defaults = {
'active': lambda *a: 1,
'user_id': _get_default_user,
@@ -417,6 +422,7 @@ class crm_case(osv.osv):
'state': lambda *a: 'draft',
'priority': lambda *a: AVAILABLE_PRIORITIES[2][0],
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'section_id': _get_section,
}
_order = 'priority, date_deadline desc, date desc,id desc'
@@ -818,8 +824,8 @@ class crm_case(osv.osv):
data['user_id'] = uid
self.write(cr, uid, ids, data)
self._action(cr,uid, cases, 'open')
- return True
-
+ return True
+
def case_cancel(self, cr, uid, ids, *args):
cases = self.browse(cr, uid, ids)
@@ -946,5 +952,15 @@ class crm_email_add_cc_wizard(osv.osv_memory):
return {}
crm_email_add_cc_wizard()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+class res_users(osv.osv):
+ _inherit = "res.users"
+ _description = "users"
+
+ _columns = {
+ 'section_id': fields.many2one('crm.case.section', 'Sales Section', required=False)
+ }
+
+res_users()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/crm/crm_claim.py b/addons/crm/crm_claim.py
index 1cddafaeca8..0606e39a052 100644
--- a/addons/crm/crm_claim.py
+++ b/addons/crm/crm_claim.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL ().
#
@@ -15,7 +15,7 @@
# 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 .
+# along with this program. If not, see .
#
##############################################################################
@@ -30,15 +30,15 @@ class crm_claim(osv.osv):
_name = "crm.claim"
_description = "Claim Cases"
_order = "id desc"
- _inherits = {'crm.case':"inherit_case_id"}
- _columns = {
+ _inherits = {'crm.case':"inherit_case_id"}
+ _columns = {
'inherit_case_id': fields.many2one('crm.case','Case',ondelete='cascade'),
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
- select = ids
+ select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@@ -61,25 +61,25 @@ class crm_claim(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
- return self._map_ids('case_close',cr,uid,ids,*args,**argv)
+ return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
- return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
- def case_escalate(self,cr, uid, ids, *args, **argv):
- return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
- def case_pending(self,cr, uid, ids, *args, **argv):
- return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
+ return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
+ def case_escalate(self,cr, uid, ids, *args, **argv):
+ return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
+ def case_pending(self,cr, uid, ids, *args, **argv):
+ return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
- def msg_new(self, cr, uid, msg):
+ def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
- 'name': msg['Subject'],
+ 'name': msg['Subject'],
'email_from': msg['From'],
- 'email_cc': msg['Cc'],
+ 'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@@ -87,15 +87,15 @@ class crm_claim(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
- res = self.create(cr, uid, data)
+ res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
- def msg_send(self, cr, uid, ids, *args, **argv):
- return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
+ def msg_send(self, cr, uid, ids, *args, **argv):
+ return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_claim()
@@ -103,7 +103,7 @@ class crm_claim_assign_wizard(osv.osv_memory):
_name = 'crm.claim.assign_wizard'
_columns = {
- 'section_id': fields.many2one('crm.case.section', 'Section', required=True),
+ 'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}
@@ -133,18 +133,18 @@ class crm_claim_assign_wizard(osv.osv_memory):
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
- }, context=context)
+ }, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_claims_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
- value = {
+ value = {
'name': _('Claims'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.claim',
- 'res_id': int(new_case_id),
+ 'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}
diff --git a/addons/crm/crm_helpdesk.py b/addons/crm/crm_helpdesk.py
index b4ecbc728d2..4cf4b951e53 100644
--- a/addons/crm/crm_helpdesk.py
+++ b/addons/crm/crm_helpdesk.py
@@ -36,16 +36,16 @@ class crm_helpdesk(osv.osv):
_name = "crm.helpdesk"
_description = "Helpdesk Cases"
_order = "id desc"
- _inherits = {'crm.case':"inherit_case_id"}
- _columns = {
+ _inherits = {'crm.case':"inherit_case_id"}
+ _columns = {
'inherit_case_id':fields.many2one('crm.case','Case'),
}
-
+
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
- select = ids
+ select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@@ -66,21 +66,21 @@ class crm_helpdesk(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
- return self._map_ids('case_close',cr,uid,ids,*args,**argv)
+ return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
-
- def msg_new(self, cr, uid, msg):
+
+ def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
- 'name': msg['Subject'],
+ 'name': msg['Subject'],
'email_from': msg['From'],
- 'email_cc': msg['Cc'],
+ 'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@@ -88,15 +88,15 @@ class crm_helpdesk(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
- res = self.create(cr, uid, data)
+ res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
- def msg_send(self, cr, uid, ids, *args, **argv):
- return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
+ def msg_send(self, cr, uid, ids, *args, **argv):
+ return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_helpdesk()
@@ -104,7 +104,7 @@ class crm_helpdesk_assign_wizard(osv.osv_memory):
_name = 'crm.helpdesk.assign_wizard'
_columns = {
- 'section_id': fields.many2one('crm.case.section', 'Section', required=True),
+ 'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}
diff --git a/addons/crm/crm_jobs_menu.xml b/addons/crm/crm_jobs_menu.xml
index 991dacc1f06..000369ec21a 100644
--- a/addons/crm/crm_jobs_menu.xml
+++ b/addons/crm/crm_jobs_menu.xml
@@ -33,7 +33,7 @@
graph
-
+