first commit
This commit is contained in:
commit
8c83703c30
1
__init__.py
Normal file
1
__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import models
|
||||
15
__manifest__.py
Normal file
15
__manifest__.py
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
'name': 'Approval Cleaner',
|
||||
'version': '1.0',
|
||||
'summary': 'Delete approvals older than a specified date',
|
||||
'category': 'Administration',
|
||||
'author': 'Antigravity',
|
||||
'depends': ['approvals'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/approval_cleaner_wizard_views.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
BIN
__pycache__/__init__.cpython-312.pyc
Normal file
BIN
__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
1
models/__init__.py
Normal file
1
models/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import approval_cleaner_wizard
|
||||
BIN
models/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
models/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
models/__pycache__/approval_cleaner_wizard.cpython-312.pyc
Normal file
BIN
models/__pycache__/approval_cleaner_wizard.cpython-312.pyc
Normal file
Binary file not shown.
48
models/approval_cleaner_wizard.py
Normal file
48
models/approval_cleaner_wizard.py
Normal file
@ -0,0 +1,48 @@
|
||||
from odoo import models, fields, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
class ApprovalCleanerWizard(models.TransientModel):
|
||||
_name = 'approval.cleaner.wizard'
|
||||
_description = 'Approval Cleaner Wizard'
|
||||
|
||||
date_end = fields.Date(string="End Date", required=True, help="Delete all approvals created before this date")
|
||||
|
||||
def action_clean_approvals(self):
|
||||
self.ensure_one()
|
||||
# Search for approvals created before the specified date
|
||||
# using 'create_date' as it is the standard Odoo field for creation time.
|
||||
# However, the user request mentioned "Date below specified date i provide".
|
||||
# 'approval.request' has a 'date' field (which seems to be a datetime) and 'create_date'.
|
||||
# I will use 'date' field as per the user's initial description if implicit, but looking at approval_request.py
|
||||
# date = fields.Datetime(string="Date")
|
||||
# So I will use that.
|
||||
|
||||
domain = [('date', '<', self.date_end)]
|
||||
approvals_to_delete = self.env['approval.request'].sudo().search(domain)
|
||||
count = len(approvals_to_delete)
|
||||
|
||||
# Detach attachments to bypass ir.attachment unlink restriction
|
||||
attachments = self.env['ir.attachment'].sudo().search([
|
||||
('res_model', '=', 'approval.request'),
|
||||
('res_id', 'in', approvals_to_delete.ids),
|
||||
])
|
||||
if attachments:
|
||||
attachments.write({'res_model': 'approval.cleaner.temp', 'res_id': 0})
|
||||
|
||||
approvals_to_delete.unlink()
|
||||
|
||||
# Now delete the attachments safely
|
||||
if attachments:
|
||||
attachments.unlink()
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': _('Success'),
|
||||
'message': _('%s approvals have been deleted.', count),
|
||||
'type': 'success',
|
||||
'sticky': False,
|
||||
'next': {'type': 'ir.actions.act_window_close'},
|
||||
}
|
||||
}
|
||||
2
security/ir.model.access.csv
Normal file
2
security/ir.model.access.csv
Normal file
@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_approval_cleaner_wizard,approval.cleaner.wizard,model_approval_cleaner_wizard,approvals.group_approval_manager,1,1,1,1
|
||||
|
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import test_approval_cleaner
|
||||
38
tests/test_approval_cleaner.py
Normal file
38
tests/test_approval_cleaner.py
Normal file
@ -0,0 +1,38 @@
|
||||
from odoo.tests import common
|
||||
from odoo import fields
|
||||
from datetime import timedelta
|
||||
|
||||
class TestApprovalCleaner(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestApprovalCleaner, self).setUp()
|
||||
self.ApprovalRequest = self.env['approval.request']
|
||||
self.category = self.env['approval.category'].create({
|
||||
'name': 'Test Category',
|
||||
'has_date': 'required',
|
||||
})
|
||||
|
||||
# Create approvals with different dates
|
||||
self.approval_old = self.ApprovalRequest.create({
|
||||
'name': 'Old Approval',
|
||||
'category_id': self.category.id,
|
||||
'date': fields.Datetime.now() - timedelta(days=100),
|
||||
})
|
||||
|
||||
self.approval_new = self.ApprovalRequest.create({
|
||||
'name': 'New Approval',
|
||||
'category_id': self.category.id,
|
||||
'date': fields.Datetime.now() - timedelta(days=10),
|
||||
})
|
||||
|
||||
def test_clean_approvals(self):
|
||||
wizard = self.env['approval.cleaner.wizard'].create({
|
||||
'date_end': fields.Date.today() - timedelta(days=30),
|
||||
})
|
||||
|
||||
wizard.action_clean_approvals()
|
||||
|
||||
# Check that old approval is deleted
|
||||
self.assertFalse(self.approval_old.exists(), "Old approval should be deleted")
|
||||
|
||||
# Check that new approval still exists
|
||||
self.assertTrue(self.approval_new.exists(), "New approval should not be deleted")
|
||||
34
views/approval_cleaner_wizard_views.xml
Normal file
34
views/approval_cleaner_wizard_views.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_approval_cleaner_wizard_form" model="ir.ui.view">
|
||||
<field name="name">approval.cleaner.wizard.form</field>
|
||||
<field name="model">approval.cleaner.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Clean Approvals">
|
||||
<group>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<strong>Warning:</strong> This action will permanently delete all approval requests created before the selected date. This cannot be undone.
|
||||
</div>
|
||||
<field name="date_end"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_clean_approvals" string="Delete Approvals" type="object" class="btn-danger"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_approval_cleaner_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Clean Approvals</field>
|
||||
<field name="res_model">approval.cleaner.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_approval_cleaner_wizard"
|
||||
name="Clean Approvals"
|
||||
parent="approvals.approvals_menu_config"
|
||||
action="action_approval_cleaner_wizard"
|
||||
sequence="100"/>
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue
Block a user