From 4d98f20cc292474b0d8c31b91a2658fd4ef5b0e7 Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Mon, 29 Dec 2025 13:49:37 +0700 Subject: [PATCH] first commit --- __init__.py | 1 + __manifest__.py | 16 +++++ __pycache__/__init__.cpython-312.pyc | Bin 0 -> 213 bytes security/ir.model.access.csv | 2 + wizard/__init__.py | 1 + wizard/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 249 bytes ..._attachment_cleanup_wizard.cpython-312.pyc | Bin 0 -> 2664 bytes wizard/sh_survey_attachment_cleanup_wizard.py | 68 ++++++++++++++++++ ...survey_attachment_cleanup_wizard_views.xml | 34 +++++++++ 9 files changed, 122 insertions(+) create mode 100644 __init__.py create mode 100644 __manifest__.py create mode 100644 __pycache__/__init__.cpython-312.pyc create mode 100644 security/ir.model.access.csv create mode 100644 wizard/__init__.py create mode 100644 wizard/__pycache__/__init__.cpython-312.pyc create mode 100644 wizard/__pycache__/sh_survey_attachment_cleanup_wizard.cpython-312.pyc create mode 100644 wizard/sh_survey_attachment_cleanup_wizard.py create mode 100644 wizard/sh_survey_attachment_cleanup_wizard_views.xml diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..4027237 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..3e968bf --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +{ + 'name': 'Survey Attachment Cleanup', + 'version': '18.0.1.0.0', + 'summary': 'Batch delete survey image attachments', + 'category': 'Tools', + 'author': 'Suherdy Yacob', + 'depends': ['base', 'survey', 'website'], + 'data': [ + 'security/ir.model.access.csv', + 'wizard/sh_survey_attachment_cleanup_wizard_views.xml', + ], + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a92110f3fab21f4f1a1ba884a0c38a7d1def6b6 GIT binary patch literal 213 zcmX@j%ge<81ZNb2GDU&(V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zY~`6%iA5=XnoPGCikN|7D;Yk6bp8s`&&bbB)h{m1NG(dK)DNgE$;i)3&QD3z&riwE zH?+`CE-fy}&rM88$VNJ$c z%EcM+#id1Msg?1GB_)Z;8M&!>CGp8Qsfl@|1@YyXRf$C@ews|T7>byI8dfrV1{wP+ zQa>XBU#O5Zz(e}hBLi- zGNN0Eh`a-d#BEGu+6IYs46zY6+2?1Tqv&)x|6^+_CT{-w+cT7FA75Q_pai!?b5iH$(|J zmo`j3iPG7bwt7;!7}atrG&`lZmdWM}B-KBOm~yHSW}O%g!1OwKOA3rTm9&cJB9ivd zb~~|_Kml9@AAJVEECZP-W|l30lm*)@Alpd{DW~@u_X=$7oMt)5&GJ(K^54@qOp0&B z**ZR1U{mgw?NETO{XO>MK!U5ilOg%3J*fT-+ z)GVv|G{TaR&mxl|9NpS@wXgc*3LNn9qcqjbV_VHDReG+j{3$ckzT^aFIW+0YC*?RX1TU+J_y zqP1Qa14%7|2J~DKVVECyFK;9@HBN@jfCe?~^!b5!PB%zE2uZ&a7-i?KMzy&&U~_Lk zPf7=3BpVaS=5Y(H;afIO>x|gN^~iy=pfgQhB4Q3~c62=ly-j_^=w{%|7RPq97Nc8U zaJaK{ed&6+`)nn6t{NP!1c#p{)`DZjvCXcd#dn{JyoK|DKu6Ut{^l1q0v)B6rIv?< z<;f=}s)JW5gIB79(aK=7eC*nK;QE%!iTF^e1pBMO3zgu7r{~s!qs6g}6Q_#N-+jH$ zt}!HyZITq&#Y{S*EoSyP%uF@%mcq%ZO+p3`rZI$R3}JvXpKXLK3DcNVZR$5{Ko)ZQ zd!%-lP>1hf+CKLYqa4A)k%~C-Q^zm4vN*CP zepvQ&Z~8-3|EY@q)SAD)?CHlRND32Szv+=ARn8zuGQAR=X1O%geUkKXPEI>Jf(0Q) zi1avCva}|cR?75@%W8hGb_}Nb9o0Zn2-~M{j36-O0lg3DWYet?fcuE)F|abQ%8cnf zVhI{kze~hC*zld68{0T^cJAh8o4D9f>RIY})cIs+y={2z#)hw}7+sinF!8AWX;uwbc6ND-t^bdcDi9Cu{LqnC&(7%8@SnmG;Od^V} literal 0 HcmV?d00001 diff --git a/wizard/sh_survey_attachment_cleanup_wizard.py b/wizard/sh_survey_attachment_cleanup_wizard.py new file mode 100644 index 0000000..8c038ad --- /dev/null +++ b/wizard/sh_survey_attachment_cleanup_wizard.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models + +class SurveyAttachmentCleanupWizard(models.TransientModel): + _name = 'sh.survey.attachment.cleanup.wizard' + _description = 'Survey Attachment Cleanup Wizard' + + website_id = fields.Many2one('website', string="Website") + limit = fields.Integer(string="Batch Limit", default=0, help="Limit number of deletions per batch (0 for no limit)") + attachment_count = fields.Integer(string="Attachments Found", compute='_compute_attachment_count') + + @api.depends('website_id') + def _compute_attachment_count(self): + for record in self: + domain = [ + ('answer_type', '=', 'upload_file'), + ] + + # Find all relevant lines first + lines = self.env['survey.user_input.line'].search(domain) + + total_count = 0 + # Iterate to count attachments + # NOTE: this might be slow for huge datasets, but accurate given the m2m structure + # To optimize, we could do SQL, but ORM is safer for now given < 15k records + + # We can't easily search ir.attachment directly because the relationship is via m2m table + # `survey_user_input_line_rel` (or similar, depending on define). + # Actually, `value_file_data_ids` is Many2many('ir.attachment') + + # Let's collect IDs first (limit to reasonable number if performance issue?) + # But count needs to be accurate-ish. + + # Filter attachments + # We search ir.attachment directly to find ALL matching files, including orphans. + # Criteria: Mimetype JPEG, Website Matches, No Res Model (typical for M2M/Orphans) + + domain = [ + ('mimetype', '=', 'image/jpeg'), + ('res_model', '=', False), + ('res_field', '=', False), + ] + + if record.website_id: + domain.append(('website_id', '=', record.website_id.id)) + + # Count directly + count = self.env['ir.attachment'].search_count(domain) + record.attachment_count = count + + def action_delete_attachments(self): + self.ensure_one() + + domain = [ + ('mimetype', '=', 'image/jpeg'), + ('res_model', '=', False), + ('res_field', '=', False), + ] + + if self.website_id: + domain.append(('website_id', '=', self.website_id.id)) + + # Search with limit if needed + limit = self.limit if self.limit > 0 else None + attachments_to_delete = self.env['ir.attachment'].search(domain, limit=limit) + + return attachments_to_delete.unlink() + diff --git a/wizard/sh_survey_attachment_cleanup_wizard_views.xml b/wizard/sh_survey_attachment_cleanup_wizard_views.xml new file mode 100644 index 0000000..c3c57c9 --- /dev/null +++ b/wizard/sh_survey_attachment_cleanup_wizard_views.xml @@ -0,0 +1,34 @@ + + + + sh.survey.attachment.cleanup.wizard.form + sh.survey.attachment.cleanup.wizard + +
+ + + + + +
+
+
+
+
+ + + Survey Attachment Cleanup + sh.survey.attachment.cleanup.wizard + form + new + + + + +