This fixes a very obscure bug that happens on workers serving multiple
databases. Consider two databases A and B with the same model M, that
does not have a field 'name', but has a custom field 'x_name' only on
database A. The bug can be reproduced with the module 'account' and its
model 'account.register.payments'.
Assume the server loads a registry for database A. In that registry,
the model M uses 'x_name' as its _rec_name, and the field 'display_name'
on model M determines its dependencies to be the field 'x_name'.
Now assume the server load a registry for database B. In that registry,
the model M has no _rec_name. However, an optimization reuses the field
'display_name' for the model M on the registry of A. The field's
attribute 'depends' is equal to the tuple ('x_name',). When the ORM
tries to resolve the field's dependencies, it does not find the field
'x_name' on M and crashes.
In order to avoid this situation, we forbid the usage of 'x_name' as
_rec_name on non-custom models.
OPW 2349238
closesodoo/odoo#61534
X-original-commit: 731e676fa8a9f7bdc6a66056c124c3b39a0800ad
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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.
closesodoo/odoo#60429
X-original-commit: 231bdca3f26d96f578503694e5aec062de2317ed
Related: odoo/enterprise#14285
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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.
closesodoo/odoo#59919
X-original-commit: 6778c4c10fa68c46bde6fae176f547f905e9c02f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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
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.
closesodoo/odoo#59034
X-original-commit: b9201ebdd65eaabab9257cf97c58410681783fa6
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Calling a compute method on 1M records inevitably brings a worst case in
cache prefetching: the code that determines which records to fetch has
time complexity O(N²). We avoid this situation by calling the compute
method on maximum 1K records. Each computed batch has a "prefetch set"
of maximum 1K records too, which avoids the worst-case scenario above.
closesodoo/odoo#58664
X-original-commit: 0b1aa660b1d94fe46dea09670b875f2d81ca36a3
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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`.
closesodoo/odoo#58144
X-original-commit: aebe9a76c9b35e84eda1f46bec3ef6da152b1539
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This prevents some code (in controllers) to retrieve an attachment for a
field that is not stored, as the code only relies on `field.attachment`.
This also makes the field definition more consistent.
closesodoo/odoo#57980
X-original-commit: 7325c3f8c538a8b8c0435963cdda3ced6fe4b324
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Non-stored readonly computed fields must be assigned by compute method.
Make the error message more explicit.
closesodoo/odoo#56269
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Consider models `M` and `L`, with a one2many field `M.l_ids` with
inverse `L.m_id`. Consider also a computed field `L.foo` that depends
on `L.m_id`.
The field `L.foo` is not computed correctly by `onchange` on a new line
in the form view of `M`: its value is forced to `False` because it has
no default, and is not recomputed by `onchange` since the field `L.m_id`
is never triggered an `onchange`.
Modify the method `onchange` to not force fields without a default to
`False`, and return all fields.
When setting the inverse many2one field on a record, the record is not
removed from its inverse relation if the field's current value is not in
cache. Fix this by setting the field's value in cache before updating.
closesodoo/odoo#54711
X-original-commit: df12c85816dfa59f298c3e6a077bd88e4b7aa6a6
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Before this commit, calling `mapped()` on a relational field of a single
record inside a for loop does not correctly propagate the prefetch ids
from the bigger recordset down to the record inside the loop:
[rec.line_ids.mapped('name') for rec in recs]
To be more precise, `recs` correctly propagates prefetching information
down to `rec.line_ids`, but method `mapped()` does not pass it along to
the record that triggers the prefetching.
This resulted in one query per record in `recs`, so if `recs` were a
1000 records recordset, at least 1000 queries would be necessary.
With this commit, the `mapped()` function correctly propagates the
`_prefetch_ids` of the larger recordset (`rec.line_ids`) so that the
prefetching works properly and the 1000 queries are brought down to 1.
This commit is a followup on #42611.
closesodoo/odoo#54565
X-original-commit: 0e97053fee36c0c76b70cb94be5340c3144b178b
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
An onchange method can remove an existing line from a one2many field of
a new record with command 2, such as:
move.line_ids = [(2, <NewId origin=42>), ...]
The processing of the command 2 above incorrectly tries to remove the
new line from the origin record, instead of the new record.
closesodoo/odoo#54545
X-original-commit: 7d138a445acbd9f2e122d9c30ca81877bae6a245
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Given an scenario in which a field F of model M is defined in module X
as `required=True` and is extended by another module Y as
`required=False` in a database with data not satisfying the original
constraint:
During an upgrade of base the original constraint will be re-applied
on the data (and fail) even though it is no longer necessary because
module Y relaxes the NOT NULL constraint.
This failure in and of itself is non-blocking, the upgrade will go
through but an error and a warning are logged anyway which are not
problematic either except in the case of automated testing
infrastructure (such as runbot), because of this it would be best if
these errors would not be logged at all unless we're 100% sure that the
constraint that was applied is not relaxed downstream.
With this commit, the `finalize_constraints` method will verify that the
constraint is applicable (field is required) before re-applying the NOT
NULL constraint.
opw-2269220
closesodoo/odoo#53529
X-original-commit: f09f4826fbdd1a547503c51a3cfad71285312c49
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
`state` was special cased in `copy_data` such that it would always be
reset to its default value if it had one.
While this special case can be useful (maybe) and is certainly
ingrained in odoo, having it not be overridable can be
problematic. Move the special case to the fields, so it's possible to
explicitly mark state fields as copy.
closesodoo/odoo#53113
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This fix looks like good practice to avoid confusing developers when
writing compute methods for fields, and should not be necessary. But it
actually fixes an extremely obscure bug in the computation of the field
`sale.order.invoice_status` when dealing with timesheets (module
sale_timesheet_enterprise). The bug seems triggered by the fact that
the field is computed on both a given sales order and a new record with
that sales order as origin.
X-original-commit: f9c128c6f567dfaab5cfb0080e4fdc847942911a
It was considered important to precise that image fields without
limitations weren't checked
at all and could therefore contain non image content (and precise some
other things on Image fields).
Forward-port of #51200closesodoo/odoo#51259
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
If the original field is defined with a selection list, overrides with
method or methods names fall back on the list.
closesodoo/odoo#51232
X-original-commit: 272ba8d2238d1d1b87f47b114b55e6eed25314a8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
The supported case of check_company on `res_company` model fields was
not considered when specifying a default domain on `check_company=True`
fields.
closesodoo/odoo#48674
Nb: It is already correctly supported in the `_check_company()` method.
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
The following loop crashes on the second iteration:
for record in records:
record.display_name # access non-stored computed field
record.unlink() # delete record
The cache has been invalidated by `unlink` on the first iteration, so
the field is computed. The computation is done on the whole recordset,
which fails with a `MissingError` because of the first record. The fix
is to retry the recomputation on the single record in this case.
closesodoo/odoo#50910
X-original-commit: 7f33ebf528b1415452ce549e3329c3fe89be0ad8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
When setting a many2one field, the corresponding one2many fields are
updated in cache. When such a one2many field has a domain, the
evaluation of the domain may require to fetch some fields from the
database. If the `towrite` cache has not been updated yet, the many2one
field is overridden by the database value.
Fix by setting the `towrite` cache before updating inverse fields.
closesodoo/odoo#50788
X-original-commit: c1ebfe05a66cfebc7ced36e25db5f6ff4bfb2d46
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Consider a sales order with a single line. Edit the sales order: remove
the line, and add another line with the same subtotal. When saving, the
total of the sales order is 0.0.
Here is the explanation: the form view performs a `write` on the sales
order, and modifies the lines with a command `2` (remove line) and a
command `0` (create line).
After deleting the first order line, the cache is emptied, and a call to
`flush()` forces the recomputation of the total. The value is computed
to be 0, and assigned to the field. The assignment converts the value
for the cache, without prefetching the currency field (optimization),
and puts 0.0 in cache. The assignment then converts the value for the
database, which prefetches most fields on the sales order: the cache is
now inconsistent and contains the old value V, while the database is
then updated with 0.0.
After creating the new order line, the total is once again recomputed.
Its value is V, and because the cache also contains that value, no
update is performed to the database, which remains at 0.0!
The fix consists in avoiding the prefetching of fields when accessing
the currency field to round a monetary value.
opw-2223134
closesodoo/odoo#49741
X-original-commit: 048ea2f20a0a2fa6d629cbe262cbbe765248d36f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
* add a `raw` computed field, though only update some of base to use
it (addons for which that makes sense can be migrated progressively)
* avoid working with base64 data when it's possible to work with the
actual data
* improve datas (base64 encoded content): should depend on bin_size
closesodoo/odoo#47212
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
The method `_init_column` for the field `alias_id` of `mail.alias.mixin`
requires the reflection of models, because `mail.alias` records have a
many2one field to `ir.model`. The actual initialization of the column
is thus performed in post-init phase (after reflection). Therefore, the
NOT NULL constraint cannot be added right away.
X-original-commit: 2e3400f149ce4ed4c00bc49a519f58993b49bc51
This greatly reduces the number of queries to add foreign keys (notably
for many2one fields).
This saves 6.5% of the total installation time.
X-original-commit: 13a2666b4da09fc0ec7608a974dadde45f76fd7a
Reduce the number of queries to create and drop indexes.
This saves 1.5% of the total installation time.
X-original-commit: 0e1e480da9d971575feba64038c4fa518ebe102b
Simply avoid browsing records for models, and use classes instead.
This saves 1% of the total installation time.
X-original-commit: 35ebaea098edeb3d34f77305b09cb36e56ea5a92
This optimization is no longer necessary. Thanks to Python 3.6's new
implementation of dicts, the memory footprint difference between slots
and dicts is now around 5%, which is no longer worth the complexity and
performance cost.
This saves 2% of the total installation time.
X-original-commit: c7f17770803744cbbb741fc11265ee914641aed7
Simplify the code to retrieve fields on a class.
Simplify the class attribute that lists the class' proper fields.
Optimize `model._add_inherited_fields()`.
Optimize `resolve_mro` by using classes instead of recordsets.
This saves 3.5% of the total installation time.
X-original-commit: 89ab71905cb6c5d3beda5eac357f8592e31aaef8
Repeated calls to `registry.setup_models()` will eventually introduce
many duplicates in the those attributes, which may slow down the
determination of computation triggers.
X-original-commit: 735e65f7ca45616881336121d10a874412446dcf
Co-authored-by: Xavier Morel <xmo@odoo.com>
Before this commit, a lot of leftover import shims existed in the
codebase for py2-py3 compatibility, these are no longer needed since
Odoo 13.0+ doesn't support Python 2 anymore and is (finally) in EOL.
With this commit, these shims are dropped, making the code cleaner,
easier to read and with one less dependency.
Queue -> queue -> py2-py3 compatibility
xmlrpclib -> xmlrpc.client -> py2-py3 compatibility
ConfigParser -> configparser -> py2-py3 compatibility
itertools.izip_longest -> itertools.zip_longest -> py2-py3 compatibility
urllib -> urllib.request -> py2-py3 compatibility
__builtins__ -> builtins -> py2-py3 compatibility
_winreg -> winreg -> py2-py3 compatibility
mock -> unittest.mock -> merged into CPython
The debian/fedora packages and requirements.txt have been updated accordingly
closesodoo/odoo#44601
Related: odoo/enterprise#8141
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
* = event, website_event_track, website_sale, website_hr_recruitment,
website_livechat, website_sale, website_slides
The option to sanitize or not the forms was not available, this will
allow better flexibility on whether forms should be sanitized or not on
an HTML field.
Also we use this new param to allow forms to be added on some already
existing html fields where forms where sanitized out.
task-2209554
closesodoo/odoo#47318
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
- Let A and B be two different modules.
- A defines a required Selection field F of model M and B extends
it through the `selection_add` argument.
- Create records of model M and have some of them have any of the
options introduced by module B selected for field F.
- Uninstall module B.
The result will be records of Model M with an option for field F that no
longer exists, this makes the registry inconsistent and prone to
crashing (it is sufficient to access the form view of such a record to
trigger a crash).
This commit introduces a mechanism similar to the `ondelete` argument
found in Many2one fields, the argument name is the same but it's
different both in behaviour and in implementation.
The `ondelete` mechanism for Selection fields is enforced for **any**
Selection field with required set to `True`, this means that the
developer is required to set a cleanup behaviour for when their module
is uninstalled. For possible cleanup options, see fields.Selection's
docstring.
As far as implementation goes, everything is implemented in Python
unlike with Many2one fields where the behaviour is delegated to
PostgreSQL.
The `ondelete` setting will be processed during
`ir.model.fields.selection.unlink()` to ensure that the registry is left
in an appropriate state after module uninstall.
Purpose of this commit is to let computed stored editable fields being
copied if their field class allows it.
Indeed the value of those fields is computed based on some triggers but
can also be updated manually by users. When copying a record, it makes
sense to consider that this value is what the user expects and allow its
copy, if the original field allows it. Either it was computed, and
copied value will be correct without having to call computation again
(well, provided all dependencies have been copied, too), or it was
updated and the copied value will be the one the user entered.
Without this fix, an edited field is not copied, and will be recomputed,
which may look like an inconsistent value.
Task ID 2209163
closesodoo/odoo#48383
X-original-commit: 4b274d3b4101fbae154a572cdf40d23838899773
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
The use case is a cache miss of a stored field with compute on a new
record with origin. The field should be computed only when explicitly
triggered, i.e., when a dependency has been modified. Otherwise it
should be fetched from the origin record.
closesodoo/odoo#47353
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Before this commit, when a user try to import data with a XLSX file, the
file was mistaken by an SVG file. This issue arises because a XLSX file
from import isn't encoded in base64, and for testing if the file is an
SVG file it will be decoded. base64.b64decode by default (when validate
is False), will remove all characters that are in the base-64 alphabet
from the input prior to decode. So in our case, when the non encoded
XSLX file is force decoded the results starts, unluckily, with '<' and
it's mistaken by an XML/SVG file. Note that, the XSLX file is wrongly
tested because a XSLX file is just a ZIP file, and all the ZIP files
start with PK\x03\x04, and P is the first byte of a base64 encoded XML
file.
Now, only files that were previously encoded into base64 are decoded to
be tested. The validate = True parameter in base64.b64decode will raise
a binascii.Error if there are a non-base64-alphabet characters in the
input, this will allow us to know if the input was or wasn't base64
prior encoded. As base64.b64decode with validate = False, removed the
non-base64-alphabet characters this allows to decode input files
compatible with RFC 2045 (MIME). The files compatible with this standard
will have a newline character (b'\n') after every 76 bytes of the
output, and end with a newline. To keep backwards compatibility, we
remove the newlines and the carriage return from the input before the
decoding.
opw-2194468
closes#36081closes#31849closes#33543closesodoo/odoo#47906
X-original-commit: 65d709c9ab386d646f682c494cfb21cb06ec8034
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Jorge Pinna Puissant (jpp) <jpp@odoo.com>
Co-authored-by: Xavier Morel <xmo@odoo.com>
Before this commit, x2m fields were described as 'sortable'
This was odd since:
- When actually sorting on one of those fields through the webclient
the sorting was gibbrish
- Even the orm silently warned in the log that
the field was not a sql column and therefore was not sortable
After this commit, only a field which is column (and a few other conditions)
can be sorted
Task 1863492
closesodoo/odoo#46921
X-original-commit: dd3094378fc322447d1aef994f6bace3f0c24288
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
Remove a leftover special case of the ORM from a former version.
This fixes a performance issue, where an onchange recomputes a field on
one2many lines one by one.
X-original-commit: 16a75d85741db8a1f87c1d26503a9bb75197cf83
This makes the behavior of `onchange()` consistent in the case of
inherited models (with `_inherits`).
closesodoo/odoo#45910
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
When a field is related, defining a selection or selection_add will
have no effect and the paramater is ignored.
Log a warning and fix all fields badly definied
Closesodoo/odoo#45716closesodoo/odoo#45832
Related: odoo/enterprise#8613
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>