first push message

This commit is contained in:
2026-07-01 14:41:49 +07:00
parent 6667dec2bf
commit 58b5f46cc4
2951 changed files with 316619 additions and 0 deletions
@@ -0,0 +1,9 @@
# -- coding: utf-8 --
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from . import project
from . import task_update
from . import project_task
from . import res
from . import task
from . import project_custom_checklist
@@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import UserError,ValidationError
from datetime import datetime, timedelta,date
from odoo.tools.safe_eval import safe_eval
class ProjectInherit(models.Model):
_inherit = "project.project"
_description = "Projects"
sub_project_ids = fields.One2many('sub.project', 'project_id', string="Sub Projects")
sub_task_count = fields.Integer(compute="compute_sub_task_count")
privacy_visibility = fields.Selection([
('followers', 'Invited employees'),
('employees', 'All employees'),
('portal', 'Portal users and all employees'),
],
string='Visibility', required=True,
default='followers',
help="Defines the visibility of the tasks of the project:\n"
"- Invited employees: employees may only see the followed project and tasks.\n"
"- All employees: employees may see all project and tasks.\n"
"- Portal users and all employees: employees may see everything."
" Portal users may see project and tasks followed by.\n"
" them or by someone of their company.")
task_auto_assign_ids = fields.One2many('task.auto.assign', 'project_id')
task_sequence_id = fields.Many2one('ir.sequence',string="Task Entry Sequence")
seq1 = fields.Char("Number")
seq2 = fields.Char(string="Add Prefix")
order_id = fields.Many2one('sale.order', string="Sale Order ")
sale_order_ids = fields.Many2many('sale.order', 'sales_order_project_project_rel', string="Sale Orders")
def compute_sub_task_count(self):
for rec in self:
rec.sub_task_count = len(rec.sub_project_ids)
def unlink(self):
for remove in self:
if len(remove.sub_project_ids) > 0:
raise UserError(_("Sorry !!! You cannot delete this project, because it has sub project(s)"))
return super(ProjectInherit, self).unlink()
@api.model
def default_get(self, fields):
res = super(ProjectInherit, self).default_get(fields)
stages_lines = []
task_ids = self.env['project.task.type'].search([])
stages = [x.id for x in task_ids]
stages_lines += [(0, 0, {'type_ids': stages})]
project_stage_ids = self.env['project.task.type'].search([('dft_for_new_project', '=', True)])
stage_list = []
if project_stage_ids:
for stage in project_stage_ids:
values = {}
values.update({'stage_id': stage.id, 'user_ids': stage.dft_assign_user_id.id})
stage_list.append((0, 0, values))
res.update({'task_auto_assign_ids': stage_list})
return res
# validation on blank user and stage.
@api.constrains('task_auto_assign_ids')
def onchange_auto_assign_ids(self):
if self.task_auto_assign_ids:
for each in self.task_auto_assign_ids:
if not each.user_ids or not each.stage_id:
raise ValidationError(_(" Please enter valid Users and Stages.!"))
# if default new is true then new created project is automatically add.
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
project_obj = self.env['project.project'].search(
[('task_auto_assign_ids.stage_id.dft_for_new_project', '=', True)])
plist = []
for vals in vals_list:
vals['seq1'] = self.env['ir.sequence'].next_by_code('project.project') or _('New')
record = super(ProjectInherit, self).create(vals)
plist.append(record.id)
for p in project_obj:
plist.append(p.id)
stage_obj = self.env['project.task.type'].search([('dft_for_new_project', '=', True)])
for stage in stage_obj:
stage.write({'project_ids': [(6, 0, plist)]})
return record
class SubProject(models.Model):
_name = 'sub.project'
_description = "Sub Projects"
user_id = fields.Many2one('res.users', "Project Manager")
partner_id = fields.Many2one('res.partner', string='Customer')
project_id = fields.Many2one('project.project', string='Project', store=True)
p_project_id = fields.Many2one('project.project', string='Project ', store=True)
@api.onchange('p_project_id')
def set_sub_project_vals(self):
if self.p_project_id:
self.user_id = self.p_project_id.user_id
self.partner_id = self.p_project_id.partner_id
def unlink(self):
for remove in self:
if len(remove.p_project_id.task_ids) > 0:
raise UserError(_("Sorry !!! You cannot delete this project, because it has Task(s)"))
return super(SubProject, self).unlink()
class CalenderEvent(models.Model):
_inherit = 'calendar.event'
task_id = fields.Many2one('project.task', string="Task", readonly=True)
project_id = fields.Many2one('project.project',string="Project")
task_count = fields.Integer('Tasks', compute='_compute_task',)
# count task
@api.depends('task_id')
def _compute_task(self):
self.task_count = self.env['project.task'].search_count([('meeting_id','=',self.id)])
class MeetingDate(models.TransientModel):
_name = 'meeting.date'
_description = "Create Meeting from Task"
start_date = fields.Datetime('Meeting Date', required=True)
def get_data(self):
task_obj= self.env['project.task'].browse(self._context.get('active_ids'))
calendar_obj = self.env['calendar.event'].create({'name':"Meeting from : "+task_obj.name , 'start':str(self.start_date),'duration':1, 'stop':self.start_date + timedelta(hours=1),'task_id':task_obj.id, 'project_id':task_obj.project_id.id})
task_obj.write({'meeting_id':calendar_obj.id})
class TaskAutoAssign(models.Model):
_name = "task.auto.assign"
_description = "Task Auto Assign"
project_id = fields.Many2one('project.project', string='Project')
stage_id = fields.Many2one('project.task.type')
user_ids = fields.Many2one('res.users')
_sql_constraints = [('project_stage_uniq', 'unique (project_id,stage_id,user_ids)',
'Duplicate entry is not allowed !')]
# add project in stages from project using add stages and user
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
project_obj = self.env['project.project'].search([])
stage_obj = self.env['project.task.type'].search([])
get_stage = vals.get('stage_id')
plist = []
record = super(TaskAutoAssign, self).create(vals)
proj_list = []
for each in project_obj:
if each.task_auto_assign_ids:
proj_list.append(each.id)
for p in proj_list:
for stage in stage_obj:
if stage.id == get_stage:
plist.append(p)
stage.write({'project_ids': [(6, 0, plist)]})
return record
class SaleOrderInherit(models.Model):
_inherit = 'sale.order'
@api.depends('project_id', 'task_ids')
def _total_task_count(self):
for order in self:
order.task_count = len(order.task_ids)
task_count = fields.Integer('Task Count', compute='_total_task_count',)
project_id = fields.Many2one('project.project', string="Project", readonly=True, copy=False)
task_ids = fields.One2many('project.task', 'order_id', string="Tasks ", readonly=True, copy=False)
order_task_created = fields.Boolean(string='Order Task Created', default=False, copy=False)
def add_task(self):
action = self.env.ref('bi_all_in_one_project_management_system.action_task_create_create').sudo().read()[0]
return action
def action_view_project(self):
domain = []
if self.order_task_created:
domain = [('id','in',self.task_ids.ids)]
action = self.with_context(active_id=self.project_id.id).env.ref('bi_all_in_one_project_management_system.act_project_project_2_project_task_my').sudo().read()[0]
if action.get('context'):
eval_context = self.env['ir.actions.actions']._get_eval_context()
eval_context.update({'active_id': self.project_id.id,'search_default_my_tasks' : 1})
action['context'] = safe_eval(action['context'], eval_context)
action['domain'] = [('is_empty','=',False)] + domain
return action
class CrmTeam(models.Model):
_inherit = 'crm.team'
order_project_id = fields.Many2one('project.project', string="Order Related Project")
@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class ProjectChecklist(models.Model):
_name = "project.checklist"
_description = "Project checklist"
sequence = fields.Integer(string="Sequence")
name = fields.Char(string="Name")
description = fields.Char(string="Description")
class ProjectChecklistLine(models.Model):
_name = "project.checklist.line"
_description = "Project checklist Line"
sequence = fields.Integer(string="Sequence")
name = fields.Char(string="Name")
checklist_id = fields.Many2one('project.checklist', string="name")
project_id = fields.Many2one("project.project", string="project id")
description = fields.Char(string="Description")
date = fields.Date(default=fields.Date.today)
state = fields.Selection([
('new', 'New'),
('complete', 'Complete'),
('cancel', 'Cancel')], string='State',
copy=False, default="new")
@api.onchange('checklist_id')
def _onchange_checklist_id(self):
for checklist in self:
description = ''
if checklist.checklist_id:
description = checklist.checklist_id.description
checklist.update({
'description' : description
})
def action_complete(self):
for rec in self:
rec.state = 'complete'
checklist_len = len(rec.project_id.checklist_line_ids)
completed_progress = len(rec.project_id.checklist_line_ids.filtered(lambda x : x.state == 'complete'))
rec.project_id.write({
'checklist_progress' : (completed_progress * 100) / (checklist_len or 1)
})
def action_cancel(self):
for rec in self:
rec.state = 'cancel'
checklist_len = len(rec.project_id.checklist_line_ids)
completed_progress = len(rec.project_id.checklist_line_ids.filtered(lambda x : x.state == 'complete'))
rec.project_id.write({
'checklist_progress' : (completed_progress * 100) / (checklist_len or 1)
})
def unlink(self):
for rec in self:
project = rec.project_id
project.checklist_line_ids -= rec
checklist_len = len(project.checklist_line_ids)
completed_progress = len(project.checklist_line_ids.filtered(lambda x: x.state == 'complete'))
project.write({
'checklist_progress': (completed_progress * 100) / max((checklist_len or 1), 1)
})
return super(ProjectChecklistLine, self).unlink()
class ProjectChecklistTemplate(models.Model):
_name = "project.checklist.template"
_description = "Project Checklist Template"
_rec_name = "template_name"
sequence = fields.Integer(string="Sequence")
template_name = fields.Char(string="Name")
checklist_ids = fields.Many2many('project.checklist', string="Checklist Template")
class ProjectProject(models.Model):
_inherit = "project.project"
checklist_progress = fields.Integer(string='Checklist Progress', store=True, default=0.0)
checklist_template = fields.Many2many('project.checklist.template', string='Project Checklist template')
checklist_line_ids = fields.One2many('project.checklist.line', 'project_id', string='Checklist')
@api.onchange('checklist_template')
def onchange_checklist_template(self):
if self.checklist_template:
checklist = []
for i in self.checklist_template:
for j in i.checklist_ids:
checklist.append((0,0,{
'checklist_id' : j._origin.id,
'description' : j.description,
'project_id' : self.id,
}))
self.update({'checklist_line_ids':False})
self.update({"checklist_line_ids" : checklist})
@api.constrains('checklist_template')
def _check_checklist_templated(self):
if not self.checklist_template:
for lines in self.checklist_line_ids:
lines.unlink()
@@ -0,0 +1,929 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from datetime import datetime, timedelta,date
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT
from odoo import SUPERUSER_ID
from dateutil.relativedelta import relativedelta
from odoo.http import request
import time
class ProjectTaskUserTime(models.Model):
_name = 'project.task.user.time'
_description = 'Task User Time Tracking'
user_id = fields.Many2one('res.users', string='User', required=True)
task_id = fields.Many2one('project.task', string='Task', required=True)
start_time = fields.Datetime(string='Start Time')
end_time = fields.Datetime(string='End Time')
duration = fields.Float(string='Duration', compute='_compute_duration')
@api.depends('start_time', 'end_time')
def _compute_duration(self):
for record in self:
if record.start_time and record.end_time:
duration = record.end_time - record.start_time
record.duration = duration.total_seconds() / 3600.0
else:
record.duration = 0.0
class Projecttask(models.Model):
_name = "project.task"
_inherit = ["project.task", 'mail.thread']
task_stage = fields.Boolean(string='Task Complete',compute='check_task_completed')
date_start= fields.Datetime(string="Date")
def task_timesheet_reminder(self):
current_user = self.env['res.users'].search([('active', '=', True)])
for user in current_user:
task_obj = self.env['project.task'].search([('user_ids','=',user.id)])
for task in task_obj:
if task.total_hours_spent > task.allocated_hours:
template_id = self.env['ir.model.data']._xmlid_lookup(
'bi_all_in_one_project_management_system.email_template_task_timesheet_reminder')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template(task.ids,
[
'subject',
'body_html',
'email_from',
'email_to',
'partner_to',
'email_cc',
'reply_to',
'scheduled_date',
'res_id',
])
for res_id, val in list(values.items()):
val['email_from'] = user.email
val['res_id'] = False
val['author_id'] = user.partner_id.id
mail_mail_obj = self.env['mail.mail']
mail_create_id = mail_mail_obj.sudo().create(val)
if mail_create_id:
mail_create_id.sudo().send()
return True
@api.model
def _cron_task_reminder(self):
sus_id = self.env['res.partner'].browse(SUPERUSER_ID)
for task in self.env['project.task'].search([]):
for tasks_id in self.env['res.config.settings'].sudo().search([],order="id desc", limit=1):
if task.date_deadline != False:
if task.reminder != False:
reminder_date = task.date_deadline
today = datetime.now().date()
if tasks_id.first_date != today:
# if tasks_id.second_date == today:
if task:
template_id = self.env['ir.model.data']._xmlid_lookup(
'bi_all_in_one_project_management_system.email_template_edi_task_reminder1')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template(task.ids,
[
'subject',
'body_html',
'email_from',
'email_to',
'partner_to',
'email_cc',
'reply_to',
'scheduled_date',
'res_id',
])
for res_id, val in list(values.items()):
emails = {user.email for user in task.user_ids if user.email}
val['email_from'] = sus_id.email
val['email_to'] = ','.join(emails) if emails else '' # Handle case with no emails
val['res_id'] = False
val['author_id'] = self.env['res.users'].sudo().browse(request.env.uid).partner_id.id
mail_mail_obj = self.env['mail.mail']
msg_id = mail_mail_obj.sudo().create(val)
if msg_id:
msg_id.sudo().send()
return True
@api.model
def _cron_task_second_reminder(self):
su_id = self.env['res.partner'].browse(SUPERUSER_ID)
for task in self.env['project.task'].search([]):
for tasks_id in self.env['res.config.settings'].sudo().search([],order="id desc", limit=1):
if task.date_deadline != False:
if task.reminder != False:
reminder_date = task.date_deadline
today = datetime.now().date()
if tasks_id.second_date == today:
if task:
template_id = self.env['ir.model.data']._xmlid_lookup(
'bi_all_in_one_project_management_system.email_template_edi_task_reminder1')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template(task.ids,
[
'subject',
'body_html',
'email_from',
'email_to',
'partner_to',
'email_cc',
'reply_to',
'scheduled_date',
'res_id',
])
for res_id, val in list(values.items()):
emails = {user.email for user in task.user_ids if user.email}
val['email_from'] = su_id.email
val['email_to'] = ','.join(emails) if emails else '' # Handle case with no emails
val['res_id'] = False
val['author_id'] = self.env['res.users'].sudo().browse(request.env.uid).partner_id.id
mail_mail_obj = self.env['mail.mail']
msg_id = mail_mail_obj.sudo().create(val)
if msg_id:
msg_id.sudo().send()
return True
def _cron_post_deadline(self):
for task in self.search([('is_task_done','=',False)]):
schedule_task = '3 Tomorrow'
today = datetime.now()
next_day = today + timedelta(days=1)
last_day_of_week = today + timedelta(days=5 - today.weekday())
start_day_of_next_week = last_day_of_week + timedelta(days=1)
last_day_of_next_week = start_day_of_next_week + timedelta(days=6)
later_day = last_day_of_next_week + timedelta(days=1)
if task.date_deadline:
if task.is_task_done:
schedule_task = '7 Done'
elif task.date_deadline < today:
schedule_task = '1 Overdue'
elif task.date_deadline == today:
schedule_task = '2 Today'
elif task.date_deadline == next_day:
schedule_task = '3 Tomorrow'
elif task.date_deadline > next_day and task.date_deadline <= last_day_of_week:
schedule_task = '4 This Week'
elif task.date_deadline >= start_day_of_next_week and task.date_deadline <= last_day_of_next_week:
schedule_task = '5 Next Week'
elif task.date_deadline > last_day_of_next_week:
schedule_task = '6 Later'
task.update({
'schedule_task' : schedule_task
})
def set_task_done(self):
res = {}
for task in self:
if task.is_task_done == False:
stage_id = self.env['project.task.type'].search([('name','=','Done'),('project_ids','in',self.project_id.ids)],limit=1)
task.write({
'is_task_done' : True,
'stage_id' : stage_id.id
})
task.message_post(body=_("The Task is Set to Done"))
else:
stage_id = self.env['project.task.type'].search([('name','=','New')])
for stage in stage_id:
task.write({
'is_task_done' : False,
'stage_id' : stage.id,
})
task.message_post(body=_("The Task is Set to New"))
@api.depends('date_deadline','is_task_done')
def check_schedule(self):
for task in self:
schedule_task = '3 Tomorrow'
today = datetime.now()
next_day = today + timedelta(days=1)
last_day_of_week = today + timedelta(days=5 - today.weekday())
start_day_of_next_week = last_day_of_week + timedelta(days=1)
last_day_of_next_week = start_day_of_next_week + timedelta(days=6)
later_day = last_day_of_next_week + timedelta(days=1)
if task.date_deadline:
if task.is_task_done:
schedule_task = '7 Done'
elif task.date_deadline < today:
schedule_task = '1 Overdue'
elif task.date_deadline == today:
schedule_task = '2 Today'
elif task.date_deadline == next_day:
schedule_task = '3 Tomorrow'
elif task.date_deadline > next_day and task.date_deadline <= last_day_of_week:
schedule_task = '4 This Week'
elif task.date_deadline >= start_day_of_next_week and task.date_deadline <= last_day_of_next_week:
schedule_task = '5 Next Week'
elif task.date_deadline > last_day_of_next_week:
schedule_task = '6 Later'
task.update({
'schedule_task' : schedule_task
})
is_task_done = fields.Boolean(string='Task Done',default=False)
schedule_task = fields.Selection([
('1 Overdue','Overdue'),
('2 Today','Today'),
('3 Tomorrow','Tomorrow'),
('4 This Week','This Week'),
('5 Next Week','Next Week'),
('6 Later','Later'),
('7 Done','Done')], default='3 Tomorrow', compute="check_schedule", store=True)
user_ids = fields.Many2many('res.users', relation='project_task_user_rel', column1='task_id', column2='user_id')
task_completed = fields.Boolean(string="Task Completed")
start_date = fields.Date(string='Start Date', index=True, copy=False, tracking=True)
state_type_name = fields.Char('Status ', related="stage_id.name")
user_in_subtask = fields.Many2one('res.users','Current User', default=lambda self: self.env.user)
subtask_check = fields.Boolean(string="Subtask", default=False)
subtask_count = fields.Integer(string='Count')
done_stage_id = fields.Boolean('Is Done',default=False,store=True)
todo_stage_id = fields.Boolean('Is ToDo',default=False,store=True)
cancel_stage_id = fields.Boolean('Is Cancel',default=False,store=True)
wiz_id = fields.Many2one('subtask.wizard', string="Wiz Parent Id")
task_parent_id = fields.Many2one('project.task', string="Parent Id")
subtask_ids = fields.One2many('project.task', 'task_parent_id', string="Subtask ")
des = fields.Char('Task Description')
is_subtask = fields.Boolean('Is a subtask')
is_task_done = fields.Boolean(string='Task Done',default=False)
schedule_task = fields.Selection([
('1 Overdue','Overdue'),
('2 Today','Today'),
('3 Tomorrow','Tomorrow'),
('4 This Week','This Week'),
('5 Next Week','Next Week'),
('6 Later','Later'),
('7 Done','Done')], default='3 Tomorrow', compute="check_schedule", store=True)
meeting_id = fields.Many2one('calendar.event', string="Meeting", readonly=True)
meeting_count = fields.Integer('Meeting ',compute='_compute_meeting')
seq3 = fields.Char('Number')
order_id = fields.Many2one('sale.order', string="Sale Order ")
order_task_created = fields.Boolean(string='Order Task Created', default=False, copy=False)
is_empty = fields.Boolean(string='Empty Task')
task_product_ids = fields.Many2many('product.template',string='Products')
task_product_id = fields.Many2one('product.template',string='Product')
reminder = fields.Boolean(string='Reminder')
task_Start = fields.Boolean(string='Task Start', default=False, readonly=True)
end_time = fields.Datetime(
string='End Date ',
)
start_time = fields.Datetime(
string='Start Date ',
)
time_left = fields.Float(string='Real Timer')
priority = fields.Selection(selection_add= [
('0', 'Normal'),
('1', 'Important'),
('2', 'Good'),
('3', 'Excellent'),
])
user_times = fields.One2many('project.task.user.time', 'task_id', string='User Times')
task_Start = fields.Boolean(string='Task Start', default=False, readonly=True, compute='_compute_task_start')
@api.depends('user_times.task_id')
def _compute_task_start(self):
for task in self:
current_user = self.env.user
user_time = self.env['project.task.user.time'].search([
('task_id', '=', task.id),
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
task.task_Start = bool(user_time)
def start_task_button(self):
allow_multi_task = self.env.company.allow_multi_task
current_user = self.env.user
user_time = self.env['project.task.user.time'].search([
('task_id', '=', self.id),
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
if allow_multi_task:
if self.env.user.has_group(
'bi_all_in_one_project_management_system.all_project_user') or self.env.user.has_group(
'bi_all_in_one_project_management_system.group_project_manager'):
if not user_time:
self.env['project.task.user.time'].create({
'task_id': self.id,
'user_id': current_user.id,
'start_time': datetime.now(),
})
self.task_Start = True
elif self.env.user.has_group('project.group_project_user'):
if self.env.user in self.user_ids:
if not user_time:
self.env['project.task.user.time'].create({
'task_id': self.id,
'user_id': current_user.id,
'start_time': datetime.now(),
})
self.task_Start = True
else:
raise UserError(_("User can only start his own task"))
else:
active_user_task = self.env['project.task.user.time'].search([
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
if active_user_task:
raise ValidationError(_('You can start only one task.....'))
else:
if self.env.user.has_group(
'bi_all_in_one_project_management_system.all_project_user') or self.env.user.has_group(
'bi_all_in_one_project_management_system.group_project_manager'):
if not user_time:
self.env['project.task.user.time'].create({
'task_id': self.id,
'user_id': current_user.id,
'start_time': datetime.now(),
})
self.task_Start = True
elif self.env.user.has_group('project.group_project_user'):
if self.env.user in self.user_ids:
if not user_time:
self.env['project.task.user.time'].create({
'task_id': self.id,
'user_id': current_user.id,
'start_time': datetime.now(),
})
self.task_Start = True
else:
raise UserError(_("User can only start his own task"))
# count meeting
@api.depends('meeting_id')
def _compute_meeting(self):
for rec in self:
rec.meeting_count = self.env['calendar.event'].search_count([('task_id','=',rec.id)])
@api.onchange('stage_id')
def _get_project_stage(self):
if self.stage_id.name == 'Done':
self.task_completed = True
else:
self.task_completed = False
if self.project_id:
for each in self.project_id.task_auto_assign_ids:
if self.stage_id.id == each.stage_id.id and self.project_id.id == each.project_id.id:
self.user_ids = each.user_ids
@api.model
def _run_delay_deadline_notification(self):
su_id = self.env['res.partner'].browse(SUPERUSER_ID)
for task in self.env['project.task'].search([('date_deadline', '!=', None), ('user_ids', '!=', None),('stage_id','not in','Done'),('stage_id','not in','Cancelled')]):
for tasks_id in self.env['res.config.settings'].sudo().search([],order="id desc", limit=1):
count_day = tasks_id.delay_count
reminder_date = task.date_deadline + relativedelta(days=count_day)
today = datetime.now()
if reminder_date < today and tasks_id.delay_notification:
if task:
template_id = self.env['ir.model.data']._xmlid_lookup('bi_all_in_one_project_management_system.email_template_edi_remainder_delay_overdue_notification')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template([task.id],('subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to'),)[task.id]
values['email_from'] = su_id.email
values['res_id'] = False
values['author_id'] = self.env['res.users'].browse(request.env.uid).partner_id.id
mail_mail_obj = self.env['mail.mail']
msg_id = mail_mail_obj.sudo().create(values)
if msg_id:
msg_id.sudo().send()
return True
@api.model
def _run_delay_start_notification(self):
su_id = self.env['res.partner'].browse(SUPERUSER_ID)
for task in self.env['project.task'].search([('start_date', '!=', None),('stage_id','not in','In Progress'),('stage_id','not in','Done'),('stage_id','not in','Cancelled')]):
for tasks_id in self.env['res.config.settings'].sudo().search([],order="id desc", limit=1):
count_day = tasks_id.start_count
reminder_date = task.start_date + relativedelta(days=count_day)
today = datetime.now().date()
if reminder_date < today and tasks_id.start_notification:
if task:
template_id = self.env['ir.model.data']._xmlid_lookup('bi_all_in_one_project_management_system.email_template_edi_remainder_delay_start_notification')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template([task.id],('subject', 'body_html', 'email_from','email_to','partner_to', 'email_cc', 'reply_to'))[task.id]
values['email_from'] = su_id.email
values['email_to'] = task.user_ids.email
values['res_id'] = False
values['author_id'] = self.env['res.users'].browse(request.env.uid).partner_id.id
mail_mail_obj = self.env['mail.mail']
msg_id = mail_mail_obj.sudo().create(values)
if msg_id:
msg_id.sudo().send()
return True
@api.model
def default_get(self, field_vals):
res = super(Projecttask, self).default_get(field_vals);
if 'recurrence_id' not in res and 'recurrence_id' in field_vals:
res['recurrence_id'] = False
project = self.env["project.project"].browse(res.get("project_id",[]));
if project:
res["priority"] = project.priority
current_stage = self._context.get('default_stage_id')
current_project = self._context.get('default_project_id')
project = self.env['project.project'].search([('id', '=', current_project)])
project_stage_ids = self.env['project.task.type'].search([('dft_for_new_project', '=', True)])
if project_stage_ids:
for rec in project_stage_ids:
if rec.id == current_stage:
res.update({'user_ids': [(4, rec.dft_assign_user_id.id)]})
if project.task_auto_assign_ids:
for stage in project.task_auto_assign_ids:
if stage.stage_id.id == current_stage:
res.update({'user_ids': [(4, stage.user_ids.id)]})
else:
pass
order_id = self.env['sale.order'].browse(self._context.get('active_id'))
if not order_id.exists():
order_id = False
if order_id:
team_id = order_id.team_id
project = self.env['project.project'].search([('id', '=', current_project)])
date = fields.Date.context_today(self)
date_deadline = date + relativedelta(days=1)
if project :
res.update({
'project_id': project.id,
'date_deadline': date_deadline
})
return res
def _find_mail_template(self, force_confirmation_template=False):
template_id = False
template_id = self.env['ir.model.data']._xmlid_to_res_id('bi_all_in_one_project_management_system.mail_template_task', raise_if_not_found=False)
return template_id
def action_send_task(self):
''' Opens a wizard to compose an email, with relevant mail template loaded by default '''
self.ensure_one()
template_id = self._find_mail_template()
lang = self.env.context.get('lang')
template = self.env['mail.template'].browse(template_id)
attachments = self.env['ir.attachment'].search([('res_model','=','project.task'),('res_id','=',self.id)])
attachments_ids=[]
for attachment in attachments:
attachments_ids.append(attachment.id)
ctx = {
'default_model': 'project.task',
'default_res_ids': self.ids,
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_attachment_ids': ([(6,0,attachments_ids)]),
'default_composition_mode': 'comment',
'custom_layout': "mail.mail_notification_paynow",
'force_email': True,
}
return {
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(False, 'form')],
'view_id': False,
'target': 'new',
'context': ctx,
}
@api.depends('wiz_id.subtask_lines')
def sub_task_found(self):
for each in self:
each.subtask_count = 0
def action_done(self):
done_stage_search = self.env['res.config.settings'].search([], limit=1, order="id desc").done_stage_ckecklist
if not done_stage_search:
raise UserError('You can not move stage, Please Configure Done stage.')
else:
self.write({'stage_id' : done_stage_search.id,'done_stage_id' : True,'todo_stage_id' : False})
def action_cancel(self):
cancel_stage_search = self.env['res.config.settings'].search([], limit=1, order="id desc").cancel_stage_ckecklist
if not cancel_stage_search:
raise UserError('You can not move stage, Please Configure Cancel stage.')
else:
self.write({'stage_id' : cancel_stage_search.id,'cancel_stage_id' : True})
def action_todo(self):
todo_stage_search = self.env['res.config.settings'].search([], limit=1, order="id desc").todo_stage_ckecklist
if not todo_stage_search:
raise UserError('You can not move stage, Please To Do stage.')
else:
self.write({'stage_id' : todo_stage_search.id, 'todo_stage_id' : True,'done_stage_id' : False})
@api.depends('stage_id', 'stage_id.task_completed')
def check_task_completed(self):
for rec in self:
if rec.stage_id and rec.stage_id.task_completed:
rec.task_stage = True
rec.date_deadline = False
else:
rec.task_stage = False
@api.depends('stage_id')
def _inverse_task_stage(self):
for rec in self:
if rec.stage_id and rec.stage_id.task_completed:
rec.task_stage = True
rec.date_deadline = False
else:
rec.task_stage = False
@api.onchange('task_stage')
def _inverse_task_completed(self):
for rec in self:
if rec.task_stage and rec.project_id and rec.project_id.type_id.task_completed:
rec.date_deadline = False
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
project = vals.get('project_id')
project_id = self.env['project.project'].browse(project)
task_sq_code = project_id.task_sequence_id.code
if project_id.seq2 and project_id.task_sequence_id:
combine_seq = project_id.seq2 + "/" + str(self.env['ir.sequence'].sudo().next_by_code(task_sq_code))
else:
combine_seq = self.env['ir.sequence'].sudo().next_by_code('project.task') or _('New')
vals.update({'seq3': combine_seq})
rec = super(Projecttask, self).create(vals_list)
for p_task in self:
for task in p_task.subtask_ids:
if task.state_type_name:
msg = task.state_type_name + ':' + task.name
else:
msg = task.name
p_task.message_post(body=msg)
return rec
def write(self, vals):
old_ids = []
if 'project_id' in vals:
project = vals.get('project_id')
project_id = self.env['project.project'].browse(project)
task_sq_code = project_id.task_sequence_id.code
if project_id.seq2 and project_id.task_sequence_id:
combine_seq = project_id.seq2 + "/" + str(self.env['ir.sequence'].next_by_code(task_sq_code))
else:
combine_seq = self.env['ir.sequence'].next_by_code('project.task') or _('New')
vals.update({'seq3': combine_seq})
for p_task in self:
for task in p_task.subtask_ids:
if task.state_type_name:
msg = task.state_type_name + ':' + task.name
else:
msg = task.name
p_task.message_post(body=msg)
for j in p_task.tag_ids:
old_ids.append(j.name)
res = super(Projecttask, self).write(vals)
for task in self:
if 'stage_id' in vals and vals['stage_id'] and task.stage_id.name == 'Done':
task.date_deadline = False
elif 'stage_id' in vals and vals['stage_id'] and task.stage_id.name != 'Done':
task.date_deadline = task.date_start
for obj in self:
new_ids = []
if vals.get('tag_ids', False):
all_ids = vals.get('tag_ids')
if all_ids[0][1] == False:
for i in all_ids[0][2]:
tag_obj = self.env['project.tags'].search([('id', '=', i)]).name
new_ids.append(tag_obj)
final_new = str(new_ids)[1:-1]
final_old = str(old_ids)[1:-1]
obj.message_post(body=_("Tags added: %s --> %s ") % (final_old, final_new))
else:
for i in all_ids:
tag_obj = self.env['project.tags'].search([('id', '=', i[1])]).name
new_ids.append(tag_obj)
final_new = str(new_ids)[1:-1]
final_old = str(old_ids)[1:-1]
obj.message_post(body=_("Tags added: %s --> %s ") % (final_old, final_new))
if vals.get('stage_id'):
task_type_search = self.env['res.config.settings'].search([], limit=1, order="id desc").warning_child_task
if task_type_search:
if vals.get('stage_id'):
stage_name = self.env['project.task.type'].browse(vals.get('stage_id')).name
if self.is_task_done == False:
vals.update({
'state' : '1_done'
})
else:
vals.update({
'state' : '04_waiting_normal',
})
if stage_name in ['Archive']:
vals.update({
'active':False
})
if vals.get('task_product_id'):
new_task_product_id = self.env['product.template'].browse(int(vals.get('task_product_id')))
old_task_product_id = self.task_product_id
new_task_product_id.write({
'task_ids' : [(4, self.id)],
'project_id' : self.project_id.id
})
if old_task_product_id:
old_task_product_id.write({
'task_ids' : [(3, self.id)],
})
return res
# @api.returns('self', lambda value: value.id)
def copy(self, default=None):
rec = super(Projecttask, self).copy(default)
return rec
def action_get_attachment_view(self):
self.ensure_one()
res = self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment')
res['domain'] = [('res_model', '=', 'project.task'), ('res_id', 'in', self.ids)]
res['context'] = {'default_res_model': 'project.task', 'default_res_id': self.id}
return res
def duplicate_task(self):
for task in self:
task.copy(default={
'name' : task.name + ' (Copy)',
'stage_id' : task.stage_id and task.stage_id.id,
})
@api.onchange('parent_id')
def button_disable(self):
if self.parent_id:
self.is_subtask = True
self.task_parent_id = self.parent_id.id
self.project_id = self.parent_id.project_id
else:
self.is_subtask = False
self.task_parent_id = self.id
# self.project_id = False
class subtask_wizard(models.Model):
_name = 'subtask.wizard'
_description = "Subtask Wizard"
subtask_lines = fields.One2many('project.task', 'wiz_id', string="Task Line")
def create_subtask(self):
list_of_stage = []
project_task_id = self.env['project.task'].browse(self._context.get('active_id'))
for stage in project_task_id.project_id.type_ids:
stage_ids = self.env['project.task.type'].search([('id', '=', stage.id)])
list_of_stage.append(stage_ids.id)
for task in self.subtask_lines:
task.task_parent_id = self._context.get('active_id')
task.description = task.des
task.is_subtask = True
task.project_id = project_task_id.project_id.id
task.subtask_check = True
if task.state_type_name:
msg = task.state_type_name + ' ' +':' + ' ' + task.name
else:
msg = 'new' + ' ' +':' + ' ' + task.name
for t in task.task_parent_id:
t.sudo().message_post(body=msg)
return True
class ProjectTaskType(models.Model):
_inherit= 'project.task.type'
task_completed = fields.Boolean(string='Task Completed')
dft_assign_user_id = fields.Many2one('res.users', string="Default Assigned User")
dft_for_new_project = fields.Boolean(string="Default for New Project")
class Project(models.Model):
_inherit = 'project.project'
priority = fields.Selection([
('0', 'Normal'),
('1', 'Important'),
('2', 'Good'),
('3', 'Excellent'),
], index=True, string="Priority")
@api.onchange('priority')
def onchange_priority(self):
project_task = self.env['project.task'].search([('project_id','in',self.ids)])
for i in project_task:
i.priority=self.priority
class AnalyticLine(models.Model):
_inherit = 'account.analytic.line'
end_time = fields.Datetime(
string='End Date',
)
start_time = fields.Datetime(
string='Start Date',
)
class Calculate_time(models.TransientModel):
_name = 'project.task.timer.wizard'
_description="Calculate Time"
description=fields.Char(string='Description')
end_time = fields.Datetime(string='End Date', readonly=True)
start_time = fields.Datetime(string='Start Date', readonly=True)
duration = fields.Float(string='Duration',readonly=True)
@api.model
def default_get(self, fields):
res = super(Calculate_time, self).default_get(fields)
active_ids = self.env.context.get('active_ids')
current_task_id = self.env['project.task'].browse(active_ids[0])
current_user = self.env.user
user_time = self.env['project.task.user.time'].search([
('task_id', '=', current_task_id.id),
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
if user_time:
diff = datetime.now() - user_time.start_time
hours, remainder = divmod(diff.total_seconds(), 3600)
minutes, _ = divmod(remainder, 60)
time_float = hours + minutes / 60.0
res.update({
'start_time': user_time.start_time,
'end_time': datetime.now(),
'duration': time_float,
})
return res
def end_task_kanban(self):
active_ids = self.env.context.get('active_ids')
current_task_id = self.env['project.task'].browse(active_ids)
current_user = self.env.user
for task in current_task_id:
user_time = self.env['project.task.user.time'].search([
('task_id', '=', task.id),
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
if user_time:
user_time.end_time = datetime.now()
user_time._compute_duration()
task.task_Start = False
if self.env.user.has_group(
'bi_all_in_one_project_management_system.all_project_user') or self.env.user.has_group(
'bi_all_in_one_project_management_system.group_project_manager'):
timesheet = self.env['account.analytic.line']
vals = {
'date': user_time.start_time,
'name': self.description,
'project_id': task.project_id.id,
'task_id': task.id,
'unit_amount': user_time.duration,
'end_time': user_time.end_time,
}
timesheet.create(vals)
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
else:
raise ValidationError("You cannot end this task.")
else:
raise ValidationError("No active task found to end for this user")
def end_task(self):
active_ids = self.env.context.get('active_ids')
current_task_id = self.env['project.task'].browse(active_ids)
current_user = self.env.user
for task in current_task_id:
user_time = self.env['project.task.user.time'].search([
('task_id', '=', task.id),
('user_id', '=', current_user.id),
('end_time', '=', False)
], limit=1)
if user_time:
user_time.end_time = datetime.now()
user_time._compute_duration()
task.task_Start = False
if self.env.user.has_group(
'bi_all_in_one_project_management_system.all_project_user') or self.env.user.has_group(
'bi_all_in_one_project_management_system.group_project_manager'):
timesheet = self.env['account.analytic.line']
vals = {
'date': user_time.start_time,
'name': self.description,
'project_id': task.project_id.id,
'task_id': task.id,
'unit_amount': user_time.duration,
'end_time': user_time.end_time,
}
timesheet.create(vals)
elif self.env.user.has_group('project.group_project_user'):
if self.env.user in current_task_id.user_ids:
timesheet = self.env['account.analytic.line']
vals = {
'date': user_time.start_time,
'name': self.description,
'project_id': task.project_id.id,
'task_id': task.id,
'unit_amount': user_time.duration,
'end_time': user_time.end_time,
}
timesheet.create(vals)
else:
raise ValidationError("You can not end this task.")
@@ -0,0 +1,85 @@
# -- coding: utf-8 --
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import fields , models , api , _
from ast import literal_eval
from odoo.exceptions import UserError
from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT
from datetime import datetime, timedelta
from odoo import models, fields
class ResCompany(models.Model):
_inherit = 'res.company'
start_notification = fields.Boolean(string='Delay Task Start Notification', default=False)
delay_notification = fields.Boolean(string='Delay Task Deadline/Overdue Notification', default=False)
start_count = fields.Integer(string='Delay Day(s)', default=0)
delay_count = fields.Integer(string='Delay Deadline Day(s)', default=0)
done_stage_ckecklist = fields.Many2one('project.task.type', 'Done Stage')
todo_stage_ckecklist = fields.Many2one('project.task.type', 'To Do Stage')
cancel_stage_ckecklist = fields.Many2one('project.task.type', 'Cancel Stage')
warning_child_task = fields.Many2one('project.task.type',
'Prevent stage to change until all tasks on the same stage')
first_reminder = fields.Float(string='First Reminder (Days)')
second_reminder = fields.Float(string='Second Reminder (Days)')
first_date = fields.Date(compute='convert_first_date')
second_date = fields.Date(compute='convert_second_date')
allow_multi_task = fields.Boolean(string='Allow Multi Task')
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
_description="Res config Settings"
start_notification = fields.Boolean(string='Delay Task Start Notification', related='company_id.start_notification', default=False, readonly=False)
delay_notification = fields.Boolean(string='Delay Task Deadline/Overdue Notification', related='company_id.delay_notification', default=False, readonly=False)
start_count = fields.Integer(string='Delay Day(s)', related='company_id.start_count', default=0, readonly=False)
delay_count = fields.Integer(string='Delay Deadline Day(s)', related='company_id.delay_count', default=0, readonly=False)
done_stage_ckecklist = fields.Many2one('project.task.type', string='Done Stage', related='company_id.done_stage_ckecklist', readonly=False)
todo_stage_ckecklist = fields.Many2one('project.task.type', string='To Do Stage', related='company_id.todo_stage_ckecklist' , readonly=False)
cancel_stage_ckecklist = fields.Many2one('project.task.type', string='Cancel Stage', related='company_id.cancel_stage_ckecklist', readonly=False)
warning_child_task = fields.Many2one('project.task.type', string='Prevent stage to change until all tasks on the same stage', related='company_id.warning_child_task' , readonly=False)
first_reminder = fields.Float(string='First Reminder (Days)', related='company_id.first_reminder', readonly=False)
second_reminder = fields.Float(string='Second Reminder (Days)', related='company_id.second_reminder', readonly=False)
first_date = fields.Date(string='First Reminder Date', related='company_id.first_date', readonly=False)
second_date = fields.Date(string='Second Reminder Date', related='company_id.second_date', readonly=False)
allow_multi_task = fields.Boolean(string='Allow Multi Task', related='company_id.allow_multi_task', readonly=False)
def validate_date(self):
if self.first_reminder > self.second_reminder:
return True
else:
raise UserError(_('First Reminder(Days) should be greater than Second Reminder(Days)'))
return False
@api.onchange('first_reminder')
def convert_first_date(self):
self.first_date = None
for tasks in self.env['project.task'].search([]):
if tasks.date_deadline !=False:
reminder_date = datetime.strptime(tasks.date_deadline.strftime("%Y/%m/%d %H:%M:%S"),"%Y/%m/%d %H:%M:%S")
first = reminder_date - timedelta(days=self.first_reminder)
then = datetime.strptime(str(first), '%Y-%m-%d %H:%M:%S').date()
today = datetime.now().date()
if then == today:
self.first_date = then
@api.onchange('second_reminder')
def convert_second_date(self):
self.second_date = None
for proj_task in self.env['project.task'].search([]):
if proj_task.date_deadline !=False:
reminders_date = datetime.strptime(proj_task.date_deadline.strftime("%Y/%m/%d %H:%M:%S"),"%Y/%m/%d %H:%M:%S")
second = reminders_date - timedelta(days=self.second_reminder)
now = datetime.strptime(str(second), '%Y-%m-%d %H:%M:%S').date()
today = datetime.now().date()
if now == today:
self.second_date = now
@@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
import time
import tempfile
import binascii
import xlrd
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
from datetime import date, datetime
from odoo.exceptions import ValidationError
from odoo import models, fields, exceptions, api, _
import logging
_logger = logging.getLogger(__name__)
import io
from io import StringIO
try:
import csv
except ImportError:
_logger.debug('Cannot `import csv`.')
try:
import xlwt
except ImportError:
_logger.debug('Cannot `import xlwt`.')
try:
import cStringIO
except ImportError:
_logger.debug('Cannot `import cStringIO`.')
try:
import base64
except ImportError:
_logger.debug('Cannot `import base64`.')
class import_task(models.TransientModel):
_name = "import.task"
_description = "Import Task"
file = fields.Binary('File')
import_option = fields.Selection([('csv', 'CSV File'), ('xls', 'XLS File')], string='Select', default='csv')
def create_task(self, values):
project_task_obj = self.env['project.task']
project_id = self.find_project(values.get('project_id'))
user_ids = self.find_user(values.get('user_ids'))
tag_ids = self.find_tags(values.get('tag_ids'))
if values.get('date_deadline') != '':
deadline_date = self.find_deadline_date(values.get('date_deadline'))
else:
deadline_date = False
vals = {
'name': values.get('name'),
'project_id': project_id.id,
'user_ids': [(6, 0, [x.id for x in user_ids])],
'tag_ids': [(6, 0, [x.id for x in tag_ids])],
'date_deadline': deadline_date,
'description': values.get('description'),
}
res = project_task_obj.create(vals)
return res
def find_project(self, name):
project_obj = self.env['project.project']
project_search = project_obj.search([('name', '=', name)])
if project_search:
return project_search
else:
project_id = project_obj.create({
'name': name})
return project_id
def find_tags(self, name):
project_tags_obj = self.env['project.tags']
project_tags_search = project_tags_obj.search([('name', '=', name)])
if project_tags_search:
return project_tags_search
else:
raise ValidationError(_(' "%s" Tags is not available.') % name)
def find_user(self, name):
user_obj = self.env['res.users']
user_search = user_obj.search([('name', '=', name)])
if user_search:
return user_search
else:
raise ValidationError(_(' "%s" User is not available.') % name)
def find_deadline_date(self, date):
project_task_obj = self.env['project.task']
DATETIME_FORMAT = "%Y-%m-%d"
if date:
try:
i_date = datetime.strptime(date, DATETIME_FORMAT)
return i_date
except Exception:
raise ValidationError(_('Wrong Date Format. Date Should be in format YYYY-MM-DD.'))
def import_task(self):
if self.import_option == 'csv':
print('if called=============')
keys = ['name', 'project_id', 'user_ids', 'tag_ids', 'date_deadline', 'description']
try:
csv_data = base64.b64decode(self.file)
data_file = io.StringIO(csv_data.decode("utf-8"))
data_file.seek(0)
file_reader = []
csv_reader = csv.reader(data_file, delimiter=',')
file_reader.extend(csv_reader)
except Exception:
raise exceptions.ValidationError(_("Please select CSV/XLS file or You have selected invalid file "))
values = {}
for i in range(len(file_reader)):
field = list(map(str, file_reader[i]))
values = dict(zip(keys, field))
if values:
if i == 0:
continue
else:
res = self.create_task(values)
elif self.import_option == 'xls':
print('elif called============')
try:
fp = tempfile.NamedTemporaryFile(delete=False, suffix=".xls")
fp.write(base64.b64decode(self.file))
fp.seek(0)
workbook = xlrd.open_workbook(fp.name)
sheet = workbook.sheet_by_index(0)
except Exception:
raise ValidationError(_("Please select CSV/XLS file or You have selected invalid file "))
for row_no in range(1, sheet.nrows): # skip header
line = [str(cell.value).strip() for cell in sheet.row(row_no)]
# Safely handle date field
date_string = False
if line[4]:
try:
if isinstance(sheet.cell(row_no, 4).value, (int, float)):
# Excel date number
a1_as_datetime = datetime(
*xlrd.xldate_as_tuple(sheet.cell(row_no, 4).value, workbook.datemode))
date_string = a1_as_datetime.strftime('%Y-%m-%d')
else:
# String date (manual input)
date_string = datetime.strptime(line[4], '%Y-%m-%d').strftime('%Y-%m-%d')
except Exception:
raise ValidationError(_('Wrong Date Format. Date Should be in format YYYY-MM-DD.'))
values = {
'name': line[0],
'project_id': line[1],
'user_ids': line[2],
'tag_ids': line[3],
'date_deadline': date_string,
'description': line[5] if len(line) > 5 else '',
}
self.create_task(values)
return True
else:
raise ValidationError(_("Invalid import option selected."))
@@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import SUPERUSER_ID
from odoo import api, fields, models, _
from datetime import datetime, timedelta ,date
import calendar
class ResUsers(models.Model):
_inherit = "res.users"
assign_update_ids = fields.One2many('task.update','assign_task_id')
created_task_ids = fields.One2many('task.update','create_task_id')
def task_update_email(self):
superuser_id = self.env['res.partner'].browse(SUPERUSER_ID)
user_ids = self.env['res.users'].search([('active','=',True),('share','=',False)])
for user in user_ids:
create_task_ids = self.env['task.update']
task_list_ids = self.env['task.update']
task_ids = self.env['project.task'].search(['|',('user_ids','=',user.id),('create_uid','=',user.id)])
if task_ids:
for task in task_ids.filtered(lambda x : x.user_ids == user):
today = datetime.now().date()
overdue_days = ''
if task.date_deadline:
days=today -task.date_deadline.date()
overdue_days=days.days
task_list_ids += self.env['task.update'].create({'name':task.name,
'date_deadline':task.date_deadline,
'stage_id':task.stage_id.id,
'dueday':overdue_days,
'assign_task_id' : user.id
})
for task in task_ids.filtered(lambda x : x.create_uid == user):
today = datetime.now().date()
overdue_days = ''
if task.date_deadline:
days=today -task.date_deadline.date()
overdue_days=days.days
create_task_ids += self.env['task.update'].create({'name':task.name,
'date_deadline':task.date_deadline,
'stage_id':task.stage_id.id,
'dueday':overdue_days,
'create_task_id' : user.id
})
user.sudo().write({
'created_task_ids' : [(6,0,create_task_ids.ids)],
'assign_update_ids' : [(6,0,task_list_ids.ids)]
})
template_id = self.env['ir.model.data']._xmlid_lookup(
'bi_all_in_one_project_management_system.email_template_task_update')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template([user.id],('subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'scheduled_date'))[user.id]
values['email_to'] = user.partner_id.email
values['res_id'] = False
values['author_id'] = user.partner_id.id
mail_mail_obj = self.env['mail.mail']
mail_create_id = mail_mail_obj.sudo().create(values)
if mail_create_id:
mail_create_id.sudo().send()
return True
def weekly_task_update_email(self):
superuser_id = self.env['res.partner'].browse(SUPERUSER_ID)
user_ids = self.env['res.users'].search([('active', '=', True), ('share', '=', False)])
for user in user_ids:
create_task_ids = self.env['task.update']
task_list_ids = self.env['task.update']
task_ids = self.env['project.task'].search(['|', ('user_ids', '=', user.id), ('create_uid', '=', user.id)])
if task_ids:
today = datetime.now().date() # Get today's date
for task in task_ids.filtered(lambda x: x.user_ids == user):
overdue_days = ''
if task.date_deadline:
days = today - task.date_deadline.date() # Ensure date comparison
overdue_days = days.days
task_list_ids += self.env['task.update'].create({
'name': task.name,
'date_deadline': task.date_deadline,
'stage_id': task.stage_id.id,
'dueday': overdue_days,
'assign_task_id': user.id
})
for task in task_ids.filtered(lambda x: x.create_uid == user):
overdue_days = ''
if task.date_deadline:
days = today - task.date_deadline.date() # Ensure date comparison
overdue_days = days.days
create_task_ids += self.env['task.update'].create({
'name': task.name,
'date_deadline': task.date_deadline,
'stage_id': task.stage_id.id,
'dueday': overdue_days,
'create_task_id': user.id
})
user.sudo().write({
'created_task_ids': [(6, 0, create_task_ids.ids)],
'assign_update_ids': [(6, 0, task_list_ids.ids)]
})
template_id = self.env['ir.model.data']._xmlid_lookup(
'bi_all_in_one_project_management_system.email_template_task_update')[1]
email_template_obj = self.env['mail.template'].browse(template_id)
if template_id:
values = email_template_obj._generate_template(
[user.id], ('subject', 'body_html', 'email_from', 'email_to',
'partner_to', 'email_cc', 'reply_to', 'scheduled_date')
)[user.id]
values['email_to'] = user.partner_id.email
values['res_id'] = False
values['author_id'] = user.partner_id.id
mail_mail_obj = self.env['mail.mail']
mail_create_id = mail_mail_obj.sudo().create(values)
if mail_create_id:
mail_create_id.sudo().send()
return True
class Task_updates(models.Model):
_name='task.update'
_description="Task Updates"
name=fields.Char(string='name')
date_deadline=fields.Date(string='Date Deadline')
stage_id = fields.Many2one('project.task.type', string='Stage')
dueday=fields.Char(string='Overdue')
assign_task_id=fields.Many2one('res.users')
create_task_id=fields.Many2one('res.users')