This commit introduce a full redesign of all JS views. We started
basically from scratch. The goal was to unify all the various views
under a common framework, to make them testable, to make then usable in
different conditions (in studio, or in the frontend), and to make our
lives easier.
Some important points are:
- we introduced new coding guidelines (camelCase, 80 chars width, ...)
- we have a brand new testing framework (still QUnit based)
- kanban view moved to the web addon
- calendar view (formerly web_calender) moved to web as well
- the tree view was removed
- all new code should be documented
We hope that this code is the start of a new era for the Odoo web
client, we want to have a high quality codebase, well documented, well
tested, well designed.
Work done by the framework team: mostly aab, ged, chm, dmo, qsm
Previously availability of meta-information (failing constraint,
impacted table and column, …) in pg errors (e.g. constraint check
failure) was limited and only available through formatted error
messages, which could be localised (by PG itself) so not did getting
that information require string extraction it was brittle in the face of
localised instances.
Postgres 9.3 adds this meta-information to error diagnostic data
(`PQresultErrorField`), allowing easy programmatic access to it.
Psycopg2 [added a Diagnostic
object](http://initd.org/psycopg/docs/extensions.html#psycopg2.extensions.Diagnostics)
around the time pg9.3 was itself released.
Assuming Odoo now requires pg >= 9.3 we can remove the old string
munging extraction for diagnostic.
* funny story, the handling of 23505 didn't actually work because
"duplicate key value violates unique constraint" is a literal part
of the error message, I'd misunderstood "value" as a field name
because my test model's field was called "value". Makes sense too
since you can set UNIQUE constraints on multiple fields (and UNIQUE
indices on expressions)
* for both errors, it should be possible to use the table_name or
constraint metadata to provide messages about sub-model issues (a
constraint on an m2o), but that's not currently handled
Fixes#15323
The fields objects are responsible for creating their column/table and indexes.
The methods that update the schema are overridden to handle cases specific to
each type of field.
Simplify the API as much as possible, and delegate all the implementation
details to the models `ir.model`, `ir.model.fields`, `ir.model.constraint` and
`ir.model.relation`.
When using read_group() and grouping by many2one fields, the many2one groupby
fields get updated from an integer id to a tuple from name_get() at the end
of the method.
e.g.: {'user_id': 1, ...} -> {'user_id': (1, u'Administrator'), ...}
To do this, it reads the many2one field by browsing on self.
When self is a model with _auto = False (typically an SQL view), searching by
id can be costly as the id column may not have usual properties for performance
(in some cases a full computation of the table is required to look up 1 id).
With the user who is trying to access and the record they are trying to access
to.
This way it is easier to understand the reason of the error.
Do not show record and user ids in the popup as it is a technical information.
Closes#13030
`model` field of `ir.model` may be used as related stored field.
Marking it as modified force recomputation of these, even no change
occurs (by definition).
This removal has led to a necessary refactoring:
- make the setup of field attributes extensible;
- make the instantiation of custom fields extensible;
- delegate model and field reflection to `ir.model` and `ir.model.fields`;
- move the implementation of sparse and serialized fields to module `base_sparse_field`;
split fields_view_get() and used an abstact mixin class in place of of FormatAddress
[IMP] base: added a m2o field (ir.ui.view) on res.country to decide the layout of the form view to input addresses.
The dictionary `_group_by_full` is replaced by a field parameter `group_expand`
that is assigned to the method name. The API of the method has been simplified
as well:
@api.multi
def _read_group_stage_ids(self, domain, read_group_order=None, access_rights_uid=None):
# the stages are given by self.ids (wrong model);
# read_group_order is the order given to read_group() on self;
# return stages.name_get(), {stage.id: stage.fold)
_group_by_full = {'stage_id': _read_group_stage_ids}
is now written:
stage_id = fields.Many2one(..., group_expand='_read_group_stage_ids')
@api.model
def _read_group_stage_ids(self, stages, domain, order):
# stages is a recordset;
# order is the order to use on stages' model;
# return a recordset which is a superset of stages