mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-09 08:02:51 +00:00
* ci: add prettier to pre-commit
(cherry picked from commit 2c16036ef3)
* style: format js files
---------
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Ankush Menat <ankush@frappe.io>
235 lines
5.7 KiB
JavaScript
235 lines
5.7 KiB
JavaScript
frappe.pages["bom-comparison-tool"].on_page_load = function (wrapper) {
|
|
var page = frappe.ui.make_app_page({
|
|
parent: wrapper,
|
|
title: __("BOM Comparison Tool"),
|
|
single_column: true,
|
|
});
|
|
|
|
new erpnext.BOMComparisonTool(page);
|
|
};
|
|
|
|
erpnext.BOMComparisonTool = class BOMComparisonTool {
|
|
constructor(page) {
|
|
this.page = page;
|
|
this.make_form();
|
|
}
|
|
|
|
make_form() {
|
|
this.form = new frappe.ui.FieldGroup({
|
|
fields: [
|
|
{
|
|
label: __("BOM 1"),
|
|
fieldname: "name1",
|
|
fieldtype: "Link",
|
|
options: "BOM",
|
|
change: () => this.fetch_and_render(),
|
|
get_query: () => {
|
|
return {
|
|
filters: {
|
|
name: ["not in", [this.form.get_value("name2") || ""]],
|
|
},
|
|
};
|
|
},
|
|
},
|
|
{
|
|
fieldtype: "Column Break",
|
|
},
|
|
{
|
|
label: __("BOM 2"),
|
|
fieldname: "name2",
|
|
fieldtype: "Link",
|
|
options: "BOM",
|
|
change: () => this.fetch_and_render(),
|
|
get_query: () => {
|
|
return {
|
|
filters: {
|
|
name: ["not in", [this.form.get_value("name1") || ""]],
|
|
},
|
|
};
|
|
},
|
|
},
|
|
{
|
|
fieldtype: "Section Break",
|
|
},
|
|
{
|
|
fieldtype: "HTML",
|
|
fieldname: "preview",
|
|
},
|
|
],
|
|
body: this.page.body,
|
|
});
|
|
this.form.make();
|
|
}
|
|
|
|
fetch_and_render() {
|
|
let { name1, name2 } = this.form.get_values();
|
|
if (!(name1 && name2)) {
|
|
this.form.get_field("preview").html("");
|
|
return;
|
|
}
|
|
|
|
// set working state
|
|
this.form.get_field("preview").html(`
|
|
<div class="text-muted margin-top">
|
|
${__("Fetching...")}
|
|
</div>
|
|
`);
|
|
|
|
frappe
|
|
.call("erpnext.manufacturing.doctype.bom.bom.get_bom_diff", {
|
|
bom1: name1,
|
|
bom2: name2,
|
|
})
|
|
.then((r) => {
|
|
let diff = r.message;
|
|
frappe.model.with_doctype("BOM", () => {
|
|
this.render("BOM", name1, name2, diff);
|
|
});
|
|
});
|
|
}
|
|
|
|
render(doctype, name1, name2, diff) {
|
|
let change_html = (title, doctype, changed) => {
|
|
let values_changed = this.get_changed_values(doctype, changed)
|
|
.map((change) => {
|
|
let [fieldname, value1, value2] = change;
|
|
return `
|
|
<tr>
|
|
<td>${frappe.meta.get_label(doctype, fieldname)}</td>
|
|
<td>${value1}</td>
|
|
<td>${value2}</td>
|
|
</tr>
|
|
`;
|
|
})
|
|
.join("");
|
|
|
|
return `
|
|
<h4 class="margin-top">${title}</h4>
|
|
<div>
|
|
<table class="table table-bordered">
|
|
<tr>
|
|
<th width="33%">${__("Field")}</th>
|
|
<th width="33%">${name1}</th>
|
|
<th width="33%">${name2}</th>
|
|
</tr>
|
|
${values_changed}
|
|
</table>
|
|
</div>
|
|
`;
|
|
};
|
|
|
|
let value_changes = change_html(__("Values Changed"), doctype, diff.changed);
|
|
|
|
let row_changes_by_fieldname = group_items(diff.row_changed, (change) => change[0]);
|
|
|
|
let table_changes = Object.keys(row_changes_by_fieldname)
|
|
.map((fieldname) => {
|
|
let changes = row_changes_by_fieldname[fieldname];
|
|
let df = frappe.meta.get_docfield(doctype, fieldname);
|
|
|
|
let html = changes
|
|
.map((change) => {
|
|
let [fieldname, , item_code, changes] = change;
|
|
let df = frappe.meta.get_docfield(doctype, fieldname);
|
|
let child_doctype = df.options;
|
|
let values_changed = this.get_changed_values(child_doctype, changes);
|
|
|
|
return values_changed
|
|
.map((change, i) => {
|
|
let [fieldname, value1, value2] = change;
|
|
let th =
|
|
i === 0 ? `<th rowspan="${values_changed.length}">${item_code}</th>` : "";
|
|
return `
|
|
<tr>
|
|
${th}
|
|
<td>${frappe.meta.get_label(child_doctype, fieldname)}</td>
|
|
<td>${value1}</td>
|
|
<td>${value2}</td>
|
|
</tr>
|
|
`;
|
|
})
|
|
.join("");
|
|
})
|
|
.join("");
|
|
|
|
return `
|
|
<h4 class="margin-top">${__("Changes in {0}", [df.label])}</h4>
|
|
<table class="table table-bordered">
|
|
<tr>
|
|
<th width="25%">${__("Item Code")}</th>
|
|
<th width="25%">${__("Field")}</th>
|
|
<th width="25%">${name1}</th>
|
|
<th width="25%">${name2}</th>
|
|
</tr>
|
|
${html}
|
|
</table>
|
|
`;
|
|
})
|
|
.join("");
|
|
|
|
let get_added_removed_html = (title, grouped_items) => {
|
|
return Object.keys(grouped_items)
|
|
.map((fieldname) => {
|
|
let rows = grouped_items[fieldname];
|
|
let df = frappe.meta.get_docfield(doctype, fieldname);
|
|
let fields = frappe.meta.get_docfields(df.options).filter((df) => df.in_list_view);
|
|
|
|
let html = rows
|
|
.map((row) => {
|
|
let [, doc] = row;
|
|
let cells = fields.map((df) => `<td>${doc[df.fieldname]}</td>`).join("");
|
|
return `<tr>${cells}</tr>`;
|
|
})
|
|
.join("");
|
|
|
|
let header = fields.map((df) => `<th>${df.label}</th>`).join("");
|
|
return `
|
|
<h4 class="margin-top">${$.format(title, [df.label])}</h4>
|
|
<table class="table table-bordered">
|
|
<tr>${header}</tr>
|
|
${html}
|
|
</table>
|
|
`;
|
|
})
|
|
.join("");
|
|
};
|
|
|
|
let added_by_fieldname = group_items(diff.added, (change) => change[0]);
|
|
let removed_by_fieldname = group_items(diff.removed, (change) => change[0]);
|
|
|
|
let added_html = get_added_removed_html(__("Rows Added in {0}"), added_by_fieldname);
|
|
let removed_html = get_added_removed_html(__("Rows Removed in {0}"), removed_by_fieldname);
|
|
|
|
let html = `
|
|
${value_changes}
|
|
${table_changes}
|
|
${added_html}
|
|
${removed_html}
|
|
`;
|
|
|
|
this.form.get_field("preview").html(html);
|
|
}
|
|
|
|
get_changed_values(doctype, changed) {
|
|
return changed.filter((change) => {
|
|
let [fieldname, value1, value2] = change;
|
|
if (!value1) value1 = "";
|
|
if (!value2) value2 = "";
|
|
if (value1 === value2) return false;
|
|
let df = frappe.meta.get_docfield(doctype, fieldname);
|
|
if (!df) return false;
|
|
if (df.hidden) return false;
|
|
return true;
|
|
});
|
|
}
|
|
};
|
|
|
|
function group_items(array, fn) {
|
|
return array.reduce((acc, item) => {
|
|
let key = fn(item);
|
|
acc[key] = acc[key] || [];
|
|
acc[key].push(item);
|
|
return acc;
|
|
}, {});
|
|
}
|