diff --git a/odex30_base/ctp_database_clean_up/__init__.py b/odex30_base/ctp_database_clean_up/__init__.py new file mode 100644 index 0000000..77bbdbd --- /dev/null +++ b/odex30_base/ctp_database_clean_up/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import models + diff --git a/odex30_base/ctp_database_clean_up/__manifest__.py b/odex30_base/ctp_database_clean_up/__manifest__.py new file mode 100644 index 0000000..4625d7d --- /dev/null +++ b/odex30_base/ctp_database_clean_up/__manifest__.py @@ -0,0 +1,25 @@ +{ + "name": "Database Clean up", + "version": "18.0.1.0.0", + "summary": """ + Cybernetics Plus Tools Database Clean up + .""", + "description": """ + Cybernetics Plus Tools Database Clean up + .""", + "author": "Cybernetics Plus", + "website": "https://www.cybernetics.plus", + "live_test_url": "https://www.cybernetics.plus", + "images": ["static/description/banner.gif"], + "category": "Odex30-Base", + "license": "LGPL-3", + "installable": True, + "application": False, + "auto_install": False, + "contributors": [ + "Developer ", + ], + "data": [ + "views/ctp_database_clean_up.xml", + ], +} diff --git a/odex30_base/ctp_database_clean_up/models/__init__.py b/odex30_base/ctp_database_clean_up/models/__init__.py new file mode 100644 index 0000000..3daf725 --- /dev/null +++ b/odex30_base/ctp_database_clean_up/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import ctp_database_clean_up + diff --git a/odex30_base/ctp_database_clean_up/models/ctp_database_clean_up.py b/odex30_base/ctp_database_clean_up/models/ctp_database_clean_up.py new file mode 100644 index 0000000..798ad39 --- /dev/null +++ b/odex30_base/ctp_database_clean_up/models/ctp_database_clean_up.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- + +import logging +from odoo import models, _ +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + +class CtpDatabaseCleanUp(models.TransientModel): + _inherit = 'res.config.settings' + + def remove_data(self, o, s=[]): + for line in o: + try: + if not self.env['ir.model']._get(line): + continue + except Exception as e: + _logger.warning('Database Clean up error get ir.model: %s,%s', line, e) + continue + obj_name = line + obj = self.pool.get(obj_name) + if not obj: + t_name = obj_name.replace('.', '_') + else: + t_name = obj._table + sql = "delete from %s" % t_name + try: + self._cr.execute(sql) + self._cr.commit() + except Exception as e: + _logger.warning('Database Clean up error: %s,%s', line, e) + for line in s: + domain = ['|', ('code', '=ilike', line + '%'), ('prefix', '=ilike', line + '%')] + try: + seqs = self.env['ir.sequence'].sudo().search(domain) + if seqs.exists(): + seqs.write({ + 'number_next': 1, + }) + except Exception as e: + _logger.warning('Reset Sequence Data error: %s,%s', line, e) + return True + + def remove_sales(self): + to_removes = [ + 'sale.order.line', + 'sale.order', + ] + seqs = [ + 'sale', + ] + return self.remove_data(to_removes, seqs) + + def remove_product(self): + to_removes = [ + 'product.product', + 'product.template', + ] + seqs = [ + 'product.product', + ] + return self.remove_data(to_removes, seqs) + + def remove_product_attribute(self): + to_removes = [ + 'product.attribute.value', + 'product.attribute', + ] + seqs = [] + return self.remove_data(to_removes, seqs) + + def remove_pos(self): + to_removes = [ + 'pos.payment', + 'pos.order.line', + 'pos.order', + 'pos.session', + ] + seqs = [ + 'pos.', + ] + res = self.remove_data(to_removes, seqs) + try: + statement = self.env['account.bank.statement'].sudo().search([]) + for s in statement: + s._end_balance() + except Exception as e: + _logger.error('Reset Sequence Data error: %s', e) + return res + + def remove_purchase(self): + to_removes = [ + 'purchase.order.line', + 'purchase.order', + 'purchase.requisition.line', + 'purchase.requisition', + ] + seqs = [ + 'purchase.', + ] + return self.remove_data(to_removes, seqs) + + def remove_expense(self): + to_removes = [ + 'hr.expense.sheet', + 'hr.expense', + 'hr.payslip', + 'hr.payslip.run', + ] + seqs = [ + 'hr.expense.', + ] + return self.remove_data(to_removes, seqs) + + def remove_mrp(self): + to_removes = [ + 'mrp.workcenter.productivity', + 'mrp.workorder', + 'mrp.production.workcenter.line', + 'change.production.qty', + 'mrp.production', + 'mrp.production.product.line', + 'mrp.unbuild', + 'change.production.qty', + 'sale.forecast.indirect', + 'sale.forecast', + ] + seqs = [ + 'mrp.', + ] + return self.remove_data(to_removes, seqs) + + def remove_mrp_bom(self): + to_removes = [ + 'mrp.bom.line', + 'mrp.bom', + ] + seqs = [] + return self.remove_data(to_removes, seqs) + + def remove_inventory(self): + to_removes = [ + 'stock.quant', + 'stock.move.line', + 'stock.package_level', + 'stock.quantity.history', + 'stock.quant.package', + 'stock.move', + 'stock.picking', + 'stock.scrap', + 'stock.picking.batch', + 'stock.inventory.line', + 'stock.inventory', + 'stock.valuation.layer', + 'stock.production.lot', + 'procurement.group', + ] + seqs = [ + 'stock.', + 'picking.', + 'procurement.group', + 'product.tracking.default', + 'WH/', + ] + return self.remove_data(to_removes, seqs) + + # VVVVVVVVVVV قم باستبدال الدالة التالية VVVVVVVVVVV + def remove_account(self): + to_removes = [ + 'payment.transaction', + 'account.bank.statement.line', + 'account.payment', + 'account.analytic.line', + 'account.analytic.account', + 'account.partial.reconcile', + 'account.move.line', + 'hr.expense.sheet', + 'account.move', + ] + res = self.remove_data(to_removes, []) + # FIX: The domain syntax was incorrect (extra '|' at the end) + domain = [ + ('company_id', '=', self.env.company.id), + '|', ('code', '=ilike', 'account.%'), + '|', ('prefix', '=ilike', 'BNK1/%'), + '|', ('prefix', '=ilike', 'CSH1/%'), + '|', ('prefix', '=ilike', 'INV/%'), + '|', ('prefix', '=ilike', 'EXCH/%'), + ('prefix', '=ilike', 'MISC/%') + ] + try: + seqs = self.env['ir.sequence'].search(domain) + if seqs.exists(): + seqs.write({ + 'number_next': 1, + }) + except Exception as e: + _logger.error('Reset Sequence Data error: %s,%s', domain, e) + self._cr.rollback() # Rollback on error + return res + + def remove_account_chart(self): + company_id = self.env.company.id + self = self.with_company(company_id) + + try: + _logger.info("Starting to unlink accounting properties...") + + if self.env['ir.model']._get('product.template'): + field1 = self.env['ir.model.fields']._get('product.template', "taxes_id") + field2 = self.env['ir.model.fields']._get('product.template', "supplier_taxes_id") + if field1 and field2: + sql = "DELETE FROM ir_default WHERE field_id IN (%s, %s) AND company_id=%s" + self._cr.execute(sql, (field1.id, field2.id, company_id)) + + self.env['res.partner'].search([]).write({ + 'property_account_receivable_id': False, + 'property_account_payable_id': False, + }) + + if self.env['ir.model']._get('product.category'): + self.env['product.category'].search([]).write({ + 'property_account_income_categ_id': False, + 'property_account_expense_categ_id': False, + }) + + if self.env['ir.model']._get('product.template'): + self.env['product.template'].search([]).write({ + 'property_account_income_id': False, + 'property_account_expense_id': False, + }) + + # FIX: Check if 'stock.location' model exists before trying to access it + if self.env['ir.model']._get('stock.location'): + self.env['stock.location'].search([]).write({ + 'valuation_in_account_id': False, 'valuation_out_account_id': False, + }) + + _logger.info("Finished unlinking properties.") + + _logger.info("Deleting from dependent M2M tax table...") + self._cr.execute("DELETE FROM account_reconcile_model_line_account_tax_rel") + + _logger.info("Deleting main accounting tables...") + to_removes = [ + 'res.partner.bank', 'account.move.line', 'account.payment', + 'account.bank.statement.line', 'account.bank.statement', + 'account.tax.account.tag', 'account.tax', + 'account.account.account.tag', 'wizard_multi_charts_accounts', + 'account.journal', 'account.account', + ] + res = self.remove_data(to_removes, []) + + _logger.info("Finalizing account chart cleanup...") + self._cr.commit() + return res + + except Exception as e: + _logger.error('Database Clean up error in remove_account_chart: %s', e, exc_info=True) + self._cr.rollback() + raise UserError(_('An error occurred while cleaning the account chart: %s') % e) + + def remove_project(self): + to_removes = [ + 'account.analytic.line', + 'project.task', + 'project.forecast', + 'project.project', + ] + seqs = [] + return self.remove_data(to_removes, seqs) + + def remove_quality(self): + to_removes = [ + 'quality.check', + 'quality.alert', + ] + seqs = [ + 'quality.check', + 'quality.alert', + ] + return self.remove_data(to_removes, seqs) + + def remove_quality_setting(self): + to_removes = [ + 'quality.point', + 'quality.alert.stage', + 'quality.alert.team', + 'quality.point.test_type', + 'quality.reason', + 'quality.tag', + ] + return self.remove_data(to_removes) + + def remove_website(self): + to_removes = [ + 'blog.tag.category', + 'blog.tag', + 'blog.post', + 'blog.blog', + 'product.wishlist', + 'website.published.multi.mixin', + 'website.published.mixin', + 'website.multi.mixin', + 'website.visitor', + 'website.redirect', + 'website.seo.metadata', + ] + seqs = [] + return self.remove_data(to_removes, seqs) + + def remove_message(self): + to_removes = [ + 'mail.message', + 'mail.followers', + 'mail.activity', + ] + seqs = [] + return self.remove_data(to_removes, seqs) + + def remove_all(self): + self.remove_account() + self.remove_quality() + self.remove_website() + self.remove_quality_setting() + self.remove_inventory() + self.remove_purchase() + self.remove_mrp() + self.remove_sales() + self.remove_project() + self.remove_pos() + self.remove_expense() + self.remove_account_chart() + self.remove_message() + return True + + def reset_cat_loc_name(self): + ids = self.env['product.category'].search([ + ('parent_id', '!=', False) + ], order='complete_name') + for rec in ids: + try: + rec._compute_complete_name() + except: + pass + ids = self.env['stock.location'].search([ + ('location_id', '!=', False), + ('usage', '!=', 'views'), + ], order='complete_name') + for rec in ids: + try: + rec._compute_complete_name() + except: + pass + return True diff --git a/odex30_base/ctp_database_clean_up/static/description/banner.gif b/odex30_base/ctp_database_clean_up/static/description/banner.gif new file mode 100644 index 0000000..c0925e1 Binary files /dev/null and b/odex30_base/ctp_database_clean_up/static/description/banner.gif differ diff --git a/odex30_base/ctp_database_clean_up/static/description/icon.png b/odex30_base/ctp_database_clean_up/static/description/icon.png new file mode 100644 index 0000000..4e01b95 Binary files /dev/null and b/odex30_base/ctp_database_clean_up/static/description/icon.png differ diff --git a/odex30_base/ctp_database_clean_up/static/description/images/cyberneticsplus-logo.png b/odex30_base/ctp_database_clean_up/static/description/images/cyberneticsplus-logo.png new file mode 100644 index 0000000..b17b106 Binary files /dev/null and b/odex30_base/ctp_database_clean_up/static/description/images/cyberneticsplus-logo.png differ diff --git a/odex30_base/ctp_database_clean_up/static/description/index.html b/odex30_base/ctp_database_clean_up/static/description/index.html new file mode 100644 index 0000000..21a7f25 --- /dev/null +++ b/odex30_base/ctp_database_clean_up/static/description/index.html @@ -0,0 +1,24 @@ +
+
+
+ +

Database Clean Up Module

+
+ + +
+
+ + \ No newline at end of file diff --git a/odex30_base/ctp_database_clean_up/static/description/screen.jpg b/odex30_base/ctp_database_clean_up/static/description/screen.jpg new file mode 100644 index 0000000..d30880b Binary files /dev/null and b/odex30_base/ctp_database_clean_up/static/description/screen.jpg differ diff --git a/odex30_base/ctp_database_clean_up/views/ctp_database_clean_up.xml b/odex30_base/ctp_database_clean_up/views/ctp_database_clean_up.xml new file mode 100644 index 0000000..1982a74 --- /dev/null +++ b/odex30_base/ctp_database_clean_up/views/ctp_database_clean_up.xml @@ -0,0 +1,95 @@ + + + + + + Database Clean up + res.config.settings + 20 + +
+
+ +

Database Cleaning (Be careful to do that!)

+ Data is Deleted Direcly from the Database Table using Queries, Once you done, It is not reversible ! +
+
+ Clean up All +
+
+ Sale +
+
+ POS +
+
+ Purchase +
+
+ Expense +
+
+ MRP +
+
+ Inventory +
+
+ + Accounting + +
+
+ Project +
+
+ Quality +
+
+ Website And Blog +
+
+ Base Models +
+
+
+
+
+ + + C+ Database Clean up + ir.actions.act_window + res.config.settings + form + + inline + + + + +
+