first commit
This commit is contained in:
commit
dcf02c0331
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.pyc
|
||||||
|
*~
|
||||||
|
__pycache__/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Accounting Audit Unlink Tracker
|
||||||
|
|
||||||
|
This Odoo module tracks deletion operations for critical business records and ensures they are recorded in the **Accounting Audit Trail** report.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Deletion Tracking**: Automatically intercepts `unlink` calls for major models.
|
||||||
|
- **Persistent Logs**: Creates audit logs with `res_id = 0` so history survives record deletion.
|
||||||
|
- **Detailed Information**: Logs capture:
|
||||||
|
- User responsible for deletion.
|
||||||
|
- Record Technical ID.
|
||||||
|
- Record Display Name.
|
||||||
|
- Model Name.
|
||||||
|
- **Audit Trail Integration**: Logs appear directly in the standard **Accounting > Reporting > Audit Trail** report.
|
||||||
|
|
||||||
|
## Supported Models
|
||||||
|
|
||||||
|
- **Accounting**: `account.move`, `account.account`, `account.tax`
|
||||||
|
- **Core/Partners**: `res.partner`, `res.company`
|
||||||
|
- **Manufacturing**: `mrp.production`, `mrp.bom`
|
||||||
|
- **Inventory/Logistics**: `stock.picking`, `stock.move`, `stock.lot`
|
||||||
|
- **Products**: `product.template`, `product.product`, `product.category`
|
||||||
|
- **Sales/Purchase**: `sale.order`, `purchase.order`
|
||||||
|
- **HR**: `hr.employee`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Add the module to your custom addons path.
|
||||||
|
2. Update the addon list in Odoo.
|
||||||
|
3. Install `account_audit_unlink`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Go to **Accounting > Reporting > Audit Reports > Audit Trail** to view all deletion logs alongside standard audit trails.
|
||||||
2
__init__.py
Normal file
2
__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import models
|
||||||
20
__manifest__.py
Normal file
20
__manifest__.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
{
|
||||||
|
'name': 'Accounting Audit Unlink Tracker',
|
||||||
|
'version': '1.0',
|
||||||
|
'summary': 'Track unlink operations and record them to accounting audit log',
|
||||||
|
'description': """
|
||||||
|
This module tracks the deletion of records in the accounting system
|
||||||
|
(Account Moves, Accounts, Taxes, Partners, Companies) and creates
|
||||||
|
a persistent log in the Accounting Audit Trail.
|
||||||
|
""",
|
||||||
|
'author': 'Antigravity',
|
||||||
|
'category': 'Accounting',
|
||||||
|
'depends': ['account', 'mrp', 'stock', 'purchase', 'sale', 'hr'],
|
||||||
|
'data': [
|
||||||
|
'views/mail_message_views.xml',
|
||||||
|
],
|
||||||
|
'installable': True,
|
||||||
|
'auto_install': False,
|
||||||
|
'license': 'LGPL-3',
|
||||||
|
}
|
||||||
2
models/__init__.py
Normal file
2
models/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import mail_thread
|
||||||
46
models/mail_thread.py
Normal file
46
models/mail_thread.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from odoo import api, models, _
|
||||||
|
|
||||||
|
class MailThread(models.AbstractModel):
|
||||||
|
_inherit = 'mail.thread'
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
""" Override unlink to create a persistent audit log record before deletion.
|
||||||
|
The audit log will have res_id=0 to ensure it survives the standard unlink process.
|
||||||
|
"""
|
||||||
|
audit_models = (
|
||||||
|
'account.move', 'account.account', 'account.tax', 'res.partner', 'res.company',
|
||||||
|
'mrp.production', 'mrp.bom', 'stock.picking', 'stock.move', 'product.template', 'product.product',
|
||||||
|
'purchase.order', 'sale.order', 'hr.employee', 'product.category', 'stock.lot'
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._name in audit_models:
|
||||||
|
for record in self:
|
||||||
|
# Get basic info while record still exists
|
||||||
|
record_id = record.id
|
||||||
|
record_name = record.display_name or _('Unknown Record')
|
||||||
|
company_id = getattr(record, 'company_id', self.env.company).id
|
||||||
|
|
||||||
|
# Create the persistent audit log
|
||||||
|
self.env['mail.message'].sudo().create({
|
||||||
|
'model': self._name,
|
||||||
|
'res_id': 0, # Persistent ID (not linked to an existing record)
|
||||||
|
'message_type': 'notification',
|
||||||
|
'subject': _('Record Unlinked: %s', record_name),
|
||||||
|
'body': _(
|
||||||
|
'<p>The following record was unlinked by <b>%s</b>:</p>'
|
||||||
|
'<ul>'
|
||||||
|
'<li><b>Model:</b> %s</li>'
|
||||||
|
'<li><b>Technical ID:</b> %s</li>'
|
||||||
|
'<li><b>Display Name:</b> %s</li>'
|
||||||
|
'</ul>',
|
||||||
|
self.env.user.name,
|
||||||
|
self._name,
|
||||||
|
record_id,
|
||||||
|
record_name
|
||||||
|
),
|
||||||
|
'author_id': self.env.user.partner_id.id,
|
||||||
|
'record_company_id': company_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return super(MailThread, self).unlink()
|
||||||
13
views/mail_message_views.xml
Normal file
13
views/mail_message_views.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="account.action_account_audit_trail_report" model="ir.actions.act_window">
|
||||||
|
<field name="domain">[
|
||||||
|
('message_type', '=', 'notification'),
|
||||||
|
('model', 'in', (
|
||||||
|
'account.move', 'account.account', 'account.tax', 'res.partner', 'res.company',
|
||||||
|
'mrp.production', 'mrp.bom', 'stock.picking', 'stock.move', 'product.template', 'product.product',
|
||||||
|
'purchase.order', 'sale.order', 'hr.employee', 'product.category', 'stock.lot'
|
||||||
|
)),
|
||||||
|
]</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in New Issue
Block a user