From 28c4e5530f062cc7c618c67810220e5126330d5e Mon Sep 17 00:00:00 2001 From: Stuart Longland Date: Fri, 23 Mar 2012 15:21:46 +1000 Subject: [PATCH 001/252] faces: Fix 24-hour and end-at-midnight timespans In cases where a working day either: - Spans 24 hours or - ends at midnight the time span calculation code incorrectly calculates the time of that day, either stating that the day is 0 minutes long, or worse, is negative. The following patch addresses this. Non-working days are specified using the Python 'None', or 'False' values, rather than specifying the same start and end time, as the latter will now be interpreted as a 24-hour period. bzr revid: me@vk4msl.yi.org-20120323052146-vosvz50lg12n7e1i --- addons/resource/faces/pcalendar.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/addons/resource/faces/pcalendar.py b/addons/resource/faces/pcalendar.py index c82c49d4816..4b023911b1e 100644 --- a/addons/resource/faces/pcalendar.py +++ b/addons/resource/faces/pcalendar.py @@ -895,7 +895,16 @@ class Calendar(object): def _recalc_working_time(self): def slot_sum_time(day): slots = self.working_times.get(day, DEFAULT_WORKING_DAYS[day]) - return sum(map(lambda slot: slot[1] - slot[0], slots)) + def time_diff(times): + (start, end) = times + if end == start: + return 24*60 # 24 hours + + diff = end - start + if end < start: + diff += (24*60) + return diff + return sum(map(time_diff, slots)) self.day_times = map(slot_sum_time, range(0, 7)) self.week_time = sum(self.day_times) From 5c4dba40f74f09d5ff0856fb9904f61ff792656e Mon Sep 17 00:00:00 2001 From: Stuart Longland Date: Fri, 23 Mar 2012 15:22:50 +1000 Subject: [PATCH 002/252] resource: Convert working hours to UTC Faces assumes that all times are given in the same timezone. OpenERP uses UTC internally, and uses UTC when communicating task and project start/end times to faces. It unfortunately gives the working hours in local time. The following converts the time zone to UTC, assuming that the working hours are in the time zone of the currently logged-in user. (This will have to be fixed to convert each resources' calendar from the resource's local time zone to UTC.) bzr revid: me@vk4msl.yi.org-20120323052250-m03bth2dy755hw1p --- addons/resource/resource.py | 145 ++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 46 deletions(-) diff --git a/addons/resource/resource.py b/addons/resource/resource.py index fb3d8c0980e..b3bfcea9664 100644 --- a/addons/resource/resource.py +++ b/addons/resource/resource.py @@ -19,7 +19,7 @@ # ############################################################################## -from datetime import datetime, timedelta +from datetime import datetime, timedelta, time, date import math from faces import * from osv import fields, osv @@ -28,6 +28,7 @@ from tools.translate import _ from itertools import groupby from operator import itemgetter +import pytz class resource_calendar(osv.osv): _name = "resource.calendar" @@ -279,8 +280,9 @@ def convert_timeformat(time_string): hour_part = split_list[0] mins_part = split_list[1] round_mins = int(round(float(mins_part) * 60,-2)) - converted_string = hour_part + ':' + str(round_mins)[0:2] - return converted_string + return time(int(hour_part), round_mins) + #converted_string = hour_part + ':' + str(round_mins)[0:2] + #return converted_string class resource_resource(osv.osv): _name = "resource.resource" @@ -366,51 +368,102 @@ class resource_resource(osv.osv): Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format. @param calendar_id : working calendar of the project """ + tz = pytz.utc + if context and ('tz' in context): + tz = pytz.timezone(context['tz']) + + wktime_local = None + week_days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] if not calendar_id: - # Calendar is not specified: working days: 24/7 - return [('fri', '8:0-12:0','13:0-17:0'), ('thu', '8:0-12:0','13:0-17:0'), ('wed', '8:0-12:0','13:0-17:0'), - ('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')] - resource_attendance_pool = self.pool.get('resource.calendar.attendance') - time_range = "8:00-8:00" - non_working = "" - week_days = {"0": "mon", "1": "tue", "2": "wed","3": "thu", "4": "fri", "5": "sat", "6": "sun"} - wk_days = {} - wk_time = {} - wktime_list = [] + # Calendar is not specified: working days: some sane default + wktime_local = [ + (0, time(8,0), time(12,0)), + (0, time(13,0), time(17,0)), + (1, time(8,0), time(12,0)), + (1, time(13,0), time(17,0)), + (2, time(8,0), time(12,0)), + (2, time(13,0), time(17,0)), + (3, time(8,0), time(12,0)), + (3, time(13,0), time(17,0)), + (4, time(8,0), time(12,0)), + (4, time(13,0), time(17,0)), + ] + #return [('fri', '8:0-12:0','13:0-17:0'), ('thu', '8:0-12:0','13:0-17:0'), ('wed', '8:0-12:0','13:0-17:0'), + # ('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')] + else: + resource_attendance_pool = self.pool.get('resource.calendar.attendance') + non_working = "" + wktime_local = [] + + week_ids = resource_attendance_pool.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context) + weeks = resource_attendance_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context) + # Convert time formats into appropriate format required + # and create lists inside wktime_local. + for week in weeks: + res_str = "" + day = None + if week['dayofweek']: + day = int(week['dayofweek']) + else: + raise osv.except_osv(_('Configuration Error!'),_('Make sure the Working time has been configured with proper week days!')) + hour_from = convert_timeformat(week['hour_from']) + hour_to = convert_timeformat(week['hour_to']) + wktime_local.append((day, hour_from, hour_to)) + + # We now have working hours _in local time_. Non-working days are an + # empty list, while working days are a list of tuples, consisting of a + # start time and an end time. We will convert these to UTC for time + # calculation purposes. + + # We need to get this into a dict + # which will be in the following format: + # { 'day': [(time(9,0), time(17,0)), ...], ... } + wktime_utc = {} + + # NOTE: This may break with regards to DST! + for (day, start, end) in wktime_local: + # Convert start time to UTC + start_dt_local = datetime.combine(date.today(), start.replace(tzinfo=tz)) + start_dt_utc = start_dt_local.astimezone(pytz.utc) + start_dt_day = (day + (start_dt_utc.date() - start_dt_local.date()).days) % 7 + + # Convert end time to UTC + end_dt_local = datetime.combine(date.today(), end.replace(tzinfo=tz)) + end_dt_utc = end_dt_local.astimezone(pytz.utc) + end_dt_day = (day + (end_dt_utc.date() - end_dt_local.date()).days) % 7 + + # Are start and end still on the same day? + if start_dt_day == end_dt_day: + day_name = week_days[start_dt_day] + if day_name not in wktime_utc: + wktime_utc[day_name] = [] + wktime_utc[day_name].append((start_dt_utc.time(), end_dt_utc.time())) + else: + day_start_name = week_days[start_dt_day] + if day_start_name not in wktime_utc: + wktime_utc[day_start_name] = [] + # We go until midnight that day + wktime_utc[day_start_name].append((start_dt_utc.time(), time(0,0))) + + day_end_name = week_days[end_dt_day] + if day_end_name not in wktime_utc: + wktime_utc[day_end_name] = [] + # Then resume from midnight that day + wktime_utc[day_end_name].append((time(0,0), end_dt_utc.time())) + + # Now having gotten a list of times together, generate the final output wktime_cal = [] - week_ids = resource_attendance_pool.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context) - weeks = resource_attendance_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context) - # Convert time formats into appropriate format required - # and create a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')] - for week in weeks: - res_str = "" - day = None - if week_days.get(week['dayofweek'],False): - day = week_days[week['dayofweek']] - wk_days[week['dayofweek']] = week_days[week['dayofweek']] - else: - raise osv.except_osv(_('Configuration Error!'),_('Make sure the Working time has been configured with proper week days!')) - hour_from_str = convert_timeformat(week['hour_from']) - hour_to_str = convert_timeformat(week['hour_to']) - res_str = hour_from_str + '-' + hour_to_str - wktime_list.append((day, res_str)) - # Convert into format like [('mon', '8:00-12:00', '13:00-18:00')] - for item in wktime_list: - if wk_time.has_key(item[0]): - wk_time[item[0]].append(item[1]) - else: - wk_time[item[0]] = [item[0]] - wk_time[item[0]].append(item[1]) - for k,v in wk_time.items(): - wktime_cal.append(tuple(v)) - # Add for the non-working days like: [('sat, sun', '8:00-8:00')] - for k, v in wk_days.items(): - if week_days.has_key(k): - week_days.pop(k) - for v in week_days.itervalues(): - non_working += v + ',' - if non_working: - wktime_cal.append((non_working[:-1], time_range)) + for day, times in wktime_utc.iteritems(): + # Sort the times + times.sort() + wktime = ['{0}-{1}'.format(s.strftime('%H:%M'), e.strftime('%H:%M')) for (s, e) in times] + wktime.insert(0, day) + wktime_cal.append(tuple(wktime)) + # Finally, add in non-working days + for day in week_days: + if day not in wktime_utc: + wktime_cal.append((day, None)) + return wktime_cal resource_resource() From fa8f714a590206f7923ef62a88bc39fe1b70491f Mon Sep 17 00:00:00 2001 From: Antonin Bourguignon Date: Thu, 8 Nov 2012 15:01:00 +0100 Subject: [PATCH 003/252] [WIP] imp crm tests bzr revid: abo@openerp.com-20121108140100-wmpa3ko8cpo840zq --- addons/crm/test/process/lead2opportunity2win.yml | 6 +++--- addons/crm/test/ui/crm_demo.yml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/crm/test/process/lead2opportunity2win.yml b/addons/crm/test/process/lead2opportunity2win.yml index dc5aadbcf16..d6f1c53de63 100644 --- a/addons/crm/test/process/lead2opportunity2win.yml +++ b/addons/crm/test/process/lead2opportunity2win.yml @@ -1,12 +1,12 @@ - - In order to test convert customer lead into opportunity, + In order to test the conversion of a lead into a opportunity, - - I open customer lead. + I open a lead. - !python {model: crm.lead}: | self.case_open(cr, uid, [ref("crm_case_4")]) - - I check lead state is "Open". + I check if the lead state is "Open". - !assert {model: crm.lead, id: crm.crm_case_4, string: Lead in open state}: - state == "open" diff --git a/addons/crm/test/ui/crm_demo.yml b/addons/crm/test/ui/crm_demo.yml index 842b3a4e887..9154ffdf513 100644 --- a/addons/crm/test/ui/crm_demo.yml +++ b/addons/crm/test/ui/crm_demo.yml @@ -1,5 +1,5 @@ - - I create lead record to call of partner onchange, stage onchange and Mailing opt-in onchange method. + I create a lead record to call a partner onchange, stage onchange and mailing opt-in onchange method. - !record {model: crm.lead, id: crm_case_25}: name: 'Need more info about your pc2' @@ -8,7 +8,7 @@ stage_id: crm.stage_lead1 state: draft - - I create lead record to call Mailing opt-out onchange method. + I create a lead record to call a mailing opt-out onchange method. - !record {model: crm.lead, id: crm_case_18}: name: 'Need 20 Days of Consultancy' @@ -16,13 +16,13 @@ state: draft opt_out: True - - I create phonecall record to call partner onchange method. + I create a phonecall record to call a partner onchange method. - !record {model: crm.phonecall, id: crm_phonecall_5}: name: 'Bad time' partner_id: base.res_partner_5 - - I setting next stage "New" for the lead. + I set the next stage to "New" for the lead. - !python {model: crm.lead}: | self.stage_next(cr, uid, [ref("crm_case_4")], context={'stage_type': 'lead'}) From 9c3aefeb022f2b795a67779b46ed62dedbbf96f9 Mon Sep 17 00:00:00 2001 From: Antonin Bourguignon Date: Thu, 8 Nov 2012 18:58:41 +0100 Subject: [PATCH 004/252] [IMP] indentation bzr revid: abo@openerp.com-20121108175841-mf5c1jhywj07cvvk --- addons/crm/test/process/lead2opportunity2win.yml | 2 +- addons/crm/wizard/crm_lead_to_partner_view.xml | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/addons/crm/test/process/lead2opportunity2win.yml b/addons/crm/test/process/lead2opportunity2win.yml index d6f1c53de63..0523c2d6296 100644 --- a/addons/crm/test/process/lead2opportunity2win.yml +++ b/addons/crm/test/process/lead2opportunity2win.yml @@ -8,7 +8,7 @@ - I check if the lead state is "Open". - - !assert {model: crm.lead, id: crm.crm_case_4, string: Lead in open state}: + !assert {model: crm.lead, id: crm.crm_case_4, string: Lead state is Open}: - state == "open" - I fill in a lead2partner wizard. diff --git a/addons/crm/wizard/crm_lead_to_partner_view.xml b/addons/crm/wizard/crm_lead_to_partner_view.xml index 21a14dd3726..136985dca65 100644 --- a/addons/crm/wizard/crm_lead_to_partner_view.xml +++ b/addons/crm/wizard/crm_lead_to_partner_view.xml @@ -1,9 +1,8 @@ - + - - - + + crm.lead2partner.view crm.lead2partner @@ -20,9 +19,8 @@ - + - Create a Partner @@ -33,5 +31,5 @@ new - + From bfc4d87f3145fe93f2918edaea31197b10a9576c Mon Sep 17 00:00:00 2001 From: "Hiral Patel (OpenERP)" Date: Fri, 9 Nov 2012 11:40:28 +0530 Subject: [PATCH 005/252] [IMP] move Email Notification on Answer boolean below Type field bzr revid: hip@tinyerp.com-20121109061028-9suru2afitw4wf57 --- addons/survey/survey_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/survey/survey_view.xml b/addons/survey/survey_view.xml index f6920c68d34..36d6fb08b3a 100644 --- a/addons/survey/survey_view.xml +++ b/addons/survey/survey_view.xml @@ -45,8 +45,8 @@ - + From b15100587788448da36b8acb1201e013acc02106 Mon Sep 17 00:00:00 2001 From: "Hiral Patel (OpenERP)" Date: Fri, 9 Nov 2012 11:52:30 +0530 Subject: [PATCH 006/252] [IMP] Resize Type field to fit Responsible field bzr revid: hip@tinyerp.com-20121109062230-yspb3pivwwggulm6 --- addons/survey/survey_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/survey/survey_view.xml b/addons/survey/survey_view.xml index 36d6fb08b3a..3c2e6055416 100644 --- a/addons/survey/survey_view.xml +++ b/addons/survey/survey_view.xml @@ -45,7 +45,7 @@ - + From 33eca6f1d64528ea6aec40194c109f163f68de12 Mon Sep 17 00:00:00 2001 From: "Hiral Patel (OpenERP)" Date: Fri, 9 Nov 2012 12:49:47 +0530 Subject: [PATCH 007/252] [IMP] Answer Survey action button should be red after sending a request bzr revid: hip@tinyerp.com-20121109071947-i25qvwx118iqn8p2 --- addons/hr_evaluation/hr_evaluation_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/hr_evaluation/hr_evaluation_view.xml b/addons/hr_evaluation/hr_evaluation_view.xml index e0978847acb..d2cb0bd8ee5 100644 --- a/addons/hr_evaluation/hr_evaluation_view.xml +++ b/addons/hr_evaluation/hr_evaluation_view.xml @@ -290,7 +290,7 @@