mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-19 22:12:01 +02:00
166 lines
6.4 KiB
Python
166 lines
6.4 KiB
Python
# Copyright 2020 Creu Blanca
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.osv import expression
|
|
|
|
|
|
class DmsDirectory(models.Model):
|
|
_inherit = "dms.directory"
|
|
|
|
parent_id = fields.Many2one(default=lambda self: self._default_parent())
|
|
|
|
@api.model
|
|
def _default_parent(self):
|
|
return self.env.context.get("default_parent_directory_id", False)
|
|
|
|
@api.constrains("res_id", "is_root_directory", "storage_id", "res_model")
|
|
def _check_resource(self):
|
|
for directory in self:
|
|
if directory.storage_id.save_type == "attachment":
|
|
continue
|
|
if (
|
|
directory.is_root_directory
|
|
and directory.storage_id.model_ids
|
|
and not directory.res_id
|
|
):
|
|
raise ValidationError(
|
|
_("Directories of this storage must be related to a record")
|
|
)
|
|
if not directory.res_id:
|
|
continue
|
|
if self.search(
|
|
[
|
|
("storage_id", "=", directory.storage_id.id),
|
|
("id", "!=", directory.id),
|
|
("res_id", "=", directory.res_id),
|
|
("res_model", "=", directory.res_model),
|
|
],
|
|
limit=1,
|
|
):
|
|
raise ValidationError(
|
|
_("This record is already related in this storage")
|
|
)
|
|
|
|
@api.model
|
|
def _build_documents_view_directory(self, directory):
|
|
return {
|
|
"id": "directory_%s" % directory.id,
|
|
"text": directory.name,
|
|
"icon": "fa fa-folder-o",
|
|
"type": "directory",
|
|
"data": {"odoo_id": directory.id, "odoo_model": "dms.directory"},
|
|
"children": directory.count_elements > 0,
|
|
}
|
|
|
|
@api.model
|
|
def _check_parent_field(self):
|
|
if self._parent_name not in self._fields:
|
|
raise TypeError("The parent (%s) field does not exist." % self._parent_name)
|
|
|
|
@api.model
|
|
def search_read_parents(
|
|
self, domain=False, fields=None, offset=0, limit=None, order=None
|
|
):
|
|
"""This method finds the top level elements of the hierarchy
|
|
for a given search query.
|
|
|
|
:param domain: a search domain <reference/orm/domains> (default: empty list)
|
|
:param fields: a list of fields to read (default: all fields of the model)
|
|
:param offset: the number of results to ignore (default: none)
|
|
:param limit: maximum number of records to return (default: all)
|
|
:param order: a string to define the sort order of the query
|
|
(default: none)
|
|
:returns: the top level elements for the given search query
|
|
"""
|
|
if not domain:
|
|
domain = []
|
|
records = self.search_parents(
|
|
domain=domain, offset=offset, limit=limit, order=order
|
|
)
|
|
if not records:
|
|
return []
|
|
if fields and fields == ["id"]:
|
|
return [{"id": record.id} for record in records]
|
|
result = records.read(fields)
|
|
if len(result) <= 1:
|
|
return result
|
|
index = {vals["id"]: vals for vals in result}
|
|
return [index[record.id] for record in records if record.id in index]
|
|
|
|
@api.model
|
|
def search_parents(
|
|
self, domain=False, offset=0, limit=None, order=None, count=False
|
|
):
|
|
"""This method finds the top level elements of the
|
|
hierarchy for a given search query.
|
|
|
|
:param domain: a search domain <reference/orm/domains> (default: empty list)
|
|
:param offset: the number of results to ignore (default: none)
|
|
:param limit: maximum number of records to return (default: all)
|
|
:param order: a string to define the sort order of the query
|
|
(default: none)
|
|
:param count: counts and returns the number of matching records
|
|
(default: False)
|
|
:returns: the top level elements for the given search query
|
|
"""
|
|
if not domain:
|
|
domain = []
|
|
res = self._search_parents(
|
|
domain=domain, offset=offset, limit=limit, order=order, count=count
|
|
)
|
|
return res if count else self.browse(res)
|
|
|
|
@api.model
|
|
def _search_parents(
|
|
self, domain=False, offset=0, limit=None, order=None, count=False
|
|
):
|
|
if not domain:
|
|
domain = []
|
|
self._check_parent_field()
|
|
self.check_access_rights("read")
|
|
if expression.is_false(self, domain):
|
|
return []
|
|
query = self._where_calc(domain)
|
|
self._apply_ir_rules(query, "read")
|
|
from_clause, where_clause, where_clause_arguments = query.get_sql()
|
|
parent_where = where_clause and (" WHERE %s" % where_clause) or ""
|
|
parent_query = 'SELECT "%s".id FROM ' % self._table + from_clause + parent_where
|
|
no_parent_clause = '"{table}"."{field}" IS NULL'.format(
|
|
table=self._table, field=self._parent_name
|
|
)
|
|
no_access_clause = '"{table}"."{field}" NOT IN ({query})'.format(
|
|
table=self._table, field=self._parent_name, query=parent_query
|
|
)
|
|
parent_clause = "({} OR {})".format(no_parent_clause, no_access_clause)
|
|
order_by = self._generate_order_by(order, query)
|
|
from_clause, where_clause, where_clause_params = query.get_sql()
|
|
where_str = (
|
|
where_clause
|
|
and (" WHERE {} AND {}".format(where_clause, parent_clause))
|
|
or (" WHERE %s" % parent_clause)
|
|
)
|
|
if count:
|
|
# pylint: disable=sql-injection
|
|
query_str = "SELECT count(1) FROM " + from_clause + where_str
|
|
self._cr.execute(query_str, where_clause_params)
|
|
return self._cr.fetchone()[0]
|
|
limit_str = limit and " limit %s" or ""
|
|
offset_str = offset and " offset %s" or ""
|
|
query_str = (
|
|
'SELECT "%s".id FROM ' % (self._table)
|
|
+ from_clause
|
|
+ where_str
|
|
+ order_by
|
|
+ limit_str
|
|
+ offset_str
|
|
)
|
|
complete_where_clause_params = where_clause_params + where_clause_arguments
|
|
if limit:
|
|
complete_where_clause_params.append(limit)
|
|
if offset:
|
|
complete_where_clause_params.append(offset)
|
|
# pylint: disable=sql-injection
|
|
self._cr.execute(query_str, complete_where_clause_params)
|
|
return list({x[0] for x in self._cr.fetchall()})
|