5 changed files with 279 additions and 32 deletions
			
			
		| @ -0,0 +1,238 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################## | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | #    Copyright (C) 2016-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). | ||||
|  | #    Author: Nilmar Shereef(<http://www.cybrosys.com>) | ||||
|  | #    you can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies | ||||
|  | #    of the Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################## | ||||
|  | from openerp import models, api, fields, _ | ||||
|  | from openerp.exceptions import Warning, ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class ProjectMaster(models.Model): | ||||
|  |     _inherit = 'project.project' | ||||
|  | 
 | ||||
|  |     use_sub_task = fields.Boolean(string="SubTasks", default=True) | ||||
|  |     label_sub_tasks = fields.Char(default='SubTasks') | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SubTaskMaster(models.Model): | ||||
|  |     _name = 'project.sub_task' | ||||
|  |      | ||||
|  |     def stage_find(self, section_id, domain=[], order='sequence'): | ||||
|  |         section_ids = [] | ||||
|  |         if section_id: | ||||
|  |             section_ids.append(section_id) | ||||
|  |         section_ids.extend(self.mapped('task_ref').ids) | ||||
|  |         search_domain = [] | ||||
|  |         if section_ids: | ||||
|  |             search_domain = [('|')] * (len(section_ids) - 1) | ||||
|  |             for section_id in section_ids: | ||||
|  |                 search_domain.append(('task_ids', '=', section_id)) | ||||
|  |         search_domain += list(domain) | ||||
|  |         # perform search, return the first found | ||||
|  |         return self.env['project.sub_task.type'].search(search_domain, order=order, limit=1).id | ||||
|  | 
 | ||||
|  |     @api.onchange('task_ref') | ||||
|  |     def get_default_stage_id(self): | ||||
|  |         """ Gives default stage_id """ | ||||
|  |         project_id = self.task_ref.id | ||||
|  |         if not project_id: | ||||
|  |             return False | ||||
|  |         self.stage_id = self.stage_find(project_id, [('fold', '=', False)]) | ||||
|  | 
 | ||||
|  |     @api.constrains('date_deadline', 'task_ref') | ||||
|  |     def date_deadline_validation(self): | ||||
|  |         if self.date_deadline > self.task_ref.date_deadline: | ||||
|  |             raise ValidationError(_("Your main task will dead at this date")) | ||||
|  | 
 | ||||
|  |     name = fields.Char(string="Name", requires=True) | ||||
|  |     priority = fields.Selection([('0', 'Normal'), ('1', 'High')], 'Priority', select=True, default='0') | ||||
|  |     assigned_user = fields.Many2one('res.users', string="Assigned Person", required=1) | ||||
|  |     task_ref = fields.Many2one('project.task', string='Task', required=1, domain=['|', '|', ('project_id.use_sub_task', '=', True), | ||||
|  |                                                                                   ('stage_id.done_state', '=', False), | ||||
|  |                                                                                   ('stage_id.cancel_state', '=', False)]) | ||||
|  |     stage_id = fields.Many2one('project.sub_task.type', string='Stage', select=True, | ||||
|  |                                domain="[('task_ids', '=', task_ref)]", copy=False) | ||||
|  |     project_id = fields.Many2one('project.project', related='task_ref.project_id', string='Project') | ||||
|  |     notes = fields.Html(string='Notes') | ||||
|  |     planned_hours = fields.Float(string='Initially Planned Hours', | ||||
|  |                                  help='Estimated time to do the Subtask, usually set by the project manager when the ' | ||||
|  |                                       'task is in draft state.') | ||||
|  |     partner_id = fields.Many2one('res.partner', string='Customer', related='task_ref.partner_id', readonly=1) | ||||
|  |     color = fields.Integer(string='Color Index') | ||||
|  |     attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=lambda self: [('res_model', '=', self._name)], | ||||
|  |                                      auto_join=True, string='Attachments') | ||||
|  |     displayed_image_id = fields.Many2one('ir.attachment', | ||||
|  |                                          domain="[('res_model', '=', 'project.sub_task'), ('res_id', '=', id), ('mimetype', 'ilike', 'image')]", | ||||
|  |                                          string='Displayed Image') | ||||
|  | 
 | ||||
|  |     tag_ids = fields.Many2one('project.sub_task.tags', string='Tags') | ||||
|  |     write_date = fields.Datetime(string='Last Modification Date', readonly=True, select=True) | ||||
|  |     date_start = fields.Datetime(string='Starting Date', readonly=True, select=True) | ||||
|  |     date_deadline = fields.Date(string='Deadline') | ||||
|  |     active = fields.Boolean(string='Active', default=True) | ||||
|  |     description = fields.Html(String='Description') | ||||
|  |     sequence = fields.Integer(string='Sequence', select=True, default=10, | ||||
|  |                               help="Gives the sequence order when displaying a list of sub tasks.") | ||||
|  |     company_id = fields.Many2one('res.company', string='Company') | ||||
|  |     date_last_stage_update = fields.Datetime(string='Last Stage Update', select=True, copy=False, readonly=True) | ||||
|  |     date_assign = fields.Datetime(string='Assigning Date', select=True, copy=False, readonly=True) | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals): | ||||
|  |         context = dict(self.env.context) | ||||
|  |         if vals.get('task_ref'): | ||||
|  |             vals['stage_id'] = self.stage_find(vals.get('task_ref'), [('fold', '=', False)]) | ||||
|  |         if vals.get('user_id'): | ||||
|  |             vals['date_assign'] = fields.Datetime.now() | ||||
|  |         task = super(SubTaskMaster, self.with_context(context)).create(vals) | ||||
|  |         return task | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class TaskMaster(models.Model): | ||||
|  |     _inherit = 'project.task' | ||||
|  | 
 | ||||
|  |     sub_task_lines = fields.One2many('project.sub_task', 'task_ref', string='Sub Tasks') | ||||
|  |     date_deadline = fields.Date('Deadline', select=True, copy=False, required=1) | ||||
|  |     use_sub_task = fields.Boolean(string="SubTasks", related='project_id.use_sub_task') | ||||
|  |     subtask_count = fields.Integer(string='Count', compute='sub_task_found') | ||||
|  | 
 | ||||
|  |     @api.depends('sub_task_lines') | ||||
|  |     def sub_task_found(self): | ||||
|  |         for each in self: | ||||
|  |             each.subtask_count = len(each.sub_task_lines) | ||||
|  | 
 | ||||
|  |     @api.constrains('stage_id') | ||||
|  |     def restrict(self): | ||||
|  |         obj = self.env['project.sub_task.type'].search([('cancel_state', '=', True)]) | ||||
|  |         if self.stage_id.cancel_state: | ||||
|  |             for each in self.sub_task_lines: | ||||
|  |                 each.write({'stage_id': obj.id}) | ||||
|  |         if self.stage_id.done_state: | ||||
|  |             for each in self.sub_task_lines: | ||||
|  |                 if not each.stage_id.done_state: | ||||
|  |                     raise ValidationError(_("You can't move it to final stage. Some child tasks are not completed yet.!")) | ||||
|  | 
 | ||||
|  |     def _check_child_task(self, cr, uid, ids, context=None): | ||||
|  |         if context == None: | ||||
|  |             context = {} | ||||
|  |         tasks = self.browse(cr, uid, ids, context=context) | ||||
|  |         for task in tasks: | ||||
|  |             if task.sub_task_lines: | ||||
|  |                 for child in task.sub_task_lines: | ||||
|  |                     if child.stage_id and not child.stage_id.fold: | ||||
|  |                         raise Warning("Sub task still open.\nPlease cancel or complete child task first.") | ||||
|  |                     else: | ||||
|  |                         child.unlink() | ||||
|  |         return True | ||||
|  | 
 | ||||
|  |     def unlink(self, cr, uid, ids, context=None): | ||||
|  |         if context is None: | ||||
|  |             context = {} | ||||
|  |         self._check_child_task(cr, uid, ids, context=context) | ||||
|  |         res = super(TaskMaster, self).unlink(cr, uid, ids, context) | ||||
|  |         return res | ||||
|  | 
 | ||||
|  |     def write(self, cr, uid, ids, vals, context=None): | ||||
|  |         if vals.get('alias_model'): | ||||
|  |             model_ids = self.pool.get('ir.model').search(cr, uid, | ||||
|  |                                                          [('model', '=', vals.get('alias_model', 'project.sub_task'))]) | ||||
|  |             vals.update(alias_model_id=model_ids[0]) | ||||
|  |         res = super(TaskMaster, self).write(cr, uid, ids, vals, context=context) | ||||
|  |         if 'active' in vals: | ||||
|  |             projects = self.browse(cr, uid, ids, context) | ||||
|  |             tasks = projects.with_context(active_test=False).mapped('sub_task_lines') | ||||
|  |             tasks.write({'active': vals['active']}) | ||||
|  |         return res | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class ProjectTaskType(models.Model): | ||||
|  |     _inherit = 'project.task.type' | ||||
|  | 
 | ||||
|  |     done_state = fields.Boolean(string='Final Stage', | ||||
|  |                                 help='This stage is Final Stage.') | ||||
|  |     cancel_state = fields.Boolean(string='Cancel Stage', | ||||
|  |                                   help='This stage is Cancel Stage.') | ||||
|  | 
 | ||||
|  |     @api.onchange('done_state', 'cancel_state') | ||||
|  |     def set_done(self): | ||||
|  |         obj = self.env['project.task.type'].search([]) | ||||
|  |         if self.done_state is True: | ||||
|  |             for each in obj: | ||||
|  |                 if each.id != self.id: | ||||
|  |                     each.write({'done_state': False}) | ||||
|  |         if self.cancel_state is True: | ||||
|  |             for each in obj: | ||||
|  |                 if each.id != self.id: | ||||
|  |                     each.write({'cancel_state': False}) | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class ProjectSubTaskType(models.Model): | ||||
|  |     _name = 'project.sub_task.type' | ||||
|  |     _description = 'Sub Task Stage' | ||||
|  |     _order = 'sequence' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Stage Name', required=True, translate=True) | ||||
|  |     description = fields.Text(string='Description', translate=True) | ||||
|  |     sequence = fields.Integer(string='Sequence') | ||||
|  |     task_ids = fields.Many2many('project.task', string="Task Ids") | ||||
|  |     legend_priority = fields.Char(string='Priority Management Explanation', translate=True, | ||||
|  |                                   help='Explanation text to help users using the star and priority mechanism on stages ' | ||||
|  |                                        'or issues that are in this stage.') | ||||
|  |     legend_blocked = fields.Char(string='Kanban Blocked Explanation', translate=True, | ||||
|  |                                  help='Override the default value displayed for the blocked state for kanban selection,' | ||||
|  |                                       'when the task or issue is in that stage.') | ||||
|  |     legend_done = fields.Char(string='Kanban Valid Explanation', translate=True, | ||||
|  |                               help='Override the default value displayed for the done state for kanban selection, when ' | ||||
|  |                                    'the task or issue is in that stage.') | ||||
|  |     legend_normal = fields.Char(string='Kanban Ongoing Explanation', translate=True, | ||||
|  |                                 help='Override the default value displayed for the normal state for kanban selection, ' | ||||
|  |                                      'when the task or issue is in that stage.') | ||||
|  |     fold = fields.Boolean(string='Folded in Tasks Pipeline', | ||||
|  |                           help='This stage is folded in the kanban view when ' | ||||
|  |                                'there are no records in that stage to display.') | ||||
|  |     done_state = fields.Boolean(string='Final Stage', | ||||
|  |                           help='This stage is Final Stage.') | ||||
|  |     cancel_state = fields.Boolean(string='Cancel Stage', | ||||
|  |                           help='This stage is Cancel Stage.') | ||||
|  | 
 | ||||
|  |     @api.onchange('done_state', 'cancel_state') | ||||
|  |     def set_done(self): | ||||
|  |         obj = self.env['project.task.type'].search([]) | ||||
|  |         if self.done_state is True: | ||||
|  |             for each in obj: | ||||
|  |                 if each.id != self.id: | ||||
|  |                     each.write({'done_state': False}) | ||||
|  |         if self.cancel_state is True: | ||||
|  |             for each in obj: | ||||
|  |                 if each.id != self.id: | ||||
|  |                     each.write({'cancel_state': False}) | ||||
|  | 
 | ||||
|  |     def _get_default_task_ids(self, cr, uid, ctx=None): | ||||
|  |         if ctx is None: | ||||
|  |             ctx = {} | ||||
|  |         default_task_ids = ctx.get('default_task_ids') | ||||
|  |         return [default_task_ids] if default_task_ids else None | ||||
|  | 
 | ||||
|  |     _defaults = { | ||||
|  |         'sequence': 1, | ||||
|  |         'task_ids': _get_default_task_ids, | ||||
|  |     } | ||||
|  |     _order = 'sequence' | ||||
|  | 
 | ||||
| 
 | 
					Loading…
					
					
				
		Reference in new issue