|
| 1 | +import ast |
| 2 | + |
| 3 | +from odoo import _, api, fields, models |
| 4 | + |
| 5 | + |
| 6 | +class DisableRemainingDaysRule(models.Model): |
| 7 | + _name = "disable.remaining.days.rule" |
| 8 | + _description = "Disable Remaining Days Rule" |
| 9 | + |
| 10 | + @api.constrains("res_model_id") |
| 11 | + def _constrains_res_model_id(self): |
| 12 | + """Ensure that there is only one rule per model""" |
| 13 | + for record in self: |
| 14 | + domain = [ |
| 15 | + ("res_model_id", "=", record.res_model_id.id), |
| 16 | + ("id", "!=", record.id), |
| 17 | + ("company_id", "=", record.company_id.id), |
| 18 | + ] |
| 19 | + if self.search_count(domain) > 0: |
| 20 | + raise models.ValidationError( |
| 21 | + _( |
| 22 | + "There is already a rule for the model '%s'." |
| 23 | + " You cannot create two rules for the same model." |
| 24 | + ) |
| 25 | + % record.res_model_id.name |
| 26 | + ) |
| 27 | + |
| 28 | + @api.model |
| 29 | + def get_all_rules(self): |
| 30 | + """ |
| 31 | + Get all rules like {'model_name': active} |
| 32 | + """ |
| 33 | + # Return one rule per model if some company has it active |
| 34 | + rules_ids = self.search([]) |
| 35 | + if self.get_disable_all_models(): |
| 36 | + # If all models are disabled, return True for all |
| 37 | + return True |
| 38 | + rules = {} |
| 39 | + for rule in rules_ids: |
| 40 | + view_types = rule.get_data_by_view_type() |
| 41 | + fields = rule.get_data_by_field() |
| 42 | + rules[rule.res_model_id.model] = { |
| 43 | + "model": rule.get_data_by_model() |
| 44 | + if not view_types and not fields |
| 45 | + else False, |
| 46 | + "view_types": view_types, |
| 47 | + "fields": fields, |
| 48 | + } |
| 49 | + return rules |
| 50 | + |
| 51 | + def get_data_by_model(self): |
| 52 | + """ |
| 53 | + Get rule data for a specific model |
| 54 | + """ |
| 55 | + self.ensure_one() |
| 56 | + return self.active |
| 57 | + |
| 58 | + def get_data_by_view_type(self): |
| 59 | + """ |
| 60 | + Get rule data for a specific model and view type |
| 61 | + """ |
| 62 | + self.ensure_one() |
| 63 | + diseable_view_types_json = ast.literal_eval( |
| 64 | + self.diseable_view_types_json or "{}" |
| 65 | + ) |
| 66 | + key_list = list(diseable_view_types_json.keys()) |
| 67 | + if not key_list: |
| 68 | + return [] |
| 69 | + return key_list |
| 70 | + |
| 71 | + def get_data_by_field(self): |
| 72 | + """ |
| 73 | + Get rule data for a specific model and field |
| 74 | + """ |
| 75 | + self.ensure_one() |
| 76 | + field_ids = self.date_type_fields_ids |
| 77 | + if not field_ids: |
| 78 | + return [] |
| 79 | + return field_ids.mapped("name") |
| 80 | + |
| 81 | + @api.depends("diseable_view_types_json") |
| 82 | + def _compute_diseable_view_types(self): |
| 83 | + """ |
| 84 | + Get Values of diseable_view_types_json |
| 85 | + """ |
| 86 | + for record in self: |
| 87 | + # Convert chart to json array |
| 88 | + diseable_view_types_json = ast.literal_eval( |
| 89 | + record.diseable_view_types_json or "{}" |
| 90 | + ) |
| 91 | + # Get values of dict |
| 92 | + view_types = [] |
| 93 | + for value in diseable_view_types_json.values(): |
| 94 | + if value: |
| 95 | + view_types.append(value) |
| 96 | + record.diseable_view_types = ", ".join(view_types) |
| 97 | + |
| 98 | + @api.model |
| 99 | + def get_disable_all_models(self): |
| 100 | + """ |
| 101 | + Get all models with the remaining days disabled |
| 102 | + :return: list of model names |
| 103 | + """ |
| 104 | + disable_remaining_days = self.env.company.disable_remaining_days |
| 105 | + if disable_remaining_days: |
| 106 | + return True |
| 107 | + return False |
| 108 | + |
| 109 | + def action_open_set_disable_remaining_days_rule_wizard(self): |
| 110 | + """ |
| 111 | + Open the wizard to set the disable remaining days rule |
| 112 | + """ |
| 113 | + self.ensure_one() |
| 114 | + model_id = self.res_model_id |
| 115 | + view_ids = model_id.view_ids |
| 116 | + if not view_ids: |
| 117 | + raise models.ValidationError( |
| 118 | + _( |
| 119 | + "The model '%s' does not have any views." |
| 120 | + " You cannot set the disable remaining days rule by view type" |
| 121 | + " for this model." |
| 122 | + ) |
| 123 | + % model_id.name |
| 124 | + ) |
| 125 | + IrUiView = self.env["ir.ui.view"] |
| 126 | + # Get selection from ir.ui.view. |
| 127 | + selection = IrUiView._fields["type"].selection |
| 128 | + view_types = [] |
| 129 | + for technical_name, name in selection: |
| 130 | + active = technical_name in ast.literal_eval( |
| 131 | + self.diseable_view_types_json or "{}" |
| 132 | + ) |
| 133 | + view_types.append((name, technical_name, active)) |
| 134 | + wizard_id = ( |
| 135 | + self.env["disable.remaining.days.rule.wizard"] |
| 136 | + .sudo() |
| 137 | + .create( |
| 138 | + { |
| 139 | + "disable_remaining_days_rule_id": self.id, |
| 140 | + "line_ids": [ |
| 141 | + ( |
| 142 | + 0, |
| 143 | + 0, |
| 144 | + { |
| 145 | + "name": name, |
| 146 | + "technical_name": technical_name, |
| 147 | + "active": active, |
| 148 | + }, |
| 149 | + ) |
| 150 | + for name, technical_name, active in view_types |
| 151 | + ], |
| 152 | + } |
| 153 | + ) |
| 154 | + ) |
| 155 | + # Return wizard created |
| 156 | + return { |
| 157 | + "type": "ir.actions.act_window", |
| 158 | + "view_mode": "form", |
| 159 | + "res_model": "disable.remaining.days.rule.wizard", |
| 160 | + "target": "new", |
| 161 | + "res_id": wizard_id.id, |
| 162 | + } |
| 163 | + |
| 164 | + @api.onchange("res_model_id") |
| 165 | + def _onchange_res_model_id(self): |
| 166 | + """ " On change of the model, reset the date field""" |
| 167 | + for record in self: |
| 168 | + record.date_type_fields_ids = False |
| 169 | + |
| 170 | + res_model_id = fields.Many2one( |
| 171 | + "ir.model", |
| 172 | + string="Model", |
| 173 | + required=True, |
| 174 | + ondelete="cascade", |
| 175 | + copy=False, |
| 176 | + help="Select the model where you want to disable the remaining days widget.", |
| 177 | + ) |
| 178 | + res_model_name = fields.Char( |
| 179 | + related="res_model_id.model", |
| 180 | + string="Technical model name", |
| 181 | + store=True, |
| 182 | + ) |
| 183 | + active = fields.Boolean(string="Active record", default=True) |
| 184 | + company_id = fields.Many2one( |
| 185 | + "res.company", |
| 186 | + required=True, |
| 187 | + default=lambda self: self.env.company, |
| 188 | + string="Company", |
| 189 | + ) |
| 190 | + diseable_view_types = fields.Char( |
| 191 | + string="Disable View Types", |
| 192 | + compute="_compute_diseable_view_types", |
| 193 | + store=True, |
| 194 | + help="Name of the view types where the remaining days widget will be disabled.", |
| 195 | + ) |
| 196 | + diseable_view_types_json = fields.Char( |
| 197 | + string="Disable View Types JSON", |
| 198 | + readonly=True, |
| 199 | + help="JSON representation of the view types where the remaining days" |
| 200 | + " widget will be disabled. {'list': List, 'form': Form}", |
| 201 | + ) |
| 202 | + date_type_fields_ids = fields.Many2many( |
| 203 | + "ir.model.fields", |
| 204 | + string="Date/Datetime Fields", |
| 205 | + help="Select the date/datetime fields of the model where you want to disable" |
| 206 | + " the remaining days widget.", |
| 207 | + domain="[('model_id', '=', res_model_id)," |
| 208 | + " ('ttype', 'in', ['date', 'datetime'])]", |
| 209 | + copy=False, |
| 210 | + ) |
0 commit comments