diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 18ae0513063021b2dff428c779e839720f71383c..65de9b2d283f2835d765063d03ffdc5eef29c998 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -381,7 +381,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe frappe.after_ajax(() => this.calculate_taxes_and_totals()); } if(frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "item_code")) { - this.setup_item_selector(); this.frm.get_field("items").grid.set_multiple_add("item_code", "qty"); } } @@ -393,6 +392,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe this.setup_sms(); this.setup_quality_inspection(); this.validate_has_items(); + this.setup_item_catalog(); erpnext.set_accounting_journal(this.frm); erpnext.utils.view_serial_batch_nos(this.frm); } @@ -1955,7 +1955,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe me.frm.set_value(party_account_field, r.message); } }) - }; + } } }, () => this.update_item_tax_map(), @@ -2083,9 +2083,16 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } } - setup_item_selector() { - if (!this.item_selector) { - this.item_selector = new erpnext.ItemCatalog({ frm: this.frm }); + setup_item_catalog() { + const has_items_field = frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "item_code"); + const read_only = this.frm.read_only || this.frm.doc.docstatus > 0; + if (has_items_field && !read_only) { + if (!this.item_catalog) { + this.item_catalog = new erpnext.ItemCatalog({ frm: this.frm }); + } + this.item_catalog.show_button(); + } else { + this.item_catalog?.hide_button(); } } diff --git a/erpnext/public/js/utils/item_catalog/erpnext_item_catalog.bundle.js b/erpnext/public/js/utils/item_catalog/erpnext_item_catalog.bundle.js index b5132445a0e1c7164a7d0acbd05f51da82fdc7fb..c5d5db7f439b447742354deb23b5ad0d1bf8c9b7 100644 --- a/erpnext/public/js/utils/item_catalog/erpnext_item_catalog.bundle.js +++ b/erpnext/public/js/utils/item_catalog/erpnext_item_catalog.bundle.js @@ -6,45 +6,33 @@ import CatalogItemContents from "./CatalogItemContents.vue"; erpnext.ItemCatalogRender = class ItemCatalogRender { constructor({ frm }) { this.frm = frm; - if (!this.item_field) { - this.item_field = "item_code"; - } + } - if (!this.item_query) { - this.item_query = erpnext.queries.item().query; - } + get_search_filters() { + const search_filters = []; + search_filters.push(["Item", "has_variants", "=", false]); + search_filters.push(["Item", "disabled", "=", false]); - this.search_filters = [["Item", "has_variants", "=", false]] - const buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"] - const selling_doctypes = ["Sales Order", "Sales Invoice", "Sales Receipt"] + const buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]; + const selling_doctypes = ["Sales Order", "Sales Invoice", "Sales Receipt"]; - if (selling_doctypes.includes(frm.doc.doctype)) { - this.search_filters.push([ - "Item", "is_sales_item", "=", true - ]) - } else if (buying_doctypes.includes(frm.doc.doctype)) { - this.search_filters.push([ - "Item", "is_purchase_item", "=", true - ]) + if (selling_doctypes.includes(this.frm.doc.doctype)) { + search_filters.push(["Item", "is_sales_item", "=", true]); + } else if (buying_doctypes.includes(this.frm.doc.doctype)) { + search_filters.push(["Item", "is_purchase_item", "=", true]); } - this.grid = this.frm.get_field("items").grid; - this.setup(); + return search_filters; } - setup() { - if (!this.grid.catalog_button) { - const callback = () => { - if (this.dialog) { - this.link_catalog?.refresh(); - } else { - this.make_dialog(); - } - - this.dialog.show(); - }; - this.grid.catalog_button = this.grid.add_custom_button(__("Catalog"), callback, "top"); + show() { + if (this.dialog) { + this.link_catalog?.refresh(); + } else { + this.make_dialog(); } + + this.dialog.show(); } make_dialog() { @@ -58,6 +46,7 @@ erpnext.ItemCatalogRender = class ItemCatalogRender { } render(wrapper) { + const get_search_filters = this.get_search_filters.bind(this); this.link_catalog = new LinkCatalog({ wrapper, frm: this.frm, @@ -75,7 +64,9 @@ erpnext.ItemCatalogRender = class ItemCatalogRender { { component: CatalogItemContents }, ], item_footer: [], - search_filters: this.search_filters + get search_filters() { + return get_search_filters(); + }, }, }); } diff --git a/erpnext/public/js/utils/item_catalog/index.js b/erpnext/public/js/utils/item_catalog/index.js index f357c0fe27db42763d1c7d86cb8d231c7b954664..739506efa71d03d7e7fd91fd3213f7e1d80ce2fe 100644 --- a/erpnext/public/js/utils/item_catalog/index.js +++ b/erpnext/public/js/utils/item_catalog/index.js @@ -1,11 +1,43 @@ erpnext.ItemCatalog = class ItemCatalog { - constructor(...args) { - this.args = args; - this.render(); + constructor(opts) { + this.opts = opts; + } + + get frm() { + return this.opts.frm; } async render() { await frappe.require("erpnext_item_catalog.bundle.js"); - this.catalog = new erpnext.ItemCatalogRender(...this.args); + this.catalog = new erpnext.ItemCatalogRender(this.opts); + } + + async show_catalog() { + if (!this.render_promise) { + this.render_promise = this.render(); + } + await this.render_promise; + this.catalog?.show() + } + + async show_button() { + if (!this.$btn) { + await this.make_button(); + } + this.$btn.show(); + } + + async hide_button() { + this.$btn?.hide(); + } + + /** + * Feel free to override this method to customize the button's location + * @returns {jQuery} + */ + make_button() { + const grid = this.frm.get_field("items").grid; + const cb = () => this.show_catalog(); + this.$btn = grid.add_custom_button(__("Catalog"), cb, "top"); } }