← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~dreis-pt/project-service/7.0-service_desk-dr into lp:project-service

 

Daniel Reis has proposed merging lp:~dreis-pt/project-service/7.0-service_desk-dr into lp:project-service.

Requested reviews:
  Project Core Editors (project-core-editors)

For more details, see:
https://code.launchpad.net/~dreis-pt/project-service/7.0-service_desk-dr/+merge/195270

New modules for managing Service Desks: 
Organize teams in Projects, but allow to link tasks and issues to contracts
-- 
https://code.launchpad.net/~dreis-pt/project-service/7.0-service_desk-dr/+merge/195270
Your team Project Core Editors is requested to review the proposed merge of lp:~dreis-pt/project-service/7.0-service_desk-dr into lp:project-service.
=== modified file 'service_desk/__init__.py' (properties changed: +x to -x)
--- service_desk/__init__.py	2012-12-21 18:34:07 +0000
+++ service_desk/__init__.py	2013-11-14 17:39:36 +0000
@@ -1,4 +1,4 @@
 # -*- coding: utf-8 -*-
-import crm_categ
-import project_issue
+import analytic_contact
+import project
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== modified file 'service_desk/__openerp__.py' (properties changed: +x to -x)
--- service_desk/__openerp__.py	2013-03-04 16:16:31 +0000
+++ service_desk/__openerp__.py	2013-11-14 17:39:36 +0000
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 ##############################################################################
 #
-#    Copyright (C) 2012 Daniel Reis
+#    Copyright (C) 2012-2013 Daniel Reis
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -18,50 +18,40 @@
 #
 ##############################################################################
 {
-    'name': 'Service Desk Central',
-    'version': '0.1',
+    'name': 'Service Desk',
+    'summary': 'Use Projects for Service Desks and service teams',
+    'version': '1.1',
     "category": "Project Management",
     'description': """\
-Concentrates all request forms in a single place.
-These can be broad Categories for Project Issues or forms from other modules,
-such as CRM Claims or HR Leave requests.
-
-The items/categories available are defined in:
-Project -> Configuration -> Issue -> Categories.
-
-Each one is representend by an icon and a description.
-When clicking on a Service Desk item, the module will find what Action should
-be executed. It this defition is found on it's form or on a parent, it will be
-used. If not, it an Action opening the Project Issue's default form will be
-used.
-
-When opening the Action, two variables are set in the "context":
-  * A default master Category (`default_master_categ_id`), the id for the
-    selected Category.
-  * A default Service Team (`default_section_id`), from the selected Category
-    or it's parent tree.
-
-For a quick start the module installs two Actions to be used here:
-  * "Issues": opens the standard Project Issue form.
-  * "New Incident": opens a showcase simple Issue form.
-
-The showcase form demonstrates the usage of these two default values:
-the Issue's Category selection list is limited to the Service Desk category
-children, and the Service Team is automatically selected.
+Available service desks/teams are defined as Projects.
+
+Incoming requests and tasks can then be related to customer Contracts and
+service locations through additional two additional fields provided by the
+module. This is optional, and is defined on a per project basis.
+
+
+Features:
+
+  * Project has new field "Use Analytic Account?",
+    with options "Yes" and "Required"
+  * Task has new fields "Analytic Account/Contract" and "Location",
+    visible or required depending on the Project's setting
+  * Analytic Account has a new field "Contact", where you can set it's
+    location/address (a Partner). It will be picked as the default locations
+    when the Analytic Account is selected in a Task or Issue.
+
+(Icon image credits to Everaldo Coelho, Crystal icon set)
 """,
     'author': 'Daniel Reis',
     'website': '',
     'depends': [
-        'project_issue',
-        'project_issue_department',
-        'project_issue_sequences',
-        'crm_categ_hierarchy',
+        'project',
     ],
     'data': [
-        'project_issue_view.xml',
-        'crm_categ_view.xml',
+        'analytic_contact_view.xml',
+        'service_desk_view.xml',
     ],
-    'installable': False,
+    'installable': True,
     'application': True,
 }
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'service_desk/analytic_contact.py'
--- service_desk/analytic_contact.py	1970-01-01 00:00:00 +0000
+++ service_desk/analytic_contact.py	2013-11-14 17:39:36 +0000
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2013 Daniel Reis
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+
+class AnalyticAccount(orm.Model):
+    """Add Contact to Analytic Accounts"""
+    _inherit = 'account.analytic.account'
+    _columns = {
+        'contact_id': fields.many2one(
+            'res.partner', 'Contact',
+            domain="[('parent_id','child_of',partner_id)"
+                   ",('parent_id','!=',False)]"),
+        }

=== added file 'service_desk/analytic_contact_view.xml'
--- service_desk/analytic_contact_view.xml	1970-01-01 00:00:00 +0000
+++ service_desk/analytic_contact_view.xml	2013-11-14 17:39:36 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+        <record id="view_account_analytic_account_form_contact" model="ir.ui.view">
+            <field name="name">view_account_analytic_account_form_contact</field>
+            <field name="model">account.analytic.account</field>
+            <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
+            <field name="arch" type="xml">
+
+                <field name="manager_id" position="after">
+                    <field name="contact_id"/>
+                </field>
+
+           </field>
+        </record>
+
+    </data>
+</openerp>

=== removed file 'service_desk/crm_categ.py'
--- service_desk/crm_categ.py	2013-01-31 13:27:23 +0000
+++ service_desk/crm_categ.py	1970-01-01 00:00:00 +0000
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-#    Copyright (C) 2012 Daniel Reis
-#
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
-#
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
-#
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
-from openerp.osv import fields, orm
-
-
-class crm_case_categ(orm.Model):
-    _inherit = 'crm.case.categ'
-    _columns = {
-        'section_id': fields.many2one('crm.case.section', 'Service Team'),
-        'icon': fields.binary('Icon'),
-        'act_window_id': fields.many2one('ir.actions.act_window', 'Action'),
-        'show_service_desk': fields.boolean('Show in Service Desk'),
-    }
-
-    def open_issue_form(self, cr, uid, ids, context=None):
-
-        def get_categ_section_id(categ_res):
-            """Get Category Team, searching parents upward if necessary"""
-            return categ_res.section_id.id or (
-                    hasattr(categ_res, 'parent_id') and
-                    categ_res.parent_id and
-                    get_categ_section_id(categ_res.parent_id))
-
-        def get_custom_action_dict(categ_res):
-            """Get dict with the custom Action details for a Category
-            If none, use the standard Project Issue form."""
-            action_id = categ_res.act_window_id.id \
-                or self.pool.get('ir.model.data').get_object_reference(
-                    cr, uid, 'project_issue', 'project_issue_categ_act0')[1]
-            return self.pool.get('ir.actions.act_window')\
-                    .read(cr, uid, action_id, context=context)
-
-        def merge_dict_into_text(text, add_dict):
-            """Return the text string with the dict contents added to it.
-            Ex: `"{'a':1}"` merged with `{'b': 2}` returns `"{'a':1, 'b':2}"`.
-            """
-            if ':' not in text:
-                return str(add_dict)
-            else:
-                return '{%s, %s}' % (text.strip()[1:-1], str(add_dict)[1:-1])
-
-        obj = self.browse(cr, uid, ids, context=context)[0]
-        action = get_custom_action_dict(obj)
-        action.update({
-            'domain': [('categ_id', 'child_of', obj.id)],
-            'context': merge_dict_into_text(
-                action.get('context', ''),
-                {'default_master_categ_id': obj.id,
-                 'default_section_id': get_categ_section_id(obj) or False,
-                 'group_by': False,  # remove inherited section_id grouping
-                   },
-                ),
-            })
-        return action
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== removed file 'service_desk/crm_categ_view.xml'
--- service_desk/crm_categ_view.xml	2012-12-21 18:34:07 +0000
+++ service_desk/crm_categ_view.xml	1970-01-01 00:00:00 +0000
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
-
-        <!-- FORM crm.case.category -->
-        <record id="crm_case_categ_view_icon" model="ir.ui.view">
-            <field name="name">crm.case.categ.form.icon</field>
-            <field name="model">crm.case.categ</field>
-            <field name="inherit_id" ref="crm_categ_hierarchy.crm_case_categ-view_dreis"/>
-            <field name="arch" type="xml">
-                <field name="note" position="replace">
-                    <separator colspan="4" string="Service Desk"/>
-                    <group colspan="2" col="2">
-                        <field name="act_window_id"/>
-                        <field name="show_service_desk"/>
-                        <field name="note"/>
-                    </group>
-                    <group colspan="2" col="1">
-                        <field name="icon" widget='image' nolabel="1"/>
-                    </group>
-                </field>
-            </field>
-        </record>
-
-        <!-- KANBAN crm.case.categories -->
-        <record model="ir.ui.view" id="categ_view_kanban">
-            <field name="name">categ_view_kanban</field>
-            <field name="model">crm.case.categ</field>
-            <field name="type">kanban</field>
-            <field name="arch" type="xml">
-
-              <kanban>
-                  <field name="name"/>
-                  <field name="note"/>
-                  <field name="section_id"/>
-                  <templates>
-                    <t t-name="kanban-box">
-                      <div class="oe_module_vignette">
-                        <a type="object" name="open_issue_form">
-                          <img t-att-src="kanban_image('crm.case.categ', 'icon', record.id.value)" class="oe_module_icon"/>
-                        </a>
-                        <div class="oe_module_desc">
-                          <h4><a type="edit"><field name="name"/></a></h4>
-                          <p><field name="note"/></p>
-                          <button type="object" name="open_issue_form" class="oe_button">Create</button>
-                        </div>
-                      </div>
-                    </t>
-                  </templates>
-
-              </kanban>
-
-            </field>
-        </record>
-
-
-        <record id="open_categ_view" model="ir.actions.act_window">
-            <field name="name">Service Desk</field>
-            <field name="res_model">crm.case.categ</field>
-            <field name="view_type">form</field>
-            <field name="view_mode">kanban</field>
-            <field name="domain">[('object_id.model','=','project.issue'),('show_service_desk','=',True)]</field>
-            <field name="context">{'group_by':'section_id'}</field>
-        </record>
-        <menuitem action="open_categ_view" id="menu_categ_view" parent="project.menu_project_management"/>
-
-
-    </data>
-</openerp>
-
-
-
-
-
-

=== added directory 'service_desk/i18n'
=== added file 'service_desk/i18n/service_desk.pot'
--- service_desk/i18n/service_desk.pot	1970-01-01 00:00:00 +0000
+++ service_desk/i18n/service_desk.pot	2013-11-14 17:39:36 +0000
@@ -0,0 +1,78 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* service_desk
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-11-14 09:22+0000\n"
+"PO-Revision-Date: 2013-11-14 09:22+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: service_desk
+#: model:ir.model,name:service_desk.model_project_project
+msgid "Project"
+msgstr ""
+
+#. module: service_desk
+#: model:ir.model,name:service_desk.model_account_analytic_location
+msgid "account.analytic.location"
+msgstr ""
+
+#. module: service_desk
+#: model:ir.model,name:service_desk.model_project_task
+msgid "Task"
+msgstr ""
+
+#. module: service_desk
+#: selection:project.project,use_analytic_account:0
+msgid "No"
+msgstr ""
+
+#. module: service_desk
+#: selection:project.project,use_analytic_account:0
+msgid "Required"
+msgstr ""
+
+#. module: service_desk
+#: model:ir.model,name:service_desk.model_account_analytic_account
+msgid "Analytic Account"
+msgstr ""
+
+#. module: service_desk
+#: view:project.task:0
+msgid "onchange_project(project_id)"
+msgstr ""
+
+#. module: service_desk
+#: field:account.analytic.account,contact_id:0
+msgid "Contact"
+msgstr ""
+
+#. module: service_desk
+#: field:project.task,location_id:0
+msgid "Location"
+msgstr ""
+
+#. module: service_desk
+#: field:project.project,use_analytic_account:0
+#: field:project.task,use_analytic_account:0
+msgid "Use Analytic Account"
+msgstr ""
+
+#. module: service_desk
+#: selection:project.project,use_analytic_account:0
+msgid "Optional"
+msgstr ""
+
+#. module: service_desk
+#: field:project.task,analytic_account_id:0
+msgid "Contract/Analytic"
+msgstr ""
+

=== added file 'service_desk/project.py'
--- service_desk/project.py	1970-01-01 00:00:00 +0000
+++ service_desk/project.py	2013-11-14 17:39:36 +0000
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2013 Daniel Reis
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+
+class ProjectProject(orm.Model):
+    _inherit = 'project.project'
+    _columns = {
+        'use_analytic_account': fields.selection(
+            [('no', 'No'), ('yes', 'Optional'), ('req', 'Required')],
+            'Use Analytic Account'),
+        }
+    _defaults = {
+        'use_analytic_account': 'no',
+        }
+
+
+class ProjectTask(orm.Model):
+    """
+    Add related `Analytic Account` and service `Location`.
+    A Location can be any Contact Partner of the AA's Partner.
+    Other logic is possible, such as maintaining a specific list of service
+    addresses for each Contract, but that's out of scpoce here.
+    Modules implementing these other possibilities are very welcome..
+    """
+    _inherit = 'project.task'
+    _columns = {
+        'analytic_account_id': fields.many2one(
+            'account.analytic.account', 'Contract/Analytic',
+            domain="[('type','in',['normal','contract'])]"),
+        'location_id': fields.many2one(
+            'res.partner', 'Location',
+            domain="[('parent_id','child_of',partner_id)]"),
+        'use_analytic_account': fields.related(
+            'project_id', 'use_analytic_account',
+            type='char', string="Use Analytic Account"),
+        }
+
+    def onchange_project(self, cr, uid, id, project_id, context=None):
+        # on_change is necessary to populate fields on Create, before saving
+        try:
+            # try applying a parent's onchange, may it exist
+            res = super(ProjectTask, self).onchange_project(
+                cr, uid, id, project_id, context) or {}
+        except AttributeError:
+            res = {}
+
+        if project_id:
+            obj = self.pool.get('project.project').browse(
+                cr, uid, project_id, context=context)
+            res.setdefault('value', {})
+            res['value']['use_analytic_account'] = (
+                obj.use_analytic_account or 'no')
+        return res
+
+    def onchange_analytic(self, cr, uid, id, analytic_id, context=None):
+        res = {}
+        model = self.pool.get('account.analytic.account')
+        obj = model.browse(cr, uid, analytic_id, context=context)
+        if obj:
+            # "contact_id" and "department_id" may be provided by other modules
+            fldmap = [  # analytic_account field -> task field
+                ('partner_id', 'partner_id'),
+                ('contact_id', 'location_id'),
+                ('department_id', 'department_id')]
+            res['value'] = {dest: getattr(obj, orig).id
+                            for orig, dest in fldmap
+                            if hasattr(obj, orig) and getattr(obj, orig)}
+        return res

=== removed file 'service_desk/project_issue.py'
--- service_desk/project_issue.py	2013-01-31 14:42:51 +0000
+++ service_desk/project_issue.py	1970-01-01 00:00:00 +0000
@@ -1,139 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-#    Copyright (C) 2012 Daniel Reis
-#
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
-#
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
-#
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
-from openerp.osv import fields, orm
-from datetime import datetime
-
-
-class project_issue(orm.Model):
-    _inherit = 'project.issue'
-
-    # `_compute_day` backported from v7.0 (just copied actually)
-    # Allows the Issue's `project_id` to be optional.
-    #---- START ----
-    def _compute_day(self, cr, uid, ids, fields, args, context=None):
-        """
-        @param cr: the current row, from the database cursor,
-        @param uid: the current user’s ID for security checks,
-        @param ids: List of Openday’s IDs
-        @return: difference between current date and log date
-        @param context: A standard dictionary for contextual values
-        """
-        cal_obj = self.pool.get('resource.calendar')
-        res_obj = self.pool.get('resource.resource')
-
-        res = {}
-        for issue in self.browse(cr, uid, ids, context=context):
-            res[issue.id] = {}
-            for field in fields:
-                duration = 0
-                ans = False
-                hours = 0
-
-                date_create = datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S")
-                if field in ['working_hours_open','day_open']:
-                    if issue.date_open:
-                        date_open = datetime.strptime(issue.date_open, "%Y-%m-%d %H:%M:%S")
-                        ans = date_open - date_create
-                        date_until = issue.date_open
-                        #Calculating no. of working hours to open the issue
-                        if issue.project_id.resource_calendar_id:
-                            hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id,
-                                                           date_create,
-                                                           date_open)
-                elif field in ['working_hours_close','day_close']:
-                    if issue.date_closed:
-                        date_close = datetime.strptime(issue.date_closed, "%Y-%m-%d %H:%M:%S")
-                        date_until = issue.date_closed
-                        ans = date_close - date_create
-                        #Calculating no. of working hours to close the issue
-                        if issue.project_id.resource_calendar_id:
-                            hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id,
-                               date_create,
-                               date_close)
-                elif field in ['days_since_creation']:
-                    if issue.create_date:
-                        days_since_creation = datetime.today() - datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S")
-                        res[issue.id][field] = days_since_creation.days
-                    continue
-
-                elif field in ['inactivity_days']:
-                    res[issue.id][field] = 0
-                    if issue.date_action_last:
-                        inactive_days = datetime.today() - datetime.strptime(issue.date_action_last, '%Y-%m-%d %H:%M:%S')
-                        res[issue.id][field] = inactive_days.days
-                    continue
-                if ans:
-                    resource_id = False
-                    if issue.user_id:
-                        resource_ids = res_obj.search(cr, uid, [('user_id','=',issue.user_id.id)])
-                        if resource_ids and len(resource_ids):
-                            resource_id = resource_ids[0]
-                    duration = float(ans.days)
-                    if issue.project_id and issue.project_id.resource_calendar_id:
-                        duration = float(ans.days) * 24
-
-                        new_dates = cal_obj.interval_min_get(cr, uid,
-                                                             issue.project_id.resource_calendar_id.id,
-                                                             date_create,
-                                                             duration, resource=resource_id)
-                        no_days = []
-                        date_until = datetime.strptime(date_until, '%Y-%m-%d %H:%M:%S')
-                        for in_time, out_time in new_dates:
-                            if in_time.date not in no_days:
-                                no_days.append(in_time.date)
-                            if out_time > date_until:
-                                break
-                        duration = len(no_days)
-
-                if field in ['working_hours_open', 'working_hours_close']:
-                    res[issue.id][field] = hours
-                else:
-                    res[issue.id][field] = abs(float(duration))
-
-        return res
-    #---- END ----
-
-    _columns = {
-        'regarding_uid': fields.many2one('res.users', 'Regarding User',
-            help="User affected by the Issue"),
-            
-        # `_compute_day` backport: redeclaring columns in order to 
-        # rebuild references for the replaced method
-        #---- START ----
-        'days_since_creation': fields.function(_compute_day, string='Days since creation date', \
-                                               multi='compute_day', type="integer", help="Difference in days between creation date and current date"),
-        'day_open': fields.function(_compute_day, string='Days to Open', \
-                                multi='compute_day', type="float", store=True),
-        'day_close': fields.function(_compute_day, string='Days to Close', \
-                                multi='compute_day', type="float", store=True),
-        'working_hours_open': fields.function(_compute_day, string='Working Hours to Open the Issue', \
-                                multi='compute_day', type="float", store=True),
-        'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \
-                                multi='compute_day', type="float", store=True),
-        'inactivity_days': fields.function(_compute_day, string='Days since last action', \
-                                multi='compute_day', type="integer", help="Difference in days between last action and current date"),
-        #---- END ----
-    }
-    _defaults = {
-        'regarding_uid': lambda s, cr, uid, c: uid,
-    }
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== removed file 'service_desk/project_issue_view.xml'
--- service_desk/project_issue_view.xml	2013-01-31 13:20:15 +0000
+++ service_desk/project_issue_view.xml	1970-01-01 00:00:00 +0000
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<openerp>
-    <data>
-        
-        <!--PROJECT ISSUE FORM -->
-        <record id="project_issue_form_view_simple" model="ir.ui.view">
-            <field name="name">project_issue_form_view_simple</field>
-            <field name="model">project.issue</field>
-            <field name="type">form</field>
-            <field name="priority" eval="20"/>
-            <field name="arch" type="xml">
-
-                <field name="name"/>
-                <field name="ref"/>
-                <field name="categ_id" required="1"
-                       domain="[('parent_id','=', default_master_categ_id)]"/>
-                <field name="section_id" readonly="1" string="Service Team"/>
-                <field name="regarding_uid"/>
-                <field name="user_id"/>
-                <!--  field name="department_id"/ -->
-                <field name="priority"/>
-
-                    <notebook colspan="4">
-                        <page string="General">
-                            <separator string="Description" colspan="4"/>
-                            <field name="description" nolabel="1" colspan="4"/>
-                            <separator colspan="4"/>
-                            <group col="8" colspan="4">
-                            <field name="state" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors="{&quot;pending&quot;:&quot;blue&quot;}"/>
-                            <button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
-                            <button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward"/>
-                            <button name="case_close" string="Done" states="open,draft,pending" type="object" icon="terp-dialog-close"/>
-                            <button name="case_pending" string="Pending" states="draft,open" type="object" icon="gtk-media-pause"/>
-                            <button name="case_escalate" string="Escalate" states="open,draft,pending" type="object" icon="gtk-go-up"/>
-                            <button name="case_reset" string="Reset to New" states="done,cancel" type="object" icon="gtk-convert"/>
-                            </group>
-                        </page>
-                        <page string="Communication &amp; History" groups="base.group_extended">
-                           <group colspan="4">
-                               <field colspan="4" name="email_cc" widget="char" size="512"/>
-                           </group>
-                            <field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
-                                <tree string="History">
-                                    <field name="display_text" string="History Information"/>
-                                    <field name="email_from" invisible="1"/>
-                                    <button
-                                        string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
-                                        name="%(mail.action_email_compose_message_wizard)d"
-                                        context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
-                                        icon="terp-mail-replied" type="action" />
-                                </tree>
-                            </field>
-                            <button string="Add Internal Note"
-                                name="%(crm.action_crm_add_note)d"
-                                context="{'model': 'crm.lead' }"
-                                icon="terp-document-new" type="action" />
-                            <button string="Send New Email"
-                                name="%(mail.action_email_compose_message_wizard)d"
-                                icon="terp-mail-message-new" type="action"/>
-                        </page>
-                        <page string="Extra Info" groups="base.group_extended">
-                            <group col="2" colspan="2">
-                            <separator colspan="2" string="Date"/>
-                            <field name="create_date"/>
-                            <field name="write_date"/>
-                            <field name="date_closed"/>
-                            <field name="date_open"/>
-                            <field name="date_action_last"/>
-                            </group>
-                            <group colspan="2" col="2">
-                            <separator string="Statistics" colspan="2" col="2"/>
-                            <field name="day_open"/>
-                            <field name="day_close"/>
-                            <field name="working_hours_open" widget="float_time"/>
-                            <field name="working_hours_close" widget="float_time"/>
-                            <field name="inactivity_days"/>
-                            <field name="days_since_creation"/>
-                            </group>
-                            <group colspan="2" col="2">
-                            <separator string="References" colspan="2"/>
-                            <field name="id"/>
-                            <field name="active"/>
-                            </group>
-                        </page>
-                    </notebook>
-               </field>
-        </record>
-
-        <!-- ACTION to open New Issue form -->
-        <record id="action_newissue_wizard" model="ir.actions.act_window">
-            <field name="name">Incidents</field>
-            <field name="res_model">project.issue</field>
-            <field name="view_type">form</field>
-            <field name="view_mode">tree,calendar</field>
-            <field name="view_id" eval="False"/>
-            <field name="domain" eval=""/>
-            <field name="context">{}</field>
-            <field name="search_view_id" ref="project_issue.view_project_issue_filter"/>
-        </record>
-
-        <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewtree">
-            <field name="sequence" eval="1"/>
-            <field name="view_mode">tree</field>
-            <field name="view_id" ref="project_issue.project_issue_tree_view"/>
-            <field name="act_window_id" ref="action_newissue_wizard"/>
-        </record>
-
-        <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewform">
-            <field name="sequence" eval="2"/>
-            <field name="view_mode">form</field>
-            <field name="view_id" ref="project_issue_form_view_simple"/>
-            <field name="act_window_id" ref="action_newissue_wizard"/>
-        </record>
-
-        <record model="ir.actions.act_window.view" id="action_newissue_wizard_viewcal">
-            <field name="sequence" eval="3"/>
-            <field name="view_mode">calendar</field>
-            <field name="view_id" ref="project_issue.project_issue_calendar_view"/>
-            <field name="act_window_id" ref="action_newissue_wizard"/>
-        </record>
-
-    </data>
-</openerp>
-
-
-
-
-
-
-
-
-
-
-

=== added file 'service_desk/service_desk_view.xml'
--- service_desk/service_desk_view.xml	1970-01-01 00:00:00 +0000
+++ service_desk/service_desk_view.xml	2013-11-14 17:39:36 +0000
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+        <!-- Project form -->
+        <record id="view_project_form_sdesk" model="ir.ui.view">
+            <field name="name">view_project_form_sdesk</field>
+            <field name="model">project.project</field>
+            <field name="inherit_id" ref="project.edit_project"/>
+            <field name="arch" type="xml">
+
+                <field name="parent_id" position="after">
+                    <field name="use_analytic_account"/>
+                </field>
+
+           </field>
+        </record>
+
+
+        <!-- Project Task form -->
+        <record id="view_project_task_form_sdesk" model="ir.ui.view">
+            <field name="name">view_project_task_form_sdesk</field>
+            <field name="model">project.task</field>
+            <field name="inherit_id" ref="project.view_task_form2"/>
+            <field name="arch" type="xml">
+
+                <field name="project_id" position="before">
+                            <field name="use_analytic_account" invisible="1"/>
+                            <field name="analytic_account_id" on_change="onchange_analytic(analytic_account_id)"
+                                   attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
+                            <field name="location_id"
+                                   attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
+                </field>
+
+                <field name="project_id" position="attributes">
+                    <attribute name="on_change">onchange_project(project_id)</attribute>
+                </field>
+
+           </field>
+        </record>
+
+
+        <!-- Project Task filter -->
+        <record id="view_task_search_form" model="ir.ui.view">
+            <field name="name">view_task_search_form_sdesk</field>
+            <field name="model">project.task</field>
+            <field name="inherit_id" ref="project.view_task_search_form"/>
+            <field name="arch" type="xml">
+
+                    <field name="name" position="after">
+                        <filter name="analytic_account_id"/>
+                        <filter name="location_id"/>
+                    </field>
+
+           </field>
+        </record>
+
+
+    </data>
+</openerp>

=== modified file 'service_desk/static/src/img/icon.png' (properties changed: +x to -x)
=== added directory 'service_desk_issue'
=== added file 'service_desk_issue/__init__.py'
--- service_desk_issue/__init__.py	1970-01-01 00:00:00 +0000
+++ service_desk_issue/__init__.py	2013-11-14 17:39:36 +0000
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+import project

=== added file 'service_desk_issue/__openerp__.py'
--- service_desk_issue/__openerp__.py	1970-01-01 00:00:00 +0000
+++ service_desk_issue/__openerp__.py	2013-11-14 17:39:36 +0000
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2012-2013 Daniel Reis
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{
+    'name': 'Service Desk for Issues',
+    'summary': 'Use Project Issues for Service Desks and service teams',
+    'version': '1.1',
+    "category": "Project Management",
+    'description': """\
+This module extends the ``service_desk`` module to also work with Issues.
+Please refer to that module's description.
+""",
+    'author': 'Daniel Reis',
+    'website': '',
+    'depends': [
+        'project_issue',
+        'service_desk',
+    ],
+    'data': [
+        'service_desk_view.xml',
+    ],
+    'installable': True,
+    'auto_install': True,
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added directory 'service_desk_issue/i18n'
=== added file 'service_desk_issue/i18n/service_desk_issue.pot'
--- service_desk_issue/i18n/service_desk_issue.pot	1970-01-01 00:00:00 +0000
+++ service_desk_issue/i18n/service_desk_issue.pot	2013-11-14 17:39:36 +0000
@@ -0,0 +1,88 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* service_desk_issue
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-11-14 16:43+0000\n"
+"PO-Revision-Date: 2013-11-14 16:43+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: service_desk_issue
+#: help:project.issue.reassign,project_id:0
+msgid "Project this issue should belong to"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue,project_code:0
+msgid "Project Code"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue,analytic_partner_id:0
+msgid "Analytic Account Partner"
+msgstr ""
+
+#. module: service_desk_issue
+#: model:ir.model,name:service_desk_issue.model_project_issue
+msgid "Project Issue"
+msgstr ""
+
+#. module: service_desk_issue
+#: view:project.issue:0
+msgid "{'default_project_id': project_id, 'default_name': name, 'default_analytic_account_id': analytic_account_id, 'default_location_id': location_id}"
+msgstr ""
+
+#. module: service_desk_issue
+#: model:ir.model,name:service_desk_issue.model_project_issue_delegate
+#: model:ir.model,name:service_desk_issue.model_project_issue_reassign
+msgid "Issue Reassign"
+msgstr ""
+
+#. module: service_desk_issue
+#: view:project.issue:0
+msgid "onchange_project(project_id)"
+msgstr ""
+
+#. module: service_desk_issue
+#: view:project.issue:0
+msgid "Contract"
+msgstr ""
+
+#. module: service_desk_issue
+#: help:project.issue.reassign,user_id:0
+msgid "User you want to assign this issue to"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue.reassign,project_id:0
+msgid "Project"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue.reassign,user_id:0
+msgid "Assign To"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue,location_id:0
+msgid "Location"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue,use_analytic_account:0
+msgid "Use Analytic Account"
+msgstr ""
+
+#. module: service_desk_issue
+#: field:project.issue,analytic_account_id:0
+msgid "Contract/Analytic"
+msgstr ""
+

=== added file 'service_desk_issue/project.py'
--- service_desk_issue/project.py	1970-01-01 00:00:00 +0000
+++ service_desk_issue/project.py	2013-11-14 17:39:36 +0000
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2013 Daniel Reis
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+from openerp.tools.translate import _
+
+
+class ProjectIssue(orm.Model):
+    _inherit = 'project.issue'
+
+    _columns = {
+        'analytic_account_id': fields.many2one(
+            'account.analytic.account', 'Contract/Analytic',
+            domain="[('type','in',['normal','contract'])]"),
+        'analytic_partner_id': fields.related(
+            'analytic_account_id', 'partner_id', relation='res.partner',
+            type='many2one', string="Analytic Account Partner"),
+        'location_id': fields.many2one(
+            'res.partner', 'Location',
+            domain="[('parent_id','child_of',analytic_partner_id)]"),
+        'use_analytic_account': fields.related(
+            'project_id', 'use_analytic_account',
+            type='char', string="Use Analytic Account"),
+        'project_code': fields.related(
+            'project_id', 'code', type='char', string="Project Code"),
+        }
+
+    def onchange_project(self, cr, uid, id, project_id, context=None):
+        # on_change is necessary to populate fields on Create, before saving
+        try:
+            res = super(ProjectIssue, self).onchange_project(
+                cr, uid, id, project_id, context) or {}
+        except AttributeError:
+            res = {}
+
+        if project_id:
+            obj = self.pool.get('project.project').browse(
+                cr, uid, project_id, context=context)
+            res.setdefault('value', {})
+            res['value']['use_analytic_account'] = (
+                obj.use_analytic_account or 'no')
+        return res
+
+    def onchange_analytic(self, cr, uid, id, analytic_id, context=None):
+        res = {}
+        model = self.pool.get('account.analytic.account')
+        obj = model.browse(cr, uid, analytic_id, context=context)
+        if obj:
+            # "contact_id" and "department_id" may be provided by other modules
+            fldmap = [  # analytic_account field -> issue field
+                ('partner_id', 'analytic_partner_id'),
+                ('contact_id', 'location_id'),
+                ('department_id', 'department_id')]
+            res['value'] = {dest: getattr(obj, orig).id
+                            for orig, dest in fldmap if hasattr(obj, orig)}
+        return res

=== added file 'service_desk_issue/service_desk_view.xml'
--- service_desk_issue/service_desk_view.xml	1970-01-01 00:00:00 +0000
+++ service_desk_issue/service_desk_view.xml	2013-11-14 17:39:36 +0000
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+
+        <!-- Project Issue form -->
+        <record id="project_issue_form_view_sdesk" model="ir.ui.view">
+            <field name="name">project_issue_form_view_sdesk</field>
+            <field name="model">project.issue</field>
+            <field name="inherit_id" ref="project_issue.project_issue_form_view"/>
+            <field name="arch" type="xml">
+
+                <!-- See Analytic Account and Location, if Project is configured so -->
+                <field name="categ_ids" position="after">
+                    <group>
+                            <field name="use_analytic_account" invisible="1"/>
+                            <field name="analytic_partner_id" invisible="1"/>
+                            <field name="analytic_account_id" on_change="onchange_analytic(analytic_account_id)"
+                                   attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
+                            <field name="location_id"
+                                   attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
+                    </group>
+                </field>
+
+                <!-- Use on_change on Project to force updating of "related" fields, used in attrs rules -->
+                <!-- Make Project mandatory, to avoid "lost" Issues not assigned to any Service Team -->
+                <field name="project_id" position="attributes">
+                    <attribute name="on_change">onchange_project(project_id)</attribute>
+                    <attribute name="required">1</attribute>
+                </field>
+
+                <!-- Make Deadline field available -->
+                <field name="priority" position="after">
+                    <field name="date_deadline"/>
+                </field>
+
+                <!-- Friendly default values when creating a ralated Task -->
+                <field name="task_id" position="attributes">
+                    <attribute name="context">{'default_project_id': project_id, 'default_name': name, 'default_analytic_account_id': analytic_account_id, 'default_location_id': location_id}</attribute>
+                </field>
+
+           </field>
+        </record>
+
+
+        <!-- Project Issue tree list  -->
+        <record model="ir.ui.view" id="project_issue_tree_view_sdesk">
+            <field name="name">project_issue_tree_view_sdesk</field>
+            <field name="model">project.issue</field>
+            <field name="inherit_id" ref="project_issue.project_issue_tree_view"/>
+            <field name="arch" type="xml">
+
+                <!-- See Analytic Account, if Project is configured so -->
+                <field name="name" position="after">
+                    <field name="use_analytic_account" invisible="1"/>
+                    <field name="analytic_partner_id" invisible="1"/>
+                    <field name="analytic_account_id"
+                           attrs="{'invisible':[('use_analytic_account','not in',['yes','req'])],'required':[('use_analytic_account','=','req')]}"/>
+                </field>
+
+            </field>
+        </record>
+
+
+        <!-- Project Issue filter -->
+        <record id="view_project_issue_filter_sdesk" model="ir.ui.view">
+            <field name="name">view_project_issue_filter_sdesk</field>
+            <field name="model">project.issue</field>
+            <field name="inherit_id" ref="project_issue.view_project_issue_filter"/>
+            <field name="arch" type="xml">
+
+                <!-- Filter by Analytic Account -->
+                <field name="id" position="after">
+                    <field name="analytic_account_id" string="Contract"/>
+                </field>
+
+           </field>
+        </record>
+
+
+        <!-- Fixed: search view was not actually being used -->
+        <record id="project_issue.act_project_project_2_project_issue_all" model="ir.actions.act_window">
+            <field name="search_view_id" ref="project_issue.view_project_issue_filter"/>
+        </record>
+
+
+    </data>
+</openerp>
+