From 0a044df336cb8a3a3246b6d852ad76a347bbabfd Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Mon, 6 Jan 2020 12:37:26 +0100 Subject: [PATCH 01/15] Add module crm_stage_probability --- crm_stage_probability/README.rst | 89 ++++ crm_stage_probability/__init__.py | 2 + crm_stage_probability/__manifest__.py | 19 + crm_stage_probability/data/crm_stage.xml | 19 + .../i18n/crm_stage_probability.pot | 183 ++++++++ crm_stage_probability/models/__init__.py | 2 + crm_stage_probability/models/crm_lead.py | 77 +++ crm_stage_probability/models/crm_stage.py | 29 ++ crm_stage_probability/readme/CONFIGURE.rst | 4 + crm_stage_probability/readme/CONTRIBUTORS.rst | 2 + crm_stage_probability/readme/DESCRIPTION.rst | 2 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 437 ++++++++++++++++++ crm_stage_probability/tests/__init__.py | 1 + .../tests/test_crm_lead_probability.py | 59 +++ crm_stage_probability/views/crm_lead.xml | 33 ++ crm_stage_probability/views/crm_stage.xml | 39 ++ crm_stage_probability/wizard/__init__.py | 1 + .../crm_lead_stage_probability_update.py | 84 ++++ .../crm_lead_stage_probability_update.xml | 43 ++ 20 files changed, 1125 insertions(+) create mode 100644 crm_stage_probability/README.rst create mode 100644 crm_stage_probability/__init__.py create mode 100644 crm_stage_probability/__manifest__.py create mode 100644 crm_stage_probability/data/crm_stage.xml create mode 100644 crm_stage_probability/i18n/crm_stage_probability.pot create mode 100644 crm_stage_probability/models/__init__.py create mode 100644 crm_stage_probability/models/crm_lead.py create mode 100644 crm_stage_probability/models/crm_stage.py create mode 100644 crm_stage_probability/readme/CONFIGURE.rst create mode 100644 crm_stage_probability/readme/CONTRIBUTORS.rst create mode 100644 crm_stage_probability/readme/DESCRIPTION.rst create mode 100644 crm_stage_probability/static/description/icon.png create mode 100644 crm_stage_probability/static/description/index.html create mode 100644 crm_stage_probability/tests/__init__.py create mode 100644 crm_stage_probability/tests/test_crm_lead_probability.py create mode 100644 crm_stage_probability/views/crm_lead.xml create mode 100644 crm_stage_probability/views/crm_stage.xml create mode 100644 crm_stage_probability/wizard/__init__.py create mode 100644 crm_stage_probability/wizard/crm_lead_stage_probability_update.py create mode 100644 crm_stage_probability/wizard/crm_lead_stage_probability_update.xml diff --git a/crm_stage_probability/README.rst b/crm_stage_probability/README.rst new file mode 100644 index 00000000000..3084abd4f1d --- /dev/null +++ b/crm_stage_probability/README.rst @@ -0,0 +1,89 @@ +===================== +CRM stage probability +===================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |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%2Fcrm-lightgray.png?logo=github + :target: https://github.com/OCA/crm/tree/13.0/crm_stage_probability + :alt: OCA/crm +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/crm-13-0/crm-13-0-crm_stage_probability + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/111/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module restore the CRM feature from Odoo <= 12.0 with lead probability +according to its stage. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Set the probabilities on the stages +2. Run the "Update leads probability" wizard on the stages to update + +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 +* Odoo SA + +Contributors +~~~~~~~~~~~~ + +* Odoo SA +* Akim Juillerat + +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/crm `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/crm_stage_probability/__init__.py b/crm_stage_probability/__init__.py new file mode 100644 index 00000000000..9b4296142f4 --- /dev/null +++ b/crm_stage_probability/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/crm_stage_probability/__manifest__.py b/crm_stage_probability/__manifest__.py new file mode 100644 index 00000000000..c7857d212a8 --- /dev/null +++ b/crm_stage_probability/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +{ + "name": "CRM stage probability", + "summary": "Define fixed probability on the stages", + "version": "13.0.1.0.0", + "development_status": "Alpha", + "category": "Sales/CRM", + "website": "https://github.com/OCA/crm", + "author": "Camptocamp, Odoo Community Association (OCA), Odoo SA", + "license": "AGPL-3", + "depends": ["crm"], + "data": [ + "views/crm_lead.xml", + "views/crm_stage.xml", + "wizard/crm_lead_stage_probability_update.xml", + "data/crm_stage.xml", + ], +} diff --git a/crm_stage_probability/data/crm_stage.xml b/crm_stage_probability/data/crm_stage.xml new file mode 100644 index 00000000000..969fa608249 --- /dev/null +++ b/crm_stage_probability/data/crm_stage.xml @@ -0,0 +1,19 @@ + + + + + 10 + + + + 30 + + + + 70 + + + + 100 + + diff --git a/crm_stage_probability/i18n/crm_stage_probability.pot b/crm_stage_probability/i18n/crm_stage_probability.pot new file mode 100644 index 00000000000..bac4d5e1dd3 --- /dev/null +++ b/crm_stage_probability/i18n/crm_stage_probability.pot @@ -0,0 +1,183 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * crm_stage_probability +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.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: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.crm_lead_view_form_inherit +msgid "% (According to stage)" +msgstr "" + +#. module: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.crm_lead_view_form_inherit +msgid "" +"" +msgstr "" + +#. module: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.view_crm_lead_stage_probability_update +msgid "All the Leads and opportunities on following stages will be updated." +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model,name:crm_stage_probability.model_crm_stage +msgid "CRM Stages" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model,name:crm_stage_probability.model_crm_lead_stage_probability_update_line +msgid "CRM leads stages to updates" +msgstr "" + +#. module: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.view_crm_lead_stage_probability_update +msgid "Cancel" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__on_change +msgid "Change Probability Automatically" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__create_uid +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__create_uid +msgid "Created by" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__create_date +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__create_date +msgid "Created on" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__crm_stage_update_ids +msgid "Crm Stage Update" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__display_name +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__display_name +msgid "Display Name" +msgstr "" + +#. module: crm_stage_probability +#: code:addons/crm_stage_probability/wizard/crm_lead_stage_probability_update.py:0 +#, python-format +msgid "" +"Following stages must be set as 'Change Probability Automatically' in order to update their related leads:\n" +"\n" +"%s" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__id +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__id +msgid "ID" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__is_stage_probability +msgid "Is Stage Probability" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update____last_update +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__write_uid +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__write_date +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model,name:crm_stage_probability.model_crm_lead +msgid "Lead/Opportunity" +msgstr "" + +#. module: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.view_crm_lead_stage_probability_update +msgid "Leads probability mass update" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model,name:crm_stage_probability.model_crm_lead_stage_probability_update +msgid "Mass update of crm lead probability according to stage" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__lead_count +msgid "No of leads" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__probability +msgid "Probability" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__probability +msgid "Probability (%)" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,help:crm_stage_probability.field_crm_stage__on_change +msgid "" +"Setting this stage will change the probability automatically on the " +"opportunity." +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__stage_id +msgid "Stage" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.constraint,message:crm_stage_probability.constraint_crm_stage_check_probability +msgid "The probability should be between 0% and 100%!" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,help:crm_stage_probability.field_crm_lead__stage_probability +#: model:ir.model.fields,help:crm_stage_probability.field_crm_stage__probability +msgid "" +"This percentage depicts the default/average probability of the Case for this" +" stage to be a success" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.actions.act_window,name:crm_stage_probability.action_crm_lead_stage_probability_update +msgid "Update leads probability" +msgstr "" + +#. module: crm_stage_probability +#: model_terms:ir.ui.view,arch_db:crm_stage_probability.view_crm_lead_stage_probability_update +msgid "Update probabilities" +msgstr "" + +#. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__wizard_id +msgid "Wizard" +msgstr "" diff --git a/crm_stage_probability/models/__init__.py b/crm_stage_probability/models/__init__.py new file mode 100644 index 00000000000..40635a2a948 --- /dev/null +++ b/crm_stage_probability/models/__init__.py @@ -0,0 +1,2 @@ +from . import crm_lead +from . import crm_stage diff --git a/crm_stage_probability/models/crm_lead.py b/crm_stage_probability/models/crm_lead.py new file mode 100644 index 00000000000..4f1096a926e --- /dev/null +++ b/crm_stage_probability/models/crm_lead.py @@ -0,0 +1,77 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import api, fields, models, tools + + +class CrmLead(models.Model): + + _inherit = "crm.lead" + + def _default_probability(self): + if "default_stage_id" in self._context: + stage_id = self._context.get("default_stage_id") + else: + stage_id = self._default_stage_id() + if stage_id: + return self.env["crm.stage"].browse(stage_id).probability + return 10 + + is_stage_probability = fields.Boolean( + compute="_compute_is_stage_probability", readonly=True + ) + stage_probability = fields.Float(related="stage_id.probability", readonly=True) + probability = fields.Float(default=lambda self: self._default_probability()) + + @api.depends("probability", "stage_id", "stage_id.probability") + def _compute_is_stage_probability(self): + for lead in self: + lead.is_stage_probability = ( + tools.float_compare(lead.probability, lead.stage_probability, 2) == 0 + ) + + @api.depends("probability", "automated_probability") + def _compute_is_automated_probability(self): + for lead in self: + if lead.probability != lead.stage_id.probability: + super(CrmLead, lead)._compute_is_automated_probability() + continue + lead.is_automated_probability = False + + def _update_probability(self): + self = self.with_context(_auto_update_probability=True) + return super()._update_probability() + + @api.model + def _onchange_stage_id_values(self, stage_id): + """ returns the new values when stage_id has changed """ + if not stage_id: + return {} + stage = self.env["crm.stage"].browse(stage_id) + if stage.on_change: + return {"probability": stage.probability} + return {} + + @api.onchange("stage_id") + def _onchange_stage_id(self): + res = super()._onchange_stage_id() + values = self._onchange_stage_id_values(self.stage_id.id) + self.update(values) + return res + + def write(self, vals): + # Avoid to update probability with automated_probability on + # _update_probability if the stage is set as on_change + # If the stage is not set as on_change, auto PLS will be applied + if ( + self.env.context.get("_auto_update_probability") + and "probability" in vals + and "stage_id" not in vals + ): + vals.update(self._onchange_stage_id_values(self.stage_id.id)) + # Force to use the probability from the stage if set as on_change + if vals.get("stage_id") and "probability" not in vals: + vals.update(self._onchange_stage_id_values(vals.get("stage_id"))) + return super().write(vals) + + def action_set_stage_probability(self): + self.write({"probability": self.stage_id.probability}) diff --git a/crm_stage_probability/models/crm_stage.py b/crm_stage_probability/models/crm_stage.py new file mode 100644 index 00000000000..9a3b0efa311 --- /dev/null +++ b/crm_stage_probability/models/crm_stage.py @@ -0,0 +1,29 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import fields, models + + +class CrmStage(models.Model): + + _inherit = "crm.stage" + + probability = fields.Float( + "Probability (%)", + required=True, + default=10.0, + help="This percentage depicts the default/average probability of the " + "Case for this stage to be a success", + ) + on_change = fields.Boolean( + "Change Probability Automatically", + help="Setting this stage will change the probability automatically on " + "the opportunity.", + ) + + _sql_constraints = [ + ( + "check_probability", + "check(probability >= 0 and probability <= 100)", + "The probability should be between 0% and 100%!", + ) + ] diff --git a/crm_stage_probability/readme/CONFIGURE.rst b/crm_stage_probability/readme/CONFIGURE.rst new file mode 100644 index 00000000000..0c87436bbe1 --- /dev/null +++ b/crm_stage_probability/readme/CONFIGURE.rst @@ -0,0 +1,4 @@ +To configure this module, you need to: + +1. Set the probabilities on the stages +2. Run the "Update leads probability" wizard on the stages to update diff --git a/crm_stage_probability/readme/CONTRIBUTORS.rst b/crm_stage_probability/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..5d54895c99a --- /dev/null +++ b/crm_stage_probability/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Odoo SA +* Akim Juillerat diff --git a/crm_stage_probability/readme/DESCRIPTION.rst b/crm_stage_probability/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..c56ab982ccc --- /dev/null +++ b/crm_stage_probability/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module restore the CRM feature from Odoo <= 12.0 with lead probability +according to its stage. diff --git a/crm_stage_probability/static/description/icon.png b/crm_stage_probability/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/crm_stage_probability/static/description/index.html b/crm_stage_probability/static/description/index.html new file mode 100644 index 00000000000..cadb3bf9831 --- /dev/null +++ b/crm_stage_probability/static/description/index.html @@ -0,0 +1,437 @@ + + + + + + +CRM stage probability + + + +
+

CRM stage probability

+ + +

Alpha License: AGPL-3 OCA/crm Translate me on Weblate Try me on Runbot

+

This module restore the CRM feature from Odoo <= 12.0 with lead probability +according to its stage.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Set the probabilities on the stages
  2. +
  3. Run the “Update leads probability” wizard on the stages to update
  4. +
+
+
+

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
  • +
  • Odoo SA
  • +
+
+
+

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/crm project on GitHub.

+

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

+
+
+
+ + diff --git a/crm_stage_probability/tests/__init__.py b/crm_stage_probability/tests/__init__.py new file mode 100644 index 00000000000..e8233436ddc --- /dev/null +++ b/crm_stage_probability/tests/__init__.py @@ -0,0 +1 @@ +from . import test_crm_lead_probability diff --git a/crm_stage_probability/tests/test_crm_lead_probability.py b/crm_stage_probability/tests/test_crm_lead_probability.py new file mode 100644 index 00000000000..41a034cb67d --- /dev/null +++ b/crm_stage_probability/tests/test_crm_lead_probability.py @@ -0,0 +1,59 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo.tests import SavepointCase + + +class TestCrmLeadProbability(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.stage_new = cls.env.ref("crm.stage_lead1") + cls.stage_qualified = cls.env.ref("crm.stage_lead2") + cls.stage_proposition = cls.env.ref("crm.stage_lead3") + cls.stage_won = cls.env.ref("crm.stage_lead4") + cls.opportunity_1 = cls.env.ref("crm.crm_case_32") + + def test_update_probability(self): + self.assertEqual(self.opportunity_1.stage_id, self.stage_qualified) + self.assertFalse(self.opportunity_1.is_automated_probability) + self.assertFalse(self.opportunity_1.is_stage_probability) + self.opportunity_1.write({"stage_id": self.stage_new.id}) + self.assertEqual(self.opportunity_1.probability, self.stage_new.probability) + self.assertFalse(self.opportunity_1.is_automated_probability) + self.assertTrue(self.opportunity_1.is_stage_probability) + self.opportunity_1.write({"stage_id": self.stage_proposition.id}) + self.assertEqual( + self.opportunity_1.probability, self.stage_proposition.probability + ) + self.assertFalse(self.opportunity_1.is_automated_probability) + self.assertTrue(self.opportunity_1.is_stage_probability) + self.opportunity_1.write({"probability": 31.56}) + self.assertFalse(self.opportunity_1.is_automated_probability) + self.assertFalse(self.opportunity_1.is_stage_probability) + self.opportunity_1.action_set_stage_probability() + self.assertEqual( + self.opportunity_1.probability, self.opportunity_1.stage_id.probability + ) + self.assertTrue(self.opportunity_1.is_stage_probability) + + def test_create_opportunity(self): + opportunity = self.env["crm.lead"].create( + {"name": "My opportunity", "type": "opportunity"} + ) + default_stage_id = self.env["crm.lead"]._default_stage_id() + default_stage = self.env["crm.stage"].browse(default_stage_id) + self.assertEqual(opportunity.probability, default_stage.probability) + self.assertFalse(opportunity.is_automated_probability) + + def test_mass_update(self): + all_stages = self.env["crm.stage"].search([]) + self.assertTrue(all(all_stages.mapped("on_change"))) + wiz = ( + self.env["crm.lead.stage.probability.update"] + .with_context(active_ids=all_stages.ids) + .create({}) + ) + wiz.execute() + all_leads = self.env["crm.lead"].search([]) + self.assertTrue(all(all_leads.mapped("is_stage_probability"))) + self.assertFalse(all(all_leads.mapped("is_automated_probability"))) diff --git a/crm_stage_probability/views/crm_lead.xml b/crm_stage_probability/views/crm_lead.xml new file mode 100644 index 00000000000..4bce6c462ed --- /dev/null +++ b/crm_stage_probability/views/crm_lead.xml @@ -0,0 +1,33 @@ + + + + crm.lead.form.inherit + + crm.lead + + + + + %% (According to stage) + + + + diff --git a/crm_stage_probability/views/crm_stage.xml b/crm_stage_probability/views/crm_stage.xml new file mode 100644 index 00000000000..3c12b7e0f28 --- /dev/null +++ b/crm_stage_probability/views/crm_stage.xml @@ -0,0 +1,39 @@ + + + + Stage - Search - inherit + + crm.stage + + + + + + + + crm.stage.tree.inherit + crm.stage + + + + + + + + + crm.stage.form.inherit + crm.stage + + + + + + + + + + + diff --git a/crm_stage_probability/wizard/__init__.py b/crm_stage_probability/wizard/__init__.py new file mode 100644 index 00000000000..572a9cfbb6a --- /dev/null +++ b/crm_stage_probability/wizard/__init__.py @@ -0,0 +1 @@ +from . import crm_lead_stage_probability_update diff --git a/crm_stage_probability/wizard/crm_lead_stage_probability_update.py b/crm_stage_probability/wizard/crm_lead_stage_probability_update.py new file mode 100644 index 00000000000..a0263a3c030 --- /dev/null +++ b/crm_stage_probability/wizard/crm_lead_stage_probability_update.py @@ -0,0 +1,84 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class CrmLeadStageProbabilityUpdate(models.TransientModel): + + _name = "crm.lead.stage.probability.update" + _description = "Mass update of crm lead probability according to stage" + + crm_stage_update_ids = fields.Many2many( + "crm.lead.stage.probability.update.line", + "crm_lead_stage_probability_update_line_rel", + "wizard_id", + "stage_id", + readonly=True, + ) + + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + if "crm_stage_update_ids" in fields_list and "active_ids" in self.env.context: + active_ids = self.env.context.get("active_ids") + stages = self.env["crm.stage"].browse(active_ids) + stages_missing_on_change = stages.filtered(lambda s: not s.on_change) + if stages_missing_on_change: + raise UserError( + _( + "Following stages must be set as 'Change Probability " + "Automatically' in order to update their related leads:" + "\n\n" + "%s" + ) + % "\n".join([s.name for s in stages_missing_on_change]) + ) + line_ids = [] + for stage in stages: + new_line = self.env["crm.lead.stage.probability.update.line"].create( + {"stage_id": stage.id} + ) + line_ids.append(new_line.id) + res["crm_stage_update_ids"] = [(6, 0, line_ids)] + return res + + def execute(self): + updated_leads_ids = [] + for stage_line in self.crm_stage_update_ids: + leads = self.env["crm.lead"].search( + [("stage_id", "=", stage_line.stage_id.id)] + ) + leads.write({"probability": stage_line.stage_id.probability}) + updated_leads_ids += leads.ids + action = self.env.ref("crm.crm_lead_all_leads").read()[0] + action["domain"] = "[('id', 'in', %s)]" % updated_leads_ids + action.pop("context") + return action + + +class CrmLeadStageProbabilityUpdateStage(models.TransientModel): + + _name = "crm.lead.stage.probability.update.line" + _description = "CRM leads stages to updates" + + wizard_id = fields.Many2many( + "crm.lead.stage.probability.update", + "crm_lead_stage_probability_update_line_rel", + "stage_id", + "wizard_id", + readonly=True, + ) + stage_id = fields.Many2one( + "crm.stage", domain=[("on_change", "=", True)], readonly=True + ) + lead_count = fields.Integer( + "No of leads", compute="_compute_lead_count", readonly=True + ) + + @api.depends("stage_id") + def _compute_lead_count(self): + for stage_line in self: + stage_line.lead_count = self.env["crm.lead"].search_count( + [("stage_id", "=", stage_line.stage_id.id)] + ) diff --git a/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml b/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml new file mode 100644 index 00000000000..f3d30663d90 --- /dev/null +++ b/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml @@ -0,0 +1,43 @@ + + + + crm.lead.stage.probability.update.form + crm.lead.stage.probability.update + +
+
+

All the Leads and opportunities on following stages will be updated.

+
+ + + + + + + + +
+
+
+
+
+ +
From 65cc6b484172bdec2d925fdec2ebb19b027416a7 Mon Sep 17 00:00:00 2001 From: Robin Goots Date: Fri, 30 Jul 2021 12:50:53 +0200 Subject: [PATCH 02/15] [MIG] crm_stage_probability: Migration to 14.0 --- crm_stage_probability/README.rst | 11 +++--- crm_stage_probability/__manifest__.py | 3 +- .../i18n/crm_stage_probability.pot | 8 +++- crm_stage_probability/models/crm_lead.py | 25 ++++++------ crm_stage_probability/readme/CONTRIBUTORS.rst | 1 + .../security/ir.model.access.csv | 3 ++ .../static/description/index.html | 7 ++-- .../tests/test_crm_lead_probability.py | 38 ++++++++++++++++++- .../crm_lead_stage_probability_update.xml | 21 +++++----- 9 files changed, 83 insertions(+), 34 deletions(-) create mode 100644 crm_stage_probability/security/ir.model.access.csv diff --git a/crm_stage_probability/README.rst b/crm_stage_probability/README.rst index 3084abd4f1d..196b7a6189d 100644 --- a/crm_stage_probability/README.rst +++ b/crm_stage_probability/README.rst @@ -14,13 +14,13 @@ CRM stage probability :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcrm-lightgray.png?logo=github - :target: https://github.com/OCA/crm/tree/13.0/crm_stage_probability + :target: https://github.com/OCA/crm/tree/14.0/crm_stage_probability :alt: OCA/crm .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/crm-13-0/crm-13-0-crm_stage_probability + :target: https://translation.odoo-community.org/projects/crm-14-0/crm-14-0-crm_stage_probability :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/111/13.0 + :target: https://runbot.odoo-community.org/runbot/111/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -52,7 +52,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. @@ -70,6 +70,7 @@ Contributors * Odoo SA * Akim Juillerat +* Robin Goots Maintainers ~~~~~~~~~~~ @@ -84,6 +85,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/crm `_ project on GitHub. +This module is part of the `OCA/crm `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/crm_stage_probability/__manifest__.py b/crm_stage_probability/__manifest__.py index c7857d212a8..12a2da148a3 100644 --- a/crm_stage_probability/__manifest__.py +++ b/crm_stage_probability/__manifest__.py @@ -3,7 +3,7 @@ { "name": "CRM stage probability", "summary": "Define fixed probability on the stages", - "version": "13.0.1.0.0", + "version": "14.0.1.0.0", "development_status": "Alpha", "category": "Sales/CRM", "website": "https://github.com/OCA/crm", @@ -15,5 +15,6 @@ "views/crm_stage.xml", "wizard/crm_lead_stage_probability_update.xml", "data/crm_stage.xml", + "security/ir.model.access.csv", ], } diff --git a/crm_stage_probability/i18n/crm_stage_probability.pot b/crm_stage_probability/i18n/crm_stage_probability.pot index bac4d5e1dd3..e8283abf971 100644 --- a/crm_stage_probability/i18n/crm_stage_probability.pot +++ b/crm_stage_probability/i18n/crm_stage_probability.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -68,8 +68,10 @@ msgid "Crm Stage Update" msgstr "" #. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__display_name #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__display_name #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__display_name +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__display_name msgid "Display Name" msgstr "" @@ -83,8 +85,10 @@ msgid "" msgstr "" #. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__id #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__id #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__id +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__id msgid "ID" msgstr "" @@ -94,8 +98,10 @@ msgid "Is Stage Probability" msgstr "" #. module: crm_stage_probability +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead____last_update #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update____last_update #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line____last_update +#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage____last_update msgid "Last Modified on" msgstr "" diff --git a/crm_stage_probability/models/crm_lead.py b/crm_stage_probability/models/crm_lead.py index 4f1096a926e..82b77b39a0e 100644 --- a/crm_stage_probability/models/crm_lead.py +++ b/crm_stage_probability/models/crm_lead.py @@ -7,21 +7,21 @@ class CrmLead(models.Model): _inherit = "crm.lead" + is_stage_probability = fields.Boolean( + compute="_compute_is_stage_probability", readonly=True + ) + stage_probability = fields.Float(related="stage_id.probability", readonly=True) + probability = fields.Float(default=lambda self: self._default_probability()) + def _default_probability(self): if "default_stage_id" in self._context: stage_id = self._context.get("default_stage_id") else: - stage_id = self._default_stage_id() + stage_id = self._stage_find(domain=[("fold", "=", False)]).id if stage_id: return self.env["crm.stage"].browse(stage_id).probability return 10 - is_stage_probability = fields.Boolean( - compute="_compute_is_stage_probability", readonly=True - ) - stage_probability = fields.Float(related="stage_id.probability", readonly=True) - probability = fields.Float(default=lambda self: self._default_probability()) - @api.depends("probability", "stage_id", "stage_id.probability") def _compute_is_stage_probability(self): for lead in self: @@ -37,13 +37,16 @@ def _compute_is_automated_probability(self): continue lead.is_automated_probability = False - def _update_probability(self): + @api.depends( + lambda self: ["tag_ids", "stage_id", "team_id"] + self._pls_get_safe_fields() + ) + def _compute_probabilities(self): self = self.with_context(_auto_update_probability=True) - return super()._update_probability() + return super()._compute_probabilities() @api.model def _onchange_stage_id_values(self, stage_id): - """ returns the new values when stage_id has changed """ + """returns the new values when stage_id has changed""" if not stage_id: return {} stage = self.env["crm.stage"].browse(stage_id) @@ -53,10 +56,8 @@ def _onchange_stage_id_values(self, stage_id): @api.onchange("stage_id") def _onchange_stage_id(self): - res = super()._onchange_stage_id() values = self._onchange_stage_id_values(self.stage_id.id) self.update(values) - return res def write(self, vals): # Avoid to update probability with automated_probability on diff --git a/crm_stage_probability/readme/CONTRIBUTORS.rst b/crm_stage_probability/readme/CONTRIBUTORS.rst index 5d54895c99a..e1f374961d6 100644 --- a/crm_stage_probability/readme/CONTRIBUTORS.rst +++ b/crm_stage_probability/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Odoo SA * Akim Juillerat +* Robin Goots diff --git a/crm_stage_probability/security/ir.model.access.csv b/crm_stage_probability/security/ir.model.access.csv new file mode 100644 index 00000000000..45de09df775 --- /dev/null +++ b/crm_stage_probability/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_crm_lead_stage_probability_update,access_crm_lead_stage_probability_update,model_crm_lead_stage_probability_update,base.group_user,1,0,1,0 +access_crm_lead_stage_probability_update_line,access_crm_lead_stage_probability_update_line,model_crm_lead_stage_probability_update_line,base.group_user,1,0,1,0 diff --git a/crm_stage_probability/static/description/index.html b/crm_stage_probability/static/description/index.html index cadb3bf9831..2ef70a23c77 100644 --- a/crm_stage_probability/static/description/index.html +++ b/crm_stage_probability/static/description/index.html @@ -367,7 +367,7 @@

CRM stage probability

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Alpha License: AGPL-3 OCA/crm Translate me on Weblate Try me on Runbot

+

Alpha License: AGPL-3 OCA/crm Translate me on Weblate Try me on Runbot

This module restore the CRM feature from Odoo <= 12.0 with lead probability according to its stage.

@@ -402,7 +402,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.

@@ -419,6 +419,7 @@

Contributors

@@ -428,7 +429,7 @@

Maintainers

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/crm project on GitHub.

+

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

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

diff --git a/crm_stage_probability/tests/test_crm_lead_probability.py b/crm_stage_probability/tests/test_crm_lead_probability.py index 41a034cb67d..ddada9555ac 100644 --- a/crm_stage_probability/tests/test_crm_lead_probability.py +++ b/crm_stage_probability/tests/test_crm_lead_probability.py @@ -1,5 +1,6 @@ # Copyright 2020 Camptocamp SA # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo.exceptions import UserError from odoo.tests import SavepointCase @@ -40,11 +41,22 @@ def test_create_opportunity(self): opportunity = self.env["crm.lead"].create( {"name": "My opportunity", "type": "opportunity"} ) - default_stage_id = self.env["crm.lead"]._default_stage_id() + default_stage_id = ( + self.env["crm.lead"]._stage_find(domain=[("fold", "=", False)]).id + ) default_stage = self.env["crm.stage"].browse(default_stage_id) self.assertEqual(opportunity.probability, default_stage.probability) self.assertFalse(opportunity.is_automated_probability) + def test_create_opportunity_default_stage_id(self): + opportunity = ( + self.env["crm.lead"] + .with_context(default_stage_id=self.stage_qualified.id) + .create({"name": "My opportunity", "type": "opportunity"}) + ) + self.assertEqual(opportunity.probability, self.stage_qualified.probability) + self.assertFalse(opportunity.is_automated_probability) + def test_mass_update(self): all_stages = self.env["crm.stage"].search([]) self.assertTrue(all(all_stages.mapped("on_change"))) @@ -57,3 +69,27 @@ def test_mass_update(self): all_leads = self.env["crm.lead"].search([]) self.assertTrue(all(all_leads.mapped("is_stage_probability"))) self.assertFalse(all(all_leads.mapped("is_automated_probability"))) + new_line = wiz.crm_stage_update_ids.filtered( + lambda x: x.stage_id == self.stage_new + ) + self.assertEqual(new_line.lead_count, 13) + won_line = wiz.crm_stage_update_ids.filtered( + lambda x: x.stage_id == self.stage_won + ) + self.assertEqual(won_line.lead_count, 3) + + def test_mass_update_no_onchange_stage(self): + new_stage = self.env["crm.stage"].create( + { + "name": "No Onchange", + "sequence": 10, + } + ) + self.assertFalse(new_stage.on_change) + with self.assertRaises(UserError) as context: + ( + self.env["crm.lead.stage.probability.update"] + .with_context(active_ids=new_stage.ids) + .create({}) + ) + self.assertTrue("Following stages must be set as" in str(context.exception)) diff --git a/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml b/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml index f3d30663d90..b19b595836a 100644 --- a/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml +++ b/crm_stage_probability/wizard/crm_lead_stage_probability_update.xml @@ -29,15 +29,14 @@ - + + + Update leads probability + crm.lead.stage.probability.update + + form + + + new + From b8fe84c445387e8f93ac9c73bd177b6059749cb9 Mon Sep 17 00:00:00 2001 From: Virginia Bonservizi Date: Wed, 24 Aug 2022 10:02:08 -0300 Subject: [PATCH 03/15] [MIG] crm_stage_probability: Migration to 15.0 --- crm_stage_probability/README.rst | 23 +++++----- crm_stage_probability/__manifest__.py | 2 +- .../i18n/crm_stage_probability.pot | 8 +--- crm_stage_probability/models/crm_lead.py | 1 + .../static/description/index.html | 42 ++++++++++--------- .../tests/test_crm_lead_probability.py | 19 ++++++++- 6 files changed, 55 insertions(+), 40 deletions(-) diff --git a/crm_stage_probability/README.rst b/crm_stage_probability/README.rst index 196b7a6189d..6b0e265101f 100644 --- a/crm_stage_probability/README.rst +++ b/crm_stage_probability/README.rst @@ -2,10 +2,13 @@ CRM stage probability ===================== -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:47229dbbe22f44a935b285fcf6a8ec095140125a64692a40024fe029c4a6a200 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png :target: https://odoo-community.org/page/development-status @@ -14,16 +17,16 @@ CRM stage probability :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcrm-lightgray.png?logo=github - :target: https://github.com/OCA/crm/tree/14.0/crm_stage_probability + :target: https://github.com/OCA/crm/tree/15.0/crm_stage_probability :alt: OCA/crm .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/crm-14-0/crm-14-0-crm_stage_probability + :target: https://translation.odoo-community.org/projects/crm-15-0/crm-15-0-crm_stage_probability :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/111/14.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/crm&target_branch=15.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module restore the CRM feature from Odoo <= 12.0 with lead probability according to its stage. @@ -51,8 +54,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. @@ -85,6 +88,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/crm `_ project on GitHub. +This module is part of the `OCA/crm `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/crm_stage_probability/__manifest__.py b/crm_stage_probability/__manifest__.py index 12a2da148a3..5b44753cb15 100644 --- a/crm_stage_probability/__manifest__.py +++ b/crm_stage_probability/__manifest__.py @@ -3,7 +3,7 @@ { "name": "CRM stage probability", "summary": "Define fixed probability on the stages", - "version": "14.0.1.0.0", + "version": "15.0.1.0.0", "development_status": "Alpha", "category": "Sales/CRM", "website": "https://github.com/OCA/crm", diff --git a/crm_stage_probability/i18n/crm_stage_probability.pot b/crm_stage_probability/i18n/crm_stage_probability.pot index e8283abf971..0955c50b7ad 100644 --- a/crm_stage_probability/i18n/crm_stage_probability.pot +++ b/crm_stage_probability/i18n/crm_stage_probability.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" @@ -68,10 +68,8 @@ msgid "Crm Stage Update" msgstr "" #. module: crm_stage_probability -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__display_name #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__display_name #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__display_name -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__display_name msgid "Display Name" msgstr "" @@ -85,10 +83,8 @@ msgid "" msgstr "" #. module: crm_stage_probability -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead__id #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update__id #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line__id -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage__id msgid "ID" msgstr "" @@ -98,10 +94,8 @@ msgid "Is Stage Probability" msgstr "" #. module: crm_stage_probability -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead____last_update #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update____last_update #: model:ir.model.fields,field_description:crm_stage_probability.field_crm_lead_stage_probability_update_line____last_update -#: model:ir.model.fields,field_description:crm_stage_probability.field_crm_stage____last_update msgid "Last Modified on" msgstr "" diff --git a/crm_stage_probability/models/crm_lead.py b/crm_stage_probability/models/crm_lead.py index 82b77b39a0e..af95a094362 100644 --- a/crm_stage_probability/models/crm_lead.py +++ b/crm_stage_probability/models/crm_lead.py @@ -36,6 +36,7 @@ def _compute_is_automated_probability(self): super(CrmLead, lead)._compute_is_automated_probability() continue lead.is_automated_probability = False + return @api.depends( lambda self: ["tag_ids", "stage_id", "team_id"] + self._pls_get_safe_fields() diff --git a/crm_stage_probability/static/description/index.html b/crm_stage_probability/static/description/index.html index 2ef70a23c77..6671af06dd3 100644 --- a/crm_stage_probability/static/description/index.html +++ b/crm_stage_probability/static/description/index.html @@ -1,20 +1,20 @@ - + - + CRM stage probability