This merge replaces the stage based probability on leads by a new Predictive Lead scoring mechanism based on Naive Bayes Probability computation theorem.
Probability are now computed automatically based on past experience (already lost and won leads)
and based on multiple criteria (field values on leads). The user is still able to set a probability on a lead manually, or come back to a automated probability, both via the lead form.
A cron runs every day to rebuild the frequency table and to recompute all the active pending leads.
See sub commits for more details.
Special thanks to @awa-odoo who did his job. Quite well indeed!
Special thanks to @tbe-odoo who helped me for testing and performance optimisation.
Task ID : 1925439
NOTE : This task must be followed by task ID 2008365 : Remove old lead scoring system
closesodoo/odoo#33589
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Before this commit, it was impossible to eval the domain if context_today was
used in domain.
closesodoo/odoo#34031
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
When the channel has a linked forum, the "Review" link on the forum should redirect the user
to the "Review" tab on the course page.
Task #2003222closesodoo/odoo#33786
Signed-off-by: Jérome Maes (jem) <jem@openerp.com>
This commit improves the footer image of the slides home page by adding
the top 3 users avatars (ordered by karm desc) in the image.
We only fetch users that have an image set as avatar.
Task #2003222
Co-authored-by: @stefanorigano <sri@odoo.com>
- On the HR module, the field `parent_id` is added on `res.users`.
The issue here, is that `res.users` inherits the fields from
`res.partner` where `parent_id` is already defined.
This causes issues when trying to read the parent `res.partner`.
Issue found by @rrahir
closesodoo/odoo#34059
Signed-off-by: Toufik Benjaa (tbe) <tbe@odoo.com>
From now, the color option 2 ('Mixed color & B/W') is not available anymore. So set the option to 1 ('Color').
Task-ID: 2008913
closesodoo/odoo#34052
Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
This tour is useless in backend.
This patch will be required in saas~12.2 as `web_editor.base` (used in
the tour) is only available in frontend.
closesodoo/odoo#34041
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
The "BoM Structure report" should not include the cost of the products
as it is often shared with third parties. We now only display the cost
on the "BoM Structure and Cost report" and remove the "BoM Cost report"
as it is redundant with the former.
Task Id: 1969709
closesodoo/odoo#33323
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
- Create a mailing campaign
- Create a mailing 1, set the subject to "Test 1"
- Create a mailing 2, set the subject to "Test 2"
The subject of mailing 1 is set to "Test 2".
When checking the code, this behavior seems the one expected. The
`_rec_name` of a mass mailing is the `subject_id`:
https://github.com/odoo/odoo/blob/7ef4ba03c4f8dce42f5a56b64d2374373d13aa8d/addons/mass_mailing/models/mass_mailing.py#L437
Moreover, there is an onchange to set the subject in line with the
subject of the campaign:
https://github.com/odoo/odoo/blob/7ef4ba03c4f8dce42f5a56b64d2374373d13aa8d/addons/mass_mailing/models/mass_mailing.py#L608
However this behavior is not present up to v11, and only appears in v12.
Surprisingly, this is due to an unrelated improvement which adds the
field in the view (in debug mode): 5b0bcaef3e.
Up to v11, the onchange exists, but since the fields are not in the
view, it has no effect. However, in v12 the fields are in the view so
the onchange has an effect.
Since this was the behavior up to v11, and that the behavior is fixed
in f50fbc6d16, we keep it consistent in v12 as
well.
opw-2007764
closesodoo/odoo#34028
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Before this commit, those pages would be flag as noupdate.
If not modified, those view would not get modification on module update, which
is not logic.
Now, those view will benefit from any update. It makes even more sense since
multi-website as those views will never get modified directly (it will COW).
closesodoo/odoo#33920
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
The tests relative to workcenters planning takes (sometimes) long time
to be executed. Before investigation more deeply, this commit relax a
bit more the tolerance delta in the test comparison
closesodoo/odoo#33939
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit aims to propagate the cancellation of a purchase order or a
request for quotation to the relative stock moves. And thus respect the
configuration of the stock rule.
Task 1913297
closesodoo/odoo#33803
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
cancelling propagation in a move chain was True be default. That means,
without any configuration, a cancel move will always cancel its next ones
This commit change the default to allow only cancelation of move chain
until the stock location. Here are 2 examples :
1. Reception and delivery in 3 steps. The moves chain is the following:
Vendor -> Input -> Quality -> Stock -> Pack -> Output -> Customer
In case the Purchase order is cancelled, we want to move from Vendor to
Stock are cancelled but not the ones from Stock.
2. pbm + sam. The manufacturing process is the following;
Stock -> Pre-prod -> Production -> Post-prod -> Stock
cancelling the first move should cancelled until Production and not after
Task : 1913297
This new Predictive Lead Scoring (aka PLS) replaces the stage based probability mechanism.
It uses Naive Bayes probability computation theorem.
The lead probability is now computated automatically based on multiple criteria (= frequency fields).
Some are mandatory and will always be used, some are optional and can be activated
in the settings.
- Mandatory fields :
- team_id
- stage_id
- tag_ids
- Optional fields :
- email_state (validity of the email_from field: correct / incorrect or empty if email_from is empty)
- phone_state (validity of the phone field !! not the mobile one !!: correct / incorrect or empty if phone is empty)
- country_id
- state_id
- source_id (UTM Source)
PLS uses a start date to consider only the lead created after that date to generate the frequency table
and to recompute the lead probability. This date is also configurable in the CRM settings.
Default start date is date.todays() (at module install).
The settings for PLS are NOT company related :
PLS Fields = Many2many to a model that store only the fields allowed for PLS computation.
PLS Start Date = Date
As Date and Many2many fields are not allowed for config_parameters,
Char fields are used to store the configuration
and Date and m2m fields are used to ease the configuration by the user in the config panel.
Date and m2m fields are both computed fields based on their corresponding Char fields.
Char field for Date store a strigified date.
char field for Many2many store a comma separated string which is a list of activated fields.
Each mandatory field is used in a specific way
- Team_id : the frequency table is split for every team_id, plus once for leads that don't have a team_id.
Considering Lead A from Team 1 and Lead B from Team 2.
Even if Lead A and Lead B have the exact same attributes (country, phone, email,stage, ...),
their probability will most likely not be the same.
That's because each teams compute their leads' probability based on their own won/lost leads.
- Stage_id : if no optional fields are activated and if there is no tag on the lead,
this will make PLS work quite the same way as it was working with removed stage based probability,
as only the stage will count in the computation.
But here, instead of fixing manually the probability for each stage,
this stage related probability is automatically computed based on past experience (won and lost leads).
- Tag_ids : each tag is considered separatelly, as if the lead had only one tag.
(no link between tag on same lead is made). To avoid that a tag take to much importance if his subset is too
small, we include the tag frequencies in the frequency table only if at least 50 won or lost leads had this tag.
The frequency table is a table where all won and lost leads are aggregated by fields
(mandatory or optional if activated). For each team_id / field couple, we store the number of
won and lost leads that has that fields values.
For example: Lead A is assigned to team 1 and client comes from France and has been won.
If we consider only this lead A, the frequency table will looks like :
id | variable | value | won_count | lost_count | team_id
--------+-------------+-------+-----------+------------+---------
1 country_id FR 1 0 1
To computed the probability of a lead, we get all the records for the frequency table
that match all fields (per team_id) and we compute a won score and a lost score.
The probability is computed and normalized based on those scores
- P = S(Won) / (S(Won) + S(Lost))
Considering two variables A and B :
- S(Won) ∝ P(A∩B | Won)*P(Won) = P(A|Won) * P(B|Won) * P(Won)
- S(Lost) ∝ P(A∩B | Lost)*P(Lost) = P(A|Lost) * P(B|Lost) * P(Lost)
To overcome the 'zero frequency problem',
we do not start at 0 for the won or lost count for each variable / value combination.
It suggested to start at 1, but to avoid that a small subset take to much weight compared to
a larger one, we start at 0.1.
For example :
If we start at 1 : If team 1 has few records from France,
it can get high probability to win even if every lead where lost.
variable | value | won_count | lost_count | team_id | Probability
-------------+-------+-----------+------------+---------+-------------
country_id FR 1 7 1 0.125
country_id FR 198 7306 2 0.0263
If we start at 0.1 :
variable | value | won_count | lost_count | team_id | Probability
-------------+-------+-----------+------------+---------+-------------
country_id FR 0.1 6.1 1 0.0161
country_id FR 197.1 7305.1 2 0.0263
The more we have records for each couple, the more the computation become precise.
The allow the user to decide himself which probability should be set on the lead,
a manual probabiltiy system has been implemented using 2 stored fields + 1 computed field :
- probability (stored): Probability set on the lead, can be set manually in the lead form.
- automated_probability (stored): Probability computed by PLS.
- is_automated_probability (computed): If both previous fields are equal, the probability is considered
as automatic. and each time the automated_probability is updated, the probability is aligned.
If both are not equal, the probability is considered as manual. The automated_probability is still
updated but the probability is not aligned. The user can reset the probability in automatic mode
by clicking on the estimated probability displayed in edit mode in the lead form.
probability and automated_probability are not computed fields as they are manually computed at write and create.
The computation is triggered if one of the activated frequency fields is modified or set.
To trigger also the computation when modifying the lead values on the lead views (form and kanban),
_onchange methods have been added for each frequency field.
Also, a cron has been added to run every day to rebuild the frequency table and to recompute all active
and pending leads (not won nor lost) probability.
Task ID : 1925439
PR #33589
remove rerun cron on action lost and won
This commit prepares the next Predictive Lead Scoring (aka PLS) ones.
With the new PLS implementation, stage based probablility is not relevant anymore
as the probability will be computed based on multiple criteria
following the Naive Bayes probabilist theorem.
To determine if the stage is a won stage, a new 'won_stage' boolean field replaces
the old probability field that is now removed.
won_stage = True is equivalent to stage.probability = 100.
Task ID : 1925439
PR #33589
This commit moves phone validation from bridge module to crm directly.
This commit prepares the PLS feature (see next commits).
PLS needs the phone state to evaluate the probability to closes a lead.
So as crm will depend of phone_validation, the content of the bridge
module is moved in crm module.
Task ID : 1925439
PR #33589
As Flanker can be used to validate an email address and was originally
used in website_crm_score module, the Flanker usage is now moved into tools.
This commit prepares the next Predictive Lead Scoring (aka PLS) ones
as PLS will use the email state as computation variable,
it will need this flanker validation to compute first the email state.
We use also the already implemented normalized email as a double validation.
Flanker is not in the required dependencies of Odoo :
So if flanker is installed, it will check if email is valid
(checking DNS and other standard rules).
If Flanker is not installed, email_validate will only normalize the email.
Anyway, the email must at least be normalizable.
Task ID : 1925439
PR #33589
Have a translation linked to a record unreadable because of a record rule
(e.g. a product that is not shared between companies).
Display the translations list view; if one such translation is in the view,
it will raise an access error.
When computing the source value, _compute_source will fail to read the record,
and raise an access error.
This will make it impossible to access untranslated terms.
Instead we guard this error.
Since it is displayed in the view, we display an informative message.
Note that since we make this error go away, we also fix the check method.
Only the superuser bypasses the record rules; so if we made the check on write
with _is_admin, it means than a user in group_erp_manager cannot read a record
but can edit its translations.
opw 2000817
closesodoo/odoo#33989
Signed-off-by: Nans Lefebvre (len) <len@odoo.com>
Since 72f7139f52, config.debug does not exist anymore, config.isDebug()
should be used.
Two commits merged at the same time were still using config.debug, 87a35d4263
and 88a26235caCloses#33961
In order for the map view to work properly:
- I moved scss property to a file only scoped to website module.
- moved the definiton of "partner_latitude" and "partner_longitude" from
base_geolocalise to base/res.partner
closesodoo/odoo#32487
Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
Since recent changes in multi company of odoo, the self.env.company is
only the preffered company and not the only selected anymore. So the
currency of a pos config is based on the pos config one and has nothing
to do with the one choosen by the current user.
closesodoo/odoo#33947
Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
The variable 'shop' that was set for POS receipt, was actually the stock
location and has been removed. But we forgot to remove its use in
pos_retaurant.
related commit: 8e30349fd1
Sale adds valued products in the default category, some tests change the
valuation of the default category and input_aml is hence wrong since it
contains aml of other products. Create a new product and category to
avoid side efffects.
Also, copying a product template and accessing its variant doesn't seem
to work anymore, i don't know why yet.
task-1875873
The examples are implemented at TestStockValuationChangeCostMethod.
The idea is that we want to keep some trace of cost method change and
keep the consistency of the data (eg what about a fifo stack when
changing to standard, that sort of things). We thus implement a simple
logic: when changing the cost method, empty the current valued stock
with the old cost method and refill the stock with the new one.
Some cost method changes are neutral accounting wise, others not.
The rationale is that cost method changes are a hard configuration changes
and databases where users changed cost method are undebuggable because
it is not possible to understand the resulting accounting entries.
The change of valuation (auto to manual and conversely) is not well
defined at the moment.
task-1875873
We need to increment the value of another layer. We don't want to write
on this layer in place as we used to do for multiple reasons:
- valuation at date: before the application of an lc, the value should
not change
- if the layer was consumed, we would need to adapt the consumers and
if one day we would have needed to understand what happened in the
fifo stack it would be hell
So we allow to create a valuation layer linked to another valuation
layer through a simple M2O O2M. At the time it is only used on the
landed costs to add value and no quantity so the code expects it would
be the case and it is not enforced. We adapt `_run_fifo` to use the full
value.
We also add a stat button on the landed cost to access the valuation
layers, like what is done for the picking and manufacturing orders.
task-1875873
Marking the invoice as open before creating the account moves breaks the
anglo saxon code as the invoice is considered openned before the account
moves are even created, see _get_anglo_saxon_price_unit of sale_stock
and the computation of qty_done (which should be renamed invoiced qty).
We did not test all the implications of this commit since the invoice
model will be removed anyway.
related to rev 299f9f1eb0
task-1875873
The tests of this module showed multiple issues with the anglos axon
accounting entries creation so we fix them by getting the value on the
valuation layer and not directly on the stock moves.
About the changes in
test_crossdock.py
> To change a standard price, we need to open the wizard
test_lifo_price.py
> To change a standard price, we need to open the wizard + read the
valuation on the layers.
test_stockvaluation.py
> Now that we create a layer in and out for a dropshipped move, the
accounting entries are similar to an in followed by an out, thus we need
to increment the number of generated AML. Not that the balance of the
accounts stay the same.
There's a slight change in fifo_perpetual_anglosaxon_ordered though.
Let's say for a start that this config doesn't make sense. Ordered means
we don't read the value on the stock move to create the accounting
entries but only the standard price. We had to change 8 by 10 in this
test because, before this task, the standard price was updated when
running fifo, even in dropshipped. As the PO line was valued at 8, the
anglos axon in stock out was at 8 because the standard price was changed
to 8 after the delivery.
task-1875873
No more hijacking _account_entry_move with context keys.
_get_accounting_data_for_valuation
> no changes
_prepare_account_move_line
> only use the cost, not the value in context
> take description as arg to pass it to _generate_valuation_lines_data
_generate_valuation_lines_data
> use the description received in arg
> remove forced ref in context
_create_account_move_line
> add a qty, descritpion, cost, svl_id as arguments
> remove forced_quantity fron context
_account_entry_move
> add a qty, descritpion, cost, svl_id as arguments
task-1875873