Merge lp:~vrt-openerp/openobject-addons/vrt-openerp into lp:openobject-addons
- vrt-openerp
- Merge into trunk
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~vrt-openerp/openobject-addons/vrt-openerp | ||||
Merge into: | lp:openobject-addons | ||||
Diff against target: |
517 lines (+241/-55) 8 files modified
crm/report/crm_lead_report.py (+4/-0) crm/report/crm_lead_report_view.xml (+93/-3) hr_timesheet_sheet/hr_timesheet_sheet_view.xml (+1/-1) project/project.py (+7/-2) project/project_view.xml (+3/-0) project_long_term/project_long_term.py (+24/-2) resource/faces/pcalendar.py (+10/-1) resource/resource.py (+99/-46) |
||||
To merge this branch: | bzr merge lp:~vrt-openerp/openobject-addons/vrt-openerp | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Olivier Dony (Odoo) | branch content | Needs Resubmitting | |
Review via email: mp+93763@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-03-23.
Commit message
Description of the change
This branch includes a number of in-house changes to OpenERP 6.1 trunk that fix some issues discovered in the move across. Updates include:
- Long term planning:
- Fix to working hours; converting the user's working hours to UTC for scheduling in Faces
- Allowing the "Schedule Phases" to also schedule tasks within each phase
- Enable assignment of a work-load for a task in percent; this is passed through to Faces for scheduling purposes
- CRM module:
- Create a new "Leads" field (taken from partner_name), for leads that do not have a partner defined yet (otherwise all these "leads" get filed under the "Undefined" partner)
- 6624. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6625. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6626. By Jean-Christophe VASSORT
-
[FIX] opw 383657: hr_expense: When unit quantity or factor value is zero > get divide by zero error
- 6627. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6628. By Raphael Collet (OpenERP)
-
[MERGE] lp:931523 (fix error message when pushing on Documents)
- 6629. By Quentin (OpenERP) <email address hidden>
-
[MERGE] merge the branch from Numérigraphe with a better label for the address of direct delivery on PO.
- 6630. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6631. By Nicolas Vanhoren (OpenERP)
-
[merge] refactoring in web client
- 6632. By Quentin (OpenERP) <email address hidden>
-
[FIX] account, cash statement: creation through web client
- 6633. By Quentin (OpenERP) <email address hidden>
-
[MERGE] lp:909124. Conflict between account_
bank_statement_ extension and point_of_sale - 6634. By Quentin (OpenERP) <email address hidden>
-
[FIX] account: cannot iter on a boolean. stupid me
- 6635. By Fabien Meghazi (OpenERP)
-
[FIX] Edi: webclient's template name has been changed from 'Interface' to 'WebClient'
- 6636. By Quentin (OpenERP) <email address hidden>
-
[IMP] account_payment: improved the module description to tackle the most common pitfall linked to this module + rst compliancy of few other modules
- 6637. By Quentin (OpenERP) <email address hidden>
-
[IMP] account_payment: improved the module description to tackle the most common pitfall linked to this module
- 6638. By Quentin (OpenERP) <email address hidden>
-
[MERGE] lp:930528
- 6639. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6640. By Quentin (OpenERP) <email address hidden>
-
[MERGE] lp:880844
- 6641. By Quentin (OpenERP) <email address hidden>
-
[REM] hr_timesheet_
invoice: removed unused report cost ledger. It was duplicated code of the same report defined in account module AND calling its rml. - 6642. By Quentin (OpenERP) <email address hidden>
-
[MERGE] fix of lp:901089
- 6643. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6644. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6645. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6646. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6647. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6648. By Olivier Dony (Odoo)
-
[MERGE] Latest bugfixes from 6.1
- 6649. By Nicolas Vanhoren (OpenERP)
-
[imp] adaptation to .js due to changes in web
- 6650. By Fabien Meghazi (OpenERP)
-
[FIX] Fixed broken web addon due to webclient's new layout
- 6651. By Fabien Meghazi (OpenERP)
-
[FIX] web_livechat: Fixed broken addon due to webclient's layout change
- 6652. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6653. By Fabien Meghazi (OpenERP)
-
[IMP] web addons: Use webclient's Systray tooltips
- 6654. By Quentin (OpenERP) <email address hidden>
-
[MERGE] merged the branch containing the refactoring of event module and the new modules event_moodle and event_sale
- 6655. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6656. By Launchpad Translations on behalf of openerp
-
Launchpad automatic translations update.
- 6671. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6672. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6673. By Stuart Longland
-
hr_timesheet_sheet: Fix user_id default value
OpenERP 6.1-1 currently fails to fill in the user_id field. On submission of a
timesheet line, the end user finds the system rejects the entered data on the
basis that the user_id field is invalid. Being a hidden field, it is
impossible for the end user to correct this.The following seems to fix the problem here.
- 6674. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6675. By Stuart Longland
-
crm: Hide "Lead" in search view of Opportunities
They don't have "lead" fields, as the lead has been already converted to
a partner by this stage. - 6676. By Stuart Longland
-
crm: Allow lead report to show individual leads
This allows the end user to navigate to an individual lead (for now via
an intermediate form). The form will need some prettying up, but at
least now if there's a heap of leads in one group, we can differentiate
them now.This also reverts my earlier commit, which broke things.
- 6677. By Stuart Longland
-
crm_lead_report: Fix broken init function
SQL was complaining we specified id twice, so we call the latter
occurance lead_id. That keeps it happy.
Olivier Dony (Odoo) (odo-openerp) wrote : | # |
Stuart Longland (redhatter) wrote : | # |
No worries, I'll split this up.
I've just spent what seems like 10 minutes hunting around for the "Register Branch" link to do exactly this, and Launchpad has "helpfully" removed it and not told anyone (thanks Launchpad).
I'm creating a fresh branch of the trunk code -- when this is done, I should be able to cherry-pick the relevant commits from it and push those into a separate new branch.
Unmerged revisions
- 6677. By Stuart Longland
-
crm_lead_report: Fix broken init function
SQL was complaining we specified id twice, so we call the latter
occurance lead_id. That keeps it happy. - 6676. By Stuart Longland
-
crm: Allow lead report to show individual leads
This allows the end user to navigate to an individual lead (for now via
an intermediate form). The form will need some prettying up, but at
least now if there's a heap of leads in one group, we can differentiate
them now.This also reverts my earlier commit, which broke things.
- 6675. By Stuart Longland
-
crm: Hide "Lead" in search view of Opportunities
They don't have "lead" fields, as the lead has been already converted to
a partner by this stage. - 6674. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6673. By Stuart Longland
-
hr_timesheet_sheet: Fix user_id default value
OpenERP 6.1-1 currently fails to fill in the user_id field. On submission of a
timesheet line, the end user finds the system rejects the entered data on the
basis that the user_id field is invalid. Being a hidden field, it is
impossible for the end user to correct this.The following seems to fix the problem here.
- 6672. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6671. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6670. By Stuart Longland
-
Rewrite and Merge with upstream changes.
- 6669. By Stuart Longland
-
project_long_term: Skip cancelled or done tasks.
These are skipped when generating the project description for faces to manage,
therefore they should also be skipped when collecting results. - 6668. By Stuart Longland
-
project_
long_term. schedule_ phases: Skip projects with no phases Projects that have no phases by definition cannot be scheduled via the "Schedule Phases" algorithm. When one attempts to do this, the following is emitted to Faces:
from resource.faces import *
import datetimedef Project():
resulting in the following stack trace:
[2012-02-17 02:07:29,
630][developmen t61] ERROR:web- services: Uncaught exception
Traceback (most recent call last):
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ osv/osv. py", line 120, in wrapper
return f(self, dbname, *args, **kwargs)
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ osv/osv. py", line 175, in execute
res = self.execute_cr(cr, uid, obj, method, *args, **kw)
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ osv/osv. py", line 163, in execute_cr
return getattr(object, method)(cr, uid, *args, **kw)
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ addons/ project_ long_term/ wizard/ project_ compute_ phases. py", line 39, in check_selection
return self.compute_date(cr, uid, ids, context=context)
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ addons/ project_ long_term/ wizard/ project_ compute_ phases. py", line 55, in compute_date
project_pool.schedule_ phases( cr, uid, project_ids, context=context)
File "/usr/lib64/python2. 7/site- packages/ openerp- 6.1rc1_ 20120112_ 173907- py2.7.egg/ openerp/ addons/ project_ long_term/ project_ long_term. py", line 238, in schedule_phases
exec result in local_dict
File "<string>", line 5^
IndentationError: expected an indented blockThis is a partial fix. The user should be warned as to what projects have been
skipped or at least, given the opportunity to schedule the tasks for those
projects.
Preview Diff
1 | === modified file 'crm/report/crm_lead_report.py' | |||
2 | --- crm/report/crm_lead_report.py 2012-01-31 13:36:57 +0000 | |||
3 | +++ crm/report/crm_lead_report.py 2012-03-06 23:39:19 +0000 | |||
4 | @@ -74,6 +74,7 @@ | |||
5 | 74 | 'delay_close': fields.float('Delay to Close',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"), | 74 | 'delay_close': fields.float('Delay to Close',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"), |
6 | 75 | 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"), | 75 | 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"), |
7 | 76 | 76 | ||
8 | 77 | 'lead_id':fields.many2one('crm.lead', 'Lead', readonly=True), | ||
9 | 77 | 'user_id':fields.many2one('res.users', 'User', readonly=True), | 78 | 'user_id':fields.many2one('res.users', 'User', readonly=True), |
10 | 78 | 'country_id':fields.many2one('res.country', 'Country', readonly=True), | 79 | 'country_id':fields.many2one('res.country', 'Country', readonly=True), |
11 | 79 | 'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True), | 80 | 'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True), |
12 | @@ -89,6 +90,7 @@ | |||
13 | 89 | domain="['|',('section_id','=',False),('section_id','=',section_id)]" , readonly=True), | 90 | domain="['|',('section_id','=',False),('section_id','=',section_id)]" , readonly=True), |
14 | 90 | 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True, domain="[('section_ids', '=', section_id)]"), | 91 | 'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True, domain="[('section_ids', '=', section_id)]"), |
15 | 91 | 'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True), | 92 | 'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True), |
16 | 93 | 'partner_name': fields.char("Lead", size=64,help='The name of the future partner that will be created while converting the lead into an opportunity', readonly=True), | ||
17 | 92 | 'nbr': fields.integer('# of Cases', readonly=True), | 94 | 'nbr': fields.integer('# of Cases', readonly=True), |
18 | 93 | 'company_id': fields.many2one('res.company', 'Company', readonly=True), | 95 | 'company_id': fields.many2one('res.company', 'Company', readonly=True), |
19 | 94 | 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), | 96 | 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), |
20 | @@ -124,6 +126,7 @@ | |||
21 | 124 | to_char(c.date_open, 'YYYY-MM-DD') as opening_date, | 126 | to_char(c.date_open, 'YYYY-MM-DD') as opening_date, |
22 | 125 | to_char(c.date_closed, 'YYYY-mm-dd') as date_closed, | 127 | to_char(c.date_closed, 'YYYY-mm-dd') as date_closed, |
23 | 126 | 128 | ||
24 | 129 | c.id as lead_id, | ||
25 | 127 | c.state, | 130 | c.state, |
26 | 128 | c.user_id, | 131 | c.user_id, |
27 | 129 | c.probability, | 132 | c.probability, |
28 | @@ -136,6 +139,7 @@ | |||
29 | 136 | c.type_id, | 139 | c.type_id, |
30 | 137 | c.categ_id, | 140 | c.categ_id, |
31 | 138 | c.partner_id, | 141 | c.partner_id, |
32 | 142 | c.partner_name, | ||
33 | 139 | c.country_id, | 143 | c.country_id, |
34 | 140 | c.planned_revenue, | 144 | c.planned_revenue, |
35 | 141 | c.planned_revenue*(c.probability/100) as probable_revenue, | 145 | c.planned_revenue*(c.probability/100) as probable_revenue, |
36 | 142 | 146 | ||
37 | === modified file 'crm/report/crm_lead_report_view.xml' | |||
38 | --- crm/report/crm_lead_report_view.xml 2011-11-14 09:27:08 +0000 | |||
39 | +++ crm/report/crm_lead_report_view.xml 2012-03-06 23:39:19 +0000 | |||
40 | @@ -25,16 +25,52 @@ | |||
41 | 25 | <field name="user_id" invisible="1"/> | 25 | <field name="user_id" invisible="1"/> |
42 | 26 | <field name="company_id" invisible="1"/> | 26 | <field name="company_id" invisible="1"/> |
43 | 27 | <field name="partner_id" invisible="1"/> | 27 | <field name="partner_id" invisible="1"/> |
44 | 28 | <field name="partner_name" invisible="1"/> | ||
45 | 28 | <field name="country_id" invisible="1"/> | 29 | <field name="country_id" invisible="1"/> |
46 | 29 | <field name="nbr" sum="# Leads"/> | 30 | <field name="nbr" sum="# Leads"/> |
47 | 30 | <field name="email" sum="# Mails"/> | 31 | <field name="email" sum="# Mails"/> |
48 | 31 | <field name="delay_open"/> | 32 | <field name="delay_open"/> |
49 | 32 | <field name="delay_close"/> | 33 | <field name="delay_close"/> |
50 | 33 | <field name="planned_revenue"/> | 34 | <field name="planned_revenue"/> |
51 | 35 | <field name="lead_id"/> | ||
52 | 34 | </tree> | 36 | </tree> |
53 | 35 | </field> | 37 | </field> |
54 | 36 | </record> | 38 | </record> |
55 | 37 | 39 | ||
56 | 40 | <!-- Leads by user and section Form View --> | ||
57 | 41 | |||
58 | 42 | <record id="view_report_crm_lead_form" model="ir.ui.view"> | ||
59 | 43 | <field name="name">crm.lead.report.form</field> | ||
60 | 44 | <field name="model">crm.lead.report</field> | ||
61 | 45 | <field name="type">form</field> | ||
62 | 46 | <field name="arch" type="xml"> | ||
63 | 47 | <form string="Lead Analysis"> | ||
64 | 48 | <field name="lead_id" colspan="4"/> | ||
65 | 49 | <field name="creation_year"/> | ||
66 | 50 | <field name="creation_month"/> | ||
67 | 51 | <field name="creation_day"/> | ||
68 | 52 | <field name="deadline_month"/> | ||
69 | 53 | <field name="state"/> | ||
70 | 54 | <field name="stage_id"/> | ||
71 | 55 | <field name="categ_id"/> | ||
72 | 56 | <field name="type_id"/> | ||
73 | 57 | <field name="channel_id"/> | ||
74 | 58 | <field name="type"/> | ||
75 | 59 | <field name="priority"/> | ||
76 | 60 | <field name="section_id"/> | ||
77 | 61 | <field name="user_id"/> | ||
78 | 62 | <field name="company_id"/> | ||
79 | 63 | <field name="partner_id"/> | ||
80 | 64 | <field name="partner_name"/> | ||
81 | 65 | <field name="country_id"/> | ||
82 | 66 | <field name="email"/> | ||
83 | 67 | <field name="delay_open"/> | ||
84 | 68 | <field name="delay_close"/> | ||
85 | 69 | <field name="planned_revenue"/> | ||
86 | 70 | </form> | ||
87 | 71 | </field> | ||
88 | 72 | </record> | ||
89 | 73 | |||
90 | 38 | <!-- Leads by user and section Graph View --> | 74 | <!-- Leads by user and section Graph View --> |
91 | 39 | 75 | ||
92 | 40 | <record id="view_report_crm_lead_graph" model="ir.ui.view"> | 76 | <record id="view_report_crm_lead_graph" model="ir.ui.view"> |
93 | @@ -126,6 +162,7 @@ | |||
94 | 126 | <newline/> | 162 | <newline/> |
95 | 127 | <group expand="0" string="Extended Filters..." groups="base.group_extended"> | 163 | <group expand="0" string="Extended Filters..." groups="base.group_extended"> |
96 | 128 | <field name="partner_id"/> | 164 | <field name="partner_id"/> |
97 | 165 | <field name="partner_name"/> | ||
98 | 129 | <separator orientation="vertical"/> | 166 | <separator orientation="vertical"/> |
99 | 130 | <field name="stage_id" widget="selection" domain="[('section_ids', '=', 'section_id')]" /> | 167 | <field name="stage_id" widget="selection" domain="[('section_ids', '=', 'section_id')]" /> |
100 | 131 | <field name="categ_id" widget="selection"/> | 168 | <field name="categ_id" widget="selection"/> |
101 | @@ -146,6 +183,7 @@ | |||
102 | 146 | domain="[]" | 183 | domain="[]" |
103 | 147 | context="{'group_by':'section_id'}" /> | 184 | context="{'group_by':'section_id'}" /> |
104 | 148 | <filter string="Partner" icon="terp-partner" context="{'group_by':'partner_id'}" /> | 185 | <filter string="Partner" icon="terp-partner" context="{'group_by':'partner_id'}" /> |
105 | 186 | <filter string="Lead" icon="terp-partner" context="{'group_by':'partner_name'}"/> | ||
106 | 149 | <filter string="Country" icon="terp-go-home" context="{'group_by':'country_id'}" /> | 187 | <filter string="Country" icon="terp-go-home" context="{'group_by':'country_id'}" /> |
107 | 150 | <filter string="Company" icon="terp-go-home" | 188 | <filter string="Company" icon="terp-go-home" |
108 | 151 | domain="[]" | 189 | domain="[]" |
109 | @@ -193,6 +231,7 @@ | |||
110 | 193 | <field name="section_id" invisible="1" groups="base.group_extended"/> | 231 | <field name="section_id" invisible="1" groups="base.group_extended"/> |
111 | 194 | <field name="user_id" invisible="1"/> | 232 | <field name="user_id" invisible="1"/> |
112 | 195 | <field name="partner_id" invisible="1"/> | 233 | <field name="partner_id" invisible="1"/> |
113 | 234 | <field name="partner_name" invisible="1"/> | ||
114 | 196 | <field name="country_id" invisible="1"/> | 235 | <field name="country_id" invisible="1"/> |
115 | 197 | <field name="state" invisible="1"/> | 236 | <field name="state" invisible="1"/> |
116 | 198 | <field name="stage_id" invisible="1"/> | 237 | <field name="stage_id" invisible="1"/> |
117 | @@ -210,18 +249,56 @@ | |||
118 | 210 | <field name="delay_expected"/> | 249 | <field name="delay_expected"/> |
119 | 211 | <field name="probability" widget="progressbar"/> | 250 | <field name="probability" widget="progressbar"/> |
120 | 212 | <field name="probable_revenue"/> | 251 | <field name="probable_revenue"/> |
121 | 252 | <field name="lead_id"/> | ||
122 | 213 | </tree> | 253 | </tree> |
123 | 214 | </field> | 254 | </field> |
124 | 215 | </record> | 255 | </record> |
125 | 216 | 256 | ||
126 | 257 | <!-- Opportunity form view --> | ||
127 | 258 | |||
128 | 259 | <record id="view_report_crm_opportunity_form" model="ir.ui.view"> | ||
129 | 260 | <field name="name">crm.lead.report.form</field> | ||
130 | 261 | <field name="model">crm.lead.report</field> | ||
131 | 262 | <field name="type">form</field> | ||
132 | 263 | <field name="arch" type="xml"> | ||
133 | 264 | <form string="Opportunities Analysis"> | ||
134 | 265 | <field name="lead_id" colspan="4"/> | ||
135 | 266 | <field name="creation_year"/> | ||
136 | 267 | <field name="creation_month"/> | ||
137 | 268 | <field name="creation_day"/> | ||
138 | 269 | <field name="deadline_month"/> | ||
139 | 270 | <field name="section_id"/> | ||
140 | 271 | <field name="user_id"/> | ||
141 | 272 | <field name="partner_id"/> | ||
142 | 273 | <field name="partner_name"/> | ||
143 | 274 | <field name="country_id"/> | ||
144 | 275 | <field name="state" /> | ||
145 | 276 | <field name="stage_id" /> | ||
146 | 277 | <field name="priority" /> | ||
147 | 278 | <field name="categ_id"/> | ||
148 | 279 | <field name="type_id"/> | ||
149 | 280 | <field name="channel_id"/> | ||
150 | 281 | <field name="type"/> | ||
151 | 282 | <field name="company_id" /> | ||
152 | 283 | <field name="planned_revenue" /> | ||
153 | 284 | <field name="email" string="# of Emails"/> | ||
154 | 285 | <field name="delay_open"/> | ||
155 | 286 | <field name="delay_close"/> | ||
156 | 287 | <field name="delay_expected"/> | ||
157 | 288 | <field name="probability" widget="progressbar"/> | ||
158 | 289 | <field name="probable_revenue"/> | ||
159 | 290 | </form> | ||
160 | 291 | </field> | ||
161 | 292 | </record> | ||
162 | 293 | |||
163 | 217 | <!-- Leads by user and section Action --> | 294 | <!-- Leads by user and section Action --> |
164 | 218 | 295 | ||
165 | 219 | <record id="action_report_crm_lead" model="ir.actions.act_window"> | 296 | <record id="action_report_crm_lead" model="ir.actions.act_window"> |
166 | 220 | <field name="name">Leads Analysis</field> | 297 | <field name="name">Leads Analysis</field> |
167 | 221 | <field name="res_model">crm.lead.report</field> | 298 | <field name="res_model">crm.lead.report</field> |
168 | 222 | <field name="view_type">form</field> | 299 | <field name="view_type">form</field> |
171 | 223 | <field name="context">{'search_default_year': 1,'search_default_lead': 1, "search_default_user":1, "search_default_this_month":1, 'group_by_no_leaf':1, 'group_by':[]}</field> | 300 | <field name="context">{'search_default_year': 1,'search_default_lead': 1, "search_default_user":1, "search_default_this_month":1, 'group_by':[]}</field> |
172 | 224 | <field name="view_mode">tree,graph</field> | 301 | <field name="view_mode">tree,graph,form</field> |
173 | 225 | <field name="domain">[]</field> | 302 | <field name="domain">[]</field> |
174 | 226 | <field name="help">Leads Analysis allows you to check different CRM related information. Check for treatment delays, number of responses given and emails sent. You can sort out your leads analysis by different groups to get accurate grained analysis.</field> | 303 | <field name="help">Leads Analysis allows you to check different CRM related information. Check for treatment delays, number of responses given and emails sent. You can sort out your leads analysis by different groups to get accurate grained analysis.</field> |
175 | 227 | </record> | 304 | </record> |
176 | @@ -237,12 +314,18 @@ | |||
177 | 237 | <field name="view_id" ref="view_report_crm_lead_graph"/> | 314 | <field name="view_id" ref="view_report_crm_lead_graph"/> |
178 | 238 | <field name="act_window_id" ref="action_report_crm_lead"/> | 315 | <field name="act_window_id" ref="action_report_crm_lead"/> |
179 | 239 | </record> | 316 | </record> |
180 | 317 | <record model="ir.actions.act_window.view" id="action_report_crm_lead_form"> | ||
181 | 318 | <field name="sequence" eval="3"/> | ||
182 | 319 | <field name="view_mode">form</field> | ||
183 | 320 | <field name="view_id" ref="view_report_crm_lead_form"/> | ||
184 | 321 | <field name="act_window_id" ref="action_report_crm_lead"/> | ||
185 | 322 | </record> | ||
186 | 240 | 323 | ||
187 | 241 | <record id="action_report_crm_opportunity" model="ir.actions.act_window"> | 324 | <record id="action_report_crm_opportunity" model="ir.actions.act_window"> |
188 | 242 | <field name="name">Opportunities Analysis</field> | 325 | <field name="name">Opportunities Analysis</field> |
189 | 243 | <field name="res_model">crm.lead.report</field> | 326 | <field name="res_model">crm.lead.report</field> |
190 | 244 | <field name="view_type">form</field> | 327 | <field name="view_type">form</field> |
192 | 245 | <field name="context">{"search_default_year":1,"search_default_opportunity":1, "search_default_user":1,"search_default_this_month":1,'group_by_no_leaf':1,'group_by':[]}</field> | 328 | <field name="context">{"search_default_year":1,"search_default_opportunity":1, "search_default_user":1,"search_default_this_month":1,'group_by':[]}</field> |
193 | 246 | <field name="view_mode">tree,graph</field> | 329 | <field name="view_mode">tree,graph</field> |
194 | 247 | <field name="help">Opportunities Analysis gives you an instant access to your opportunities with information such as the expected revenue, planned cost, missed deadlines or the number of interactions per opportunity. This report is mainly used by the sales manager in order to do the periodic review with the teams of the sales pipeline.</field> | 330 | <field name="help">Opportunities Analysis gives you an instant access to your opportunities with information such as the expected revenue, planned cost, missed deadlines or the number of interactions per opportunity. This report is mainly used by the sales manager in order to do the periodic review with the teams of the sales pipeline.</field> |
195 | 248 | </record> | 331 | </record> |
196 | @@ -261,6 +344,13 @@ | |||
197 | 261 | <field name="act_window_id" ref="action_report_crm_opportunity"/> | 344 | <field name="act_window_id" ref="action_report_crm_opportunity"/> |
198 | 262 | </record> | 345 | </record> |
199 | 263 | 346 | ||
200 | 347 | <record model="ir.actions.act_window.view" id="action_report_crm_opportunity_form"> | ||
201 | 348 | <field name="sequence" eval="3"/> | ||
202 | 349 | <field name="view_mode">form</field> | ||
203 | 350 | <field name="view_id" ref="view_report_crm_opportunity_form"/> | ||
204 | 351 | <field name="act_window_id" ref="action_report_crm_opportunity"/> | ||
205 | 352 | </record> | ||
206 | 353 | |||
207 | 264 | <menuitem name="Leads Analysis" id="menu_report_crm_leads_tree" | 354 | <menuitem name="Leads Analysis" id="menu_report_crm_leads_tree" |
208 | 265 | groups="base.group_extended" | 355 | groups="base.group_extended" |
209 | 266 | parent="base.next_id_64" action="action_report_crm_lead" sequence="3"/> | 356 | parent="base.next_id_64" action="action_report_crm_lead" sequence="3"/> |
210 | 267 | 357 | ||
211 | === modified file 'hr_timesheet_sheet/hr_timesheet_sheet_view.xml' | |||
212 | --- hr_timesheet_sheet/hr_timesheet_sheet_view.xml 2012-02-13 15:27:55 +0000 | |||
213 | +++ hr_timesheet_sheet/hr_timesheet_sheet_view.xml 2012-03-06 23:39:19 +0000 | |||
214 | @@ -95,7 +95,7 @@ | |||
215 | 95 | <button name="sign_out" string="Sign Out" type="object" icon="terp-gtk-jump-to-rtl"/> | 95 | <button name="sign_out" string="Sign Out" type="object" icon="terp-gtk-jump-to-rtl"/> |
216 | 96 | <field name="total_attendance_day" widget="float_time" colspan="4"/> | 96 | <field name="total_attendance_day" widget="float_time" colspan="4"/> |
217 | 97 | </group> | 97 | </group> |
219 | 98 | <field colspan="4" context="{'date':date_current,'user_id':user_id}" domain="[('name','=',date_current)]" name="timesheet_ids" nolabel="1"> | 98 | <field colspan="4" context="{'date':date_current,'user_id':uid}" domain="[('name','=',date_current)]" name="timesheet_ids" nolabel="1"> |
220 | 99 | <tree editable="top" string="Timesheet Lines"> | 99 | <tree editable="top" string="Timesheet Lines"> |
221 | 100 | <field invisible="1" name="date"/> | 100 | <field invisible="1" name="date"/> |
222 | 101 | <field domain="[('type','=','normal'), ('state', '<>', 'close')]" name="account_id" on_change="on_change_account_id(account_id)"/> | 101 | <field domain="[('type','=','normal'), ('state', '<>', 'close')]" name="account_id" on_change="on_change_account_id(account_id)"/> |
223 | 102 | 102 | ||
224 | === modified file 'project/project.py' | |||
225 | --- project/project.py 2012-02-28 14:08:16 +0000 | |||
226 | +++ project/project.py 2012-03-06 23:39:19 +0000 | |||
227 | @@ -666,6 +666,7 @@ | |||
228 | 666 | 'id': fields.integer('ID', readonly=True), | 666 | 'id': fields.integer('ID', readonly=True), |
229 | 667 | 'color': fields.integer('Color Index'), | 667 | 'color': fields.integer('Color Index'), |
230 | 668 | 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), | 668 | 'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True), |
231 | 669 | 'work_load': fields.integer('Workload (%)', help='Indicates how much time each person is to spend working on this task as a percentage of their total working hours. The default is 100%. The value must be greater than 0, else it will be treated as 100%.'), | ||
232 | 669 | } | 670 | } |
233 | 670 | 671 | ||
234 | 671 | _defaults = { | 672 | _defaults = { |
235 | @@ -676,7 +677,7 @@ | |||
236 | 676 | 'sequence': 10, | 677 | 'sequence': 10, |
237 | 677 | 'active': True, | 678 | 'active': True, |
238 | 678 | 'user_id': lambda obj, cr, uid, context: uid, | 679 | 'user_id': lambda obj, cr, uid, context: uid, |
240 | 679 | 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c) | 680 | 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c), |
241 | 680 | } | 681 | } |
242 | 681 | 682 | ||
243 | 682 | _order = "priority, sequence, date_start, name, id" | 683 | _order = "priority, sequence, date_start, name, id" |
244 | @@ -1067,8 +1068,12 @@ | |||
245 | 1067 | continue | 1068 | continue |
246 | 1068 | result += ''' | 1069 | result += ''' |
247 | 1069 | %sdef Task_%s(): | 1070 | %sdef Task_%s(): |
248 | 1071 | %s load = %4.2f | ||
249 | 1070 | %s todo = \"%.2fH\" | 1072 | %s todo = \"%.2fH\" |
251 | 1071 | %s effort = \"%.2fH\"''' % (ident,task.id, ident,task.remaining_hours, ident,task.total_hours) | 1073 | %s effort = \"%.2fH\"''' % ( ident,task.id, |
252 | 1074 | ident,((task.work_load / 100.0) if task.work_load else 1.0), | ||
253 | 1075 | ident,task.remaining_hours, | ||
254 | 1076 | ident,task.total_hours ) | ||
255 | 1072 | start = [] | 1077 | start = [] |
256 | 1073 | for t2 in task.parent_ids: | 1078 | for t2 in task.parent_ids: |
257 | 1074 | start.append("up.Task_%s.end" % (t2.id,)) | 1079 | start.append("up.Task_%s.end" % (t2.id,)) |
258 | 1075 | 1080 | ||
259 | === modified file 'project/project_view.xml' | |||
260 | --- project/project_view.xml 2012-02-13 15:27:55 +0000 | |||
261 | +++ project/project_view.xml 2012-03-06 23:39:19 +0000 | |||
262 | @@ -228,6 +228,9 @@ | |||
263 | 228 | <field name="total_hours" widget="float_time"/> | 228 | <field name="total_hours" widget="float_time"/> |
264 | 229 | <field name="date_deadline" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}"/> | 229 | <field name="date_deadline" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}"/> |
265 | 230 | <field name="user_id" select="1" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}"/> | 230 | <field name="user_id" select="1" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}"/> |
266 | 231 | <field name="work_load"/> | ||
267 | 232 | </group> | ||
268 | 233 | <group colspan="4"> | ||
269 | 231 | <field name="progress" widget="progressbar"/> | 234 | <field name="progress" widget="progressbar"/> |
270 | 232 | </group> | 235 | </group> |
271 | 233 | <notebook colspan="4"> | 236 | <notebook colspan="4"> |
272 | 234 | 237 | ||
273 | === modified file 'project_long_term/project_long_term.py' | |||
274 | --- project_long_term/project_long_term.py 2012-01-31 13:36:57 +0000 | |||
275 | +++ project_long_term/project_long_term.py 2012-03-06 23:39:19 +0000 | |||
276 | @@ -224,9 +224,16 @@ | |||
277 | 224 | ids = [ids] | 224 | ids = [ids] |
278 | 225 | projects = self.browse(cr, uid, ids, context=context) | 225 | projects = self.browse(cr, uid, ids, context=context) |
279 | 226 | result = self._schedule_header(cr, uid, ids, context=context) | 226 | result = self._schedule_header(cr, uid, ids, context=context) |
280 | 227 | do_schedule = False | ||
281 | 227 | for project in projects: | 228 | for project in projects: |
284 | 228 | result += self._schedule_project(cr, uid, project, context=context) | 229 | if len(project.phase_ids) > 0: |
285 | 229 | result += self.pool.get('project.phase').generate_phase(cr, uid, project.phase_ids, context=context) | 230 | result += self._schedule_project(cr, uid, project, context=context) |
286 | 231 | result += self.pool.get('project.phase').generate_phase(cr, uid, project.phase_ids, context=context) | ||
287 | 232 | do_schedule = True | ||
288 | 233 | |||
289 | 234 | if not do_schedule: | ||
290 | 235 | # Nothing to do here | ||
291 | 236 | return True | ||
292 | 230 | 237 | ||
293 | 231 | local_dict = {} | 238 | local_dict = {} |
294 | 232 | exec result in local_dict | 239 | exec result in local_dict |
295 | @@ -256,6 +263,21 @@ | |||
296 | 256 | 'date_start': p.start.strftime('%Y-%m-%d %H:%M:%S'), | 263 | 'date_start': p.start.strftime('%Y-%m-%d %H:%M:%S'), |
297 | 257 | 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') | 264 | 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') |
298 | 258 | }, context=context) | 265 | }, context=context) |
299 | 266 | |||
300 | 267 | # Schedule sub-tasks | ||
301 | 268 | for task in phase.task_ids: | ||
302 | 269 | if task.state in ('done','cancelled'): | ||
303 | 270 | continue | ||
304 | 271 | |||
305 | 272 | t = getattr(p, 'Task_%d' % (task.id,)) | ||
306 | 273 | self.pool.get('project.task').write(cr, uid, [task.id], { | ||
307 | 274 | 'date_start': t.start.strftime('%Y-%m-%d %H:%M:%S'), | ||
308 | 275 | 'date_end': t.end.strftime('%Y-%m-%d %H:%M:%S'), | ||
309 | 276 | }, context=context) | ||
310 | 277 | if (not task.user_id) and (t.booked_resource): | ||
311 | 278 | self.pool.get('project.task').write(cr, uid, [task.id], { | ||
312 | 279 | 'user_id': int(t.booked_resource[0].name[5:]), | ||
313 | 280 | }, context=context) | ||
314 | 259 | return True | 281 | return True |
315 | 260 | project() | 282 | project() |
316 | 261 | 283 | ||
317 | 262 | 284 | ||
318 | === modified file 'resource/faces/pcalendar.py' | |||
319 | --- resource/faces/pcalendar.py 2011-12-19 16:54:40 +0000 | |||
320 | +++ resource/faces/pcalendar.py 2012-03-06 23:39:19 +0000 | |||
321 | @@ -895,7 +895,16 @@ | |||
322 | 895 | def _recalc_working_time(self): | 895 | def _recalc_working_time(self): |
323 | 896 | def slot_sum_time(day): | 896 | def slot_sum_time(day): |
324 | 897 | slots = self.working_times.get(day, DEFAULT_WORKING_DAYS[day]) | 897 | slots = self.working_times.get(day, DEFAULT_WORKING_DAYS[day]) |
326 | 898 | return sum(map(lambda slot: slot[1] - slot[0], slots)) | 898 | def time_diff(times): |
327 | 899 | (start, end) = times | ||
328 | 900 | if end == start: | ||
329 | 901 | return 24*60 # 24 hours | ||
330 | 902 | |||
331 | 903 | diff = end - start | ||
332 | 904 | if end < start: | ||
333 | 905 | diff += (24*60) | ||
334 | 906 | return diff | ||
335 | 907 | return sum(map(time_diff, slots)) | ||
336 | 899 | 908 | ||
337 | 900 | self.day_times = map(slot_sum_time, range(0, 7)) | 909 | self.day_times = map(slot_sum_time, range(0, 7)) |
338 | 901 | self.week_time = sum(self.day_times) | 910 | self.week_time = sum(self.day_times) |
339 | 902 | 911 | ||
340 | === modified file 'resource/resource.py' | |||
341 | --- resource/resource.py 2011-12-21 12:37:24 +0000 | |||
342 | +++ resource/resource.py 2012-03-06 23:39:19 +0000 | |||
343 | @@ -19,7 +19,7 @@ | |||
344 | 19 | # | 19 | # |
345 | 20 | ############################################################################## | 20 | ############################################################################## |
346 | 21 | 21 | ||
348 | 22 | from datetime import datetime, timedelta | 22 | from datetime import datetime, timedelta, time, date |
349 | 23 | import math | 23 | import math |
350 | 24 | from faces import * | 24 | from faces import * |
351 | 25 | from osv import fields, osv | 25 | from osv import fields, osv |
352 | @@ -28,6 +28,7 @@ | |||
353 | 28 | from itertools import groupby | 28 | from itertools import groupby |
354 | 29 | from operator import itemgetter | 29 | from operator import itemgetter |
355 | 30 | 30 | ||
356 | 31 | import pytz | ||
357 | 31 | 32 | ||
358 | 32 | class resource_calendar(osv.osv): | 33 | class resource_calendar(osv.osv): |
359 | 33 | _name = "resource.calendar" | 34 | _name = "resource.calendar" |
360 | @@ -279,8 +280,9 @@ | |||
361 | 279 | hour_part = split_list[0] | 280 | hour_part = split_list[0] |
362 | 280 | mins_part = split_list[1] | 281 | mins_part = split_list[1] |
363 | 281 | round_mins = int(round(float(mins_part) * 60,-2)) | 282 | round_mins = int(round(float(mins_part) * 60,-2)) |
366 | 282 | converted_string = hour_part + ':' + str(round_mins)[0:2] | 283 | return time(int(hour_part), round_mins) |
367 | 283 | return converted_string | 284 | #converted_string = hour_part + ':' + str(round_mins)[0:2] |
368 | 285 | #return converted_string | ||
369 | 284 | 286 | ||
370 | 285 | class resource_resource(osv.osv): | 287 | class resource_resource(osv.osv): |
371 | 286 | _name = "resource.resource" | 288 | _name = "resource.resource" |
372 | @@ -366,51 +368,102 @@ | |||
373 | 366 | Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format. | 368 | Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format. |
374 | 367 | @param calendar_id : working calendar of the project | 369 | @param calendar_id : working calendar of the project |
375 | 368 | """ | 370 | """ |
376 | 371 | tz = pytz.utc | ||
377 | 372 | if context and ('tz' in context): | ||
378 | 373 | tz = pytz.timezone(context['tz']) | ||
379 | 374 | |||
380 | 375 | wktime_local = None | ||
381 | 376 | week_days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] | ||
382 | 369 | if not calendar_id: | 377 | if not calendar_id: |
393 | 370 | # Calendar is not specified: working days: 24/7 | 378 | # Calendar is not specified: working days: some sane default |
394 | 371 | 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'), | 379 | wktime_local = [ |
395 | 372 | ('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')] | 380 | (0, time(8,0), time(12,0)), |
396 | 373 | resource_attendance_pool = self.pool.get('resource.calendar.attendance') | 381 | (0, time(13,0), time(17,0)), |
397 | 374 | time_range = "8:00-8:00" | 382 | (1, time(8,0), time(12,0)), |
398 | 375 | non_working = "" | 383 | (1, time(13,0), time(17,0)), |
399 | 376 | week_days = {"0": "mon", "1": "tue", "2": "wed","3": "thu", "4": "fri", "5": "sat", "6": "sun"} | 384 | (2, time(8,0), time(12,0)), |
400 | 377 | wk_days = {} | 385 | (2, time(13,0), time(17,0)), |
401 | 378 | wk_time = {} | 386 | (3, time(8,0), time(12,0)), |
402 | 379 | wktime_list = [] | 387 | (3, time(13,0), time(17,0)), |
403 | 388 | (4, time(8,0), time(12,0)), | ||
404 | 389 | (4, time(13,0), time(17,0)), | ||
405 | 390 | ] | ||
406 | 391 | #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'), | ||
407 | 392 | # ('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')] | ||
408 | 393 | else: | ||
409 | 394 | resource_attendance_pool = self.pool.get('resource.calendar.attendance') | ||
410 | 395 | non_working = "" | ||
411 | 396 | wktime_local = [] | ||
412 | 397 | |||
413 | 398 | week_ids = resource_attendance_pool.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context) | ||
414 | 399 | weeks = resource_attendance_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context) | ||
415 | 400 | # Convert time formats into appropriate format required | ||
416 | 401 | # and create lists inside wktime_local. | ||
417 | 402 | for week in weeks: | ||
418 | 403 | res_str = "" | ||
419 | 404 | day = None | ||
420 | 405 | if week['dayofweek']: | ||
421 | 406 | day = int(week['dayofweek']) | ||
422 | 407 | else: | ||
423 | 408 | raise osv.except_osv(_('Configuration Error!'),_('Make sure the Working time has been configured with proper week days!')) | ||
424 | 409 | hour_from = convert_timeformat(week['hour_from']) | ||
425 | 410 | hour_to = convert_timeformat(week['hour_to']) | ||
426 | 411 | wktime_local.append((day, hour_from, hour_to)) | ||
427 | 412 | |||
428 | 413 | # We now have working hours _in local time_. Non-working days are an | ||
429 | 414 | # empty list, while working days are a list of tuples, consisting of a | ||
430 | 415 | # start time and an end time. We will convert these to UTC for time | ||
431 | 416 | # calculation purposes. | ||
432 | 417 | |||
433 | 418 | # We need to get this into a dict | ||
434 | 419 | # which will be in the following format: | ||
435 | 420 | # { 'day': [(time(9,0), time(17,0)), ...], ... } | ||
436 | 421 | wktime_utc = {} | ||
437 | 422 | |||
438 | 423 | # NOTE: This may break with regards to DST! | ||
439 | 424 | for (day, start, end) in wktime_local: | ||
440 | 425 | # Convert start time to UTC | ||
441 | 426 | start_dt_local = datetime.combine(date.today(), start.replace(tzinfo=tz)) | ||
442 | 427 | start_dt_utc = start_dt_local.astimezone(pytz.utc) | ||
443 | 428 | start_dt_day = (day + (start_dt_utc.date() - start_dt_local.date()).days) % 7 | ||
444 | 429 | |||
445 | 430 | # Convert end time to UTC | ||
446 | 431 | end_dt_local = datetime.combine(date.today(), end.replace(tzinfo=tz)) | ||
447 | 432 | end_dt_utc = end_dt_local.astimezone(pytz.utc) | ||
448 | 433 | end_dt_day = (day + (end_dt_utc.date() - end_dt_local.date()).days) % 7 | ||
449 | 434 | |||
450 | 435 | # Are start and end still on the same day? | ||
451 | 436 | if start_dt_day == end_dt_day: | ||
452 | 437 | day_name = week_days[start_dt_day] | ||
453 | 438 | if day_name not in wktime_utc: | ||
454 | 439 | wktime_utc[day_name] = [] | ||
455 | 440 | wktime_utc[day_name].append((start_dt_utc.time(), end_dt_utc.time())) | ||
456 | 441 | else: | ||
457 | 442 | day_start_name = week_days[start_dt_day] | ||
458 | 443 | if day_start_name not in wktime_utc: | ||
459 | 444 | wktime_utc[day_start_name] = [] | ||
460 | 445 | # We go until midnight that day | ||
461 | 446 | wktime_utc[day_start_name].append((start_dt_utc.time(), time(0,0))) | ||
462 | 447 | |||
463 | 448 | day_end_name = week_days[end_dt_day] | ||
464 | 449 | if day_end_name not in wktime_utc: | ||
465 | 450 | wktime_utc[day_end_name] = [] | ||
466 | 451 | # Then resume from midnight that day | ||
467 | 452 | wktime_utc[day_end_name].append((time(0,0), end_dt_utc.time())) | ||
468 | 453 | |||
469 | 454 | # Now having gotten a list of times together, generate the final output | ||
470 | 380 | wktime_cal = [] | 455 | wktime_cal = [] |
504 | 381 | week_ids = resource_attendance_pool.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context) | 456 | for day, times in wktime_utc.iteritems(): |
505 | 382 | weeks = resource_attendance_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context) | 457 | # Sort the times |
506 | 383 | # Convert time formats into appropriate format required | 458 | times.sort() |
507 | 384 | # and create a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')] | 459 | wktime = ['{0}-{1}'.format(s.strftime('%H:%M'), e.strftime('%H:%M')) for (s, e) in times] |
508 | 385 | for week in weeks: | 460 | wktime.insert(0, day) |
509 | 386 | res_str = "" | 461 | wktime_cal.append(tuple(wktime)) |
510 | 387 | day = None | 462 | # Finally, add in non-working days |
511 | 388 | if week_days.get(week['dayofweek'],False): | 463 | for day in week_days: |
512 | 389 | day = week_days[week['dayofweek']] | 464 | if day not in wktime_utc: |
513 | 390 | wk_days[week['dayofweek']] = week_days[week['dayofweek']] | 465 | wktime_cal.append((day, None)) |
514 | 391 | else: | 466 | |
482 | 392 | raise osv.except_osv(_('Configuration Error!'),_('Make sure the Working time has been configured with proper week days!')) | ||
483 | 393 | hour_from_str = convert_timeformat(week['hour_from']) | ||
484 | 394 | hour_to_str = convert_timeformat(week['hour_to']) | ||
485 | 395 | res_str = hour_from_str + '-' + hour_to_str | ||
486 | 396 | wktime_list.append((day, res_str)) | ||
487 | 397 | # Convert into format like [('mon', '8:00-12:00', '13:00-18:00')] | ||
488 | 398 | for item in wktime_list: | ||
489 | 399 | if wk_time.has_key(item[0]): | ||
490 | 400 | wk_time[item[0]].append(item[1]) | ||
491 | 401 | else: | ||
492 | 402 | wk_time[item[0]] = [item[0]] | ||
493 | 403 | wk_time[item[0]].append(item[1]) | ||
494 | 404 | for k,v in wk_time.items(): | ||
495 | 405 | wktime_cal.append(tuple(v)) | ||
496 | 406 | # Add for the non-working days like: [('sat, sun', '8:00-8:00')] | ||
497 | 407 | for k, v in wk_days.items(): | ||
498 | 408 | if week_days.has_key(k): | ||
499 | 409 | week_days.pop(k) | ||
500 | 410 | for v in week_days.itervalues(): | ||
501 | 411 | non_working += v + ',' | ||
502 | 412 | if non_working: | ||
503 | 413 | wktime_cal.append((non_working[:-1], time_range)) | ||
515 | 414 | return wktime_cal | 467 | return wktime_cal |
516 | 415 | 468 | ||
517 | 416 | resource_resource() | 469 | resource_resource() |
Hello Stuart,
The proposed patches sound good, but the merge proposal is hard to review because it seems to contain a certain number of unrelated changes (CRM stuff). As a rule we prefer to keep only related changesets in each merge proposal, especially for bugfix branches - so they can be independently reviewed and merged.
Perhaps the easiest course is to apply your patch for bug 932584 on a fresh copy of our official addons branch, and submit that as a separate merge proposal.
If you'd like more details, our merge proposal documentation includes a step-by-step guide for this process [1].
Thanks for your contributions to OpenERP!
[1] http:// doc.openerp. com/v6. 0/contribute/ 15_guidelines/ contribution_ guidelines. html#merge- proposal- guidelines