From ee321295173524239ef17a5f9272b0bcaaeaf59c Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Wed, 8 Apr 2026 17:56:45 +0530 Subject: [PATCH 1/9] feat: Add 'Include in Import Template' field to DocField configuration --- frappe/core/doctype/docfield/docfield.json | 10 +++++++++- frappe/core/doctype/docfield/docfield.py | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index cdfa20d072..cf4b95f4f4 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -41,6 +41,7 @@ "print_hide", "print_hide_if_no_value", "report_hide", + "include_in_import_template", "column_break_28", "depends_on", "collapsible", @@ -640,6 +641,13 @@ "fieldname": "show_description_on_click", "fieldtype": "Check", "label": "Show Description on Click" + }, + { + "default": "0", + "description": "Enable this option to include the field in the data import template", + "fieldname": "include_in_import_template", + "fieldtype": "Check", + "label": "Include in Import Template" } ], "grid_page_length": 50, @@ -647,7 +655,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-03-10 21:39:58.400441", + "modified": "2026-04-07 15:23:18.264098", "modified_by": "Administrator", "module": "Core", "name": "DocField", diff --git a/frappe/core/doctype/docfield/docfield.py b/frappe/core/doctype/docfield/docfield.py index b97291b754..1613dc96eb 100644 --- a/frappe/core/doctype/docfield/docfield.py +++ b/frappe/core/doctype/docfield/docfield.py @@ -86,6 +86,7 @@ class DocField(Document): in_list_view: DF.Check in_preview: DF.Check in_standard_filter: DF.Check + include_in_import_template: DF.Check is_virtual: DF.Check label: DF.Data | None length: DF.Int From fe1019f7cc89ca6905a23106877c2fc01a94f579 Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Wed, 8 Apr 2026 17:57:46 +0530 Subject: [PATCH 2/9] fix: show ID field only when its for export and in import if naming series is Set by User --- .../js/frappe/data_import/data_exporter.js | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/frappe/public/js/frappe/data_import/data_exporter.js b/frappe/public/js/frappe/data_import/data_exporter.js index 8253ea80df..72ac191c30 100644 --- a/frappe/public/js/frappe/data_import/data_exporter.js +++ b/frappe/public/js/frappe/data_import/data_exporter.js @@ -1,9 +1,10 @@ frappe.provide("frappe.data_import"); frappe.data_import.DataExporter = class DataExporter { - constructor(doctype, exporting_for, filetype = "CSV") { + constructor(doctype, exporting_for, filetype = "CSV", hide_blank_template = false) { this.doctype = doctype; this.exporting_for = exporting_for; + this.hide_blank_template = hide_blank_template; frappe.model.with_doctype(doctype, () => { this.make_dialog(filetype); }); @@ -37,13 +38,20 @@ frappe.data_import.DataExporter = class DataExporter { label: __("5 Records"), value: "5_records", }, - { - label: __("Blank Template"), - value: "blank_template", - }, - ], + ].concat( + this.hide_blank_template + ? [] + : [ + { + label: __("Blank Template"), + value: "blank_template", + }, + ] + ), default: - this.exporting_for === "Insert New Records" ? "blank_template" : "all", + this.exporting_for === "Insert New Records" && !this.hide_blank_template + ? "blank_template" + : "all", change: () => { this.update_record_count_message(); }, @@ -189,7 +197,7 @@ frappe.data_import.DataExporter = class DataExporter { ...multicheck_fields.map((fieldname) => { let field = this.dialog.get_field(fieldname); return field.options - .filter((option) => option.danger) + .filter((option) => option.danger || option.include_in_import_template) .map((option) => option.$checkbox.find("input").get(0)); }) ); @@ -274,6 +282,10 @@ frappe.data_import.DataExporter = class DataExporter { let fieldname = meta.autoname.slice("field:".length); autoname_field = frappe.meta.get_field(doctype, fieldname); } + const hide_name_for_insert_when_not_set_by_user = + this.exporting_for === "Insert New Records" && + !this.hide_blank_template && + !["Prompt", "prompt"].includes(meta.autoname); let fields = child_fieldname ? this.column_map[child_fieldname] : this.column_map[doctype]; @@ -305,7 +317,11 @@ frappe.data_import.DataExporter = class DataExporter { return fields .filter((df) => { - if (autoname_field && df.fieldname === "name") { + if ( + this.exporting_for === "Insert New Records" && + (autoname_field || hide_name_for_insert_when_not_set_by_user) && + df.fieldname === "name" + ) { return false; } return true; @@ -316,6 +332,7 @@ frappe.data_import.DataExporter = class DataExporter { value: df.fieldname, danger: is_field_mandatory(df), warning: is_field_depends_on(df), + include_in_import_template: !!df.include_in_import_template, checked: false, description: `${df.fieldname} ${df.reqd ? __("(Mandatory)") : ""}`, }; From 041ab77e557ea1c0d4725dd7e9647ca44eb9fe0a Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Wed, 8 Apr 2026 17:58:24 +0530 Subject: [PATCH 3/9] fix: hide Blank Template option if its exporting data --- frappe/public/js/frappe/list/bulk_operations.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/bulk_operations.js b/frappe/public/js/frappe/list/bulk_operations.js index 3d0c2924ae..033d7aa353 100644 --- a/frappe/public/js/frappe/list/bulk_operations.js +++ b/frappe/public/js/frappe/list/bulk_operations.js @@ -476,7 +476,9 @@ export default class BulkOperations { frappe.require("data_import_tools.bundle.js", () => { const data_exporter = new frappe.data_import.DataExporter( doctype, - "Insert New Records" + "Insert New Records", + "CSV", + true ); data_exporter.dialog.set_value("export_records", "by_filter"); data_exporter.filter_group.add_filters_to_filter_group([ From 9995bee63ce80b25f1c18965cba490f3738c7591 Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Fri, 10 Apr 2026 12:16:21 +0530 Subject: [PATCH 4/9] feat: Enhance Data Exporter and MultiCheck UI with warning titles and tooltips --- .../js/frappe/data_import/data_exporter.js | 13 +++++++--- .../js/frappe/form/controls/multicheck.js | 26 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/data_import/data_exporter.js b/frappe/public/js/frappe/data_import/data_exporter.js index 72ac191c30..c905039612 100644 --- a/frappe/public/js/frappe/data_import/data_exporter.js +++ b/frappe/public/js/frappe/data_import/data_exporter.js @@ -309,11 +309,17 @@ frappe.data_import.DataExporter = class DataExporter { if (autoname_field && df.fieldname == autoname_field.fieldname) { return true; } - if (df.fieldname === "name") { - return true; - } return false; }; + let get_info_title = (df) => { + if (df.depends_on) { + return __("Depends on: {0}", [df.depends_on]); + } + if (autoname_field && df.fieldname == autoname_field.fieldname) { + return __("Autoname: {0}", [autoname_field.label]); + } + return ""; + }; return fields .filter((df) => { @@ -332,6 +338,7 @@ frappe.data_import.DataExporter = class DataExporter { value: df.fieldname, danger: is_field_mandatory(df), warning: is_field_depends_on(df), + warning_title: get_info_title(df), include_in_import_template: !!df.include_in_import_template, checked: false, description: `${df.fieldname} ${df.reqd ? __("(Mandatory)") : ""}`, diff --git a/frappe/public/js/frappe/form/controls/multicheck.js b/frappe/public/js/frappe/form/controls/multicheck.js index 9b59dc5b3c..52a79be20c 100644 --- a/frappe/public/js/frappe/form/controls/multicheck.js +++ b/frappe/public/js/frappe/form/controls/multicheck.js @@ -82,12 +82,10 @@ frappe.ui.form.ControlMultiCheck = class ControlMultiCheck extends frappe.ui.for } this.options.forEach((option) => { let checkbox = this.get_checkbox_element(option).appendTo(this.$checkbox_area); - if (option.danger) { - checkbox.find(".label-area").addClass("text-danger"); - } - if (option.warning) { - checkbox.find(".label-area").addClass("text-warning"); - } + checkbox.find('[data-toggle="tooltip"]').tooltip({ + delay: { show: 600, hide: 100 }, + trigger: "hover", + }); option.$checkbox = checkbox; }); @@ -165,11 +163,25 @@ frappe.ui.form.ControlMultiCheck = class ControlMultiCheck extends frappe.ui.for } get_checkbox_element(option) { + const mandatory_marker = option.danger + ? `*` + : ""; + const warning_title = frappe.utils.escape_html( + option.warning_title || __("Condition based field") + ); + const warning_icon = option.warning + ? `${frappe.utils.icon( + "info", + "xs" + )}` + : ""; return $(`
`); From df2947b546d76dcd3527d3106014d52cae887d62 Mon Sep 17 00:00:00 2001 From: Sumit Jain <59503001+sumitjain236@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:20:33 +0530 Subject: [PATCH 5/9] fix(multicheck): move warning icon style to checkbox stylesheet --- frappe/public/js/frappe/form/controls/multicheck.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/multicheck.js b/frappe/public/js/frappe/form/controls/multicheck.js index 52a79be20c..493c6688d5 100644 --- a/frappe/public/js/frappe/form/controls/multicheck.js +++ b/frappe/public/js/frappe/form/controls/multicheck.js @@ -82,10 +82,7 @@ frappe.ui.form.ControlMultiCheck = class ControlMultiCheck extends frappe.ui.for } this.options.forEach((option) => { let checkbox = this.get_checkbox_element(option).appendTo(this.$checkbox_area); - checkbox.find('[data-toggle="tooltip"]').tooltip({ - delay: { show: 600, hide: 100 }, - trigger: "hover", - }); + checkbox.find('[data-toggle="tooltip"]').tooltip(); option.$checkbox = checkbox; }); From 78b81fc7cf34a2bae8a105495c26643a099e7ffb Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Fri, 24 Apr 2026 13:34:42 +0530 Subject: [PATCH 6/9] refactor: Rename 'include_in_import_template' to 'in_import_template' --- frappe/core/doctype/docfield/docfield.json | 6 +++--- frappe/core/doctype/docfield/docfield.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index cf4b95f4f4..2e4b6c5ece 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -41,7 +41,7 @@ "print_hide", "print_hide_if_no_value", "report_hide", - "include_in_import_template", + "in_import_template", "column_break_28", "depends_on", "collapsible", @@ -645,7 +645,7 @@ { "default": "0", "description": "Enable this option to include the field in the data import template", - "fieldname": "include_in_import_template", + "fieldname": "in_import_template", "fieldtype": "Check", "label": "Include in Import Template" } @@ -655,7 +655,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-04-07 15:23:18.264098", + "modified": "2026-04-24 13:21:02.590853", "modified_by": "Administrator", "module": "Core", "name": "DocField", diff --git a/frappe/core/doctype/docfield/docfield.py b/frappe/core/doctype/docfield/docfield.py index 1613dc96eb..eed0e4724e 100644 --- a/frappe/core/doctype/docfield/docfield.py +++ b/frappe/core/doctype/docfield/docfield.py @@ -83,10 +83,10 @@ class DocField(Document): ignore_xss_filter: DF.Check in_filter: DF.Check in_global_search: DF.Check + in_import_template: DF.Check in_list_view: DF.Check in_preview: DF.Check in_standard_filter: DF.Check - include_in_import_template: DF.Check is_virtual: DF.Check label: DF.Data | None length: DF.Int From 75c43493a8aa238bbaf312ec215cce3adc10637e Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Fri, 24 Apr 2026 13:35:24 +0530 Subject: [PATCH 7/9] refactor: change variable name from hide_name_for_insert_when_not_set_by_user ton hide_name_for_autoname --- frappe/public/js/frappe/data_import/data_exporter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/data_import/data_exporter.js b/frappe/public/js/frappe/data_import/data_exporter.js index c905039612..f4c37e6b4e 100644 --- a/frappe/public/js/frappe/data_import/data_exporter.js +++ b/frappe/public/js/frappe/data_import/data_exporter.js @@ -197,7 +197,7 @@ frappe.data_import.DataExporter = class DataExporter { ...multicheck_fields.map((fieldname) => { let field = this.dialog.get_field(fieldname); return field.options - .filter((option) => option.danger || option.include_in_import_template) + .filter((option) => option.danger || option.in_import_template) .map((option) => option.$checkbox.find("input").get(0)); }) ); @@ -282,7 +282,7 @@ frappe.data_import.DataExporter = class DataExporter { let fieldname = meta.autoname.slice("field:".length); autoname_field = frappe.meta.get_field(doctype, fieldname); } - const hide_name_for_insert_when_not_set_by_user = + const hide_name_for_autoname = this.exporting_for === "Insert New Records" && !this.hide_blank_template && !["Prompt", "prompt"].includes(meta.autoname); @@ -325,7 +325,7 @@ frappe.data_import.DataExporter = class DataExporter { .filter((df) => { if ( this.exporting_for === "Insert New Records" && - (autoname_field || hide_name_for_insert_when_not_set_by_user) && + (autoname_field || hide_name_for_autoname) && df.fieldname === "name" ) { return false; @@ -339,7 +339,7 @@ frappe.data_import.DataExporter = class DataExporter { danger: is_field_mandatory(df), warning: is_field_depends_on(df), warning_title: get_info_title(df), - include_in_import_template: !!df.include_in_import_template, + in_import_template: !!df.in_import_template, checked: false, description: `${df.fieldname} ${df.reqd ? __("(Mandatory)") : ""}`, }; From 42470e9201569d7bbb094e83e1d0312bd1b3d7c0 Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Fri, 24 Apr 2026 13:35:46 +0530 Subject: [PATCH 8/9] fix(multicheck): move warning icon style to checkbox stylesheet --- frappe/public/js/frappe/form/controls/multicheck.js | 2 +- frappe/public/scss/element/checkbox.scss | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/controls/multicheck.js b/frappe/public/js/frappe/form/controls/multicheck.js index 493c6688d5..2f47d58bce 100644 --- a/frappe/public/js/frappe/form/controls/multicheck.js +++ b/frappe/public/js/frappe/form/controls/multicheck.js @@ -167,7 +167,7 @@ frappe.ui.form.ControlMultiCheck = class ControlMultiCheck extends frappe.ui.for option.warning_title || __("Condition based field") ); const warning_icon = option.warning - ? `${frappe.utils.icon( + ? `${frappe.utils.icon( "info", "xs" )}` diff --git a/frappe/public/scss/element/checkbox.scss b/frappe/public/scss/element/checkbox.scss index 628667f902..9a4303350f 100644 --- a/frappe/public/scss/element/checkbox.scss +++ b/frappe/public/scss/element/checkbox.scss @@ -56,6 +56,14 @@ input[type="checkbox"] { } } +.checkbox .multicheck-warning-icon { + margin-left: 4px !important; + display: inline-flex; + align-items: center; + vertical-align: middle; + line-height: 1; +} + /* The switch - the box around the slider */ .switch { position: relative; From 440c94ff9e6037763c40792eafa153ed3fe54d2d Mon Sep 17 00:00:00 2001 From: Sumit Jain Date: Mon, 27 Apr 2026 10:43:04 +0530 Subject: [PATCH 9/9] feat(customize_form): add 'in_import_template' field option to customize form and field --- frappe/custom/doctype/customize_form/customize_form.py | 1 + .../customize_form_field/customize_form_field.json | 10 +++++++++- .../customize_form_field/customize_form_field.py | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 472a80c6a7..d1c9e5c969 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -787,6 +787,7 @@ docfield_properties = { "print_hide": "Check", "print_hide_if_no_value": "Check", "report_hide": "Check", + "in_import_template": "Check", "allow_on_submit": "Check", "translatable": "Check", "mandatory_depends_on": "Data", diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 3e658738bf..89a3d14f95 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -48,6 +48,7 @@ "ignore_user_permissions", "allow_on_submit", "report_hide", + "in_import_template", "remember_last_selected_value", "hide_border", "ignore_xss_filter", @@ -293,6 +294,13 @@ "oldfieldname": "report_hide", "oldfieldtype": "Check" }, + { + "default": "0", + "description": "Enable this option to include the field in the data import template", + "fieldname": "in_import_template", + "fieldtype": "Check", + "label": "Include in Import Template" + }, { "default": "0", "depends_on": "eval:(doc.fieldtype == 'Link')", @@ -523,7 +531,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-03-22 10:36:12.968197", + "modified": "2026-04-27 12:00:00.000000", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.py b/frappe/custom/doctype/customize_form_field/customize_form_field.py index bd4d46ffe7..dd103969e4 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.py +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.py @@ -81,6 +81,7 @@ class CustomizeFormField(Document): ignore_xss_filter: DF.Check in_filter: DF.Check in_global_search: DF.Check + in_import_template: DF.Check in_list_view: DF.Check in_preview: DF.Check in_standard_filter: DF.Check