diff --git a/dms_partner_attachment_link/README.rst b/dms_partner_attachment_link/README.rst new file mode 100644 index 000000000..e49014ce0 --- /dev/null +++ b/dms_partner_attachment_link/README.rst @@ -0,0 +1,92 @@ +==================================== +DMS Partner related attachments Link +==================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a61f8d1ea1456465ff0a0f416e59e8ba923a39072c6350bdc369a5e0fc6f0870 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdms-lightgray.png?logo=github + :target: https://github.com/OCA/dms/tree/16.0/dms_partner_attachment_link + :alt: OCA/dms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_partner_attachment_link + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds a DMS Attachment smart button to the partner form, +which opens a view containing a list of all DMS files stored in the +attachment storages and related to the Odoo records associated with the +selected partner. + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +Sometimes we need to collect all files related to a partner in one +place. In OCA DMS, we can collect at least the files stored in the +attachment storages. + +Usage +===== + +Open the partner form view and click the button to see a list of files +stored in the attachment stores and related to the current partner. + +Known issues / Roadmap +====================== + +- Add related folders to the view + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Cetmix + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/dms `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/dms_partner_attachment_link/__init__.py b/dms_partner_attachment_link/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/dms_partner_attachment_link/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/dms_partner_attachment_link/__manifest__.py b/dms_partner_attachment_link/__manifest__.py new file mode 100644 index 000000000..e505f1101 --- /dev/null +++ b/dms_partner_attachment_link/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +{ + "name": "DMS Partner related attachments Link", + "summary": """ + This module adds a button to the Partner form, linking to + related files stored in the attachment storage. + """, + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "Cetmix, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/dms", + "depends": ["dms"], + "data": [ + "views/res_partner_views.xml", + "views/dms_file_views.xml", + ], +} diff --git a/dms_partner_attachment_link/models/__init__.py b/dms_partner_attachment_link/models/__init__.py new file mode 100644 index 000000000..91fed54d4 --- /dev/null +++ b/dms_partner_attachment_link/models/__init__.py @@ -0,0 +1 @@ +from . import res_partner diff --git a/dms_partner_attachment_link/models/res_partner.py b/dms_partner_attachment_link/models/res_partner.py new file mode 100644 index 000000000..2a46b0279 --- /dev/null +++ b/dms_partner_attachment_link/models/res_partner.py @@ -0,0 +1,121 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class Partner(models.Model): + _inherit = "res.partner" + + dms_file_ids = fields.Many2many( + comodel_name="dms.file", + string="DMS Attachments", + compute="_compute_dms_files", + ) + dms_file_count = fields.Integer(compute="_compute_dms_files") + + @api.model + def _get_partner_relations_in_models(self, models): + """ + Finds all m2o fields with comodel 'res.partner' in + a given list of models + + :param models: List of model names + :type models: list[str] + + :return: Dictionary where key is model name + and value is list of m2o field names + """ + partner_relations = {} + for model in models: + fields = self.env[model]._fields + partner_relations[model] = [ + field_name + for field_name, field in fields.items() + if field.type == "many2one" and field.comodel_name == "res.partner" + ] + return partner_relations + + @api.model + def _map_partner_dms_files(self, files: list, relations: dict): + """ + Map all found files to partner ids + + :param files: List of attachment files + :type files: list[dict] + :param relations: Dictionary where key is model name + and value is list of m2o field names + + :return: Dictionary where key is partner id + and value is list of file ids + """ + partner_files = {} + for file in files: + if file["res_model"] == "res.partner": + if file["res_id"] not in partner_files: + partner_files[file["res_id"]] = [] + partner_files[file["res_id"]].append(file["id"]) + + elif file["res_model"] in relations: + linked_record = self.env[file["res_model"]].browse(file["res_id"]) + for field_name in relations[file["res_model"]]: + partner_id = linked_record[field_name].id + if partner_id: + if partner_id not in partner_files: + partner_files[partner_id] = [] + partner_files[partner_id].append(file["id"]) + + partner_id = file["res_id"] + if partner_id not in partner_files: + partner_files[partner_id] = [] + partner_files[partner_id].append(file["id"]) + return partner_files + + def _compute_dms_files(self): + """ + Compute DMS files + related to these partners + """ + dms_storage_obj = self.env["dms.storage"] + attachment_storages = dms_storage_obj.search([("save_type", "=", "attachment")]) + attachment_files = attachment_storages.mapped("storage_file_ids").read( + ["res_id", "res_model"] + ) + partner_relations = self._get_partner_relations_in_models( + list(set(map(lambda x: x["res_model"], attachment_files))) + ) + partner_files = self._map_partner_dms_files(attachment_files, partner_relations) + for partner in self: + partner.dms_file_ids = self.env["dms.file"].browse( + partner_files.get(partner.id, []) + ) + partner.dms_file_count = len(partner.dms_file_ids) + + def action_open_dms_attachments(self): + """ + Open action windows for DMS attachments + related to this partner + + :return: Action Window + :rtype: dict + """ + self.ensure_one() + action = self.env.ref("dms.action_dms_file").read()[0] + action.update( + { + "context": { + "create": 0, + }, + "domain": [ + ("id", "in", self.dms_file_ids.ids), + ], + "kanban_view_ref": self.env.ref( + "dms_partner_attachment_link." + "view_dms_file_kanban_inherit_partner_link" + ).id, + "tree_view_ref": self.env.ref( + "dms_partner_attachment_link." + "view_dms_file_tree_inherit_partner_link" + ).id, + } + ) + return action diff --git a/dms_partner_attachment_link/readme/CONTEXT.md b/dms_partner_attachment_link/readme/CONTEXT.md new file mode 100644 index 000000000..53af6b41c --- /dev/null +++ b/dms_partner_attachment_link/readme/CONTEXT.md @@ -0,0 +1 @@ +Sometimes we need to collect all files related to a partner in one place. In OCA DMS, we can collect at least the files stored in the attachment storages. \ No newline at end of file diff --git a/dms_partner_attachment_link/readme/DESCRIPTION.md b/dms_partner_attachment_link/readme/DESCRIPTION.md new file mode 100644 index 000000000..56def8e4b --- /dev/null +++ b/dms_partner_attachment_link/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module adds a DMS Attachment smart button to the partner form, which opens a view containing a list of all DMS files stored in the attachment storages and related to the Odoo records associated with the selected partner. \ No newline at end of file diff --git a/dms_partner_attachment_link/readme/ROADMAP.md b/dms_partner_attachment_link/readme/ROADMAP.md new file mode 100644 index 000000000..73c94b2db --- /dev/null +++ b/dms_partner_attachment_link/readme/ROADMAP.md @@ -0,0 +1 @@ +* Add related folders to the view \ No newline at end of file diff --git a/dms_partner_attachment_link/readme/USAGE.md b/dms_partner_attachment_link/readme/USAGE.md new file mode 100644 index 000000000..511ec3eaa --- /dev/null +++ b/dms_partner_attachment_link/readme/USAGE.md @@ -0,0 +1 @@ +Open the partner form view and click the button to see a list of files stored in the attachment stores and related to the current partner. \ No newline at end of file diff --git a/dms_partner_attachment_link/static/description/icon.png b/dms_partner_attachment_link/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/dms_partner_attachment_link/static/description/icon.png differ diff --git a/dms_partner_attachment_link/static/description/index.html b/dms_partner_attachment_link/static/description/index.html new file mode 100644 index 000000000..ee243d734 --- /dev/null +++ b/dms_partner_attachment_link/static/description/index.html @@ -0,0 +1,439 @@ + + + + + +DMS Partner related attachments Link + + + + + + diff --git a/dms_partner_attachment_link/views/dms_file_views.xml b/dms_partner_attachment_link/views/dms_file_views.xml new file mode 100644 index 000000000..4f4bbed03 --- /dev/null +++ b/dms_partner_attachment_link/views/dms_file_views.xml @@ -0,0 +1,32 @@ + + + + + dms.file.view.kanban.inherit.partner.link + dms.file + + primary + + + + o_kanban_small_column align-content-start + + + + + + + res.partner.view.tree.inherit.partner.link + res.partner + + primary + + + + + + + + diff --git a/dms_partner_attachment_link/views/res_partner_views.xml b/dms_partner_attachment_link/views/res_partner_views.xml new file mode 100644 index 000000000..9ceffbf85 --- /dev/null +++ b/dms_partner_attachment_link/views/res_partner_views.xml @@ -0,0 +1,26 @@ + + + + + res.partner.view.form.inherit.dms + res.partner + + +
+ +
+
+
+ +
diff --git a/setup/dms_partner_attachment_link/odoo/addons/dms_partner_attachment_link b/setup/dms_partner_attachment_link/odoo/addons/dms_partner_attachment_link new file mode 120000 index 000000000..f92c3cd0c --- /dev/null +++ b/setup/dms_partner_attachment_link/odoo/addons/dms_partner_attachment_link @@ -0,0 +1 @@ +../../../../dms_partner_attachment_link \ No newline at end of file diff --git a/setup/dms_partner_attachment_link/setup.py b/setup/dms_partner_attachment_link/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/dms_partner_attachment_link/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)