From f6d23b0cc91a93b42c9cede1bf3028f6946f9a6d Mon Sep 17 00:00:00 2001 From: SilvioC2C Date: Mon, 2 Aug 2021 16:27:15 +0200 Subject: [PATCH 01/15] [14.0] web_m2x_options_manager: New module to manage create/edit options from interface --- web_m2x_options_manager/__init__.py | 4 + web_m2x_options_manager/__manifest__.py | 23 +++ .../demo/res_partner_demo_view.xml | 29 +++ web_m2x_options_manager/models/__init__.py | 6 + web_m2x_options_manager/models/ir_model.py | 52 ++++++ web_m2x_options_manager/models/ir_ui_view.py | 20 +++ .../models/m2x_create_edit_option.py | 170 ++++++++++++++++++ .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 2 + web_m2x_options_manager/readme/USAGE.rst | 7 + .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes web_m2x_options_manager/tests/__init__.py | 4 + .../tests/test_m2x_create_edit_option.py | 109 +++++++++++ web_m2x_options_manager/views/ir_model.xml | 37 ++++ 15 files changed, 469 insertions(+) create mode 100644 web_m2x_options_manager/__init__.py create mode 100644 web_m2x_options_manager/__manifest__.py create mode 100644 web_m2x_options_manager/demo/res_partner_demo_view.xml create mode 100644 web_m2x_options_manager/models/__init__.py create mode 100644 web_m2x_options_manager/models/ir_model.py create mode 100644 web_m2x_options_manager/models/ir_ui_view.py create mode 100644 web_m2x_options_manager/models/m2x_create_edit_option.py create mode 100644 web_m2x_options_manager/readme/CONTRIBUTORS.rst create mode 100644 web_m2x_options_manager/readme/DESCRIPTION.rst create mode 100644 web_m2x_options_manager/readme/USAGE.rst create mode 100644 web_m2x_options_manager/security/ir.model.access.csv create mode 100644 web_m2x_options_manager/static/description/icon.png create mode 100644 web_m2x_options_manager/tests/__init__.py create mode 100644 web_m2x_options_manager/tests/test_m2x_create_edit_option.py create mode 100644 web_m2x_options_manager/views/ir_model.xml diff --git a/web_m2x_options_manager/__init__.py b/web_m2x_options_manager/__init__.py new file mode 100644 index 000000000..2a7f1c54a --- /dev/null +++ b/web_m2x_options_manager/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/web_m2x_options_manager/__manifest__.py b/web_m2x_options_manager/__manifest__.py new file mode 100644 index 000000000..68d81d280 --- /dev/null +++ b/web_m2x_options_manager/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Web M2X Options Manager", + "summary": 'Adds an interface to manage the "Create" and' + ' "Create and Edit" options for specific models and' + " fields.", + "version": "14.0.1.0.0", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Web", + "data": [ + "security/ir.model.access.csv", + "views/ir_model.xml", + ], + "demo": [ + "demo/res_partner_demo_view.xml", + ], + "depends": ["base", "web_m2x_options"], + "website": "https://github.com/OCA/web", + "installable": True, +} diff --git a/web_m2x_options_manager/demo/res_partner_demo_view.xml b/web_m2x_options_manager/demo/res_partner_demo_view.xml new file mode 100644 index 000000000..8a53c630c --- /dev/null +++ b/web_m2x_options_manager/demo/res_partner_demo_view.xml @@ -0,0 +1,29 @@ + + + + + res.partner.demo.form.view + res.partner + 1000 + +
+ + + + + + + + + + + + + + + +
+
+
+ +
diff --git a/web_m2x_options_manager/models/__init__.py b/web_m2x_options_manager/models/__init__.py new file mode 100644 index 000000000..699352799 --- /dev/null +++ b/web_m2x_options_manager/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ir_model +from . import ir_ui_view +from . import m2x_create_edit_option diff --git a/web_m2x_options_manager/models/ir_model.py b/web_m2x_options_manager/models/ir_model.py new file mode 100644 index 000000000..e51446572 --- /dev/null +++ b/web_m2x_options_manager/models/ir_model.py @@ -0,0 +1,52 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class IrModel(models.Model): + _inherit = "ir.model" + + m2x_create_edit_option_ids = fields.One2many( + "m2x.create.edit.option", + "model_id", + ) + + def button_empty(self): + for ir_model in self: + ir_model._empty_m2x_create_edit_option() + + def button_fill(self): + for ir_model in self: + ir_model._fill_m2x_create_edit_option() + + def _empty_m2x_create_edit_option(self): + """Removes every option for model ``self``""" + self.ensure_one() + self.m2x_create_edit_option_ids.unlink() + + def _fill_m2x_create_edit_option(self): + """Adds every missing field option for model ``self``""" + self.ensure_one() + existing = self.m2x_create_edit_option_ids.mapped("field_id") + valid = self.field_id.filtered(lambda f: f.ttype in ("many2many", "many2one")) + vals = [(0, 0, {"field_id": f.id}) for f in valid - existing] + self.write({"m2x_create_edit_option_ids": vals}) + + +class IrModelFields(models.Model): + _inherit = "ir.model.fields" + + @api.model + def name_search(self, name="", args=None, operator="ilike", limit=100): + res = super().name_search(name, args, operator, limit) + if not (name and self.env.context.get("search_by_technical_name")): + return res + domain = list(args or []) + [("name", operator, name)] + new_fids = self.search(domain, limit=limit).ids + for fid in [x[0] for x in res]: + if fid not in new_fids: + new_fids.append(fid) + if limit and limit > 0: + new_fids = new_fids[:limit] + return self.browse(new_fids).sudo().name_get() diff --git a/web_m2x_options_manager/models/ir_ui_view.py b/web_m2x_options_manager/models/ir_ui_view.py new file mode 100644 index 000000000..172ef6696 --- /dev/null +++ b/web_m2x_options_manager/models/ir_ui_view.py @@ -0,0 +1,20 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class IrUiView(models.Model): + _inherit = "ir.ui.view" + + def postprocess(self, node, current_node_path, editable, name_manager): + res = super().postprocess(node, current_node_path, editable, name_manager) + if node.tag == "field": + mname = name_manager.Model._name + fname = node.attrib["name"] + field = self.env[mname]._fields.get(fname) + if field and field.type in ("many2many", "many2one"): + rec = self.env["m2x.create.edit.option"].get(mname, field.name) + if rec: + rec._apply_options(node) + return res diff --git a/web_m2x_options_manager/models/m2x_create_edit_option.py b/web_m2x_options_manager/models/m2x_create_edit_option.py new file mode 100644 index 000000000..07ae01e77 --- /dev/null +++ b/web_m2x_options_manager/models/m2x_create_edit_option.py @@ -0,0 +1,170 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.cache import ormcache +from odoo.tools.safe_eval import safe_eval + + +class M2xCreateEditOption(models.Model): + _name = "m2x.create.edit.option" + _description = "Manage Options 'Create/Edit' For Fields" + + field_id = fields.Many2one( + "ir.model.fields", + domain=[("ttype", "in", ("many2many", "many2one"))], + ondelete="cascade", + required=True, + string="Field", + ) + + field_name = fields.Char( + related="field_id.name", + store=True, + string="Field Name", + ) + + model_id = fields.Many2one( + "ir.model", + ondelete="cascade", + required=True, + string="Model", + ) + + model_name = fields.Char( + compute="_compute_model_name", + inverse="_inverse_model_name", + store=True, + string="Model Name", + ) + + option_create = fields.Selection( + [ + ("none", "Do nothing"), + ("set_true", "Add"), + ("force_true", "Force Add"), + ("set_false", "Remove"), + ("force_false", "Force Remove"), + ], + default="set_false", + help="Defines behaviour for 'Create' option:\n" + "* Do nothing: nothing is done\n" + "* Add/Remove: option 'Create' is set to True/False only if not" + " already present in view definition\n" + "* Force Add/Remove: option 'Create' is always set to True/False," + " overriding any pre-existing option", + required=True, + string="Create Option", + ) + + option_create_edit = fields.Selection( + [ + ("none", "Do nothing"), + ("set_true", "Add"), + ("force_true", "Force Add"), + ("set_false", "Remove"), + ("force_false", "Force Remove"), + ], + default="set_false", + help="Defines behaviour for 'Create & Edit' option:\n" + "* Do nothing: nothing is done\n" + "* Add/Remove: option 'Create & Edit' is set to True/False only if not" + " already present in view definition\n" + "* Force Add/Remove: option 'Create & Edit' is always set to" + " True/False, overriding any pre-existing option", + required=True, + string="Create & Edit Option", + ) + + _sql_constraints = [ + ( + "model_field_uniqueness", + "unique(field_id,model_id)", + "Options must be unique for each model/field couple!", + ), + ] + + @api.model_create_multi + def create(self, vals_list): + # Clear cache to avoid misbehavior from cached :meth:`_get()` + type(self)._get.clear_cache(self.browse()) + return super().create(vals_list) + + def write(self, vals): + # Clear cache to avoid misbehavior from cached :meth:`_get()` + type(self)._get.clear_cache(self.browse()) + return super().write(vals) + + def unlink(self): + # Clear cache to avoid misbehavior from cached :meth:`_get()` + type(self)._get.clear_cache(self.browse()) + return super().unlink() + + @api.depends("model_id") + def _compute_model_name(self): + for opt in self: + opt.model_name = opt.model_id.model + + def _inverse_model_name(self): + getter = self.env["ir.model"]._get + for opt in self: + # This also works as a constrain: if ``model_name`` is not a + # valid model name, then ``model_id`` will be emptied, but it's + # a required field! + opt.model_id = getter(opt.model_name) + + @api.constrains("model_id", "field_id") + def _check_field_in_model(self): + for opt in self: + if opt.field_id.model_id != opt.model_id: + msg = _("'%s' is not a valid field for model '%s'!") + raise ValidationError(msg % (opt.field_name, opt.model_name)) + + @api.constrains("field_id") + def _check_field_type(self): + ttypes = ("many2many", "many2one") + if any(o.field_id.ttype not in ttypes for o in self): + msg = _("Only Many2many and Many2one fields can be chosen!") + raise ValidationError(msg) + + def _apply_options(self, node): + """Applies options ``self`` to ``node``""" + self.ensure_one() + options = node.attrib.get("options") or {} + if isinstance(options, str): + options = safe_eval(options, dict(self.env.context or [])) or {} + for k in ("create", "create_edit"): + opt = self["option_%s" % k] + if opt == "none": + continue + mode, val = opt.split("_") + if mode == "force" or k not in options: + options[k] = val == "true" + node.set("options", str(options)) + + @api.model + def get(self, model_name, field_name): + """Returns specific record for ``field_name`` in ``model_name`` + + :param str model_name: technical model name (i.e. "sale.order") + :param str field_name: technical field name (i.e. "partner_id") + """ + return self.browse(self._get(model_name, field_name)) + + @api.model + @ormcache("model_name", "field_name") + def _get(self, model_name, field_name): + """Inner implementation of ``get``. + An ID is returned to allow caching (see :class:`ormcache`); :meth:`get` + will then convert it to a proper record. + + :param str model_name: technical model name (i.e. "sale.order") + :param str field_name: technical field name (i.e. "partner_id") + """ + dom = [ + ("model_name", "=", model_name), + ("field_name", "=", field_name), + ] + # `_check_field_model_uniqueness()` grants uniqueness if existing + return self.search(dom, limit=1).id diff --git a/web_m2x_options_manager/readme/CONTRIBUTORS.rst b/web_m2x_options_manager/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..02ad49af4 --- /dev/null +++ b/web_m2x_options_manager/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Camptocamp `__: + + * Silvio Gregorini diff --git a/web_m2x_options_manager/readme/DESCRIPTION.rst b/web_m2x_options_manager/readme/DESCRIPTION.rst new file mode 100644 index 000000000..8a8a770d3 --- /dev/null +++ b/web_m2x_options_manager/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Allows managing the "Create..." and "Create and Edit..." options for `Many2one` +and `Many2many` fields directly from the `ir.model` form view. diff --git a/web_m2x_options_manager/readme/USAGE.rst b/web_m2x_options_manager/readme/USAGE.rst new file mode 100644 index 000000000..a68d0f1b6 --- /dev/null +++ b/web_m2x_options_manager/readme/USAGE.rst @@ -0,0 +1,7 @@ +Go to Settings > Technical > Models. + +Choose the model you wish to edit, and open its form view. Go to the +"Create/Edit Options" tab, and add the fields you want to manage. + +Button "Fill" will add every missing field to the options. +Button "Empty" will remove every option. diff --git a/web_m2x_options_manager/security/ir.model.access.csv b/web_m2x_options_manager/security/ir.model.access.csv new file mode 100644 index 000000000..796d5b922 --- /dev/null +++ b/web_m2x_options_manager/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_m2x_create_edit_option_user,access_m2x_create_edit_option_user,model_m2x_create_edit_option,base.group_user,1,0,0,0 +access_m2x_create_edit_option_system,access_m2x_create_edit_option_system,model_m2x_create_edit_option,base.group_system,1,1,1,1 diff --git a/web_m2x_options_manager/static/description/icon.png b/web_m2x_options_manager/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/web_m2x_options_manager/tests/__init__.py b/web_m2x_options_manager/tests/__init__.py new file mode 100644 index 000000000..f803479e2 --- /dev/null +++ b/web_m2x_options_manager/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_m2x_create_edit_option diff --git a/web_m2x_options_manager/tests/test_m2x_create_edit_option.py b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py new file mode 100644 index 000000000..de6e1d8c0 --- /dev/null +++ b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py @@ -0,0 +1,109 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from lxml import etree + +from odoo.exceptions import ValidationError +from odoo.tests.common import SavepointCase +from odoo.tools.safe_eval import safe_eval + + +class TestM2xCreateEditOption(SavepointCase): + def setUp(self): + super(TestM2xCreateEditOption, self).setUp() + ref = self.env.ref + # View to be used + self.view = ref("web_m2x_options_manager.res_partner_demo_form_view") + # res.partner model and fields + self.res_partner_model = ref("base.model_res_partner") + self.categ_field = ref("base.field_res_partner__category_id") + self.title_field = ref("base.field_res_partner__title") + self.users_field = ref("base.field_res_partner__user_ids") + # res.users model and fields + self.res_users_model = ref("base.model_res_users") + self.company_field = ref("base.field_res_users__company_id") + # Options setup + self.title_opt = self.env["m2x.create.edit.option"].create( + { + "field_id": self.title_field.id, + "model_id": self.res_partner_model.id, + "option_create": "set_true", + "option_create_edit": "set_true", + } + ) + self.categories_opt = self.env["m2x.create.edit.option"].create( + { + "field_id": self.categ_field.id, + "model_id": self.res_partner_model.id, + "option_create": "set_true", + "option_create_edit": "set_true", + } + ) + self.company_opt = self.env["m2x.create.edit.option"].create( + { + "field_id": self.company_field.id, + "model_id": self.res_users_model.id, + "option_create": "force_true", + "option_create_edit": "set_true", + } + ) + + def test_errors(self): + with self.assertRaises(ValidationError): + # Fails ``_check_field_in_model``: model is res.partner, field is + # res.users's company_id + self.env["m2x.create.edit.option"].create( + { + "field_id": self.company_field.id, + "model_id": self.res_partner_model.id, + "option_create": "set_true", + "option_create_edit": "set_true", + } + ) + with self.assertRaises(ValidationError): + # Fails ``_check_field_type``: users_field is a One2many + self.env["m2x.create.edit.option"].create( + { + "field_id": self.users_field.id, + "model_id": self.res_partner_model.id, + "option_create": "set_true", + "option_create_edit": "set_true", + } + ) + + def test_apply_options(self): + res = self.env["res.partner"].fields_view_get(self.view.id) + + # Check fields on res.partner form view + form_arch = res["arch"] + form_doc = etree.XML(form_arch) + title_node = form_doc.xpath("//field[@name='title']")[0] + self.assertEqual( + safe_eval(title_node.attrib.get("options"), nocopy=True), + {"create": True, "create_edit": True}, + ) + categ_node = form_doc.xpath("//field[@name='category_id']")[0] + self.assertEqual( + safe_eval(categ_node.attrib.get("options"), nocopy=True), + {"create": False, "create_edit": True}, + ) + + # Check fields on res.users tree view (contained in ``user_ids`` field) + tree_arch = res["fields"]["user_ids"]["views"]["tree"]["arch"] + tree_doc = etree.XML(tree_arch) + company_node = tree_doc.xpath("//field[@name='company_id']")[0] + self.assertEqual( + safe_eval(company_node.attrib.get("options"), nocopy=True), + {"create": True, "create_edit": True}, + ) + + # Update options, check that node has been updated too + self.title_opt.option_create_edit = "force_false" + res = self.env["res.partner"].fields_view_get(self.view.id) + form_arch = res["arch"] + form_doc = etree.XML(form_arch) + title_node = form_doc.xpath("//field[@name='title']")[0] + self.assertEqual( + safe_eval(title_node.attrib.get("options"), nocopy=True), + {"create": True, "create_edit": False}, + ) diff --git a/web_m2x_options_manager/views/ir_model.xml b/web_m2x_options_manager/views/ir_model.xml new file mode 100644 index 000000000..d05011571 --- /dev/null +++ b/web_m2x_options_manager/views/ir_model.xml @@ -0,0 +1,37 @@ + + + + + view.model.form.inherit + ir.model + + + + +
+
+ + + + + + + + +
+
+
+
+ +
From 06657da209251db5e9c025e989f7644fc1c224d6 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Thu, 14 Oct 2021 07:49:30 +0000 Subject: [PATCH 02/15] [UPD] Update web_m2x_options_manager.pot --- .../i18n/web_m2x_options_manager.pot | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 web_m2x_options_manager/i18n/web_m2x_options_manager.pot diff --git a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot new file mode 100644 index 000000000..40c6acd7d --- /dev/null +++ b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot @@ -0,0 +1,198 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_m2x_options_manager +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: web_m2x_options_manager +#: code:addons/web_m2x_options_manager/models/m2x_create_edit_option.py:0 +#, python-format +msgid "'%s' is not a valid field for model '%s'!" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create__set_true +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create_edit__set_true +msgid "Add" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit +msgid "Create & Edit Option" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create +msgid "Create Option" +msgstr "" + +#. module: web_m2x_options_manager +#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit +msgid "Create/Edit Options" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__create_uid +msgid "Created by" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__create_date +msgid "Created on" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,help:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit +msgid "" +"Defines behaviour for 'Create & Edit' option:\n" +"* Do nothing: nothing is done\n" +"* Add/Remove: option 'Create & Edit' is set to True/False only if not already present in view definition\n" +"* Force Add/Remove: option 'Create & Edit' is always set to True/False, overriding any pre-existing option" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,help:web_m2x_options_manager.field_m2x_create_edit_option__option_create +msgid "" +"Defines behaviour for 'Create' option:\n" +"* Do nothing: nothing is done\n" +"* Add/Remove: option 'Create' is set to True/False only if not already present in view definition\n" +"* Force Add/Remove: option 'Create' is always set to True/False, overriding any pre-existing option" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__display_name +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__display_name +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__display_name +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__display_name +msgid "Display Name" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create__none +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create_edit__none +msgid "Do nothing" +msgstr "" + +#. module: web_m2x_options_manager +#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit +msgid "Empty" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__field_id +msgid "Field" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__field_name +msgid "Field Name" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model,name:web_m2x_options_manager.model_ir_model_fields +msgid "Fields" +msgstr "" + +#. module: web_m2x_options_manager +#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit +msgid "Fields Description" +msgstr "" + +#. module: web_m2x_options_manager +#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit +msgid "Fill" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create__force_true +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create_edit__force_true +msgid "Force Add" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create__force_false +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create_edit__force_false +msgid "Force Remove" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__id +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__id +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__id +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__id +msgid "ID" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model____last_update +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields____last_update +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view____last_update +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option____last_update +msgid "Last Modified on" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__write_date +msgid "Last Updated on" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__m2x_create_edit_option_ids +msgid "M2X Create Edit Option" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model,name:web_m2x_options_manager.model_m2x_create_edit_option +msgid "Manage Options 'Create/Edit' For Fields" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__model_id +msgid "Model" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__model_name +msgid "Model Name" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model,name:web_m2x_options_manager.model_ir_model +msgid "Models" +msgstr "" + +#. module: web_m2x_options_manager +#: code:addons/web_m2x_options_manager/models/m2x_create_edit_option.py:0 +#, python-format +msgid "Only Many2many and Many2one fields can be chosen!" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.constraint,message:web_m2x_options_manager.constraint_m2x_create_edit_option_model_field_uniqueness +msgid "Options must be unique for each model/field couple!" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create__set_false +#: model:ir.model.fields.selection,name:web_m2x_options_manager.selection__m2x_create_edit_option__option_create_edit__set_false +msgid "Remove" +msgstr "" + +#. module: web_m2x_options_manager +#: model:ir.model,name:web_m2x_options_manager.model_ir_ui_view +msgid "View" +msgstr "" From 3e0ba44ab0b908552d8679069a37a082569a85c5 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 14 Oct 2021 08:02:34 +0000 Subject: [PATCH 03/15] [UPD] README.rst --- web_m2x_options_manager/README.rst | 87 ++++ .../static/description/index.html | 432 ++++++++++++++++++ 2 files changed, 519 insertions(+) create mode 100644 web_m2x_options_manager/README.rst create mode 100644 web_m2x_options_manager/static/description/index.html diff --git a/web_m2x_options_manager/README.rst b/web_m2x_options_manager/README.rst new file mode 100644 index 000000000..0355c3525 --- /dev/null +++ b/web_m2x_options_manager/README.rst @@ -0,0 +1,87 @@ +======================= +Web M2X Options Manager +======================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github + :target: https://github.com/OCA/web/tree/14.0/web_m2x_options_manager + :alt: OCA/web +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/web-14-0/web-14-0-web_m2x_options_manager + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/162/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Allows managing the "Create..." and "Create and Edit..." options for `Many2one` +and `Many2many` fields directly from the `ir.model` form view. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Go to Settings > Technical > Models. + +Choose the model you wish to edit, and open its form view. Go to the +"Create/Edit Options" tab, and add the fields you want to manage. + +Button "Fill" will add every missing field to the options. +Button "Empty" will remove every option. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* `Camptocamp `__: + + * Silvio Gregorini + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/web `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_m2x_options_manager/static/description/index.html b/web_m2x_options_manager/static/description/index.html new file mode 100644 index 000000000..66f76efac --- /dev/null +++ b/web_m2x_options_manager/static/description/index.html @@ -0,0 +1,432 @@ + + + + + + +Web M2X Options Manager + + + +
+

Web M2X Options Manager

+ + +

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runbot

+

Allows managing the “Create…” and “Create and Edit…” options for Many2one +and Many2many fields directly from the ir.model form view.

+

Table of contents

+ +
+

Usage

+

Go to Settings > Technical > Models.

+

Choose the model you wish to edit, and open its form view. Go to the +“Create/Edit Options” tab, and add the fields you want to manage.

+

Button “Fill” will add every missing field to the options. +Button “Empty” will remove every option.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/web project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + From 7a7030cf20bb443dde10d33afbf13c5809f8aa09 Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Mon, 18 Oct 2021 13:12:56 +0300 Subject: [PATCH 04/15] [UPD] web_m2x_options_manager: Add option to prevent Create/Edit wizard to pop up --- .../i18n/web_m2x_options_manager.pot | 12 ++++++++++ .../models/m2x_create_edit_option.py | 10 ++++++++ .../tests/test_m2x_create_edit_option.py | 24 +++++++++++++++++++ web_m2x_options_manager/views/ir_model.xml | 1 + 4 files changed, 47 insertions(+) diff --git a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot index 40c6acd7d..3559937a3 100644 --- a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot +++ b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot @@ -25,6 +25,11 @@ msgstr "" msgid "Add" msgstr "" +#. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit_wizard +msgid "Create & Edit Wizard" +msgstr "" + #. module: web_m2x_options_manager #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit msgid "Create & Edit Option" @@ -50,6 +55,13 @@ msgstr "" msgid "Created on" msgstr "" +#. module: web_m2x_options_manager +#: model:ir.model.fields,help:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit_wizard +msgid "" +"Defines behaviour for 'Create & Edit' Wizard\n" +"Set to False to prevent 'Create & Edit' Wizard to pop up" +msgstr "" + #. module: web_m2x_options_manager #: model:ir.model.fields,help:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit msgid "" diff --git a/web_m2x_options_manager/models/m2x_create_edit_option.py b/web_m2x_options_manager/models/m2x_create_edit_option.py index 07ae01e77..29c4a7b56 100644 --- a/web_m2x_options_manager/models/m2x_create_edit_option.py +++ b/web_m2x_options_manager/models/m2x_create_edit_option.py @@ -77,6 +77,13 @@ class M2xCreateEditOption(models.Model): string="Create & Edit Option", ) + option_create_edit_wizard = fields.Boolean( + default=True, + help="Defines behaviour for 'Create & Edit' Wizard\n" + "Set to False to prevent 'Create & Edit' Wizard to pop up", + string="Create & Edit Wizard", + ) + _sql_constraints = [ ( "model_field_uniqueness", @@ -142,6 +149,9 @@ class M2xCreateEditOption(models.Model): if mode == "force" or k not in options: options[k] = val == "true" node.set("options", str(options)) + if not self.option_create_edit_wizard: + node.set("can_create", "false") + node.set("can_write", "false") @api.model def get(self, model_name, field_name): diff --git a/web_m2x_options_manager/tests/test_m2x_create_edit_option.py b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py index de6e1d8c0..27640df5b 100644 --- a/web_m2x_options_manager/tests/test_m2x_create_edit_option.py +++ b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py @@ -29,6 +29,7 @@ class TestM2xCreateEditOption(SavepointCase): "model_id": self.res_partner_model.id, "option_create": "set_true", "option_create_edit": "set_true", + "option_create_edit_wizard": True, } ) self.categories_opt = self.env["m2x.create.edit.option"].create( @@ -37,6 +38,7 @@ class TestM2xCreateEditOption(SavepointCase): "model_id": self.res_partner_model.id, "option_create": "set_true", "option_create_edit": "set_true", + "option_create_edit_wizard": True, } ) self.company_opt = self.env["m2x.create.edit.option"].create( @@ -45,6 +47,7 @@ class TestM2xCreateEditOption(SavepointCase): "model_id": self.res_users_model.id, "option_create": "force_true", "option_create_edit": "set_true", + "option_create_edit_wizard": False, } ) @@ -82,11 +85,25 @@ class TestM2xCreateEditOption(SavepointCase): safe_eval(title_node.attrib.get("options"), nocopy=True), {"create": True, "create_edit": True}, ) + self.assertEqual( + ( + title_node.attrib.get("can_create"), + title_node.attrib.get("can_write"), + ), + ("true", "true"), + ) categ_node = form_doc.xpath("//field[@name='category_id']")[0] self.assertEqual( safe_eval(categ_node.attrib.get("options"), nocopy=True), {"create": False, "create_edit": True}, ) + self.assertEqual( + ( + categ_node.attrib.get("can_create"), + categ_node.attrib.get("can_write"), + ), + ("true", "true"), + ) # Check fields on res.users tree view (contained in ``user_ids`` field) tree_arch = res["fields"]["user_ids"]["views"]["tree"]["arch"] @@ -96,6 +113,13 @@ class TestM2xCreateEditOption(SavepointCase): safe_eval(company_node.attrib.get("options"), nocopy=True), {"create": True, "create_edit": True}, ) + self.assertEqual( + ( + company_node.attrib.get("can_create"), + company_node.attrib.get("can_write"), + ), + ("false", "false"), + ) # Update options, check that node has been updated too self.title_opt.option_create_edit = "force_false" diff --git a/web_m2x_options_manager/views/ir_model.xml b/web_m2x_options_manager/views/ir_model.xml index d05011571..f0e6502d4 100644 --- a/web_m2x_options_manager/views/ir_model.xml +++ b/web_m2x_options_manager/views/ir_model.xml @@ -27,6 +27,7 @@ /> + From 33b2953b5eae8672384c00201dc3d8860ea40ecf Mon Sep 17 00:00:00 2001 From: oca-travis Date: Fri, 22 Oct 2021 09:58:15 +0000 Subject: [PATCH 05/15] [UPD] Update web_m2x_options_manager.pot --- web_m2x_options_manager/i18n/web_m2x_options_manager.pot | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot index 3559937a3..1014c9ca5 100644 --- a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot +++ b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot @@ -26,13 +26,13 @@ msgid "Add" msgstr "" #. module: web_m2x_options_manager -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit_wizard -msgid "Create & Edit Wizard" +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit +msgid "Create & Edit Option" msgstr "" #. module: web_m2x_options_manager -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit -msgid "Create & Edit Option" +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__option_create_edit_wizard +msgid "Create & Edit Wizard" msgstr "" #. module: web_m2x_options_manager From 2bcc7a19996e3fc39db634831e89442978238fb8 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 22 Oct 2021 10:16:58 +0000 Subject: [PATCH 06/15] web_m2x_options_manager 14.0.1.1.0 --- web_m2x_options_manager/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_m2x_options_manager/__manifest__.py b/web_m2x_options_manager/__manifest__.py index 68d81d280..3a39a7366 100644 --- a/web_m2x_options_manager/__manifest__.py +++ b/web_m2x_options_manager/__manifest__.py @@ -6,7 +6,7 @@ "summary": 'Adds an interface to manage the "Create" and' ' "Create and Edit" options for specific models and' " fields.", - "version": "14.0.1.0.0", + "version": "14.0.1.1.0", "author": "Camptocamp, Odoo Community Association (OCA)", "license": "AGPL-3", "category": "Web", From ece722d5d7fa9ae138a9f8328bde9f03fa51123d Mon Sep 17 00:00:00 2001 From: Germana Date: Mon, 15 Nov 2021 15:36:05 -0400 Subject: [PATCH 07/15] [MIG] web_m2x_options_manager: Migration to 15.0 - Fix postprocess inherit (removed from v15), and use _postprocess_tag_field for create/edit options: In v14 it worked with inheriting the "postprocess" method because in each recursive call it passed a section of the view, in the way that it went through all the child nodes of the root node, and passed through the fields, and now in v15 the method "_postprocess_view "it just does the while, and we never go through the nodes. - Fix pylint errors: xml-deprecated-tree-attributte, attribute-string-redundant, translation-positional-used --- web_m2x_options_manager/__manifest__.py | 2 +- web_m2x_options_manager/models/ir_ui_view.py | 6 +++--- web_m2x_options_manager/models/m2x_create_edit_option.py | 9 ++++++--- .../tests/test_m2x_create_edit_option.py | 4 ++-- web_m2x_options_manager/views/ir_model.xml | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/web_m2x_options_manager/__manifest__.py b/web_m2x_options_manager/__manifest__.py index 3a39a7366..623712a8b 100644 --- a/web_m2x_options_manager/__manifest__.py +++ b/web_m2x_options_manager/__manifest__.py @@ -6,7 +6,7 @@ "summary": 'Adds an interface to manage the "Create" and' ' "Create and Edit" options for specific models and' " fields.", - "version": "14.0.1.1.0", + "version": "15.0.1.0.0", "author": "Camptocamp, Odoo Community Association (OCA)", "license": "AGPL-3", "category": "Web", diff --git a/web_m2x_options_manager/models/ir_ui_view.py b/web_m2x_options_manager/models/ir_ui_view.py index 172ef6696..66393622d 100644 --- a/web_m2x_options_manager/models/ir_ui_view.py +++ b/web_m2x_options_manager/models/ir_ui_view.py @@ -7,10 +7,10 @@ from odoo import models class IrUiView(models.Model): _inherit = "ir.ui.view" - def postprocess(self, node, current_node_path, editable, name_manager): - res = super().postprocess(node, current_node_path, editable, name_manager) + def _postprocess_tag_field(self, node, name_manager, node_info): + res = super()._postprocess_tag_field(node, name_manager, node_info) if node.tag == "field": - mname = name_manager.Model._name + mname = name_manager.model._name fname = node.attrib["name"] field = self.env[mname]._fields.get(fname) if field and field.type in ("many2many", "many2one"): diff --git a/web_m2x_options_manager/models/m2x_create_edit_option.py b/web_m2x_options_manager/models/m2x_create_edit_option.py index 29c4a7b56..d3c5bb1ea 100644 --- a/web_m2x_options_manager/models/m2x_create_edit_option.py +++ b/web_m2x_options_manager/models/m2x_create_edit_option.py @@ -36,7 +36,6 @@ class M2xCreateEditOption(models.Model): compute="_compute_model_name", inverse="_inverse_model_name", store=True, - string="Model Name", ) option_create = fields.Selection( @@ -125,8 +124,12 @@ class M2xCreateEditOption(models.Model): def _check_field_in_model(self): for opt in self: if opt.field_id.model_id != opt.model_id: - msg = _("'%s' is not a valid field for model '%s'!") - raise ValidationError(msg % (opt.field_name, opt.model_name)) + msg = _( + "%(field)s is not a valid field for model %(model)s!", + field=opt.field_name, + model=opt.model_name, + ) + raise ValidationError(msg) @api.constrains("field_id") def _check_field_type(self): diff --git a/web_m2x_options_manager/tests/test_m2x_create_edit_option.py b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py index 27640df5b..7f61c9c2b 100644 --- a/web_m2x_options_manager/tests/test_m2x_create_edit_option.py +++ b/web_m2x_options_manager/tests/test_m2x_create_edit_option.py @@ -4,11 +4,11 @@ from lxml import etree from odoo.exceptions import ValidationError -from odoo.tests.common import SavepointCase +from odoo.tests.common import TransactionCase from odoo.tools.safe_eval import safe_eval -class TestM2xCreateEditOption(SavepointCase): +class TestM2xCreateEditOption(TransactionCase): def setUp(self): super(TestM2xCreateEditOption, self).setUp() ref = self.env.ref diff --git a/web_m2x_options_manager/views/ir_model.xml b/web_m2x_options_manager/views/ir_model.xml index f0e6502d4..e52a1b864 100644 --- a/web_m2x_options_manager/views/ir_model.xml +++ b/web_m2x_options_manager/views/ir_model.xml @@ -17,7 +17,7 @@ nolabel="1" context="{'default_model_name': model}" > - + Date: Tue, 16 Nov 2021 23:23:42 +0000 Subject: [PATCH 08/15] [UPD] Update web_m2x_options_manager.pot --- .../i18n/web_m2x_options_manager.pot | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot index 1014c9ca5..b7598b32e 100644 --- a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot +++ b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 14.0\n" +"Project-Id-Version: Odoo Server 15.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -16,7 +16,7 @@ msgstr "" #. module: web_m2x_options_manager #: code:addons/web_m2x_options_manager/models/m2x_create_edit_option.py:0 #, python-format -msgid "'%s' is not a valid field for model '%s'!" +msgid "%(field)s is not a valid field for model %(model)s!" msgstr "" #. module: web_m2x_options_manager @@ -81,9 +81,6 @@ msgid "" msgstr "" #. module: web_m2x_options_manager -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__display_name -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__display_name -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__display_name #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__display_name msgid "Display Name" msgstr "" @@ -114,11 +111,6 @@ msgstr "" msgid "Fields" msgstr "" -#. module: web_m2x_options_manager -#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit -msgid "Fields Description" -msgstr "" - #. module: web_m2x_options_manager #: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit msgid "Fill" @@ -137,17 +129,11 @@ msgid "Force Remove" msgstr "" #. module: web_m2x_options_manager -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__id -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__id -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__id #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__id msgid "ID" msgstr "" #. module: web_m2x_options_manager -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model____last_update -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields____last_update -#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view____last_update #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option____last_update msgid "Last Modified on" msgstr "" From 921792f8c17d0e5504b3a26ced81d469b1f52db3 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 16 Nov 2021 23:25:59 +0000 Subject: [PATCH 09/15] [UPD] README.rst --- web_m2x_options_manager/README.rst | 10 +++++----- web_m2x_options_manager/static/description/index.html | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/web_m2x_options_manager/README.rst b/web_m2x_options_manager/README.rst index 0355c3525..26a7498a5 100644 --- a/web_m2x_options_manager/README.rst +++ b/web_m2x_options_manager/README.rst @@ -14,13 +14,13 @@ Web M2X Options Manager :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github - :target: https://github.com/OCA/web/tree/14.0/web_m2x_options_manager + :target: https://github.com/OCA/web/tree/15.0/web_m2x_options_manager :alt: OCA/web .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/web-14-0/web-14-0-web_m2x_options_manager + :target: https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_m2x_options_manager :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/162/14.0 + :target: https://runbot.odoo-community.org/runbot/162/15.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -50,7 +50,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -82,6 +82,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/web `_ project on GitHub. +This module is part of the `OCA/web `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_m2x_options_manager/static/description/index.html b/web_m2x_options_manager/static/description/index.html index 66f76efac..5d15168ea 100644 --- a/web_m2x_options_manager/static/description/index.html +++ b/web_m2x_options_manager/static/description/index.html @@ -367,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runbot

Allows managing the “Create…” and “Create and Edit…” options for Many2one and Many2many fields directly from the ir.model form view.

Table of contents

@@ -396,7 +396,7 @@ Button “Empty” will remove every option.

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -423,7 +423,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/web project on GitHub.

+

This module is part of the OCA/web project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

From 6fd6b7ab6e5bf6c145df45f2e17811cf1330f869 Mon Sep 17 00:00:00 2001 From: AmmarOfficewalaSerpentCS Date: Mon, 13 Mar 2023 23:12:45 +0530 Subject: [PATCH 10/15] [MIG] web_m2x_options_manager : Migration to 16.0. --- web_m2x_options_manager/README.rst | 24 ++++++++------ web_m2x_options_manager/__manifest__.py | 2 +- .../i18n/web_m2x_options_manager.pot | 18 ++++++++-- web_m2x_options_manager/models/ir_model.py | 17 ++-------- web_m2x_options_manager/models/ir_ui_view.py | 3 +- .../models/m2x_create_edit_option.py | 17 +++++----- .../readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 13 +++++--- .../tests/test_m2x_create_edit_option.py | 33 ++++++------------- web_m2x_options_manager/views/ir_model.xml | 2 +- 10 files changed, 63 insertions(+), 67 deletions(-) diff --git a/web_m2x_options_manager/README.rst b/web_m2x_options_manager/README.rst index 26a7498a5..803940c13 100644 --- a/web_m2x_options_manager/README.rst +++ b/web_m2x_options_manager/README.rst @@ -2,10 +2,13 @@ Web M2X Options Manager ======================= -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:e2c7c70fbcb74be8ffaed3747c322112463936bb6fbb5a48c42d659a5f8ddce7 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -14,16 +17,16 @@ Web M2X Options Manager :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github - :target: https://github.com/OCA/web/tree/15.0/web_m2x_options_manager + :target: https://github.com/OCA/web/tree/16.0/web_m2x_options_manager :alt: OCA/web .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_m2x_options_manager + :target: https://translation.odoo-community.org/projects/web-16-0/web-16-0-web_m2x_options_manager :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/162/15.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=16.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| Allows managing the "Create..." and "Create and Edit..." options for `Many2one` and `Many2many` fields directly from the `ir.model` form view. @@ -49,8 +52,8 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -68,6 +71,7 @@ Contributors * `Camptocamp `__: * Silvio Gregorini +* Duong (Tran Quoc) Maintainers ~~~~~~~~~~~ @@ -82,6 +86,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/web `_ project on GitHub. +This module is part of the `OCA/web `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_m2x_options_manager/__manifest__.py b/web_m2x_options_manager/__manifest__.py index 623712a8b..8c3aae5d4 100644 --- a/web_m2x_options_manager/__manifest__.py +++ b/web_m2x_options_manager/__manifest__.py @@ -6,7 +6,7 @@ "summary": 'Adds an interface to manage the "Create" and' ' "Create and Edit" options for specific models and' " fields.", - "version": "15.0.1.0.0", + "version": "16.0.1.0.0", "author": "Camptocamp, Odoo Community Association (OCA)", "license": "AGPL-3", "category": "Web", diff --git a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot index b7598b32e..1014c9ca5 100644 --- a/web_m2x_options_manager/i18n/web_m2x_options_manager.pot +++ b/web_m2x_options_manager/i18n/web_m2x_options_manager.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 15.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -16,7 +16,7 @@ msgstr "" #. module: web_m2x_options_manager #: code:addons/web_m2x_options_manager/models/m2x_create_edit_option.py:0 #, python-format -msgid "%(field)s is not a valid field for model %(model)s!" +msgid "'%s' is not a valid field for model '%s'!" msgstr "" #. module: web_m2x_options_manager @@ -81,6 +81,9 @@ msgid "" msgstr "" #. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__display_name +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__display_name +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__display_name #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__display_name msgid "Display Name" msgstr "" @@ -111,6 +114,11 @@ msgstr "" msgid "Fields" msgstr "" +#. module: web_m2x_options_manager +#: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit +msgid "Fields Description" +msgstr "" + #. module: web_m2x_options_manager #: model_terms:ir.ui.view,arch_db:web_m2x_options_manager.view_model_form_inherit msgid "Fill" @@ -129,11 +137,17 @@ msgid "Force Remove" msgstr "" #. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model__id +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields__id +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view__id #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option__id msgid "ID" msgstr "" #. module: web_m2x_options_manager +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model____last_update +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_model_fields____last_update +#: model:ir.model.fields,field_description:web_m2x_options_manager.field_ir_ui_view____last_update #: model:ir.model.fields,field_description:web_m2x_options_manager.field_m2x_create_edit_option____last_update msgid "Last Modified on" msgstr "" diff --git a/web_m2x_options_manager/models/ir_model.py b/web_m2x_options_manager/models/ir_model.py index e51446572..dbf1c0277 100644 --- a/web_m2x_options_manager/models/ir_model.py +++ b/web_m2x_options_manager/models/ir_model.py @@ -1,7 +1,7 @@ # Copyright 2021 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import fields, models class IrModel(models.Model): @@ -36,17 +36,4 @@ class IrModel(models.Model): class IrModelFields(models.Model): _inherit = "ir.model.fields" - - @api.model - def name_search(self, name="", args=None, operator="ilike", limit=100): - res = super().name_search(name, args, operator, limit) - if not (name and self.env.context.get("search_by_technical_name")): - return res - domain = list(args or []) + [("name", operator, name)] - new_fids = self.search(domain, limit=limit).ids - for fid in [x[0] for x in res]: - if fid not in new_fids: - new_fids.append(fid) - if limit and limit > 0: - new_fids = new_fids[:limit] - return self.browse(new_fids).sudo().name_get() + _rec_names_search = ["name", "field_description"] diff --git a/web_m2x_options_manager/models/ir_ui_view.py b/web_m2x_options_manager/models/ir_ui_view.py index 66393622d..23f26b4bf 100644 --- a/web_m2x_options_manager/models/ir_ui_view.py +++ b/web_m2x_options_manager/models/ir_ui_view.py @@ -11,8 +11,7 @@ class IrUiView(models.Model): res = super()._postprocess_tag_field(node, name_manager, node_info) if node.tag == "field": mname = name_manager.model._name - fname = node.attrib["name"] - field = self.env[mname]._fields.get(fname) + field = name_manager.model._fields.get(node.get("name")) if field and field.type in ("many2many", "many2one"): rec = self.env["m2x.create.edit.option"].get(mname, field.name) if rec: diff --git a/web_m2x_options_manager/models/m2x_create_edit_option.py b/web_m2x_options_manager/models/m2x_create_edit_option.py index d3c5bb1ea..2712b2627 100644 --- a/web_m2x_options_manager/models/m2x_create_edit_option.py +++ b/web_m2x_options_manager/models/m2x_create_edit_option.py @@ -22,7 +22,6 @@ class M2xCreateEditOption(models.Model): field_name = fields.Char( related="field_id.name", store=True, - string="Field Name", ) model_id = fields.Many2one( @@ -125,9 +124,9 @@ class M2xCreateEditOption(models.Model): for opt in self: if opt.field_id.model_id != opt.model_id: msg = _( - "%(field)s is not a valid field for model %(model)s!", - field=opt.field_name, - model=opt.model_name, + "'%(field_name)s' is not a valid field for model '%(model_name)s'!", + field_name=opt.field_name, + model_name=opt.model_name, ) raise ValidationError(msg) @@ -144,17 +143,19 @@ class M2xCreateEditOption(models.Model): options = node.attrib.get("options") or {} if isinstance(options, str): options = safe_eval(options, dict(self.env.context or [])) or {} + for k in ("create", "create_edit"): opt = self["option_%s" % k] if opt == "none": continue mode, val = opt.split("_") - if mode == "force" or k not in options: + if k not in options: options[k] = val == "true" - node.set("options", str(options)) + if mode == "force": + options["no_%s" % k] = val == "false" if not self.option_create_edit_wizard: - node.set("can_create", "false") - node.set("can_write", "false") + options["no_quick_create"] = True + node.set("options", str(options)) @api.model def get(self, model_name, field_name): diff --git a/web_m2x_options_manager/readme/CONTRIBUTORS.rst b/web_m2x_options_manager/readme/CONTRIBUTORS.rst index 02ad49af4..491d1f18c 100644 --- a/web_m2x_options_manager/readme/CONTRIBUTORS.rst +++ b/web_m2x_options_manager/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `Camptocamp `__: * Silvio Gregorini +* Duong (Tran Quoc) diff --git a/web_m2x_options_manager/static/description/index.html b/web_m2x_options_manager/static/description/index.html index 5d15168ea..f7afc49de 100644 --- a/web_m2x_options_manager/static/description/index.html +++ b/web_m2x_options_manager/static/description/index.html @@ -3,7 +3,7 @@ - + Web M2X Options Manager