Skip to content

Commit

Permalink
[MIG]: base_tier_validation: Migration to 16
Browse files Browse the repository at this point in the history
  • Loading branch information
bizzappdev committed Dec 6, 2022
1 parent 8979568 commit 145c570
Show file tree
Hide file tree
Showing 27 changed files with 661 additions and 429 deletions.
19 changes: 12 additions & 7 deletions base_tier_validation/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"name": "Base Tier Validation",
"summary": "Implement a validation process based on tiers.",
"version": "15.0.1.2.0",
"version": "16.0.1.0.0",
"development_status": "Mature",
"maintainers": ["LoisRForgeFlow"],
"category": "Tools",
Expand All @@ -25,14 +25,19 @@
],
"assets": {
"web.assets_backend": [
"/base_tier_validation/static/src/js/systray.js",
"/base_tier_validation/static/src/js/tier_review_widget.js",
"/base_tier_validation/static/src/scss/systray.scss",
"/base_tier_validation/static/src/scss/review.scss",
],
"web.assets_qweb": [
"base_tier_validation/static/src/xml/systray.xml",
"base_tier_validation/static/src/xml/tier_review_template.xml",
"/base_tier_validation/static/src/js/main.esm.js",
"/base_tier_validation/static/src/js/ir_model.esm.js",
"/base_tier_validation/static/src/js/systray_service.esm.js",
"/base_tier_validation/static/src/js/systray.esm.js",
"/base_tier_validation/static/src/js/review_groups.esm.js",
"/base_tier_validation/static/src/js/reviewer_menu_view.esm.js",
"/base_tier_validation/static/src/js/tier_review_widget.esm.js",
"/base_tier_validation/static/src/js/review_group_view.esm.js",
"/base_tier_validation/static/src/js/reviewer_menu_container.esm.js",
"/base_tier_validation/static/src/js/review_notification_handler.esm.js",
"/base_tier_validation/static/src/xml/**/*",
],
},
}
12 changes: 7 additions & 5 deletions base_tier_validation/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo import models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

module_base_tier_validation_formula = fields.Boolean(string="Tier Formula")
module_base_tier_validation_forward = fields.Boolean("Tier Forward & Backward")
module_base_tier_validation_server_action = fields.Boolean("Tier Server Action")
module_base_tier_validation_report = fields.Boolean("Tier Reports")
# Activate me back when modules are migrated

# module_base_tier_validation_formula = fields.Boolean(string="Tier Formula")
# module_base_tier_validation_forward = fields.Boolean("Tier Forward & Backward")
# module_base_tier_validation_server_action = fields.Boolean("Tier Server Action")
# module_base_tier_validation_report = fields.Boolean("Tier Reports")
5 changes: 4 additions & 1 deletion base_tier_validation/models/res_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ def review_user_count(self):
.search([("id", "in", reviews.mapped("res_id"))])
.filtered(lambda x: not x.rejected and x.can_review)
)
if len(records):
# if len(records):
for rec in records:
record = self.env[model]
user_reviews[model] = {
"id": rec.id,
"name": record._description,
"model": model,
"icon": modules.module.get_module_icon(record._original_module),
"type": "tier_review",
"pending_count": len(records),
}
return list(user_reviews.values())
Expand Down
16 changes: 16 additions & 0 deletions base_tier_validation/models/tier_review.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import pytz

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError

Expand Down Expand Up @@ -44,6 +46,9 @@ class TierReview(models.Model):
done_by = fields.Many2one(comodel_name="res.users")
requested_by = fields.Many2one(comodel_name="res.users")
reviewed_date = fields.Datetime(string="Validation Date")
reviewed_formated_date = fields.Char(
string="Validation Formated Date", compute="_compute_reviewed_formated_date"
)
has_comment = fields.Boolean(related="definition_id.has_comment", readonly=True)
comment = fields.Char(string="Comments")
can_review = fields.Boolean(
Expand All @@ -56,6 +61,17 @@ class TierReview(models.Model):
related="definition_id.approve_sequence", readonly=True
)

@api.depends_context("tz")
def _compute_reviewed_formated_date(self):
timezone = self._context.get("tz") or self.env.user.partner_id.tz or "UTC"
for review in self:
if not review.reviewed_date:
review.reviewed_formated_date = False
continue
requested_date_utc = pytz.timezone(timezone).localize(review.reviewed_date)
requested_date = requested_date_utc.astimezone(pytz.timezone(timezone))
review.reviewed_formated_date = requested_date.replace(tzinfo=None)

@api.depends("definition_id.approve_sequence")
def _compute_can_review(self):
for record in self:
Expand Down
65 changes: 40 additions & 25 deletions base_tier_validation/models/tier_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.misc import frozendict


class TierValidation(models.AbstractModel):
Expand Down Expand Up @@ -333,7 +334,7 @@ def validate_tier(self):
if self.has_comment:
return self._add_comment("validate", reviews)
self._validate_tier(reviews)
self._update_counter()
self._update_counter({"review_deleted": True})

def reject_tier(self):
self.ensure_one()
Expand All @@ -342,7 +343,7 @@ def reject_tier(self):
if self.has_comment:
return self._add_comment("reject", reviews)
self._rejected_tier(reviews)
self._update_counter()
self._update_counter({"review_deleted": True})

def _notify_rejected_review_body(self):
has_comment = self.review_ids.filtered(
Expand Down Expand Up @@ -424,7 +425,7 @@ def request_validation(self):
"requested_by": self.env.uid,
}
)
self._update_counter()
self._update_counter({"review_created": True})
self._notify_review_requested(created_trs)
return created_trs

Expand All @@ -442,63 +443,77 @@ def _notify_restarted_review(self):
def restart_validation(self):
for rec in self:
if getattr(rec, self._state_field) in self._state_from:
to_update_counter = (
rec.mapped("review_ids").filtered(lambda a: a.status == "pending")
and True
or False
)
rec.mapped("review_ids").unlink()
self._update_counter()
if to_update_counter:
self._update_counter({"review_deleted": True})
rec._notify_restarted_review()

@api.model
def _update_counter(self):
def _update_counter(self, review_counter):
self.review_ids._compute_can_review()
notifications = []
channel = "base.tier.validation"
notifications.append([self.env.user.partner_id, channel, {}])
channel = "base.tier.validation/updated"
notifications.append([self.env.user.partner_id, channel, review_counter])
self.env["bus.bus"]._sendmany(notifications)

def unlink(self):
self.mapped("review_ids").unlink()
return super().unlink()

@api.model
def fields_view_get(
self, view_id=None, view_type="form", toolbar=False, submenu=False
):
res = super().fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
)
def get_view(self, view_id=None, view_type="form", **options):
res = super().get_view(view_id=view_id, view_type=view_type, **options)

View = self.env["ir.ui.view"]

# Override context for postprocessing
if view_id and res.get("base_model", self._name) != self._name:
View = View.with_context(base_model_name=res["base_model"])
if view_type == "form" and not self._tier_validation_manual_config:
doc = etree.XML(res["arch"])
params = {
"state_field": self._state_field,
"state_from": ",".join("'%s'" % state for state in self._state_from),
}
all_models = res["models"].copy()
for node in doc.xpath(self._tier_validation_buttons_xpath):
# By default, after the last button of the header
str_element = self.env["ir.qweb"]._render(
"base_tier_validation.tier_validation_buttons", params
)
new_node = etree.fromstring(str_element)
new_arch, new_models = View.postprocess_and_fields(new_node, self._name)
new_node = etree.fromstring(new_arch)
for new_element in new_node:
node.addnext(new_element)
for node in doc.xpath("/form/sheet"):
str_element = self.env["ir.qweb"]._render(
"base_tier_validation.tier_validation_label", params
)
new_node = etree.fromstring(str_element)
new_arch, new_models = View.postprocess_and_fields(new_node, self._name)
new_node = etree.fromstring(new_arch)
for new_element in new_node:
node.addprevious(new_element)
str_element = self.env["ir.qweb"]._render(
"base_tier_validation.tier_validation_reviews", params
)
node.addnext(etree.fromstring(str_element))
View = self.env["ir.ui.view"]

# Override context for postprocessing
if view_id and res.get("base_model", self._name) != self._name:
View = View.with_context(base_model_name=res["base_model"])
new_arch, new_fields = View.postprocess_and_fields(doc, self._name)
res["arch"] = new_arch
# We don't want to loose previous configuration, so, we only want to add
# the new fields
new_fields.update(res["fields"])
res["fields"] = new_fields
new_node = etree.fromstring(str_element)
new_arch, new_models = View.postprocess_and_fields(new_node, self._name)
for model in new_models:
if model in all_models:
continue
if model not in res["models"]:
all_models[model] = new_models[model]
else:
all_models[model] = res["models"][model]
new_node = etree.fromstring(new_arch)
node.append(new_node)
res["arch"] = etree.tostring(doc)
res["models"] = frozendict(all_models)
return res
29 changes: 29 additions & 0 deletions base_tier_validation/static/src/js/ir_model.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/** @odoo-module **/

import {registerModel} from "@mail/model/model_core";
import {attr, one} from "@mail/model/model_field";

registerModel({
name: "ir.model.review",
fields: {
/**
* Determines the name of the views that are available for this model.
*/
availableWebViews: attr({
compute() {
return ["kanban", "list", "form", "activity"];
},
}),
reviewGroup: one("ReviewGroup", {
inverse: "irModel",
}),
iconUrl: attr(),
id: attr({
identifying: true,
}),
model: attr({
required: true,
}),
name: attr(),
},
});
8 changes: 8 additions & 0 deletions base_tier_validation/static/src/js/main.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @odoo-module **/

import {systrayService} from "@base_tier_validation/js/systray_service.esm";

import {registry} from "@web/core/registry";

const serviceRegistry = registry.category("services");
serviceRegistry.add("review_systray_service", systrayService);
46 changes: 46 additions & 0 deletions base_tier_validation/static/src/js/review_group_view.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/** @odoo-module **/

import {registerModel} from "@mail/model/model_core";
import {one} from "@mail/model/model_field";

registerModel({
name: "ReviewGroupView",
recordMethods: {
/**
* @param {MouseEvent} ev
*/
onClickFilterButton(ev) {
this.reviewMenuViewOwner.update({isOpen: false});
// Fetch the data from the button otherwise fetch the ones from the parent (.o_ActivityMenuView_activityGroup).
const data = _.extend({}, $(ev.currentTarget).data(), $(ev.target).data());
const context = {};

this.env.services.action.doAction(
{
context,
name: data.model_name,
res_model: data.res_model,
search_view_id: [false],
type: "ir.actions.act_window",
domain: [["can_review", "=", true]],
views: this.reviewGroup.irModel.availableWebViews.map(
(viewName) => [false, viewName]
),
},
{
clearBreadcrumbs: true,
}
);
},
},
fields: {
reviewGroup: one("ReviewGroup", {
identifying: true,
inverse: "reviewGroupViews",
}),
reviewMenuViewOwner: one("ReviewerMenuView", {
identifying: true,
inverse: "reviewGroupViews",
}),
},
});
52 changes: 52 additions & 0 deletions base_tier_validation/static/src/js/review_groups.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/** @odoo-module **/

import {registerModel} from "@mail/model/model_core";
import {attr, many, one} from "@mail/model/model_field";

registerModel({
name: "ReviewGroup",
modelMethods: {
convertData(data) {
return {
domain: data.domain,
irModel: {
iconUrl: data.icon,
id: data.id,
model: data.model,
name: data.name,
},
pending_count: data.pending_count,
};
},
},
recordMethods: {
/**
* @private
*/
_onChangePendingCount() {
if (this.type === "tier_review" && this.pending_count === 0) {
this.delete();
}
},
},
fields: {
reviewGroupViews: many("ReviewGroupView", {
inverse: "reviewGroup",
}),
domain: attr(),
irModel: one("ir.model.review", {
identifying: true,
inverse: "reviewGroup",
}),
pending_count: attr({
default: 0,
}),
type: attr(),
},
onChanges: [
{
dependencies: ["pending_count", "type"],
methodName: "_onChangePendingCount",
},
],
});
Loading

0 comments on commit 145c570

Please sign in to comment.