diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js
index 79d9138a886..89429cd66d8 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js
@@ -10,7 +10,7 @@ frappe.ui.form.on("Accounts Settings", {
},
};
});
- if (!frm.naming_controller) frm.naming_controller = new erpnext.NamingSeriesController(frm);
+ if (!frm.naming_controller) frm.naming_controller = new frappe.ui.NamingSeriesController(frm);
frm.naming_controller.render_table("transaction_naming_html", get_transactions(frm));
},
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.js b/erpnext/buying/doctype/buying_settings/buying_settings.js
index 9cc43220226..453a816ac18 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.js
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.js
@@ -3,7 +3,7 @@
frappe.ui.form.on("Buying Settings", {
refresh(frm) {
- if (!frm.naming_controller) frm.naming_controller = new erpnext.NamingSeriesController(frm);
+ if (!frm.naming_controller) frm.naming_controller = new frappe.ui.NamingSeriesController(frm);
const display = frm.doc.supp_master_name === "Naming Series";
frm.set_df_property("naming_series_details", "hidden", !display);
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js
index 69b587ba002..221e3a62c6a 100644
--- a/erpnext/public/js/erpnext.bundle.js
+++ b/erpnext/public/js/erpnext.bundle.js
@@ -37,6 +37,5 @@ import "./utils/demo.js";
import "./financial_statements.js";
import "./sales_trends_filters.js";
import "./purchase_trends_filters.js";
-import "./utils/naming_series.js";
// import { sum } from 'frappe/public/utils/util.js'
diff --git a/erpnext/public/js/utils/naming_series.js b/erpnext/public/js/utils/naming_series.js
deleted file mode 100644
index 9a1725529aa..00000000000
--- a/erpnext/public/js/utils/naming_series.js
+++ /dev/null
@@ -1,417 +0,0 @@
-frappe.provide("erpnext");
-
-erpnext.NamingSeriesDialog = class NamingSeriesDialog {
- constructor(opts = {}) {
- this.opts = Object.assign(
- {
- title: __("Document Naming"),
- single_doctype: "Document Naming Settings",
- },
- opts
- );
-
- this.current_doctype = null;
- this.loaded = false;
- this.make_dialog();
- }
-
- make_dialog() {
- this.dialog = new frappe.ui.Dialog({
- title: this.opts.title,
- size: "medium",
- fields: [
- {
- fieldtype: "Table",
- fieldname: "naming_series_options",
- label: __("Add Series Prefix"),
- reqd: 1,
- in_place_edit: true,
- data: [],
- fields: [
- {
- fieldtype: "Data",
- fieldname: "series",
- label: __("Series"),
- in_list_view: 1,
- change: async function () {
- const preview = await this.grid_row.grid._naming_dialog.get_series_preview(
- this.doc.series
- );
- this.doc.preview = preview;
- this.grid_row.refresh_field("preview");
- },
- },
- {
- fieldtype: "Data",
- fieldname: "preview",
- label: __("Preview"),
- in_list_view: 1,
- placeholder: " ",
- read_only: 1,
- },
- ],
- },
- { fieldtype: "Section Break", label: __("Rules for configuring series"), collapsible: 1 },
- {
- fieldtype: "HTML",
- fieldname: "naming_series_description",
- },
- ],
- primary_action_label: __("Update"),
- primary_action: () => this.save(),
- });
-
- this.dialog.fields_dict.naming_series_options.grid._naming_dialog = this;
- }
-
- async show() {
- this.dialog.show();
- this.render_help();
-
- if (this.opts.doctype && !this.loaded) {
- await this.get_transaction(this.opts.doctype);
- this.loaded = true;
- return;
- }
- }
-
- render_help() {
- this.dialog.get_field("naming_series_description").$wrapper.html(`
-
- - ${__("Allowed special characters are '/' and '-'")}
- -
- ${__(
- "Optionally, set the number of digits in the series using dot (.) followed by hashes (#). For example, '.####' means that the series will have four digits. Default is five digits."
- )}
-
- - ${__("You can also use variables in the series name by putting them between (.) dots")}
-
- ${__("Supported Variables:")}
-
- .YYYY. - ${__("Year in 4 digits")}
- .YY. - ${__("Year in 2 digits")}
- .MM. - ${__("Month")}
- .DD. - ${__("Day of month")}
- .WW. - ${__("Week of the year")}
- -
-
.{fieldname}. - ${__("fieldname on the document e.g.")}
- branch
-
- .FY. - ${__("Fiscal Year (requires ERPNext to be installed)")}
- .ABBR. - ${__("Company Abbreviation (requires ERPNext to be installed)")}
-
-
-
- Examples:
-
- - INV-
- - INV-10-
- - INVK-
- - INV-.YYYY.-._{branch}.-.MM.-.####
-
-
`);
- }
-
- get_series_preview(series) {
- if (!series) return "";
-
- return this.get_document_naming_doc().then((doc) => {
- doc.try_naming_series = series;
- doc.transaction_type = this.current_doctype;
- return frappe
- .call({
- doc: doc,
- method: "preview_series",
- freeze: true,
- })
- .then((r) => (r.message || "").split("\n")[0] || "");
- });
- }
-
- get_document_naming_doc() {
- const dt = this.opts.single_doctype;
- return frappe.model.with_doc(dt, dt).then(() => {
- return frappe.model.get_doc(dt, dt);
- });
- }
-
- async get_transaction(doctype) {
- this.current_doctype = doctype;
-
- await frappe.model.with_doctype(doctype, async () => {
- const meta = frappe.get_meta(doctype);
- const naming_df = (meta?.fields || []).find((df) => df.fieldname === "naming_series");
- const series_list = (naming_df?.options || "").split("\n").filter(Boolean);
- const rows = await Promise.all(
- series_list.map(async (series) => ({
- series: series,
- preview: await this.get_series_preview(series),
- }))
- );
-
- this.dialog.fields_dict.naming_series_options.df.data = rows;
- this.dialog.fields_dict.naming_series_options.grid.refresh();
- });
- }
-
- save() {
- const rows = this.dialog.fields_dict.naming_series_options.grid.get_data();
- const naming_series_options = rows
- .map((r) => (r.series || "").trim())
- .filter(Boolean)
- .join("\n");
-
- if (!this.current_doctype) {
- frappe.msgprint(__("Please select a transaction."));
- return;
- }
-
- if (!naming_series_options) {
- frappe.msgprint(__("Please add at least one naming series."));
- return;
- }
-
- this.get_document_naming_doc().then((doc) => {
- doc.transaction_type = this.current_doctype;
- doc.naming_series_options = naming_series_options;
-
- frappe.call({
- doc: doc,
- method: "update_series",
- freeze: true,
- callback: async () => {
- const updated_rows = await Promise.all(
- naming_series_options
- .split("\n")
- .filter(Boolean)
- .map(async (series) => ({
- series: series,
- preview: await this.get_series_preview(series),
- }))
- );
-
- this.dialog.fields_dict.naming_series_options.df.data = updated_rows;
- this.dialog.fields_dict.naming_series_options.grid.refresh();
-
- frappe.show_alert({ message: __("Naming Series updated"), indicator: "green" });
- this.dialog.hide();
- this.opts.on_update?.({ doctype: this.current_doctype, naming_series_options });
- },
- });
- });
- }
-};
-
-erpnext.NamingSeriesTable = class NamingSeriesTable {
- constructor(opts = {}) {
- this.frm = opts.frm;
- this.transactions = opts.transactions || [];
- this.$wrapper = opts.frm.get_field(opts.fieldname).$wrapper;
- this.theme_observer = null;
- }
- render() {
- this.$wrapper.html(`
-
- `);
-
- const $rows = this.$wrapper.find(".naming-series-table-rows");
- this.map_configure_button($rows);
- this.get_row_data($rows);
-
- if (this.theme_observer) {
- this.theme_observer.disconnect();
- }
-
- const observer = new MutationObserver(() => {
- const badge_class = this.get_current_badge_class();
-
- this.$wrapper.find(".badge").removeClass("badge-light badge-dark").addClass(badge_class);
- });
-
- observer.observe(document.documentElement, {
- attributes: true,
- attributeFilter: ["data-theme"],
- });
- }
-
- map_configure_button($rows) {
- $rows.on("click", ".configure-btn", (e) => {
- const $btn = $(e.currentTarget);
- const doctype = $btn.data("doctype");
- const label = $btn.data("label");
-
- if (!this.frm._naming_dialogs) this.frm._naming_dialogs = {};
-
- if (!this.frm._naming_dialogs[doctype]) {
- this.frm._naming_dialogs[doctype] = new erpnext.NamingSeriesDialog({
- doctype: doctype,
- title: __("{0} Naming Series", [__(label)]),
- on_update: ({ naming_series_options }) => {
- const series = naming_series_options.split("\n").filter(Boolean);
- this.$wrapper
- .find(`.series-cell-${frappe.scrub(doctype)}`)
- .html(this.series_list_background(series));
- },
- });
- }
-
- this.frm._naming_dialogs[doctype].show();
- });
- }
-
- async get_row_data($rows) {
- const rows = await Promise.all(
- this.transactions.map(async (t) => {
- await new Promise((resolve) => frappe.model.with_doctype(t.doctype, resolve));
-
- const meta = frappe.get_meta(t.doctype);
- const naming_df = (meta?.fields || []).find((df) => df.fieldname === "naming_series");
- const series = (naming_df?.options || "")
- .split("\n")
- .map((s) => s.trim())
- .filter(Boolean);
-
- return this.make_row(t, series);
- })
- );
-
- $rows.empty();
- rows.forEach(($row) => $rows.append($row));
- }
-
- make_row(t, series) {
- return $(`
-
- |
- ${frappe.utils.escape_html(t.label)}
- |
-
- ${this.series_list_background(series)}
- |
-
-
- ${frappe.utils.icon("edit", "sm")}
-
- |
-
- `);
- }
-
- get_current_badge_class() {
- return document.documentElement.getAttribute("data-theme") === "dark" ? "badge-dark" : "badge-light";
- }
-
- series_list_background(series_list) {
- if (!series_list.length) {
- return `${__("Not configured")}`;
- }
-
- const badge_class = this.get_current_badge_class();
-
- return series_list
- .map(
- (s) => `
- ${frappe.utils.escape_html(s)}
- `
- )
- .join("");
- }
-};
-
-/**
- * @param {Object} frm - Frappe form instance.
- */
-erpnext.NamingSeriesController = class NamingSeriesController {
- constructor(frm) {
- this.frm = frm;
- }
-
- /**
- * Renders the naming series table in the given field.
- *
- * @param {string} fieldname - Fieldname where the table should be rendered.
- * @param {Array<{doctype: string, label: string}>} [transactions=[]] - Transactions to display.
- * @returns {void}
- */
- render_table(fieldname, transactions = []) {
- this.frm._naming_series_table = new erpnext.NamingSeriesTable({
- frm: this.frm,
- fieldname: fieldname,
- transactions: transactions,
- });
- this.frm._naming_series_table.render();
- }
-
- /**
- * Loads naming series from the given master doctype into a field.
- *
- * @param {string} doctype - Master doctype name.
- * @param {string} field - Fieldname where series should be shown.
- * @returns {void}
- */
- load_master_series(doctype, field) {
- frappe.model.with_doctype(doctype, () => {
- const meta = frappe.get_meta(doctype);
- const naming_df = (meta?.fields || []).find((df) => df.fieldname === "naming_series");
- const options = naming_df?.options || "";
- const series_list = options
- .split("\n")
- .map((s) => s.trim())
- .filter(Boolean);
-
- this.frm.doc[field] = series_list.length
- ? series_list.join("\n")
- : __("No naming series defined");
- this.frm.refresh_field(field);
- });
- }
-
- /**
- * Opens the naming series dialog for a doctype.
- *
- * @param {string} doctype - Transaction doctype.
- * @param {Function} [on_update] - Called after series are updated.
- * @returns {void}
- */
- show_naming_series_dialog(doctype, on_update) {
- if (!this.frm._naming_dialogs) this.frm._naming_dialogs = {};
-
- if (!this.frm._naming_dialogs[doctype]) {
- this.frm._naming_dialogs[doctype] = new erpnext.NamingSeriesDialog({
- doctype: doctype,
- title: __("{0} Naming Series", [__(doctype)]),
- on_update: ({ naming_series_options }) => {
- const series = naming_series_options.split("\n").filter(Boolean);
- this.frm
- .get_field(this.opts.table_field)
- .$wrapper.find(`.series-cell-${frappe.scrub(doctype)}`)
- .html(this.frm._naming_series_table?.series_list_background(series));
- on_update?.({ doctype, naming_series_options });
- },
- });
- }
-
- this.frm._naming_dialogs[doctype].show();
- }
-};
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.js b/erpnext/selling/doctype/selling_settings/selling_settings.js
index ce22db3fff0..9ffe9390a24 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.js
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.js
@@ -3,7 +3,7 @@
frappe.ui.form.on("Selling Settings", {
refresh(frm) {
- if (!frm.naming_controller) frm.naming_controller = new erpnext.NamingSeriesController(frm);
+ if (!frm.naming_controller) frm.naming_controller = new frappe.ui.NamingSeriesController(frm);
const display = frm.doc.cust_master_name === "Naming Series";
frm.set_df_property("naming_series_details", "hidden", !display);
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index e6289b1cca8..3d70c199d05 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -14,7 +14,7 @@ frappe.ui.form.on("Stock Settings", {
frm.set_query("default_warehouse", filters);
frm.set_query("sample_retention_warehouse", filters);
- if (!frm.naming_controller) frm.naming_controller = new erpnext.NamingSeriesController(frm);
+ if (!frm.naming_controller) frm.naming_controller = new frappe.ui.NamingSeriesController(frm);
const item_display = frm.doc.item_naming_by === "Naming Series";
const serial_and_batch_naming_display =
frm.doc.set_serial_and_batch_bundle_naming_based_on_naming_series;