feat: Adding option to trim custom tables (#31180)

* feat: Adding option to trim custom tables

* refactor: extracting trim_table to index.js from doctype.js & customize_form.js

* refactor: running pre-commit
This commit is contained in:
Sandeep Kakde 2025-04-06 21:18:23 +05:30 committed by GitHub
parent 5285a3b83f
commit 8fcd5d1cfa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 34 deletions

View file

@ -32,6 +32,12 @@ frappe.ui.form.on("DocType", {
},
refresh: function (frm) {
if (frm.doc.custom === 1) {
frm.add_custom_button(__("Trim Table"), function () {
frm.trigger("trim_table");
});
}
frm.set_query("role", "permissions", function (doc) {
if (doc.custom && frappe.session.user != "Administrator") {
return {

View file

@ -1058,6 +1058,17 @@ class DocType(Document):
)
return True
@frappe.whitelist()
def trim_table(self):
from frappe.model.meta import trim_table
"""Removes database fields that don't exist in the doctype.
This may be needed as maintenance since removing a field in a DocType
doesn't automatically delete the db field.
"""
trim_table(self.name, dry_run=False)
def validate_series(dt, autoname=None, name=None):
"""Validate if `autoname` property is correctly set."""

View file

@ -202,40 +202,6 @@ frappe.ui.form.on("Customize Form", {
);
},
async trim_table(frm) {
let dropped_columns = await frappe.xcall(
"frappe.custom.doctype.customize_form.customize_form.get_orphaned_columns",
{ doctype: frm.doc.doc_type }
);
if (!dropped_columns?.length) {
frappe.toast(__("This doctype has no orphan fields to trim"));
return;
}
let msg = __(
"Warning: DATA LOSS IMMINENT! Proceeding will permanently delete following database columns from doctype {0}:",
[frm.doc.doc_type.bold()]
);
msg += "<ol>" + dropped_columns.map((col) => `<li>${col}</li>`).join("") + "</ol>";
msg += __("This action is irreversible. Do you wish to continue?");
frappe.confirm(msg, () => {
return frm.call({
doc: frm.doc,
method: "trim_table",
callback: function (r) {
if (!r.exc) {
frappe.show_alert({
message: __("Table Trimmed"),
indicator: "green",
});
frappe.customize_form.clear_locals_and_refresh(frm);
}
},
});
});
},
setup_export(frm) {
if (frappe.boot.developer_mode) {
frm.add_custom_button(

View file

@ -222,4 +222,51 @@ frappe.model.DocTypeController = class DocTypeController extends frappe.ui.form.
update_fieldname_options();
}
}
async trim_table() {
let frm = this.frm;
let doctype = null;
if (frm.doc.doctype === "DocType") {
doctype = frm.doc.name;
} else {
// In customize form name field is "Customize Form". Doctype name is stored in doc_type.
doctype = frm.doc.doc_type;
}
let dropped_columns = await frappe.xcall(
"frappe.custom.doctype.customize_form.customize_form.get_orphaned_columns",
{ doctype: doctype }
);
if (!dropped_columns?.length) {
frappe.toast(__("This doctype has no orphan fields to trim"));
return;
}
let msg = __(
"Warning: DATA LOSS IMMINENT! Proceeding will permanently delete following database columns from doctype {0}:",
[frm.doc.name.bold()]
);
msg += "<ol>" + dropped_columns.map((col) => `<li>${col}</li>`).join("") + "</ol>";
msg += __("This action is irreversible. Do you wish to continue?");
frappe.confirm(msg, () => {
return frm.call({
doc: frm.doc,
method: "trim_table",
callback: function (r) {
if (!r.exc) {
frappe.show_alert({
message: __("Table Trimmed"),
indicator: "green",
});
if (frm.doc.doctype === "DocType") {
frm.refresh();
} else {
frappe.customize_form.clear_locals_and_refresh(frm);
}
}
},
});
});
}
};