diff --git a/project_sla/__init__.py b/project_sla/__init__.py new file mode 100644 index 00000000..9ea8fe78 --- /dev/null +++ b/project_sla/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +import project_sla +import analytic_account +import project_sla_control +import project_issue diff --git a/project_sla/__openerp__.py b/project_sla/__openerp__.py new file mode 100644 index 00000000..df8afb89 --- /dev/null +++ b/project_sla/__openerp__.py @@ -0,0 +1,132 @@ +# -*- 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 . +# +############################################################################## +{ + 'name': 'Service Level Agreements', + 'summary': 'Define SLAs for your Contracts', + 'version': '1.0', + "category": "Project Management", + 'description': """\ +Contract SLAs +=============== + +SLAs are assigned to Contracts, on the Analytic Account form, SLA Definition +separator. This is also where new SLA Definitions are created. + +One Contract can have several SLA Definitions attached, allowing for +"composite SLAs". For example, a contract could have a Response Time SLA (time +to start resolution) and a Resolution Time SLA (time to close request). + + +SLA Controlled Documents +======================== + +Only Project Issue documents are made SLA controllable. +However, a framework is made available to easilly build extensions to make +other documents models SLA controlled. + +SLA controlled documents have attached information on the list of SLA rules +they should meet (more than one in the case for composite SLAs) and a summary +SLA status: + + * "watching" the service level (it has SLA requirements to meet) + * under "warning" (limit dates are close, special attention is needed) + * "failed" (one on the SLA limits has not been met) + * "achieved" (all SLA limits have been met) + +Transient states, such as "watching" and "warning", are regularly updated by +a hourly scheduled job, that reevaluates the warning and limit dates against +the current time and changes the state when find dates that have been exceeded. + +To decide what SLA Definitions apply for a specific document, first a lookup +is made for a ``analytic_account_id`` field. If not found, then it will +look up for the ``project_id`` and it's corresponding ``analytic_account_id``. + +Specifically, the Service Desk module introduces a Analytic Account field for +Project Issues. This makes it possible for a Service Team (a "Project") to +have a generic SLA, but at the same time allow for some Contracts to have +specific SLAs (such as the case for "premium" service conditions). + + +SLA Definitions and Rules +========================= + +New SLA Definitions are created from the Analytic Account form, SLA Definition +field. + +Each definition can have one or more Rules. +The particular rule to use is decided by conditions, so that you can set +different service levels based on request attributes, such as Priority or +Category. +Each rule condition is evaluated in "sequence" order, and the first onea to met +is the one to be used. +In the simplest case, a single rule with no condition is just what is needed. + +Each rule sets a number of hours until the "limit date", and the number of +hours until a "warning date". The former will be used to decide if the SLA +was achieved, and the later can be used for automatic alarms or escalation +procedures. + +Time will be counted from creation date, until the "Control Date" specified for +the SLA Definition. That would usually be the "Close" (time until resolution) +or the "Open" (time until response) dates. + +The working calendar set in the related Project definitions will be used (see +the "Other Info" tab). If none is defined, a builtin "all days, 8-12 13-17" +default calendar is used. + +A timezone and leave calendars will also used, based on either the assigned +user (document's `user_id`) or on the current user. + + +Setup checklist +=============== + +The basic steps to configure SLAs for a Project are: + + * Set Project's Working Calendar, at Project definitions, "Other Info" tab + * Go to the Project's Analytic Account form; create and set SLA Definitions + * Use the "Reapply SLAs" button on the Analytic Account form + * See Project Issue's calculated SLAs in the new "Service Levels" tab + + +Credits and Contributors +======================== + + * Daniel Reis (https://launchpad.net/~dreis-pt) + * David Vignoni, author of the icon from the KDE 3.x Nuvola icon theme +""", + 'author': 'Daniel Reis', + 'website': '', + 'depends': [ + 'project_issue', + ], + 'data': [ + 'project_sla_view.xml', + 'project_sla_control_view.xml', + 'project_sla_control_data.xml', + 'analytic_account_view.xml', + 'project_view.xml', + 'project_issue_view.xml', + 'security/ir.model.access.csv', + ], + 'demo': ['project_sla_demo.xml'], + 'test': ['test/project_sla.yml'], + 'installable': True, +} diff --git a/project_sla/analytic_account.py b/project_sla/analytic_account.py new file mode 100644 index 00000000..eaf64ce2 --- /dev/null +++ b/project_sla/analytic_account.py @@ -0,0 +1,71 @@ +# -*- 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 . +# +############################################################################## + +from openerp.osv import fields, orm +import logging +_logger = logging.getLogger(__name__) + + +class AnalyticAccount(orm.Model): + """ Add SLA to Analytic Accounts """ + _inherit = 'account.analytic.account' + _columns = { + 'sla_ids': fields.many2many( + 'project.sla', string='Service Level Agreement'), + } + + def _reapply_sla(self, cr, uid, ids, recalc_closed=False, context=None): + """ + Force SLA recalculation on open documents that already are subject to + this SLA Definition. + To use after changing a Contract SLA or it's Definitions. + The ``recalc_closed`` flag allows to also recompute closed documents. + """ + ctrl_obj = self.pool.get('project.sla.control') + proj_obj = self.pool.get('project.project') + exclude_states = ['cancelled'] + (not recalc_closed and ['done'] or []) + for contract in self.browse(cr, uid, ids, context=context): + # for each contract, and for each model under SLA control ... + for m_name in set([sla.control_model for sla in contract.sla_ids]): + model = self.pool.get(m_name) + doc_ids = [] + if 'analytic_account_id' in model._columns: + doc_ids += model.search( + cr, uid, + [('analytic_account_id', '=', contract.id), + ('state', 'not in', exclude_states)], + context=context) + if 'project_id' in model._columns: + proj_ids = proj_obj.search( + cr, uid, [('analytic_account_id', '=', contract.id)], + context=context) + doc_ids += model.search( + cr, uid, + [('project_id', 'in', proj_ids), + ('state', 'not in', exclude_states)], + context=context) + if doc_ids: + docs = model.browse(cr, uid, doc_ids, context=context) + ctrl_obj.store_sla_control(cr, uid, docs, context=context) + return True + + def reapply_sla(self, cr, uid, ids, context=None): + """ Reapply SLAs button action """ + return self._reapply_sla(cr, uid, ids, context=context) diff --git a/project_sla/analytic_account_view.xml b/project_sla/analytic_account_view.xml new file mode 100644 index 00000000..5b74a43c --- /dev/null +++ b/project_sla/analytic_account_view.xml @@ -0,0 +1,24 @@ + + + + + + view_account_analytic_account_form_sla + account.analytic.account + + + + + + +