204 lines
9.2 KiB
Python
204 lines
9.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from datetime import timedelta
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
class ProjectPhaseType(models.Model):
|
|
_name = "project.phase.type"
|
|
_description = 'Phase Type'
|
|
|
|
name = fields.Char(string="Name")
|
|
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.user.company_id)
|
|
|
|
|
|
class ProjectPhase(models.Model):
|
|
_name = 'project.phase'
|
|
_description = 'Phase'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_order = 'project_id,start_date'
|
|
|
|
name = fields.Char(string='Phase Name', compute='_compute_name', store=True)
|
|
phase_id = fields.Many2one('project.phase.type', string="Phase")
|
|
sequence = fields.Integer(string='Sequence')
|
|
project_id = fields.Many2one('project.project', string='Project',ondelete="restrict",
|
|
default=lambda self: self.env.context.get('default_project_id'))
|
|
start_date = fields.Date(string='Start Date', copy=True)
|
|
end_date = fields.Date(string='End Date', copy=True)
|
|
estimated_hours = fields.Float("Allocated By",copy=False)
|
|
company_id = fields.Many2one('res.company', related="project_id.company_id", string='Company')
|
|
task_count = fields.Integer(compute="get_task", string='Tasks')
|
|
task_ids = fields.One2many("project.task",'phase_id',string='Tasks')
|
|
weight = fields.Float(string="Weight")
|
|
progress = fields.Float(compute="get_progress", store=True, string="Progress")
|
|
notes = fields.Text(string='Notes',copy=False)
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('open', 'Running'),
|
|
('close', 'Closed')], string='Status',
|
|
copy=False, default='draft', required=True, readonly=True, tracking=True)
|
|
# phase_id = fields.Many2one('project.phase', string="Stage")
|
|
|
|
allowed_internal_user_ids = fields.Many2many('res.users', 'project_phase_allowed_internal_users_rel',
|
|
string="Allowed Internal Users", default=lambda self: self.env.user, domain=[('share', '=', False)])
|
|
allowed_portal_user_ids = fields.Many2many('res.users', 'project_phase_allowed_portal_users_rel', string="Allowed Portal Users", domain=[('share', '=', True)])
|
|
# allowed_user_ids = fields.Many2many('res.users', compute='_compute_allowed_users', inverse='_inverse_allowed_user')
|
|
|
|
# @api.depends('allowed_internal_user_ids', 'allowed_portal_user_ids')
|
|
# def _compute_allowed_users(self):
|
|
# for project in self:
|
|
# users = project.allowed_internal_user_ids | project.allowed_portal_user_ids
|
|
# project.allowed_user_ids = users
|
|
|
|
# def _inverse_allowed_user(self):
|
|
# for project in self:
|
|
# allowed_users = project.allowed_user_ids
|
|
# project.allowed_portal_user_ids = allowed_users.filtered('share')
|
|
# project.allowed_internal_user_ids = allowed_users - project.allowed_portal_user_ids
|
|
|
|
def write(self, values):
|
|
if 'start_date' in values or 'end_date' in values:
|
|
#send notification to pm to edit ivoice date
|
|
if self.project_id.user_id:
|
|
users = [self.project_id.user_id]
|
|
notification_ids = [(0, 0,
|
|
{
|
|
'res_partner_id': user.partner_id.id,
|
|
'notification_type': 'inbox'
|
|
}
|
|
) for user in users if user.partner_id]
|
|
|
|
if notification_ids:
|
|
self.env['mail.message'].create({
|
|
'message_type': "notification",
|
|
'body': _(
|
|
"The Stage %s Dates for project %s Edit ,edit invoice dates accordingly") % (self.display_name,self.project_id.display_name),
|
|
'subject': _("Stage Dates has been updated"),
|
|
'partner_ids': [(4, user.partner_id.id) for user in users if users],
|
|
'model': self._name,
|
|
'res_id': self.id,
|
|
'notification_ids': notification_ids,
|
|
'author_id': self.env.user.partner_id and self.env.user.partner_id.id
|
|
})
|
|
if self._context.get('open_from',False):
|
|
if self._context.get('open_from',False) == 'vo':
|
|
vo_id = self._context.get('vo_id',[])
|
|
vo = self.env['project.variation.order'].browse(vo_id)
|
|
message = str('from ' + (vo and vo.name or "VO"))
|
|
if self._context.get('edit_reasone',False):
|
|
message = message + _(" For Reasone: %s"%(self._context.get('edit_reasone'," ")))
|
|
else:
|
|
message = _("From Project For Reasone: %s"%(self._context.get('edit_reasone'," ")))
|
|
|
|
body = _("<p style='color: #FF0000;'><b>Project Phase updated %s</b></p><ul>"%( message ))
|
|
fields = self.fields_get()
|
|
old_values = self.read(values.keys())[0]
|
|
for k, v in values.items():
|
|
field = fields.get(k)
|
|
if field['type'] == 'selection':
|
|
val = dict(field['selection'])[v]
|
|
old_val = dict(field['selection'])[old_values[k]]
|
|
elif field['type'] == 'many2one':
|
|
val = self.env[field['relation']].sudo().browse(v).name_get()[0][1]
|
|
old_val = old_values[k][1]
|
|
elif field['type'] == 'many2many':
|
|
val = ""
|
|
old_val = ""
|
|
for mv in v:
|
|
val += self.env[field['relation']].sudo().browse(mv).name_get()[0][1] +" "
|
|
else:
|
|
val = v
|
|
old_val = old_values[k]
|
|
body += "<li>%s: %s -> %s</li>" % (field['string'], old_val, val)
|
|
body += "</ul>"
|
|
self.env['mail.message'].create({
|
|
'body': body,
|
|
'model': 'project.phase',
|
|
'res_id': self.id,
|
|
'subtype_id': '2',
|
|
})
|
|
return super(ProjectPhase, self).write(values)
|
|
|
|
def unlink(self):
|
|
for rec in self:
|
|
invoice_ids = self.env['project.invoice'].search([('phase_id','=',rec.id), ('project_id', '=', rec.project_id.id)])
|
|
invoice_ids.unlink()
|
|
super(ProjectPhase, self).unlink()
|
|
|
|
@api.depends('task_ids.weight', 'task_ids.task_progress','task_ids')
|
|
def get_progress(self):
|
|
for rec in self:
|
|
progress = 0.0
|
|
if rec.task_ids:
|
|
done_task = self.env['project.task'].search([('phase_id', '=', rec.id)])
|
|
# import pdb
|
|
# pdb.set_trace()
|
|
progress = ((sum([x.weight * x.task_progress for x in done_task])) / 100)
|
|
# progress = round(100.0 * float((len(done_task) / len(rec.task_ids))), 2)
|
|
rec.progress = progress
|
|
|
|
@api.constrains('start_date', 'end_date')
|
|
def _check_dates(self):
|
|
for rec in self:
|
|
if rec.start_date and rec.end_date and rec.start_date > rec.end_date:
|
|
raise ValidationError(_('Phase start date must be earlier than Phase end date.'))
|
|
|
|
project = rec.project_id
|
|
if not project.start or not project.date:
|
|
continue
|
|
|
|
if rec.start_date and (rec.start_date < project.start or rec.start_date > project.date):
|
|
raise ValidationError(_('Phase dates must be between project dates.'))
|
|
|
|
if rec.end_date and (rec.end_date < project.start or rec.end_date > project.date):
|
|
raise ValidationError(_('Phase dates must be between project dates.'))
|
|
|
|
def action_draft(self):
|
|
return self.write({'state': 'draft'})
|
|
|
|
def action_confirm(self):
|
|
for rec in self:
|
|
if not rec.start_date or not rec.end_date:
|
|
raise ValidationError(_('Make sure that stage dates is set.'))
|
|
return self.write({'state': 'open'})
|
|
|
|
def action_close(self):
|
|
return self.write({'state': 'close'})
|
|
|
|
def action_reopen(self):
|
|
return self.write({'state': 'open'})
|
|
|
|
@api.depends('phase_id')
|
|
def _compute_name(self):
|
|
for rec in self:
|
|
rec.name = rec.phase_id.name
|
|
|
|
def action_project_phase_task(self):
|
|
self.ensure_one()
|
|
return {
|
|
'name': 'Tasks',
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'tree,form',
|
|
'res_model': 'project.task',
|
|
'domain': [('phase_id', '=', self.id)],
|
|
}
|
|
|
|
def action_view_project_invoice(self):
|
|
self.ensure_one()
|
|
action_window = {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": "project.invoice",
|
|
"name": "Invoice Requests",
|
|
'view_type': 'form',
|
|
'view_mode': 'tree,form',
|
|
"context": {"create": False, "edit": False},
|
|
"domain": [('phase_id', '=', self.id), ('project_id', '=', self.project_id.id)]
|
|
}
|
|
return action_window
|
|
|
|
def get_task(self):
|
|
for rec in self:
|
|
records = self.env['project.task'].search([('phase_id', '=', rec.id)])
|
|
rec.task_count = len(records)
|
|
|