Merge lp:~dreis-pt/project-service/7.0-service_desk-dr into lp:~project-core-editors/project-service/trunk

Proposed by Daniel Reis
Status: Merged
Merged at revision: 36
Proposed branch: lp:~dreis-pt/project-service/7.0-service_desk-dr
Merge into: lp:~project-core-editors/project-service/trunk
Diff against target: 1167 lines (+600/-461)
16 files modified
service_desk/__init__.py (+2/-3)
service_desk/__openerp__.py (+26/-36)
service_desk/analytic_contact.py (+32/-0)
service_desk/analytic_contact_view.xml (+19/-0)
service_desk/crm_categ.py (+0/-74)
service_desk/crm_categ_view.xml (+0/-75)
service_desk/i18n/service_desk.pot (+78/-0)
service_desk/project.py (+87/-0)
service_desk/project_issue.py (+0/-139)
service_desk/project_issue_view.xml (+0/-134)
service_desk/service_desk_view.xml (+60/-0)
service_desk_issue/__init__.py (+2/-0)
service_desk_issue/__openerp__.py (+41/-0)
service_desk_issue/i18n/service_desk_issue.pot (+88/-0)
service_desk_issue/project.py (+72/-0)
service_desk_issue/service_desk_view.xml (+93/-0)
To merge this branch: bzr merge lp:~dreis-pt/project-service/7.0-service_desk-dr
Reviewer Review Type Date Requested Status
Raphaël Valyi - http://www.akretion.com Approve
Nicolas Bessi - Camptocamp (community) Approve
Yannick Vaucher @ Camptocamp Needs Fixing
Maxime Chambreuil (http://www.savoirfairelinux.com) code review Approve
Joël Grand-Guillaume @ camptocamp code review, no tests Needs Fixing
Review via email: mp+195270@code.launchpad.net

Description of the change

New modules for managing Service Desks:
Organize teams in Projects, but allow to link tasks and issues to contracts

To post a comment you must log in.
Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

Hi Daniel,

Thanks for the contribs ! Just 2 little stuffs:

 * Line 8-9 and 852: Use from . import *
 * Line 470 and 1046: Kwargs for context, please write context=context

Regards,

Joël

review: Needs Fixing (code review, no tests)
29. By Daniel Reis

Minor fixes; added filter and grouping by Analytic Account and Partner

30. By Daniel Reis

Fix typo

Revision history for this message
Daniel Reis (dreis-pt) wrote :

Fixed.

31. By Daniel Reis

Explicitly named modules to import

32. By Daniel Reis

Explicitly named modules to import

33. By Daniel Reis

Fix code typo

34. By Daniel Reis

Fix code typo

Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) :
review: Approve (code review)
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Hello,

Thanks for the patch.

Some neat picks:

PEP8 in string domain line 134.

More help on columns especially selection fields will be welcome.

Tests are missing. It would be nice to add some.

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

I set a need fixing after Nicolas comment

Otherwise LGTM

review: Needs Fixing
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Hello Daniel,

Any news on this one.

Regards

Nicolas

Revision history for this message
Daniel Reis (dreis-pt) wrote :

Hello Nicolas, sorry for the delay; I still need to find some spare time submit a fix .

While I'm at it:
- Fixing PEP on domain should be a no brainer
- on selection fields, IMO they are quite self explanatory, but I'll make an effort to review and add help on thenew fields
- Regarding tests, I'm not sure what I can do here: added logic is mostly "on_change" GUI methods; will YML tests be of any use here?

Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Hello,

YAML should provides all batteries included to test the onchange, but you can also only test the call to onchange function with unit test and dumb mock. That should make sense too.

Regards

Nicolas

review: Approve
Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'service_desk/__init__.py' (properties changed: +x to -x)
2--- service_desk/__init__.py 2012-12-21 18:34:07 +0000
3+++ service_desk/__init__.py 2013-12-16 15:38:33 +0000
4@@ -1,4 +1,3 @@
5 # -*- coding: utf-8 -*-
6-import crm_categ
7-import project_issue
8-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
9+from . import analytic_contact
10+from . import project
11
12=== modified file 'service_desk/__openerp__.py' (properties changed: +x to -x)
13--- service_desk/__openerp__.py 2013-03-04 16:16:31 +0000
14+++ service_desk/__openerp__.py 2013-12-16 15:38:33 +0000
15@@ -1,7 +1,7 @@
16 # -*- coding: utf-8 -*-
17 ##############################################################################
18 #
19-# Copyright (C) 2012 Daniel Reis
20+# Copyright (C) 2012-2013 Daniel Reis
21 #
22 # This program is free software: you can redistribute it and/or modify
23 # it under the terms of the GNU Affero General Public License as
24@@ -18,50 +18,40 @@
25 #
26 ##############################################################################
27 {
28- 'name': 'Service Desk Central',
29- 'version': '0.1',
30+ 'name': 'Service Desk',
31+ 'summary': 'Use Projects for Service Desks and service teams',
32+ 'version': '1.1',
33 "category": "Project Management",
34 'description': """\
35-Concentrates all request forms in a single place.
36-These can be broad Categories for Project Issues or forms from other modules,
37-such as CRM Claims or HR Leave requests.
38-
39-The items/categories available are defined in:
40-Project -> Configuration -> Issue -> Categories.
41-
42-Each one is representend by an icon and a description.
43-When clicking on a Service Desk item, the module will find what Action should
44-be executed. It this defition is found on it's form or on a parent, it will be
45-used. If not, it an Action opening the Project Issue's default form will be
46-used.
47-
48-When opening the Action, two variables are set in the "context":
49- * A default master Category (`default_master_categ_id`), the id for the
50- selected Category.
51- * A default Service Team (`default_section_id`), from the selected Category
52- or it's parent tree.
53-
54-For a quick start the module installs two Actions to be used here:
55- * "Issues": opens the standard Project Issue form.
56- * "New Incident": opens a showcase simple Issue form.
57-
58-The showcase form demonstrates the usage of these two default values:
59-the Issue's Category selection list is limited to the Service Desk category
60-children, and the Service Team is automatically selected.
61+Available service desks/teams are defined as Projects.
62+
63+Incoming requests and tasks can then be related to customer Contracts and
64+service locations through additional two additional fields provided by the
65+module. This is optional, and is defined on a per project basis.
66+
67+
68+Features:
69+
70+ * Project has new field "Use Analytic Account?",
71+ with options "Yes" and "Required"
72+ * Task has new fields "Analytic Account/Contract" and "Location",
73+ visible or required depending on the Project's setting
74+ * Analytic Account has a new field "Contact", where you can set it's
75+ location/address (a Partner). It will be picked as the default locations
76+ when the Analytic Account is selected in a Task or Issue.
77+
78+(Icon image credits to Everaldo Coelho, Crystal icon set)
79 """,
80 'author': 'Daniel Reis',
81 'website': '',
82 'depends': [
83- 'project_issue',
84- 'project_issue_department',
85- 'project_issue_sequences',
86- 'crm_categ_hierarchy',
87+ 'project',
88 ],
89 'data': [
90- 'project_issue_view.xml',
91- 'crm_categ_view.xml',
92+ 'analytic_contact_view.xml',
93+ 'service_desk_view.xml',
94 ],
95- 'installable': False,
96+ 'installable': True,
97 'application': True,
98 }
99 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
100
101=== added file 'service_desk/analytic_contact.py'
102--- service_desk/analytic_contact.py 1970-01-01 00:00:00 +0000
103+++ service_desk/analytic_contact.py 2013-12-16 15:38:33 +0000
104@@ -0,0 +1,32 @@
105+# -*- coding: utf-8 -*-
106+##############################################################################
107+#
108+# Copyright (C) 2013 Daniel Reis
109+#
110+# This program is free software: you can redistribute it and/or modify
111+# it under the terms of the GNU Affero General Public License as
112+# published by the Free Software Foundation, either version 3 of the
113+# License, or (at your option) any later version.
114+#
115+# This program is distributed in the hope that it will be useful,
116+# but WITHOUT ANY WARRANTY; without even the implied warranty of
117+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118+# GNU Affero General Public License for more details.
119+#
120+# You should have received a copy of the GNU Affero General Public License
121+# along with this program. If not, see <http://www.gnu.org/licenses/>.
122+#
123+##############################################################################
124+
125+from openerp.osv import fields, orm
126+
127+
128+class AnalyticAccount(orm.Model):
129+ """Add Contact to Analytic Accounts"""
130+ _inherit = 'account.analytic.account'
131+ _columns = {
132+ 'contact_id': fields.many2one(
133+ 'res.partner', 'Contact',
134+ domain="[('parent_id','child_of',partner_id)"
135+ ",('parent_id','!=',False)]"),
136+ }
137
138=== added file 'service_desk/analytic_contact_view.xml'
139--- service_desk/analytic_contact_view.xml 1970-01-01 00:00:00 +0000
140+++ service_desk/analytic_contact_view.xml 2013-12-16 15:38:33 +0000
141@@ -0,0 +1,19 @@
142+<?xml version="1.0" encoding="utf-8"?>
143+<openerp>
144+ <data>
145+
146+ <record id="view_account_analytic_account_form_contact" model="ir.ui.view">
147+ <field name="name">view_account_analytic_account_form_contact</field>
148+ <field name="model">account.analytic.account</field>
149+ <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
150+ <field name="arch" type="xml">
151+
152+ <field name="manager_id" position="after">
153+ <field name="contact_id"/>
154+ </field>
155+
156+ </field>
157+ </record>
158+
159+ </data>
160+</openerp>
161
162=== removed file 'service_desk/crm_categ.py'
163--- service_desk/crm_categ.py 2013-01-31 13:27:23 +0000
164+++ service_desk/crm_categ.py 1970-01-01 00:00:00 +0000
165@@ -1,74 +0,0 @@
166-# -*- coding: utf-8 -*-
167-##############################################################################
168-#
169-# Copyright (C) 2012 Daniel Reis
170-#
171-# This program is free software: you can redistribute it and/or modify
172-# it under the terms of the GNU Affero General Public License as
173-# published by the Free Software Foundation, either version 3 of the
174-# License, or (at your option) any later version.
175-#
176-# This program is distributed in the hope that it will be useful,
177-# but WITHOUT ANY WARRANTY; without even the implied warranty of
178-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179-# GNU Affero General Public License for more details.
180-#
181-# You should have received a copy of the GNU Affero General Public License
182-# along with this program. If not, see <http://www.gnu.org/licenses/>.
183-#
184-##############################################################################
185-
186-from openerp.osv import fields, orm
187-
188-
189-class crm_case_categ(orm.Model):
190- _inherit = 'crm.case.categ'
191- _columns = {
192- 'section_id': fields.many2one('crm.case.section', 'Service Team'),
193- 'icon': fields.binary('Icon'),
194- 'act_window_id': fields.many2one('ir.actions.act_window', 'Action'),
195- 'show_service_desk': fields.boolean('Show in Service Desk'),
196- }
197-
198- def open_issue_form(self, cr, uid, ids, context=None):
199-
200- def get_categ_section_id(categ_res):
201- """Get Category Team, searching parents upward if necessary"""
202- return categ_res.section_id.id or (
203- hasattr(categ_res, 'parent_id') and
204- categ_res.parent_id and
205- get_categ_section_id(categ_res.parent_id))
206-
207- def get_custom_action_dict(categ_res):
208- """Get dict with the custom Action details for a Category
209- If none, use the standard Project Issue form."""
210- action_id = categ_res.act_window_id.id \
211- or self.pool.get('ir.model.data').get_object_reference(
212- cr, uid, 'project_issue', 'project_issue_categ_act0')[1]
213- return self.pool.get('ir.actions.act_window')\
214- .read(cr, uid, action_id, context=context)
215-
216- def merge_dict_into_text(text, add_dict):
217- """Return the text string with the dict contents added to it.
218- Ex: `"{'a':1}"` merged with `{'b': 2}` returns `"{'a':1, 'b':2}"`.
219- """
220- if ':' not in text:
221- return str(add_dict)
222- else:
223- return '{%s, %s}' % (text.strip()[1:-1], str(add_dict)[1:-1])
224-
225- obj = self.browse(cr, uid, ids, context=context)[0]
226- action = get_custom_action_dict(obj)
227- action.update({
228- 'domain': [('categ_id', 'child_of', obj.id)],
229- 'context': merge_dict_into_text(
230- action.get('context', ''),
231- {'default_master_categ_id': obj.id,
232- 'default_section_id': get_categ_section_id(obj) or False,
233- 'group_by': False, # remove inherited section_id grouping
234- },
235- ),
236- })
237- return action
238-
239-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
240
241=== removed file 'service_desk/crm_categ_view.xml'
242--- service_desk/crm_categ_view.xml 2012-12-21 18:34:07 +0000
243+++ service_desk/crm_categ_view.xml 1970-01-01 00:00:00 +0000
244@@ -1,75 +0,0 @@
245-<?xml version="1.0" encoding="utf-8"?>
246-<openerp>
247- <data>
248-
249- <!-- FORM crm.case.category -->
250- <record id="crm_case_categ_view_icon" model="ir.ui.view">
251- <field name="name">crm.case.categ.form.icon</field>
252- <field name="model">crm.case.categ</field>
253- <field name="inherit_id" ref="crm_categ_hierarchy.crm_case_categ-view_dreis"/>
254- <field name="arch" type="xml">
255- <field name="note" position="replace">
256- <separator colspan="4" string="Service Desk"/>
257- <group colspan="2" col="2">
258- <field name="act_window_id"/>
259- <field name="show_service_desk"/>
260- <field name="note"/>
261- </group>
262- <group colspan="2" col="1">
263- <field name="icon" widget='image' nolabel="1"/>
264- </group>
265- </field>
266- </field>
267- </record>
268-
269- <!-- KANBAN crm.case.categories -->
270- <record model="ir.ui.view" id="categ_view_kanban">
271- <field name="name">categ_view_kanban</field>
272- <field name="model">crm.case.categ</field>
273- <field name="type">kanban</field>
274- <field name="arch" type="xml">
275-
276- <kanban>
277- <field name="name"/>
278- <field name="note"/>
279- <field name="section_id"/>
280- <templates>
281- <t t-name="kanban-box">
282- <div class="oe_module_vignette">
283- <a type="object" name="open_issue_form">
284- <img t-att-src="kanban_image('crm.case.categ', 'icon', record.id.value)" class="oe_module_icon"/>
285- </a>
286- <div class="oe_module_desc">
287- <h4><a type="edit"><field name="name"/></a></h4>
288- <p><field name="note"/></p>
289- <button type="object" name="open_issue_form" class="oe_button">Create</button>
290- </div>
291- </div>
292- </t>
293- </templates>
294-
295- </kanban>
296-
297- </field>
298- </record>
299-
300-
301- <record id="open_categ_view" model="ir.actions.act_window">
302- <field name="name">Service Desk</field>
303- <field name="res_model">crm.case.categ</field>
304- <field name="view_type">form</field>
305- <field name="view_mode">kanban</field>
306- <field name="domain">[('object_id.model','=','project.issue'),('show_service_desk','=',True)]</field>
307- <field name="context">{'group_by':'section_id'}</field>
308- </record>
309- <menuitem action="open_categ_view" id="menu_categ_view" parent="project.menu_project_management"/>
310-
311-
312- </data>
313-</openerp>
314-
315-
316-
317-
318-
319-
320
321=== added directory 'service_desk/i18n'
322=== added file 'service_desk/i18n/service_desk.pot'
323--- service_desk/i18n/service_desk.pot 1970-01-01 00:00:00 +0000
324+++ service_desk/i18n/service_desk.pot 2013-12-16 15:38:33 +0000
325@@ -0,0 +1,78 @@
326+# Translation of OpenERP Server.
327+# This file contains the translation of the following modules:
328+# * service_desk
329+#
330+msgid ""
331+msgstr ""
332+"Project-Id-Version: OpenERP Server 7.0\n"
333+"Report-Msgid-Bugs-To: \n"
334+"POT-Creation-Date: 2013-11-14 09:22+0000\n"
335+"PO-Revision-Date: 2013-11-14 09:22+0000\n"
336+"Last-Translator: <>\n"
337+"Language-Team: \n"
338+"MIME-Version: 1.0\n"
339+"Content-Type: text/plain; charset=UTF-8\n"
340+"Content-Transfer-Encoding: \n"
341+"Plural-Forms: \n"
342+
343+#. module: service_desk
344+#: model:ir.model,name:service_desk.model_project_project
345+msgid "Project"
346+msgstr ""
347+
348+#. module: service_desk
349+#: model:ir.model,name:service_desk.model_account_analytic_location
350+msgid "account.analytic.location"
351+msgstr ""
352+
353+#. module: service_desk
354+#: model:ir.model,name:service_desk.model_project_task
355+msgid "Task"
356+msgstr ""
357+
358+#. module: service_desk
359+#: selection:project.project,use_analytic_account:0
360+msgid "No"
361+msgstr ""
362+
363+#. module: service_desk
364+#: selection:project.project,use_analytic_account:0
365+msgid "Required"
366+msgstr ""
367+
368+#. module: service_desk
369+#: model:ir.model,name:service_desk.model_account_analytic_account
370+msgid "Analytic Account"
371+msgstr ""
372+
373+#. module: service_desk
374+#: view:project.task:0
375+msgid "onchange_project(project_id)"
376+msgstr ""
377+
378+#. module: service_desk
379+#: field:account.analytic.account,contact_id:0
380+msgid "Contact"
381+msgstr ""
382+
383+#. module: service_desk
384+#: field:project.task,location_id:0
385+msgid "Location"
386+msgstr ""
387+
388+#. module: service_desk
389+#: field:project.project,use_analytic_account:0
390+#: field:project.task,use_analytic_account:0
391+msgid "Use Analytic Account"
392+msgstr ""
393+
394+#. module: service_desk
395+#: selection:project.project,use_analytic_account:0
396+msgid "Optional"
397+msgstr ""
398+
399+#. module: service_desk
400+#: field:project.task,analytic_account_id:0
401+msgid "Contract/Analytic"
402+msgstr ""
403+
404
405=== added file 'service_desk/project.py'
406--- service_desk/project.py 1970-01-01 00:00:00 +0000
407+++ service_desk/project.py 2013-12-16 15:38:33 +0000
408@@ -0,0 +1,87 @@
409+# -*- coding: utf-8 -*-
410+##############################################################################
411+#
412+# Copyright (C) 2013 Daniel Reis
413+#
414+# This program is free software: you can redistribute it and/or modify
415+# it under the terms of the GNU Affero General Public License as
416+# published by the Free Software Foundation, either version 3 of the
417+# License, or (at your option) any later version.
418+#
419+# This program is distributed in the hope that it will be useful,
420+# but WITHOUT ANY WARRANTY; without even the implied warranty of
421+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
422+# GNU Affero General Public License for more details.
423+#
424+# You should have received a copy of the GNU Affero General Public License
425+# along with this program. If not, see <http://www.gnu.org/licenses/>.
426+#
427+##############################################################################
428+
429+from openerp.osv import fields, orm
430+
431+
432+class ProjectProject(orm.Model):
433+ _inherit = 'project.project'
434+ _columns = {
435+ 'use_analytic_account': fields.selection(
436+ [('no', 'No'), ('yes', 'Optional'), ('req', 'Required')],
437+ 'Use Analytic Account'),
438+ }
439+ _defaults = {
440+ 'use_analytic_account': 'no',
441+ }
442+
443+
444+class ProjectTask(orm.Model):
445+ """
446+ Add related ``Analytic Account`` and service ``Location``.
447+ A Location can be any Contact Partner of the AA's Partner.
448+ Other logic is possible, such as maintaining a specific list of service
449+ addresses for each Contract, but that's out of scope here -
450+ modules implementing these other possibilities are very welcome.
451+ """
452+ _inherit = 'project.task'
453+ _columns = {
454+ 'analytic_account_id': fields.many2one(
455+ 'account.analytic.account', 'Contract/Analytic',
456+ domain="[('type','in',['normal','contract'])]"),
457+ 'location_id': fields.many2one(
458+ 'res.partner', 'Location',
459+ domain="[('parent_id','child_of',partner_id)]"),
460+ 'use_analytic_account': fields.related(
461+ 'project_id', 'use_analytic_account',
462+ type='char', string="Use Analytic Account"),
463+ }
464+
465+ def onchange_project(self, cr, uid, id, project_id, context=None):
466+ # on_change is necessary to populate fields on Create, before saving
467+ try:
468+ # try applying a parent's onchange, may it exist
469+ res = super(ProjectTask, self).onchange_project(
470+ cr, uid, id, project_id, context=context) or {}
471+ except AttributeError:
472+ res = {}
473+
474+ if project_id:
475+ obj = self.pool.get('project.project').browse(
476+ cr, uid, project_id, context=context)
477+ res.setdefault('value', {})
478+ res['value']['use_analytic_account'] = (
479+ obj.use_analytic_account or 'no')
480+ return res
481+
482+ def onchange_analytic(self, cr, uid, id, analytic_id, context=None):
483+ res = {}
484+ model = self.pool.get('account.analytic.account')
485+ obj = model.browse(cr, uid, analytic_id, context=context)
486+ if obj:
487+ # "contact_id" and "department_id" may be provided by other modules
488+ fldmap = [ # analytic_account field -> task field
489+ ('partner_id', 'partner_id'),
490+ ('contact_id', 'location_id'),
491+ ('department_id', 'department_id')]
492+ res['value'] = {dest: getattr(obj, orig).id
493+ for orig, dest in fldmap
494+ if hasattr(obj, orig) and getattr(obj, orig)}
495+ return res
496
497=== removed file 'service_desk/project_issue.py'
498--- service_desk/project_issue.py 2013-01-31 14:42:51 +0000
499+++ service_desk/project_issue.py 1970-01-01 00:00:00 +0000
500@@ -1,139 +0,0 @@
501-# -*- coding: utf-8 -*-
502-##############################################################################
503-#
504-# Copyright (C) 2012 Daniel Reis
505-#
506-# This program is free software: you can redistribute it and/or modify
507-# it under the terms of the GNU Affero General Public License as
508-# published by the Free Software Foundation, either version 3 of the
509-# License, or (at your option) any later version.
510-#
511-# This program is distributed in the hope that it will be useful,
512-# but WITHOUT ANY WARRANTY; without even the implied warranty of
513-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
514-# GNU Affero General Public License for more details.
515-#
516-# You should have received a copy of the GNU Affero General Public License
517-# along with this program. If not, see <http://www.gnu.org/licenses/>.
518-#
519-##############################################################################
520-
521-from openerp.osv import fields, orm
522-from datetime import datetime
523-
524-
525-class project_issue(orm.Model):
526- _inherit = 'project.issue'
527-
528- # `_compute_day` backported from v7.0 (just copied actually)
529- # Allows the Issue's `project_id` to be optional.
530- #---- START ----
531- def _compute_day(self, cr, uid, ids, fields, args, context=None):
532- """
533- @param cr: the current row, from the database cursor,
534- @param uid: the current user’s ID for security checks,
535- @param ids: List of Openday’s IDs
536- @return: difference between current date and log date
537- @param context: A standard dictionary for contextual values
538- """
539- cal_obj = self.pool.get('resource.calendar')
540- res_obj = self.pool.get('resource.resource')
541-
542- res = {}
543- for issue in self.browse(cr, uid, ids, context=context):
544- res[issue.id] = {}
545- for field in fields:
546- duration = 0
547- ans = False
548- hours = 0
549-
550- date_create = datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S")
551- if field in ['working_hours_open','day_open']:
552- if issue.date_open:
553- date_open = datetime.strptime(issue.date_open, "%Y-%m-%d %H:%M:%S")
554- ans = date_open - date_create
555- date_until = issue.date_open
556- #Calculating no. of working hours to open the issue
557- if issue.project_id.resource_calendar_id:
558- hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id,
559- date_create,
560- date_open)
561- elif field in ['working_hours_close','day_close']:
562- if issue.date_closed:
563- date_close = datetime.strptime(issue.date_closed, "%Y-%m-%d %H:%M:%S")
564- date_until = issue.date_closed
565- ans = date_close - date_create
566- #Calculating no. of working hours to close the issue
567- if issue.project_id.resource_calendar_id:
568- hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id,
569- date_create,
570- date_close)
571- elif field in ['days_since_creation']:
572- if issue.create_date:
573- days_since_creation = datetime.today() - datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S")
574- res[issue.id][field] = days_since_creation.days
575- continue
576-
577- elif field in ['inactivity_days']:
578- res[issue.id][field] = 0
579- if issue.date_action_last:
580- inactive_days = datetime.today() - datetime.strptime(issue.date_action_last, '%Y-%m-%d %H:%M:%S')
581- res[issue.id][field] = inactive_days.days
582- continue
583- if ans:
584- resource_id = False
585- if issue.user_id:
586- resource_ids = res_obj.search(cr, uid, [('user_id','=',issue.user_id.id)])
587- if resource_ids and len(resource_ids):
588- resource_id = resource_ids[0]
589- duration = float(ans.days)
590- if issue.project_id and issue.project_id.resource_calendar_id:
591- duration = float(ans.days) * 24
592-
593- new_dates = cal_obj.interval_min_get(cr, uid,
594- issue.project_id.resource_calendar_id.id,
595- date_create,
596- duration, resource=resource_id)
597- no_days = []
598- date_until = datetime.strptime(date_until, '%Y-%m-%d %H:%M:%S')
599- for in_time, out_time in new_dates:
600- if in_time.date not in no_days:
601- no_days.append(in_time.date)
602- if out_time > date_until:
603- break
604- duration = len(no_days)
605-
606- if field in ['working_hours_open', 'working_hours_close']:
607- res[issue.id][field] = hours
608- else:
609- res[issue.id][field] = abs(float(duration))
610-
611- return res
612- #---- END ----
613-
614- _columns = {
615- 'regarding_uid': fields.many2one('res.users', 'Regarding User',
616- help="User affected by the Issue"),
617-
618- # `_compute_day` backport: redeclaring columns in order to
619- # rebuild references for the replaced method
620- #---- START ----
621- 'days_since_creation': fields.function(_compute_day, string='Days since creation date', \
622- multi='compute_day', type="integer", help="Difference in days between creation date and current date"),
623- 'day_open': fields.function(_compute_day, string='Days to Open', \
624- multi='compute_day', type="float", store=True),
625- 'day_close': fields.function(_compute_day, string='Days to Close', \
626- multi='compute_day', type="float", store=True),
627- 'working_hours_open': fields.function(_compute_day, string='Working Hours to Open the Issue', \
628- multi='compute_day', type="float", store=True),
629- 'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \
630- multi='compute_day', type="float", store=True),
631- 'inactivity_days': fields.function(_compute_day, string='Days since last action', \
632- multi='compute_day', type="integer", help="Difference in days between last action and current date"),
633- #---- END ----
634- }
635- _defaults = {
636- 'regarding_uid': lambda s, cr, uid, c: uid,
637- }
638-
639-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
640
641=== removed file 'service_desk/project_issue_view.xml'
642--- service_desk/project_issue_view.xml 2013-01-31 13:20:15 +0000
643+++ service_desk/project_issue_view.xml 1970-01-01 00:00:00 +0000
644@@ -1,134 +0,0 @@
645-<?xml version="1.0" encoding="utf-8"?>
646-<openerp>
647- <data>
648-
649- <!--PROJECT ISSUE FORM -->
650- <record id="project_issue_form_view_simple" model="ir.ui.view">
651- <field name="name">project_issue_form_view_simple</field>
652- <field name="model">project.issue</field>
653- <field name="type">form</field>
654- <field name="priority" eval="20"/>
655- <field name="arch" type="xml">
656-
657- <field name="name"/>
658- <field name="ref"/>
659- <field name="categ_id" required="1"
660- domain="[('parent_id','=', default_master_categ_id)]"/>
661- <field name="section_id" readonly="1" string="Service Team"/>
662- <field name="regarding_uid"/>
663- <field name="user_id"/>
664- <!-- field name="department_id"/ -->
665- <field name="priority"/>
666-
667- <notebook colspan="4">
668- <page string="General">
669- <separator string="Description" colspan="4"/>
670- <field name="description" nolabel="1" colspan="4"/>
671- <separator colspan="4"/>
672- <group col="8" colspan="4">
673- <field name="state" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors="{&quot;pending&quot;:&quot;blue&quot;}"/>
674- <button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
675- <button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward"/>
676- <button name="case_close" string="Done" states="open,draft,pending" type="object" icon="terp-dialog-close"/>
677- <button name="case_pending" string="Pending" states="draft,open" type="object" icon="gtk-media-pause"/>
678- <button name="case_escalate" string="Escalate" states="open,draft,pending" type="object" icon="gtk-go-up"/>
679- <button name="case_reset" string="Reset to New" states="done,cancel" type="object" icon="gtk-convert"/>
680- </group>
681- </page>
682- <page string="Communication &amp; History" groups="base.group_extended">
683- <group colspan="4">
684- <field colspan="4" name="email_cc" widget="char" size="512"/>
685- </group>
686- <field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
687- <tree string="History">
688- <field name="display_text" string="History Information"/>
689- <field name="email_from" invisible="1"/>
690- <button
691- string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
692- name="%(mail.action_email_compose_message_wizard)d"
693- context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
694- icon="terp-mail-replied" type="action" />
695- </tree>
696- </field>
697- <button string="Add Internal Note"
698- name="%(crm.action_crm_add_note)d"
699- context="{'model': 'crm.lead' }"
700- icon="terp-document-new" type="action" />
701- <button string="Send New Email"
702- name="%(mail.action_email_compose_message_wizard)d"
703- icon="terp-mail-message-new" type="action"/>
704- </page>
705- <page string="Extra Info" groups="base.group_extended">
706- <group col="2" colspan="2">
707- <separator colspan="2" string="Date"/>
708- <field name="create_date"/>
709- <field name="write_date"/>
710- <field name="date_closed"/>
711- <field name="date_open"/>
712- <field name="date_action_last"/>
713- </group>
714- <group colspan="2" col="2">
715- <separator string="Statistics" colspan="2" col="2"/>
716- <field name="day_open"/>
717- <field name="day_close"/>
718- <field name="working_hours_open" widget="float_time"/>
719- <field name="working_hours_close" widget="float_time"/>
720- <field name="inactivity_days"/>
721- <field name="days_since_creation"/>
722- </group>
723- <group colspan="2" col="2">
724- <separator string="References" colspan="2"/>
725- <field name="id"/>
726- <field name="active"/>
727- </group>
728- </page>
729- </notebook>
730- </field>
731- </record>
732-
733- <!-- ACTION to open New Issue form -->
734- <record id="action_newissue_wizard" model="ir.actions.act_window">
735- <field name="name">Incidents</field>
736- <field name="res_model">project.issue</field>
737- <field name="view_type">form</field>
738- <field name="view_mode">tree,calendar</field>
739- <field name="view_id" eval="False"/>
740- <field name="domain" eval=""/>
741- <field name="context">{}</field>
742- <field name="search_view_id" ref="project_issue.view_project_issue_filter"/>
743- </record>
744-
745- <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewtree">
746- <field name="sequence" eval="1"/>
747- <field name="view_mode">tree</field>
748- <field name="view_id" ref="project_issue.project_issue_tree_view"/>
749- <field name="act_window_id" ref="action_newissue_wizard"/>
750- </record>
751-
752- <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewform">
753- <field name="sequence" eval="2"/>
754- <field name="view_mode">form</field>
755- <field name="view_id" ref="project_issue_form_view_simple"/>
756- <field name="act_window_id" ref="action_newissue_wizard"/>
757- </record>
758-
759- <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewcal">
760- <field name="sequence" eval="3"/>
761- <field name="view_mode">calendar</field>
762- <field name="view_id" ref="project_issue.project_issue_calendar_view"/>
763- <field name="act_window_id" ref="action_newissue_wizard"/>
764- </record>
765-
766- </data>
767-</openerp>
768-
769-
770-
771-
772-
773-
774-
775-
776-
777-
778-
779
780=== added file 'service_desk/service_desk_view.xml'
781--- service_desk/service_desk_view.xml 1970-01-01 00:00:00 +0000
782+++ service_desk/service_desk_view.xml 2013-12-16 15:38:33 +0000
783@@ -0,0 +1,60 @@
784+<?xml version="1.0" encoding="utf-8"?>
785+<openerp>
786+ <data>
787+
788+ <!-- Project form -->
789+ <record id="view_project_form_sdesk" model="ir.ui.view">
790+ <field name="name">view_project_form_sdesk</field>
791+ <field name="model">project.project</field>
792+ <field name="inherit_id" ref="project.edit_project"/>
793+ <field name="arch" type="xml">
794+
795+ <field name="parent_id" position="after">
796+ <field name="use_analytic_account"/>
797+ </field>
798+
799+ </field>
800+ </record>
801+
802+
803+ <!-- Project Task form -->
804+ <record id="view_project_task_form_sdesk" model="ir.ui.view">
805+ <field name="name">view_project_task_form_sdesk</field>
806+ <field name="model">project.task</field>
807+ <field name="inherit_id" ref="project.view_task_form2"/>
808+ <field name="arch" type="xml">
809+
810+ <field name="project_id" position="before">
811+ <field name="use_analytic_account" invisible="1"/>
812+ <field name="analytic_account_id" on_change="onchange_analytic(analytic_account_id)"
813+ attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
814+ <field name="location_id"
815+ attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
816+ </field>
817+
818+ <field name="project_id" position="attributes">
819+ <attribute name="on_change">onchange_project(project_id)</attribute>
820+ </field>
821+
822+ </field>
823+ </record>
824+
825+
826+ <!-- Project Task filter -->
827+ <record id="view_task_search_form" model="ir.ui.view">
828+ <field name="name">view_task_search_form_sdesk</field>
829+ <field name="model">project.task</field>
830+ <field name="inherit_id" ref="project.view_task_search_form"/>
831+ <field name="arch" type="xml">
832+
833+ <field name="name" position="after">
834+ <filter name="analytic_account_id"/>
835+ <filter name="location_id"/>
836+ </field>
837+
838+ </field>
839+ </record>
840+
841+
842+ </data>
843+</openerp>
844
845=== modified file 'service_desk/static/src/img/icon.png' (properties changed: +x to -x)
846=== added directory 'service_desk_issue'
847=== added file 'service_desk_issue/__init__.py'
848--- service_desk_issue/__init__.py 1970-01-01 00:00:00 +0000
849+++ service_desk_issue/__init__.py 2013-12-16 15:38:33 +0000
850@@ -0,0 +1,2 @@
851+# -*- coding: utf-8 -*-
852+from . import project
853
854=== added file 'service_desk_issue/__openerp__.py'
855--- service_desk_issue/__openerp__.py 1970-01-01 00:00:00 +0000
856+++ service_desk_issue/__openerp__.py 2013-12-16 15:38:33 +0000
857@@ -0,0 +1,41 @@
858+# -*- coding: utf-8 -*-
859+##############################################################################
860+#
861+# Copyright (C) 2012-2013 Daniel Reis
862+#
863+# This program is free software: you can redistribute it and/or modify
864+# it under the terms of the GNU Affero General Public License as
865+# published by the Free Software Foundation, either version 3 of the
866+# License, or (at your option) any later version.
867+#
868+# This program is distributed in the hope that it will be useful,
869+# but WITHOUT ANY WARRANTY; without even the implied warranty of
870+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
871+# GNU Affero General Public License for more details.
872+#
873+# You should have received a copy of the GNU Affero General Public License
874+# along with this program. If not, see <http://www.gnu.org/licenses/>.
875+#
876+##############################################################################
877+{
878+ 'name': 'Service Desk for Issues',
879+ 'summary': 'Use Project Issues for Service Desks and service teams',
880+ 'version': '1.1',
881+ "category": "Project Management",
882+ 'description': """\
883+This module extends the ``service_desk`` module to also work with Issues.
884+Please refer to that module's description.
885+""",
886+ 'author': 'Daniel Reis',
887+ 'website': '',
888+ 'depends': [
889+ 'project_issue',
890+ 'service_desk',
891+ ],
892+ 'data': [
893+ 'service_desk_view.xml',
894+ ],
895+ 'installable': True,
896+ 'auto_install': True,
897+}
898+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
899
900=== added directory 'service_desk_issue/i18n'
901=== added file 'service_desk_issue/i18n/service_desk_issue.pot'
902--- service_desk_issue/i18n/service_desk_issue.pot 1970-01-01 00:00:00 +0000
903+++ service_desk_issue/i18n/service_desk_issue.pot 2013-12-16 15:38:33 +0000
904@@ -0,0 +1,88 @@
905+# Translation of OpenERP Server.
906+# This file contains the translation of the following modules:
907+# * service_desk_issue
908+#
909+msgid ""
910+msgstr ""
911+"Project-Id-Version: OpenERP Server 7.0\n"
912+"Report-Msgid-Bugs-To: \n"
913+"POT-Creation-Date: 2013-11-15 10:46+0000\n"
914+"PO-Revision-Date: 2013-11-15 10:46+0000\n"
915+"Last-Translator: <>\n"
916+"Language-Team: \n"
917+"MIME-Version: 1.0\n"
918+"Content-Type: text/plain; charset=UTF-8\n"
919+"Content-Transfer-Encoding: \n"
920+"Plural-Forms: \n"
921+
922+#. module: service_desk_issue
923+#: help:project.issue.reassign,project_id:0
924+msgid "Project this issue should belong to"
925+msgstr ""
926+
927+#. module: service_desk_issue
928+#: field:project.issue,project_code:0
929+msgid "Project Code"
930+msgstr ""
931+
932+#. module: service_desk_issue
933+#: field:project.issue,analytic_partner_id:0
934+msgid "Analytic Account Partner"
935+msgstr ""
936+
937+#. module: service_desk_issue
938+#: model:ir.model,name:service_desk_issue.model_project_issue
939+msgid "Project Issue"
940+msgstr ""
941+
942+#. module: service_desk_issue
943+#: view:project.issue:0
944+msgid "{'default_project_id': project_id, 'default_name': name, 'default_analytic_account_id': analytic_account_id, 'default_location_id': location_id}"
945+msgstr ""
946+
947+#. module: service_desk_issue
948+#: model:ir.model,name:service_desk_issue.model_project_issue_delegate
949+#: model:ir.model,name:service_desk_issue.model_project_issue_reassign
950+msgid "Issue Reassign"
951+msgstr ""
952+
953+#. module: service_desk_issue
954+#: view:project.issue:0
955+msgid "onchange_project(project_id)"
956+msgstr ""
957+
958+#. module: service_desk_issue
959+#: view:project.issue:0
960+msgid "Contract"
961+msgstr ""
962+
963+#. module: service_desk_issue
964+#: help:project.issue.reassign,user_id:0
965+msgid "User you want to assign this issue to"
966+msgstr ""
967+
968+#. module: service_desk_issue
969+#: field:project.issue.reassign,project_id:0
970+msgid "Project"
971+msgstr ""
972+
973+#. module: service_desk_issue
974+#: field:project.issue.reassign,user_id:0
975+msgid "Assign To"
976+msgstr ""
977+
978+#. module: service_desk_issue
979+#: field:project.issue,location_id:0
980+msgid "Location"
981+msgstr ""
982+
983+#. module: service_desk_issue
984+#: field:project.issue,use_analytic_account:0
985+msgid "Use Analytic Account"
986+msgstr ""
987+
988+#. module: service_desk_issue
989+#: field:project.issue,analytic_account_id:0
990+msgid "Contract/Analytic"
991+msgstr ""
992+
993
994=== added file 'service_desk_issue/project.py'
995--- service_desk_issue/project.py 1970-01-01 00:00:00 +0000
996+++ service_desk_issue/project.py 2013-12-16 15:38:33 +0000
997@@ -0,0 +1,72 @@
998+# -*- coding: utf-8 -*-
999+##############################################################################
1000+#
1001+# Copyright (C) 2013 Daniel Reis
1002+#
1003+# This program is free software: you can redistribute it and/or modify
1004+# it under the terms of the GNU Affero General Public License as
1005+# published by the Free Software Foundation, either version 3 of the
1006+# License, or (at your option) any later version.
1007+#
1008+# This program is distributed in the hope that it will be useful,
1009+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1010+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1011+# GNU Affero General Public License for more details.
1012+#
1013+# You should have received a copy of the GNU Affero General Public License
1014+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1015+#
1016+##############################################################################
1017+
1018+from openerp.osv import fields, orm
1019+
1020+
1021+class ProjectIssue(orm.Model):
1022+ _inherit = 'project.issue'
1023+
1024+ _columns = {
1025+ 'analytic_account_id': fields.many2one(
1026+ 'account.analytic.account', 'Contract/Analytic',
1027+ domain="[('type','in',['normal','contract'])]"),
1028+ 'analytic_partner_id': fields.related(
1029+ 'analytic_account_id', 'partner_id', relation='res.partner',
1030+ type='many2one', string="Analytic Account Partner", store=True),
1031+ 'location_id': fields.many2one(
1032+ 'res.partner', 'Location',
1033+ domain="[('parent_id','child_of',analytic_partner_id)]"),
1034+ 'use_analytic_account': fields.related(
1035+ 'project_id', 'use_analytic_account',
1036+ type='char', string="Use Analytic Account"),
1037+ 'project_code': fields.related(
1038+ 'project_id', 'code', type='char', string="Project Code"),
1039+ }
1040+
1041+ def onchange_project(self, cr, uid, id, project_id, context=None):
1042+ # on_change is necessary to populate fields on Create, before saving
1043+ try:
1044+ res = super(ProjectIssue, self).onchange_project(
1045+ cr, uid, id, project_id, context=context) or {}
1046+ except AttributeError:
1047+ res = {}
1048+
1049+ if project_id:
1050+ obj = self.pool.get('project.project').browse(
1051+ cr, uid, project_id, context=context)
1052+ res.setdefault('value', {})
1053+ res['value']['use_analytic_account'] = (
1054+ obj.use_analytic_account or 'no')
1055+ return res
1056+
1057+ def onchange_analytic(self, cr, uid, id, analytic_id, context=None):
1058+ res = {}
1059+ model = self.pool.get('account.analytic.account')
1060+ obj = model.browse(cr, uid, analytic_id, context=context)
1061+ if obj:
1062+ # "contact_id" and "department_id" may be provided by other modules
1063+ fldmap = [ # analytic_account field -> issue field
1064+ ('partner_id', 'analytic_partner_id'),
1065+ ('contact_id', 'location_id'),
1066+ ('department_id', 'department_id')]
1067+ res['value'] = {dest: getattr(obj, orig).id
1068+ for orig, dest in fldmap if hasattr(obj, orig)}
1069+ return res
1070
1071=== added file 'service_desk_issue/service_desk_view.xml'
1072--- service_desk_issue/service_desk_view.xml 1970-01-01 00:00:00 +0000
1073+++ service_desk_issue/service_desk_view.xml 2013-12-16 15:38:33 +0000
1074@@ -0,0 +1,93 @@
1075+<?xml version="1.0" encoding="utf-8"?>
1076+<openerp>
1077+ <data>
1078+
1079+
1080+ <!-- Project Issue form -->
1081+ <record id="project_issue_form_view_sdesk" model="ir.ui.view">
1082+ <field name="name">project_issue_form_view_sdesk</field>
1083+ <field name="model">project.issue</field>
1084+ <field name="inherit_id" ref="project_issue.project_issue_form_view"/>
1085+ <field name="arch" type="xml">
1086+
1087+ <!-- See Analytic Account and Location, if Project is configured so -->
1088+ <field name="categ_ids" position="after">
1089+ <group>
1090+ <field name="use_analytic_account" invisible="1"/>
1091+ <field name="analytic_partner_id" invisible="1"/>
1092+ <field name="analytic_account_id" on_change="onchange_analytic(analytic_account_id)"
1093+ attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
1094+ <field name="location_id"
1095+ attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
1096+ </group>
1097+ </field>
1098+
1099+ <!-- Use on_change on Project to force updating of "related" fields, used in attrs rules -->
1100+ <!-- Make Project mandatory, to avoid "lost" Issues not assigned to any Service Team -->
1101+ <field name="project_id" position="attributes">
1102+ <attribute name="on_change">onchange_project(project_id)</attribute>
1103+ <attribute name="required">1</attribute>
1104+ </field>
1105+
1106+ <!-- Make Deadline field available -->
1107+ <field name="priority" position="after">
1108+ <field name="date_deadline"/>
1109+ </field>
1110+
1111+ <!-- Friendly default values when creating a ralated Task -->
1112+ <field name="task_id" position="attributes">
1113+ <attribute name="context">{'default_project_id': project_id, 'default_name': name, 'default_analytic_account_id': analytic_account_id, 'default_location_id': location_id}</attribute>
1114+ </field>
1115+
1116+ </field>
1117+ </record>
1118+
1119+
1120+ <!-- Project Issue tree list -->
1121+ <record model="ir.ui.view" id="project_issue_tree_view_sdesk">
1122+ <field name="name">project_issue_tree_view_sdesk</field>
1123+ <field name="model">project.issue</field>
1124+ <field name="inherit_id" ref="project_issue.project_issue_tree_view"/>
1125+ <field name="arch" type="xml">
1126+
1127+ <!-- See Analytic Account, if Project is configured so -->
1128+ <field name="name" position="after">
1129+ <field name="use_analytic_account" invisible="1"/>
1130+ <field name="analytic_partner_id" invisible="1"/>
1131+ <field name="analytic_account_id"
1132+ attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
1133+ </field>
1134+
1135+ </field>
1136+ </record>
1137+
1138+
1139+ <!-- Project Issue filter -->
1140+ <record id="view_project_issue_filter_sdesk" model="ir.ui.view">
1141+ <field name="name">view_project_issue_filter_sdesk</field>
1142+ <field name="model">project.issue</field>
1143+ <field name="inherit_id" ref="project_issue.view_project_issue_filter"/>
1144+ <field name="arch" type="xml">
1145+
1146+ <!-- Filter and group by Analytic Account -->
1147+ <field name="id" position="after">
1148+ <field name="analytic_partner_id"/>
1149+ <field name="analytic_account_id" string="Contract"/>
1150+ </field>
1151+ <filter string="Responsible" position="after">
1152+ <filter string="Contract Customer" context="{'group_by':'analytic_partner_id'}" />
1153+ </filter>
1154+
1155+ </field>
1156+ </record>
1157+
1158+
1159+ <!-- Fixed: search view was not actually being used -->
1160+ <record id="project_issue.act_project_project_2_project_issue_all" model="ir.actions.act_window">
1161+ <field name="search_view_id" ref="project_issue.view_project_issue_filter"/>
1162+ </record>
1163+
1164+
1165+ </data>
1166+</openerp>
1167+

Subscribers

People subscribed via source and target branches