1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/documents_project/models/documents_folder.py
2024-12-10 09:04:09 +07:00

116 lines
5.5 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.osv import expression
class DocumentFolder(models.Model):
_inherit = 'documents.folder'
def default_get(self, fields):
res = super().default_get(fields)
if self.env.context.get('documents_project') and not res.get('parent_folder_id'):
res['parent_folder_id'] = self.env.ref('documents_project.documents_project_folder').id
return res
project_ids = fields.One2many('project.project', 'documents_folder_id')
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
domain = domain or []
if 'project_documents_template_folder' in self.env.context:
template_folder_id = self.env.context.get('project_documents_template_folder')
domain = expression.AND([
domain,
['!', ('id', 'child_of', template_folder_id)]
])
return super()._name_search(name, domain, operator, limit, order)
@api.ondelete(at_uninstall=False)
def unlink_except_project_folder(self):
project_folder = self.env.ref('documents_project.documents_project_folder')
project_folder_ancestors = {int(ancestor_id) for ancestor_id in project_folder.parent_path.split('/')[:-1]}
if project_folder_ancestors & set(self.ids):
raise UserError(_('The "%s" workspace is required by the Project application and cannot be deleted.', project_folder.name))
@api.constrains('company_id')
def _check_no_company_on_projects_folder(self):
if not self.company_id:
return
projects_folder = self.env.ref('documents_project.documents_project_folder')
if projects_folder in self:
raise UserError(_("You cannot set a company on the %s workspace.", projects_folder.name))
@api.constrains('company_id')
def _check_company_is_projects_company(self):
for folder in self:
if folder.project_ids and folder.project_ids.company_id:
different_company_projects = folder.project_ids.filtered(lambda project: project.company_id != self.company_id)
if not different_company_projects:
continue
if len(different_company_projects) == 1:
project = different_company_projects[0]
message = _('This workspace should remain in the same company as the "%s" project to which it is linked. Please update the company of the "%s" project, or leave the company of this workspace empty.', project.name, project.name),
else:
lines = [f"- {project.name}" for project in different_company_projects]
message = _('This workspace should remain in the same company as the following projects to which it is linked:\n%s\n\nPlease update the company of those projects, or leave the company of this workspace empty.', '\n'.join(lines)),
raise UserError(message)
def _copy_and_merge(self, vals=None):
if not self:
return self.env['documents.folder']
if vals is None:
vals = {}
if 'name' not in vals:
vals['name'] = _('Merged Workspace')
merged_folder = self.create(vals)
descriptions = []
for folder in self:
if folder.description:
descriptions.append(folder.description)
for facet in folder.facet_ids:
facet.copy({'folder_id': merged_folder.id})
self.env['documents.tag'].flush_model(['folder_id'])
old_facet_id_to_new_facet_id, old_tag_id_to_new_tag_id = folder._get_old_id_to_new_id_maps(merged_folder)
folder._copy_workflow_rules_and_actions(merged_folder, old_facet_id_to_new_facet_id, old_tag_id_to_new_tag_id)
for child_folder in folder.children_folder_ids:
child_folder.with_context({
'ancestors_facet_map': old_facet_id_to_new_facet_id,
'ancestors_tag_map': old_tag_id_to_new_tag_id,
}).copy({'parent_folder_id': merged_folder.id})
merged_folder.description = '<br/>'.join(descriptions)
return merged_folder
def _get_project_from_closest_ancestor(self):
"""
If the current folder is linked to exactly one project, this method returns
that project.
If the current folder doesn't match the criteria, but one of its ancestors
does, this method will return the project linked to the closest ancestor
matching the criteria.
:return: The project linked to the closest valid ancestor, or an empty
recordset if no project is found.
"""
self.ensure_one()
eligible_projects = self.env['project.project'].sudo()._read_group(
[('documents_folder_id', 'parent_of', self.id)],
['documents_folder_id'],
having=[('__count', '=', 1)],
)
if not eligible_projects:
return self.env['project.project']
# dict {folder_id: position}, where position is a value used to sort projects by their folder_id
folder_id_order = {int(folder_id): i for i, folder_id in enumerate(reversed(self.parent_path[:-1].split('/')))}
eligible_projects.sort(key=lambda project_group: folder_id_order[project_group[0].id])
return self.env['project.project'].sudo().search([('documents_folder_id', '=', eligible_projects[0][0].id)], limit=1)