diff --git a/task_manager/__init__.py b/task_manager/__init__.py new file mode 100644 index 00000000000..1793d20a10e --- /dev/null +++ b/task_manager/__init__.py @@ -0,0 +1,46 @@ +from . import models + +from odoo import Command + + +def add_tags(env): + tags = [] + for i in range(10): + tags.append( + { + "name": f"tag_{i + 1}", + "color": i, + } + ) + + env["task.manager.tags"].create(tags) + + +def _pre_init_hook(env): + query = """ + DO $$ + DECLARE + i INT; + new_partner_id INT; + BEGIN + FOR i IN 0..9 LOOP + INSERT INTO res_partner (name, phone, company_id, active, type) + VALUES ('user_' || i, '0987654321', 1, true, 'contact') + RETURNING id INTO new_partner_id; + + INSERT INTO res_users (login, partner_id, company_id, active, notification_type) + VALUES ('user_' || i || '@example.com', new_partner_id, 1, true, 'email'); + END LOOP; + END $$; + """ + env.cr.execute(query) + + +def remove_users_with_mobile_number(env): + target_logins = [f"user_{i}@example.com" for i in range(10)] + users_to_remove = env["res.users"].search([("login", "in", target_logins)]) + + if users_to_remove: + partner_records = users_to_remove.partner_id + users_to_remove.unlink() + partner_records.unlink() diff --git a/task_manager/__manifest__.py b/task_manager/__manifest__.py new file mode 100644 index 00000000000..344ec6d5bdf --- /dev/null +++ b/task_manager/__manifest__.py @@ -0,0 +1,18 @@ +{ + "name": "Task Manager", + "application": True, + "installable": True, + "author": "sngoh", + "depends": ["mail"], + "license": "LGPL-3", + "data": [ + "security/ir.access.csv", + "data/ir_cron_data.xml", + "views/task_manager_tags_view.xml", + "views/task_manager_view.xml", + "views/task_manager_menus.xml", + ], + "pre_init_hook": "_pre_init_hook", + "post_init_hook": "add_tags", + "uninstall_hook": "remove_users_with_mobile_number", +} diff --git a/task_manager/data/ir_cron_data.xml b/task_manager/data/ir_cron_data.xml new file mode 100644 index 00000000000..f56eb37fa09 --- /dev/null +++ b/task_manager/data/ir_cron_data.xml @@ -0,0 +1,20 @@ + + + + + + + Auto Archive Task After 7pm + + code + model._auto_archive() + 1 + days + + + + + + + + diff --git a/task_manager/models/__init__.py b/task_manager/models/__init__.py new file mode 100644 index 00000000000..21ceadcea5e --- /dev/null +++ b/task_manager/models/__init__.py @@ -0,0 +1,2 @@ +from . import task_manager +from . import task_manager_tags diff --git a/task_manager/models/task_manager.py b/task_manager/models/task_manager.py new file mode 100644 index 00000000000..6877d280f90 --- /dev/null +++ b/task_manager/models/task_manager.py @@ -0,0 +1,134 @@ +from odoo import api, Command, fields, models +from odoo.exceptions import UserError + + +class TaskManagerTask(models.Model): + _name = "task.manager" + _inherit = ["mail.thread"] + _description = "Task Manager" + + def _get_default_deadline(self): + return fields.Datetime.add(fields.Datetime.today(), days=3) + + name = fields.Char(tracking=True, required=True) + active = fields.Boolean(default=True) + assigned_user = fields.Many2one("res.users", tracking=True) + deadline = fields.Datetime( + tracking=True, + required=True, + default=lambda self: self._get_default_deadline(), + ) + status = fields.Selection( + string="Status", + selection=[ + ("new", "New"), + ("in_progress", "In Progress"), + ("done", "Done"), + ], + default="new", + tracking=True, + ) + tag_ids = fields.Many2many( + "task.manager.tags", + compute="_compute_assigned_user", + store=True, + ) + days_remaining = fields.Integer(compute="_compute_days_remaining") + count_of_assignes = fields.Integer(compute="_compute_count_of_assignes") + + @api.depends("deadline") + def _compute_days_remaining(self): + for task in self: + task.days_remaining = (task.deadline - fields.Datetime.today()).days + + @api.depends("assigned_user") + def _compute_count_of_assignes(self): + for task in self: + task.count_of_assignes = len(task.assigned_user) + + @api.depends("assigned_user") + def _compute_assigned_user(self): + tag_name = "assigned" + tag = self.env["task.manager.tags"].search([("name", "=", tag_name)], limit=1) + if not tag: + tag = self.env["task.manager.tags"].create({"name": tag_name}) + + unlink_ids = [] + link_ids = [] + + for task in self: + if not task.assigned_user and tag in task.tag_ids: + unlink_ids.append(task.id) + elif task.assigned_user and tag not in task.tag_ids: + link_ids.append(task.id) + + if unlink_ids: + self.browse(unlink_ids).tag_ids = [Command.unlink(tag.id)] + if link_ids: + self.browse(link_ids).tag_ids = [Command.link(tag.id)] + + def write(self, vals): + is_archiving = "active" in vals + for task in self: + if task.status == "done" and not is_archiving: + raise UserError("Cannot update task's details in the Done state.") + + return super().write(vals) + + def quick_archive(self): + if self: + tasks = self.filtered(lambda t: t.status == "done" and t.active) + else: + tasks = self.env["task.manager"].search( + [ + ("status", "=", "done"), + ("active", "=", True), + ], + ) + if tasks: + tasks.action_archive() + + def print_task_count(self): + task_count = self.env["task.manager"].search_count([]) + return { + "effect": { + "fadeout": "slow", + "message": f"{task_count} Tasks are there.", + "img_url": "/web/static/img/smile.svg", + "type": "rainbow_man", + } + } + + def generate_multiple_tasks(self): + tasks = [ + {"name": "Generated Task 1", "deadline": fields.Datetime.today()}, + {"name": "Generated Task 2", "deadline": fields.Datetime.today()}, + ] + self.env["task.manager"].create(tasks) + + def _auto_archive(self): + done_tasks = self.env["task.manager"].search( + [ + ("status", "=", "done"), + ("active", "=", True), + ], + ) + done_tasks.action_archive() + + @api.autovacuum + def _gc_delete_archive_task(self): + old_archived_tasks = self.env["task.manager"].search( + [ + ("active", "=", False), + ( + "create_date", + "<", + fields.Datetime.subtract( + fields.Datetime.today(), + days=31, + ), + ), + ], + ) + # breakpoint() + old_archived_tasks.unlink() diff --git a/task_manager/models/task_manager_tags.py b/task_manager/models/task_manager_tags.py new file mode 100644 index 00000000000..814fa75c462 --- /dev/null +++ b/task_manager/models/task_manager_tags.py @@ -0,0 +1,15 @@ +from odoo import fields, models + + +class TaskManagerTags(models.Model): + _name = "task.manager.tags" + _description = "Tags for Tasks" + _order = "name" + + name = fields.Char(required=True) + color = fields.Integer() + + _check_unique_tag = models.Constraint( + "UNIQUE(name)", + "A property tag name must be unique", + ) diff --git a/task_manager/security/ir.access.csv b/task_manager/security/ir.access.csv new file mode 100644 index 00000000000..542acada176 --- /dev/null +++ b/task_manager/security/ir.access.csv @@ -0,0 +1,3 @@ +id,name,model_id,group_id/id,operation,domain +access_task_manager,access_task_manager,task.manager,base.group_user,crud, +access_task_manager_tags,access_task_manager_tags,task.manager.tags,base.group_user,crud, diff --git a/task_manager/views/task_manager_menus.xml b/task_manager/views/task_manager_menus.xml new file mode 100644 index 00000000000..545f8a7b31b --- /dev/null +++ b/task_manager/views/task_manager_menus.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/task_manager/views/task_manager_tags_view.xml b/task_manager/views/task_manager_tags_view.xml new file mode 100644 index 00000000000..f4162f560bc --- /dev/null +++ b/task_manager/views/task_manager_tags_view.xml @@ -0,0 +1,37 @@ + + + + + task.manager.tags.view.list + task.manager.tags + + + + + + + + + + task.manager.tags.view.form + task.manager.tags + +
+ +

+ +

+ + +
+
+
+
+ + + Task Tags + task.manager.tags + list,form + + +
diff --git a/task_manager/views/task_manager_view.xml b/task_manager/views/task_manager_view.xml new file mode 100644 index 00000000000..d3f2d92d731 --- /dev/null +++ b/task_manager/views/task_manager_view.xml @@ -0,0 +1,85 @@ + + + + + task.manager.list + task.manager + + +
+
+ + + + + + + +
+
+
+ + + task.manager.form + task.manager + +
+
+ +
+ +

+ +

+ + + + + + + + + + + +
+ + +
+
+ + + task.manager.view.kanban + task.manager + + + + + + + + + + + Tasks + task.manager + list,form,kanban + + +