diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index e01ff58e1f7..3912f665916 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -1714,35 +1714,37 @@ form
- - - - - - + + + + + + + + + + + + + - - - - - - @@ -1769,7 +1771,7 @@ - + diff --git a/addons/account_invoice_layout/account_invoice_layout_view.xml b/addons/account_invoice_layout/account_invoice_layout_view.xml index 6bdabae9326..062349f7716 100644 --- a/addons/account_invoice_layout/account_invoice_layout_view.xml +++ b/addons/account_invoice_layout/account_invoice_layout_view.xml @@ -55,6 +55,18 @@ + + account.invoice.supplier.form.layout + account.invoice + + form + + + + + + + notify.message.search diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index fc349337b5d..45624a280f1 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -995,15 +995,24 @@ class calendar_event(osv.osv): """ result = {} + if not isinstance(ids, list): + ids = [ids] + for datas in self.read(cr, uid, ids, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'select1', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'exrule', 'day', 'week_list' ], context=context): event = datas['id'] if datas.get('interval', 0) < 0: raise osv.except_osv(_('Warning!'), _('Interval cannot be negative')) if datas.get('count', 0) < 0: raise osv.except_osv(_('Warning!'), _('Count cannot be negative')) - result[event] = self.compute_rule_string(datas) + if datas['recurrency']: + result[event] = self.compute_rule_string(datas) + else: + result[event] = "" return result - + + + + _columns = { 'id': fields.integer('ID', readonly=True), 'sequence': fields.integer('Sequence'), @@ -1072,6 +1081,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), 'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"), 'edit_all': fields.boolean('Edit All', help="Edit all Occurrences of recurrent Meeting."), } + def default_organizer(self, cr, uid, context=None): user_pool = self.pool.get('res.users') user = user_pool.browse(cr, uid, uid, context=context) @@ -1177,7 +1187,6 @@ rule or repeating pattern of time to exclude from the recurring rule."), @param self: the object pointer @param datas: dictionary of freq and interval value. """ - def get_week_string(freq, datas): weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] if freq == 'weekly': @@ -1211,9 +1220,88 @@ rule or repeating pattern of time to exclude from the recurring rule."), interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or '' return 'FREQ=' + freq.upper() + get_week_string(freq, datas) + interval_srting + get_end_date(datas) + get_month_string(freq, datas) + + def _get_empty_rrule_data(self): + return { + 'byday' : False, + 'recurrency' : False, + 'end_date' : False, + 'rrule_type' : False, + 'select1' : False, + 'interval' : 0, + 'count' : False, + 'end_type' : False, + 'mo' : False, + 'tu' : False, + 'we' : False, + 'th' : False, + 'fr' : False, + 'sa' : False, + 'su' : False, + 'exrule' : False, + 'day' : False, + 'week_list' : False + } + + def _write_rrule(self, cr, uid, ids, field_value, rule_date=False, context=None): + data = self._get_empty_rrule_data() + + if field_value: + data['recurrency'] = True + for event in self.browse(cr, uid, ids, context=context): + rdate = rule_date or event.date + update_data = self._parse_rrule(field_value, dict(data), rdate) + data.update(update_data) + #parse_rrule + self.write(cr, uid, event.id, data, context=context) + + + def _parse_rrule(self, rule, data, date_start): + day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] + rrule_type = ['yearly', 'monthly', 'weekly', 'daily'] + r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, "%Y-%m-%d %H:%M:%S")) + + if r._freq > 0 and r._freq < 4: + data['rrule_type'] = rrule_type[r._freq] + + data['count'] = r._count + data['interval'] = r._interval + data['end_date'] = r._until and r._until.strftime("%Y-%m-%d %H:%M:%S") + #repeat weekly + if r._byweekday: + for i in xrange(0,7): + if i in r._byweekday: + data[day_list[i]] = True + data['rrule_type'] = 'weekly' + #repeat monthly bynweekday ((weekday, weeknumber), ) + if r._bynweekday: + data['week_list'] = day_list[r._bynweekday[0][0]].upper() + data['byday'] = r._bynweekday[0][1] + data['select1'] = 'day' + data['rrule_type'] = 'monthly' + + if r._bymonthday: + data['day'] = r._bymonthday[0] + data['select1'] = 'date' + data['rrule_type'] = 'monthly' + + #yearly but for openerp it's monthly, take same information as monthly but interval is 12 times + if r._bymonth: + data['interval'] = data['interval'] * 12 + + #FIXEME handle forever case + #end of recurrence + #in case of repeat for ever that we do not support right now + if not (data.get('count') or data.get('end_date')): + data['count'] = 100 + if data.get('count'): + data['end_type'] = 'count' + else: + data['end_type'] = 'end_date' + return data def remove_virtual_id(self, ids): - if isinstance(ids, (str, int)): + if isinstance(ids, (str, int, long)): return base_calendar_id2real_id(ids) if isinstance(ids, (list, tuple)): @@ -1243,7 +1331,6 @@ rule or repeating pattern of time to exclude from the recurring rule."), if until_date: continue until_date = arg[2] - res = super(calendar_event, self).search(cr, uid, args_without_date, \ 0, 0, order, context, count=False) res = self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit, context=context) @@ -1289,6 +1376,9 @@ rule or repeating pattern of time to exclude from the recurring rule."), select = [ids] else: select = ids + + + new_ids = [] res = False for event_id in select: @@ -1339,6 +1429,13 @@ rule or repeating pattern of time to exclude from the recurring rule."), context=context) vals.update(updated_vals.get('value', {})) if new_ids: + if 'rrule' in vals.keys(): + if 'date' in vals.keys(): + date_to_write = vals['date'] + else: + date_to_write = False + self._write_rrule(cr, uid, new_ids, vals['rrule'], date_to_write, context) + res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context) if ('alarm_id' in vals or 'base_calendar_alarm_id' in vals)\ @@ -1465,6 +1562,11 @@ rule or repeating pattern of time to exclude from the recurring rule."), if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'): vals['vtimezone'] = vals['vtimezone'][40:] + + if 'date' in vals and 'rrule' in vals and vals['rrule']: + update_datas = self._parse_rrule(vals['rrule'], self._get_empty_rrule_data(), vals['date']) + update_datas['recurrency'] = True + vals.update(update_datas) updated_vals = self.onchange_dates(cr, uid, [], vals.get('date', False), diff --git a/addons/base_calendar/test/base_calendar_test.yml b/addons/base_calendar/test/base_calendar_test.yml index 5512839e635..e9a0f21e26e 100644 --- a/addons/base_calendar/test/base_calendar_test.yml +++ b/addons/base_calendar/test/base_calendar_test.yml @@ -15,7 +15,7 @@ Now I will set recurrence for this event to occur monday and friday of week - !python {model: calendar.event}: | - data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00'} + data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00', 'recurrency' : True} self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], data) - | In order to check that recurrent events are views successfully in calendar view, diff --git a/addons/base_contact/base_contact.py b/addons/base_contact/base_contact.py index cf0bc610be8..9a4b0eace6b 100644 --- a/addons/base_contact/base_contact.py +++ b/addons/base_contact/base_contact.py @@ -143,6 +143,17 @@ class res_partner_address(osv.osv): res.append((r['id'], addr.strip() or '/')) return res + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): + if not args: + args=[] + ids = self.search(cr, user, [('name',operator,name)] + args, limit=limit, context=context) + jobs = self.pool.get('res.partner.job') + if name: + job_ids = jobs.search(cr, user, [('contact_id', operator, name)] + args, limit=limit, context=context) + for job in jobs.browse(cr, user, job_ids): + ids += [job.address_id.id] + return self.name_get(cr, user, ids, context) + _name = 'res.partner.address' _inherit = 'res.partner.address' _description ='Partner Address' diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py index 5272d0fc1fd..71e9bdc2468 100644 --- a/addons/caldav/caldav_node.py +++ b/addons/caldav/caldav_node.py @@ -324,7 +324,6 @@ class node_calendar(nodes.node_class): uid = self.context.uid res = self.set_data(cr, data) - if res and len(res): # We arbitrarily construct only the first node of the data # that have been imported. ICS may have had more elements, @@ -332,6 +331,7 @@ class node_calendar(nodes.node_class): assert isinstance(res[0], (int, long)) fnodes = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=[('id','=',res[0])], context=ctx) + if self.context.get('DAV-client','') in ('iPhone', 'iCalendar',): # For those buggy clients, register the alias bca_obj = fil_obj.pool.get('basic.calendar.alias') diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py index a70a31bc017..94d28e4ad37 100644 --- a/addons/caldav/calendar.py +++ b/addons/caldav/calendar.py @@ -121,10 +121,10 @@ def str2mailto(emailstr, multi=False): for mas in mailz: m = mege.match(mas.strip()) if not m: - # one of the rare non-matching strings is "sad" :( - # retz.append({ 'name': mas.strip() }) - # continue - raise ValueError("Invalid email address %r" % mas) + #one of the rare non-matching strings is "sad" :( + retz.append({ 'name': mas.strip() }) + continue + # raise ValueError("Invalid email address %r" % mas) rd = { 'name': m.group(1).strip(), 'email': m.group(5), } if m.group(2): @@ -189,6 +189,9 @@ def map_data(cr, uid, obj, context=None): field = obj.ical_get(map_dict, 'field') field_type = obj.ical_get(map_dict, 'type') if field: + #ignore write date, this field is resered for the orm + if field == 'write_date': + continue if field_type == 'selection': if not map_val: continue @@ -299,7 +302,6 @@ class CalDAV(object): att_data = [] exdates = [] _server_tzinfo = pytz.timezone(tools.get_server_timezone()) - for cal_data in child.getChildren(): if cal_data.name.lower() == 'organizer': dmail = { 'name': cal_data.params.get('CN', ['',])[0], @@ -552,7 +554,7 @@ class CalDAV(object): @param data_id: Get Data’s ID or False @param context: A standard dictionary for contextual values """ - + ical_data = content self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, context) parsedCal = vobject.readOne(ical_data) diff --git a/addons/caldav/wizard/caldav_browse.py b/addons/caldav/wizard/caldav_browse.py index f6ecc5dccd5..5b78c480d07 100644 --- a/addons/caldav/wizard/caldav_browse.py +++ b/addons/caldav/wizard/caldav_browse.py @@ -24,6 +24,7 @@ from tools import config import base64 import addons from tools.translate import _ +import tools class caldav_browse(osv.osv_memory): @@ -176,16 +177,6 @@ configuration pref_ids = pref_obj.browse(cr, uid ,context.get('rec_id',False), context=context) res = {} host = context.get('host') - port = '' - prefix = 'http://' - if not config.get('xmlrpc'): - if not config.get('netrpc'): - prefix = 'https://' - port = config.get('xmlrpcs_port', 8071) - else: - port = config.get('netrpc_port',8070) - else: - port = config.get('xmlrpc_port',8069) if not config.get_misc('webdav','enable',True): raise Exception("WebDAV is disabled, cannot continue") user_pool = self.pool.get('res.users') @@ -195,16 +186,16 @@ configuration if pref_ids: pref_ids = pref_ids[0] if pref_ids.device == 'iphone': - url = host + ':' + str(port) + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/' + url = host + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/' else : - url = host + ':' + str(port) + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/'+ 'users/'+ current_user.login + '/'+ pref_ids.collection.name+ '/'+ pref_ids.calendar.name + url = host + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/'+ 'users/'+ current_user.login + '/'+ pref_ids.collection.name+ '/'+ pref_ids.calendar.name res['description'] = self.__doc.get(pref_ids.device , self.__doc['other']) file = open(addons.get_module_resource('caldav','doc', 'caldav_doc.pdf'),'rb') res['caldav_doc_file'] = base64.encodestring(file.read()) #res['doc_link'] = 'http://doc.openerp.com/' - res['url'] = prefix+url + res['url'] = url return res def browse_caldav(self, cr, uid, ids, context): @@ -239,12 +230,8 @@ class user_preference(osv.osv_memory): return ids[0] def _get_default_host(self, cr, uid, context): - ids=self.search(cr,uid,[]) - host_name = '' - if ids: - ids = len(ids)> 1 and len(ids)-1 or ids[0] # Use len(ids)-1 for taking the value of last id - host_name = self.browse(cr, uid,[ids],context=context)[0].host_name - return host_name + + return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='http://localhost:8069', context=context) _defaults={ 'service': 'webdav', diff --git a/addons/crm/test/process/meeting.yml b/addons/crm/test/process/meeting.yml index 508b1eaff59..063d7e5b6f3 100644 --- a/addons/crm/test/process/meeting.yml +++ b/addons/crm/test/process/meeting.yml @@ -9,4 +9,4 @@ assert meeting_rec.state == 'open', "Meeting is not in confirm state" self.case_close(cr, uid, [ref('crm_case_initialdiscussion0')]) meeting_rec_close = self.browse(cr, uid, ref("crm_case_initialdiscussion0")) - assert meeting_rec_close.state == 'done', "Meeting is not in done state" \ No newline at end of file + assert meeting_rec_close.state == 'done', "Meeting is not in done state" diff --git a/addons/crm_profiling/__openerp__.py b/addons/crm_profiling/__openerp__.py index 1c78859ecb6..85421301380 100644 --- a/addons/crm_profiling/__openerp__.py +++ b/addons/crm_profiling/__openerp__.py @@ -39,7 +39,7 @@ It also has been merged with the earlier CRM & SRM segmentation tool because the 'website': 'http://www.openerp.com', 'depends': ['base', 'crm'], 'init_xml': [], - 'update_xml': ['security/ir.model.access.csv', 'wizard/open_questionnaire_view.xml', 'crm_profiling_view.xml'], + 'update_xml': ['security/ir.model.access.csv', 'crm_profiling_view.xml'], 'demo_xml': ['crm_profiling_demo.xml'], 'test': [#'test/process/profiling.yml', #TODO:It's not debuging because problem to write data for open.questionnaire from partner section. 'test/process/segmentation.yml',], diff --git a/addons/crm_profiling/crm_profiling.py b/addons/crm_profiling/crm_profiling.py index 17cc04bc1d9..59137966da0 100644 --- a/addons/crm_profiling/crm_profiling.py +++ b/addons/crm_profiling/crm_profiling.py @@ -159,19 +159,19 @@ class questionnaire(osv.osv): _name="crm_profiling.questionnaire" _description= "Questionnaire" - def build_form(self, cr, uid, questionnaire_id, context=None): + def build_form(self, cr, uid, data, context=None): """ @param self: The object pointer @param cr: the current row, from the database cursor, @param uid: the current user’s ID for security checks, @param data: Get Data @param context: A standard dictionary for contextual values """ - + query = """ select name, id from crm_profiling_question where id in ( select question from profile_questionnaire_quest_rel where questionnaire = %s)""" - res = cr.execute(query, (questionnaire_id,)) + res = cr.execute(query, (data['form']['questionnaire_name'],)) result = cr.fetchall() quest_fields={} quest_form=''' @@ -180,6 +180,7 @@ class questionnaire(osv.osv): quest_form = quest_form + '' % (oid,) quest_fields['quest_form%d' % (oid,)] = {'string': name, 'type': 'many2one', \ 'relation': 'crm_profiling.answer', 'domain': [('question_id','=',oid)] } + quest_form = quest_form + '''''' return quest_form, quest_fields _columns = { @@ -218,16 +219,16 @@ class partner(osv.osv): @param context: A standard dictionary for contextual values """ temp = [] - for x in context.get('fields'): - if x.startswith("quest_form") and data[x] != 0 : - if data[x] and data[x][0]: - temp.append(data[x][0]) - partner_id = context.get('active_id') + for x in data['form']: + if x.startswith("quest_form") and data['form'][x] != 0 : + temp.append(data['form'][x]) + query = "select answer from partner_question_rel where partner=%s" - cr.execute(query, (partner_id,)) + cr.execute(query, (data['id'],)) for x in cr.fetchall(): temp.append(x[0]) - self.write(cr, uid, [partner_id], {'answers_ids':[[6, 0, temp]]}, context=context) + + self.write(cr, uid, [data['id']], {'answers_ids':[[6, 0, temp]]}, context=context) return {} diff --git a/addons/crm_profiling/crm_profiling_view.xml b/addons/crm_profiling/crm_profiling_view.xml index a54d3d4b0a9..258de2e4e2d 100644 --- a/addons/crm_profiling/crm_profiling_view.xml +++ b/addons/crm_profiling/crm_profiling_view.xml @@ -2,6 +2,13 @@ + + Questionnaires crm_profiling.questionnaire @@ -133,7 +140,7 @@