Commit Graph
286 Commits
Author SHA1 Message Date
Raphael Collet 4347491670 [FIX] core: unexpected display_name "False"
If a form view contains the field 'display_name', when creating a new
record, the initial value of 'display_name' is the string "False", and
that weird value also appears in the breadcrumb instead of "New".  In
order to avoid this unexpected behavior, the conversion of a value to a
display name should be False, like any other field would.

closes odoo/odoo#81788

Signed-off-by: Raphael Collet <rco@odoo.com>
2021-12-22 09:39:08 +00:00
Raphael Collet 1616d47efa [FIX] core: computed inversed fields partly assigned
This fixes inconsistencies when dealing with fields that are computed
and inversed by the same methods.

Consider two fields F1, F2 with the same compute and inverse methods.
Consider a record where we wrote on a dependency of the common compute
method.  At this point, both fields F1 and F2 are marked to be computed.

Now let us write on F1 only.  Here is what happens:
 - the write discards the computation of F1, but not F2
 - the inverse method of F1 is called:
    - the method accesses F2
       -> this calls the compute method, which assigns both F1 and F2
    - the method accesses F1
       -> the value of F1 has been replaced by the computation above

The issue comes from a combination of factors:
 - the value of F2 must be determined by the computation;
 - the computation assigns both F1 and F2;
 - the computation is done while inversing F1 (and F2).

The solution is to force the computation before actually writing on the
fields and calling their inverse methods.  Note that this is necessary
only when part of the fields computed by a common method are updated.
When all fields computed by a common method are updated, the computation
will automatically be cancelled.

closes odoo/odoo#81172

X-original-commit: fb4d6ee4ba8bcb5cd8030105ac57e9e02850bfc4
Signed-off-by: Raphael Collet <rco@odoo.com>
2021-12-09 20:26:52 +00:00
Raphael Collet 6af689fd0a [FIX] base: fix search on company depend fields
This is a bunch of fixes (65 corner cases) for the search on
company-dependent fields:

Without a default value:
- `char` fields:
    - operators `not like`/`not ilike` don't return records with unset value
    - `(..., '=', False)` doesn't return records with unset value
    - `(..., '!=', '<string>')` doesn't return records with unset value
    - `(..., 'in', [..., False])` doesn't return records with unset value
    - `(..., 'not in', value)` without `False` inside `value` doesn't return records with unset value
- `date` and `datetime` fields:
    - `(..., '!=', <Date/datetime>)` doesn't return records with unset value
    - `(..., '=', False)` doesn't return records with unset value
- `many2one` fields:
    - operators `not like`/`not ilike` don't return records with unset value
    - `(..., 'in', [..., False])` doesn't return records with unset value
    - `(..., 'not in', value)` without `False` inside `value` doesn't return records with unset value
- `boolean` fields:
    - `(..., '=', False)` and `(..., '!=', True)` don't return records with unset and `False` values
- `integer`/`float` fields:
    - `(..., '!=', <number>)` doesn't return records with unset value

With a truthy default value:
- `many2one` fields:
    - operators `not like`/`not ilike` don't return records with unset value
    - `(..., '=', False)` returns the record with the default value (which isn't `False`)
- `boolean` fields:
    - `(..., '=', False)` doesn't return records with unset and `False` value
    - `(..., '!=', False)` returns records with unset and `False` value
- `integer`/`float` fields:
    - all `(..., operator, value)` which include value 0, return all records with unset value, even if the default value does not satisfy the domain

closes odoo/odoo#80994

X-original-commit: 3e3be652ece83420782070bdb13da2c3a4930046
Signed-off-by: Raphael Collet <rco@odoo.com>
2021-12-07 17:10:48 +00:00
d04a5b5c8c [REF] core: compute fields before database insertion.
Until now, stored compute fields were computed after database insertion.
This meant that required fields should not be computed, for instance,
unless some hackish code was added to make it work.  Another trick was
to provide some default value, but this actually prevents the field for
being computed after insertion.

This commit provides a field parameter to specify that the field should
be precomputed: adding precompute=True on the field definition force the
method create() to compute its value before inserting the new record in
the database.  For the reason explained below, precomputing fields is
not always correct, and therefore the default remains to not precompute
a field.

Some stored fields must be computed after insertion, for instance:
* statistics fields computed with search/read_group/...
* fields referencing the current record (res.partner.commercial_partner_id)
* fields referencing another record that does not exist yet (think about
  records created by one2many fields)
* fields depending on the create_date/write_date/create_uid/write_uid

Those fields shouldn't be defined with precompute=True, which triggers
their computation post record creation.  This is why, by safety, we
consider the default behavior to be precompute=False.

closes odoo/odoo#80449

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Yannick Tivisse <yti@odoo.com>
2021-11-30 14:30:48 +00:00
Raphael Collet aa0cdacced [FIX] core: related field attributes
A related field copies the attributes from its target field, except for
the attributes defined on the related field itself.  The implementation
of this feature was not working properly for attributes with a truthy
default value.

closes odoo/odoo#79025

X-original-commit: dec4a7ec478fa02f19dee8c8426c88d17dc3c7f3
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-10-26 16:06:48 +00:00
Jeremy Kersten 300954d8c4 [IMP] base: auto resize attachment to 1080p
After some analyze on a lot of customer databases, seems like most of the time
their are performance probleme, and big store, it is due to  a lot of big file
uploaded without reason. E.g. barcode, photo, ... a small one will be enough.

Now, we decided (in stable) to auto resize these pictures to 1920x1920px
by default and compress it with a quality of 80 when the source is bigger.

You can bypass this behaviour in your specific use case,
using a context key: 'image_no_postprocess' set to True.

You can disable the resize (and quality implicitely)
using an icp: 'base.image_autoresize_max_px' set to '0'.

You can change the default resize (1920x1920) format using an icp:
'base.image_autoresize_max_px' set to '<width>x<height>' (e.g. '1024x768')

You can change the default quality (80) using an icp:
'base.image_autoresize_quality' with a value between 0 and 100 where 0 skip it.

You can change the type of file that will be post process using icp:
'base.image_autoresize_extensions' (subtype of the mimetype comma separated).

Api of image has not be changed in this commit, only refactored to allow to
work with image directly without the need to encode/Decode in base64 the raw.

We decide to keep 1920x1920 by default instead of 1080p to avoid to resize
portrait picture in 1080px and stay consistent with field image_1920 that
return a 1920px image for width or height whatever the orientation.

+ fix some lint diff for ci style in master

closes odoo/odoo#78556

X-original-commit: d9ce0507960f247e1187baf7bd8399f90be237aa
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
2021-10-22 17:34:29 +00:00
Raphael Collet 56660e39e6 [FIX] core: one2many linking non-existing lines
The processing of the LINK command in a one2many should fail when the
line being linked does not exist.  However, there is one case where it
should not fail: when that line existed and was linked before applying
the commands.  That use-case may seem strange, but it actually exists:
deleting a line in a sales order automatically deletes the corresponding
reward lines.

closes odoo/odoo#78318

X-original-commit: 4bfe1b5cab10d3171d386d76799a7d7729f49154
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-10-13 18:24:42 +00:00
william-andre d3f4ce1152 [IMP] core: allow set [value] in selection ondelete
In some cases we migh want to change to a value that isn't the default
one when uninstalling.
For instance: when we uninstall the module `event_sale`, a product has
the field `detailed_type` set to `event`, which is a subtype of `service`.
So we want to update the value to `service` when uninstalling instead of
the default value, which would be `consu` and wouldn't make any sense.

Part-of: odoo/odoo#77876
2021-10-11 10:15:48 +00:00
Raphael ColletandWilliam André 71fc2e55f9 [FIX] core: inherited computed fields in onchange
Assume that model A has a computed field G that depends on both fields
F1 and F2.  Assume that model B inherits from A (_inherits).  When G is
computed during an onchange, it must use the form values for all its
dependencies F1 and F2.  Before this commit, only the field triggering
the onchange was assigned on the parent record (see (*) below.)

                      record        parent
    --- ------------+-------------+------------
     initial state  | F1=0, F2=0  | F1=0, F2=0
     assign F1=1    | F1=1, F2=0  | F1=1, F2=0
     assign F2=2    | F1=1, F2=1  | F1=0, F2=1 (*)

The commit also includes another patch: when assigning the parent
record, the ORM determines the dependent records (in this case, the main
record in the onchange).  If the delegate field (many2one from B to A)
has an inverse one2many field, the ORM uses that field to determine
dependent records.  However, in the case of a new record, that field is
not in cache, and its value is determined to be... empty!  The patch
consists in "fixing" the value of that field when we determine the
parent record (when the delegate field is accessed.)

Part-of: odoo/odoo#76042
Co-authored-by: William André <wan@odoo.com>
2021-09-06 18:29:03 +00:00
Florent de Labarre 9e1e0ebb02 [FIX] core: better error message on wrong related path definitions
Before this commit, if a related field's path definition contained a
non-existing field (either because of a typo or field removal) the ORM
would simply send a generic Python KeyError that didn't really help in
debugging.

With this commit, we raise our own KeyError stating which related field
has the wrong path definition and exactly which field within the path is
incorrect.

See test for an example.

closes odoo/odoo#31889

Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2021-07-16 10:17:30 +00:00
Raphael Collet 376ed8dc5f [FIX] core: in onchange, do not force delegate fields to False
The use-case is when a "parent" field is put on the form view, as a
readonly field, and we create a new record.  Before the fix, the fields
that depend on the parent record are always False, until the record is
actually created.

closes odoo/odoo#73446

X-original-commit: ff2af932c3b73dc59620a4ce17da3a13cab12cbe
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-07-08 15:29:20 +00:00
Raphael Collet be73b9ae26 [FIX] core: in onchange, assign inherited fields that have changed
This allows onchange to recompute fields that depend on the inherited
field that has changed.  The use-case we have is a model that inherits
from 'account.move'.  On its form view, setting the (inherited) journal
field does not recompute the (inherited) company field.

When the field 'journal_id' is modified, the onchange should:
 - assign the new value to move_id.journal_id (*)
 - recompute move_id.company_id (related='journal_id.company_id')
 - recompute company_id

This commit adds the missing part (*).

X-original-commit: 2e05d0a361aa06a34eecf64613821f2e92295298
2021-07-08 15:29:17 +00:00
Raphael Collet ddcabf3acb [FIX] core: origin of main record in onchange
When invoking onchange() on a line in a one2many field, the inverse
many2one field is given as a dict of values.  Those values are the ones
of the "container" record in the form view, and they include the "id" of
the container record.  The method onchange() instantiates the container
record as a new record with the given values.  Fix the code to set the
expected "origin" of that record to the record with the given "id".

closes odoo/odoo#71491

X-original-commit: ebfb5d90fd4ff65ee1d2fc73faf8f9eaa18f4521
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-05-31 12:01:55 +00:00
Raphael Collet 8ff079366d [FIX] core: computed editable one2many field with a domain
Manually adding a line should not trigger the computation of the field,
just like modifying the line fields that occur in the field's domain.
In other words, the dependencies of the field should be limited to the
ones declared on field or its compute method.

closes odoo/odoo#71049

X-original-commit: 1c39814bd729cc08882f1545c7d88b0592e63f9a
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-05-19 16:29:53 +00:00
Raphael Collet 1abe965b59 [IMP] core: keep field.related as a string
This mainly keeps field.related's type consistent.

On a registry with 296 modules, this saves 325 kilobytes of memory,
which is about 3% of the registry's memory footprint.
2021-05-10 14:29:42 +00:00
Raphael Collet cd12293386 [IMP] core: speed up loading of registry
The base classes of models in the registry are modified when models are
extended by inheritance.  But modifying cls.__bases__ is a costly
operation, so we manage to do it once per model when loading a registry.

Our benchmark consists in loading a registry with 296 modules.  The net
time to load the registry is 25% smaller.  In other words, the registry
loads 25% faster.  Note that the time does not include the time to load
modules themselves, which does not change.
2021-05-06 07:20:00 +00:00
Raphael Collet 81ff2717cf [REM] core: remove optimization sharing fields across registries
The optimization will be reintroduced later in a different form.
2021-05-03 12:33:29 +00:00
Raphael Collet 960cd72774 [REF] core: add method get_currency_field() on Monetary to retrieve it
This replaces the setup of the attribute 'currency_field', which depends
on the presence of other fields on the model, and may therefore vary
from one registry to another.  This is necessary to make monetary fields
shareable across registries.
2021-05-03 12:33:29 +00:00
Raphael Collet 34d6f87d54 [REF] core: put field.depends on registry and make field.recursive explicit
The attributes field.depends and field.depends_context are problematic
for sharing fields across registries, because they depend on the model's
registry class, which may vary from one registry to another.  In order
to make computed fields shareable, we have to move those values away
from fields.

For the same reason, field.recursive should not be inferred, because its
value may depend on the registry, although it is generally not the case.
Moreover, the flag recursive=True is set on a field when field triggers
are determined (on the registry).  A compute method may be called before
the flag is set (if no update has been done yet), and that can lead to
incorrect computations.

This happened in test TestUsers2.test_reified_groups in module 'base'.
The user groups view was apparently determined without the flag being
set, and the view depends on the recursive field 'trans_implied_ids',
which was not correctly computed.

We thus force developers to be explicit about recursive computed fields.
The code now logs a warning when the flag is not set up properly.
2021-05-03 12:33:29 +00:00
Raphael Collet 1ca2c7e457 [REF] core: new field setup API
The basic setup of fields is now made in Field.__set_name__(), which
automatically makes this information shared across registries, because
it is done when importing Odoo modules.
2021-05-03 12:33:29 +00:00
Adrian Torres ab7b5af3e8 [FIX] base: properly execute Selection field ondelete actions
With this commit, 2 changes are made to the way that the
fields.Selection.ondelete cleanup action works:

1) We manually delete ir.model.fields.selection **before** the deletion
of ir.model.fields purposefully to **avoid** SQL CASCADE deletes, as we
do not know which selections are deleted in cascade and thus we cannot
perform the corresponding ondelete cleanup action (which is implemented
within the ORM).

2) In some actions, namely 'set default' and 'set null', we write a
"safe" value to the records containing the Selection being deleted,
before this commit this would go through the ORM (records.write()) but
this is problematic if there's a write override for the record's model
that raises an error for the field being written to. With this commit,
we first try to go through the ORM but if there's a failure (because of
the raise in a write override) then we will bypass the ORM and set it
with SQL.

opw-2451126

closes odoo/odoo#67616

X-original-commit: f5c7e861ee3ca0cdeb6c2f06d227ada07f923ed0
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2021-03-11 06:45:42 +00:00
Adrian Torres 75243d5a43 [FIX] base: do not assign default ondelete policy for base fields
Previously, an ondelete policy would be assigned to any required
Selection fields, the default policy being 'set null'.

Base fields do **not** require an ondelete value, since if they are
deleted there is no "data fix" to apply because the field's column is
dropped, and in fact it's error-prone to do so because during
`_process_ondelete`, the system would attempt to set to null fields that
were required (i.e. NOT NULL).

This issue is hidden by the fact that ir.model.fields are usually
deleted **before** ir.model.fields.selection and thus the ondelete
action won't be applied on the field with the original definition
(because it has probably been deleted by SQL CASCADE)

X-original-commit: 2e238f1e0202d65a98177939dac166dd659bb39c
2021-03-10 16:45:06 +00:00
Christophe MonniezandRaphael Collet c23b13eafe [FIX] models: call inverse method right after cache invalidation
When a record is written on a computed field with an inverse method and
an x2many field wit a delete command, the computed field is not properly
handled by the inverse method, because of a whole cache invalidation
that happens during the unlink.

With this commit, we write in cache on the fields that have been
invalidated before invoking the inverse method.

opw #2439861

closes odoo/odoo#67525

X-original-commit: d39855bad5153654d443d1b7ede3907f8bae3e66
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
2021-03-09 11:24:09 +00:00
Raphael Collet b652d84cd1 [FIX] core: convert_to_write() of x2many field with new records
When comparing the values of a new record with its origin, x2many fields
are always different because we compare new records with real records.
For instance, converting the value of a one2many field where lines have
a many2many field always returns update commands for the many2many
field.

closes odoo/odoo#66950

X-original-commit: 03a4137cc3fa398dbd0cb214dc5472a083ae33b8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-02-26 16:32:16 +00:00
Raphael ColletandVictor Feyens 840609975a [IMP] core: better way to set/update magic fields
The goal of this change is to simplify the code managing `create_date`
and `write_date` in methods `create()` and `write()`, and also to remove
weird behaviors caused by the way those fields were updated.

Assume we update a simple field on a record.  This adds pending updates
for the field and `write_date`.  However, the value of `write_date` is
not known yet: it will be updated as `NOW() AT TIME ZONE 'UTC'` in SQL.
So `write_date` is actually given a dummy value in pending updates, and
it is invalidated from cache, until its value is flushed to the database
and fetched again.

Now assume we access another field on the record, and that field is not
in cache.  The prefetching mechanism will read all column fields,
including `write_date`, and flush them first.

    # this adds pending updates foo: 42, write_uid: 1, write_date: False
    record.foo = 42

    # assume 'bar' is not in cache; this prefetches all column fields,
    # which flushes the pending updates above before reading them back
    result = record.bar

We can avoid flushing pending updates if the values read from database
do not overwrite existing values in cache.  If you assume that the value
of a pending update is in cache (in the example, `foo: 42`), you don't
need to flush the corresponding field.  Indeed, the value of `foo` will
remain 42 in cache, whatever its value in the database.  This assumption
(pending updates are in cache) is true for all fields *except* for
`write_date`: it is invalidated from cache, and given a dummy value in
pending updates.  This branch actually makes this assumption true for
all fields.  The avoidance of flushing pending updates will be done in
another commit.

In order to directly assign `write_date` its value, we use a cache for
the value `NOW() AT TIME ZONE 'UTC'` from the database.  This costs at
most one query per transaction, and potentially saves a few queries.

Co-authored-by: Victor Feyens <vfe@odoo.com>
2021-02-22 16:20:55 +00:00
Raphael Collet be100b8b6c [FIX] core: flush domain before searching for records in many2many field
This guarantees the cache consistency of the many2many field values.

closes odoo/odoo#66299

X-original-commit: 421631d7f222f1fcc3381c79320e109562533f22
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-02-16 17:38:11 +00:00
Raphael Collet 2f93046cf7 [FIX] core: writing on one2many field on new record
When using command "6" (SET), the one2many field's inverse was not
assigned on the lines.

closes odoo/odoo#65675

X-original-commit: ba733a9ac73dcf978ed7eaab7681781b2d5a9bfc
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-02-07 14:32:19 +00:00
Martin Trigaux 76f305a556 [FIX] base: query company dependant as superuser
When retrieving company dependant values, the computed domain called
search_multi method of ir.property as normal user.
Since odoo/odoo@8f57863707 ir.property records are no longer
readable by a normal classical user.

To reproduce:
Add a domain using a company_dependant field
e.g. on res.partner, with purchase installed, modify the parent_id
field in form view to

  <field name="parent_id" ... domain="[('property_purchase_currency_id','=',property_purchase_currency_id)]" />

When clicking on the parent_id with a low priviledge user, an
access-right error is raised, as the user doesn't have access to
ir.property records

Fixes odoo/odoo#65450

closes odoo/odoo#65643

X-original-commit: 33868b4e14124800035ea99df111b35b4199ae60
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2021-02-05 16:20:49 +00:00
Raphael Collet 4de2ec280c [FIX] core: compute editable field with a default should not recompute
Consider a model with a field F and a computed editable field G that
depends on F.  Assume we open a form view, and both F and G have a
default value.  The first onchange should return F and G with their
respective default values.  In other words, the field G should not be
recomputed even if its dependency F was assigned a default value.

The use-case that showed the issue is batch payments.  When adding a new
payment in the one2many field of a batch, the new payment should use the
batch's payment method by default.  The default value for the payment's
method is assigned by context on the one2many field in the view.  Before
this patch, the new payment's method was given by the computation of the
field, and its default value was ignored.

Side note: another test was fixed, but that's because the test was not
consistent with the way Odoo 14.0 manages defaults and onchanges.

X-original-commit: 2ccc735253405b03927e2b08eab57427e65e4050
2021-01-13 16:19:13 +00:00
Raphael ColletandThibault Delavallée 65fd4373c5 [FIX] core: invoke constraint methods once per write
Consider a constraint method with two fields: a normal field, and a
field with an inverse method.  When calling write() with both fields,
the constraint method should be invoked once.

closes odoo/odoo#64433

X-original-commit: 25760348859f594abb796b5bc7b28f63e298cd53
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Thibault Delavallée <tde@odoo.com>
2021-01-12 15:59:10 +00:00
Raphael Collet 1e7659ad48 [FIX] core: avoid access error when flushing
This takes a former patch one step further.

Assume you recompute a field on two records, and the computation assigns
the first record but not the second one.  Before this patch, the
recomputation process was accessing the field on both records.  When
accessing the first record, both records are recomputed, and the value
of the first one is found in cache.  When accessing the second record,
no recomputation is made (it has been done already), and the cache is
empty. The field is thus fetched from database, and this crashes because
of insufficient access rights.

This scenario was causing some obscure nondeterministic crashes in
tests. The nondeterminism comes from the choice of the environment for
flushing (it should not be in superuser mode); the order of records in
the set to compute; the order in which records are assigned in the
compute method; the fact that the compute method should assign some
records and some not.

The fix consists in adding a method that processes pending computations,
without doing anything special for unassigned records.  The method is
used in field accessors (__get__ and mapped) and in method recompute().
The access error is gone because the recomputation no longer tries to
get the value of a field to compute.

closes odoo/odoo#64264

X-original-commit: b7676ec33172e6196b5fd1eda4df730ebf90eb6b
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-01-08 13:06:25 +00:00
Guewen BaconnierandRaphael Collet e14b52a56d [FIX] core: marking of stored computed recursive fields during creation
Fixes 3a6ac95 that ignores computation of recursive stored fields during
creation of records.

The problem happens when we have:

* a recursive stored computed field
* an `api.depends` of this field which is a relation to another record

When this "another record" is created and should recompute the recursive
field, it is ignored.

closes odoo/odoo#64117

X-original-commit: 9fe4fe404b73e9ab18ab6b3b913f075c64bb6954
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet (rco) <rco@openerp.com>
2021-01-05 19:09:16 +00:00
Raphael Collet 0a098aceaf [FIX] core: marking and traversing computed fields before modification
This fixes an issue that occurs when marking fields to compute in the
following situation:
 - it occurs before the actual modification,
 - a relational field is marked to compute,
 - the same field is traversed to inverse some dependency.

When the marking occurs after the modification, the traversal of the
field should actually recompute the field.  However, if the marking
occurs before the modification, the inversion of dependencies must be
based on the current value of the field.  This is the case with method
unlink(): we call method modified() to mark the fields that currently
depend on the records to be deleted, and the fields must be computed
only after the deletion!

X-original-commit: cd19c2d93db8911fe42802640ea32e5d87aadeec
2021-01-04 09:16:20 +00:00
svs-odoo 603d907450 [FIX] core: avoid duplicate onchanges
When performing the onchange for the first time on a new record, if a
field has a default value, it could be two times in the `todo` field
list to compute.

closes odoo/odoo#64005

X-original-commit: cf2b0a505c117a50a91fa022bc1d6bf1eb6d9f77
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-01-04 12:16:46 +00:00
Raphael Collet dcc2a7e39d [FIX] core: first onchange should always compute fields
When a form view is opened, the first call to `onchange` should always
compute fields, even if their dependencies have no default value.  Make
sure it is the case for main records, and for records inside one2many
fields.  The latter case was actually not working as expected.

closes odoo/odoo#63646

X-original-commit: 45422d56bce413b8577f1784e10dd22ede93c751
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-12-21 13:55:20 +00:00
Adrian Torres 1c8a958098 [IMP] core: introduce api.ondelete decorator
With this commit, a new ORM api decorator is introduced:
`api.ondelete(*, at_uninstall)`.

This decorator is to be applied to Model methods that check for specific
business conditions when attempting to unlink a record via the
interface.

E.g. trying to unlink a validated journal entry

This decorator allows this logic to exist outside the `BaseModel.unlink`
method and is automatically bypassed when in uninstall mode, this means
that during an uninstall any and all data related to a module can and
will be removed easily and cleanly while still being able to apply
business logic to manual deletion of records.

This feature opens the gates to solving a very big problem with
uninstalls: records and tables that remain in a database despite the
relevant module being uninstalled, because if an override to unlink
raises an error, the data will never be deleted from the database.

Henceforth, overrides of unlink shall solely be used for data-cleaning
purposes, i.e. deletion or modification of data that is related to the
one currently being deleted but cannot be automatically deleted because
there are no proper SQL relations.

In certain very specific, low-level scenarios an unlink may be
overridden to raise an error, but this should only be done if you know
what the fuck you're doing, most of the time you'll want to resort to
`@api.ondelete`.

Note that this new decorator includes a keyword-only, required argument
called `at_uninstall`, in most business cases this argument shall be
False as this argument dictates whether or not this method should be
executed in the `unlink` call during uninstall. It should only be set to
True if you are certain of all the implications which most likely means
that the records of the model in which this ondelete function is defined
will NOT be removed during uninstall, they will forever linger in the DB
until manual intervention, this in turn can mean a wide range of
undefined problems due to crap left on the database.

Following commits will replace any `unlink` overrides that raise
business errors by methods decorated with `api.ondelete`, another commit
will introduce a pylint checker that will raise a warning any time that
an unlink override raises an error.
2020-12-04 09:15:51 +00:00
Laurent Smet 6f2a6f7f2e [FIX] core: invalidation of computed editable field in one2many
This fixes the issue introduced by revision fd50ba9fb8

The way computed fields are invalidated depends on the order of the dict
passed as a parameter to method onchange().  This causes some unexpected
behavior when dealing with computed editable fields: the user loses the
value in that field because of the onchange.

Explanation: during the onchange, the modified field is cached by

    record._update_cache(changed_values, validate=True)

If the field is a one2many, 'value' contains an update command for each
modified line.  Because of 'validate=True', the assignment triggers
field computations on the lines, which are already handled by another
call to onchange().  In case anything on the parent model modifies some
line, the whole one2many values are returned to the user, and
accidentally recomputed fields show up in the interface.

closes odoo/odoo#62748

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-12-02 15:36:51 +00:00
Julien Castiaux ca903577d2 [REF] test_*: Use Command helper for x2many
Task: 2366606
2020-11-30 10:16:09 +00:00
Raphael Collet b580f74502 [FIX] base, test_new_api: tests on custom fields 2020-11-24 13:23:32 +00:00
Denis LedouxandRaphael Collet 5e6bf8579b [FIX] registry: unit test for #60899
The field `display_name` is a magic field automatically added to all
models.  On a custom model, it depends on `x_name`.

As it is automatically added by the ORM, `display_name` is considered a
`base` field, while `x_name` is considered a `manual` field.

On loading the transitive dependencies of `display_name` of a custom
model, for which the loading of the `x_name` has been skipped because it
depends on field not yet loaded, the exception was not ignored because
exceptions are ignored only for `manual` field, and `display_name` is
considered a `base` field.

Upgrade request 56274

X-original-commit: e57e2798ed7871967487d953ffcdc10884bcf9a2
Co-authored-by: Raphael Collet <rco@odoo.com>
2020-11-19 11:39:38 +00:00
Raphael Collet af6c56711f [FIX] core: avoid access error when flushing
This patch guarantees that computed fields with `compute_sudo=True` do
not cause access errors when fetched from database.

This fixes a non-deterministic access error upon `commit`, where fields
are recomputed and flushed with some random environment.  The method
`recompute` performs its duty by accessing the fields to recompute.  The
compute method of a field is called but does not assign it.  As the
field is not in cache, its value is read from database.  However, as the
latter is not done in superuser mode, it may cause some access error.

closes odoo/odoo#61842

X-original-commit: cfb942ab5902e0992434eb2c7db2940526df404e
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-11-17 11:32:42 +00:00
Raphael Collet 8de95a3fb4 [FIX] core: validation of field parameters
The feature was actually not working as expected.  It has been fixed,
and a test now ensures it does work as expected.  This commit also fixes
some invalid parameters, hopefully nothing critical.

closes odoo/odoo#60429

X-original-commit: 231bdca3f26d96f578503694e5aec062de2317ed
Related: odoo/enterprise#14285
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-10-21 10:18:36 +00:00
Adrian Torres b7017e58cc [FIX] *: adapt business code to function-redefined error
This commit adapts the business code in which
class/module/function/method redefinition took place so that it no
longer happens and the pylint test passes.
2020-10-16 12:56:52 +00:00
Raphael Collet 7a1e0b2ada [FIX] core: assignment of binary field on new record with origin
The assignment of a binary field on a new record with origin did
actually modify the attachment storing the value of the field on the
origin record!  The fix is simply to avoid messing up with attachments
when updating new records.

closes odoo/odoo#59919

X-original-commit: 6778c4c10fa68c46bde6fae176f547f905e9c02f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-10-13 17:28:48 +00:00
Raphael Collet 11d521d918 [FIX] core: assignment of size to new records
Upon onchange, the web client sends unchanged image fields on one2many
lines as "bin size" values, while changed image fields are sent as their
full value.  As the value is not base64-encoded, the assignment of that
value crashes.

Fix it by making assignment on new records not crash when decoding the
image: the value is simply not assigned to the field.  In the situation
described above, the record being assigned is a new record with a real
record as origin.  Because the field is actually not assigned, its value
is implicitly the value of the field on the origin record, which is
consistent with the fact that the field was not modified in the form.

X-original-commit: 4442d6f0f29a2bf6e992515cd535c88215855a36
2020-10-13 17:28:48 +00:00
Xavier-Do 71549030c7 [FIX] core: cache consistency of one2many field with computed inverse
Consider a one2many field with a corresponding many2one field that is
computed.  After modifying the many2one field's dependencies, the cached
value of the one2many field is inconsistent until the many2one field has
been recomputed.  Therefore, one has to force the computation of the
many2one field before accessing the cached value of the one2many field.

closes odoo/odoo#59034

X-original-commit: b9201ebdd65eaabab9257cf97c58410681783fa6
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-10-02 17:20:10 +00:00
Raphael Collet f55fcbe15f [FIX] core: always evaluate field.depends upon setup
This is necessary when a field's dependencies are given by a callable.
This functionality was broken with the support for an explicit parameter
`depends` in the fields' definition, because the implementation could
not distinguish between the field parameter `depends` and the `depends`
evaluated from compute functions.

The fix consists in storing the field parameter `depends` into
`field._depends`, and the result of the setup into `field.depends`.

closes odoo/odoo#58144

X-original-commit: aebe9a76c9b35e84eda1f46bec3ef6da152b1539
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-09-21 14:04:25 +00:00
Raphael Collet 0e6a8b5faf [FIX] core: filtered_domain with operators 'like' and 'ilike'
Make the method work when the value to test is `False`.

closes odoo/odoo#58064

X-original-commit: 6fb19219d333dc324603bcb2a937e977eecb037e
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-09-18 16:20:05 +00:00
Raphael Collet 75ad1559ec [FIX] core: flush() domain returned by search method
Assume field B depends on A, and searching on B is rewritten as a domain
that mentions A.  If A is modified, and then we search on B, one has to
flush A to the database before searching.

closes odoo/odoo#57963

X-original-commit: b242b7b1382ee39ebefa58c556931b7dae77f669
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-09-17 14:33:44 +00:00
Raphael Collet 126ebbc905 [IMP] core: error message for computed field left unassigned
Non-stored readonly computed fields must be assigned by compute method.
Make the error message more explicit.

closes odoo/odoo#56269

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-08-21 09:39:27 +00:00