Files
erpnext/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
mergify[bot] 7d3d2eb928 ci: add prettier to pre-commit (backport #40206) (#40362)
* 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>
2024-03-11 10:47:18 +05:30

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;
}, {});
}