diff --git a/cypress/integration/form_builder.js b/cypress/integration/form_builder.js index a02febedc1..85d7ef91e0 100644 --- a/cypress/integration/form_builder.js +++ b/cypress/integration/form_builder.js @@ -273,4 +273,29 @@ context("Form Builder", () => { .find(".msgprint") .should("contain", "cannot be hidden and mandatory without any default value"); }); + + it("Undo/Redo", () => { + cy.visit(`/app/form-builder/${doctype_name}`); + + // click on second tab + cy.get(".tabs .tab:last").click(); + + let first_column = ".tab-content.active .section-columns-container:first .column:first"; + let first_field = first_column + " .field:first"; + let label = "div[title='Double click to edit label'] span:first"; + + // drag the first field to second position + cy.get(first_field).drag(first_column + " .field:nth-child(2)", { + target: { x: 100, y: 10 }, + }); + cy.get(first_field).find(label).should("have.text", "Check"); + + // undo + cy.get("body").type("{ctrl}z"); + cy.get(first_field).find(label).should("have.text", "Data"); + + // redo + cy.get("body").type("{ctrl}{shift}z"); + cy.get(first_field).find(label).should("have.text", "Check"); + }); }); diff --git a/cypress/integration/list_view_settings.js b/cypress/integration/list_view_settings.js index 898fe1dec4..ff9a30ce5c 100644 --- a/cypress/integration/list_view_settings.js +++ b/cypress/integration/list_view_settings.js @@ -15,11 +15,13 @@ context("List View Settings", () => { cy.clear_filters(); cy.wait(300); cy.get(".list-count").should("contain", "20 of"); + cy.get("[href='#icon-small-message']").should("be.visible"); cy.get(".menu-btn-group button").click(); cy.get(".dropdown-menu li").filter(":visible").contains("List Settings").click(); cy.get(".modal-dialog").should("contain", "DocType Settings"); cy.findByLabelText("Disable Count").check({ force: true }); + cy.findByLabelText("Disable Comment Count").check({ force: true }); cy.findByLabelText("Disable Sidebar Stats").check({ force: true }); cy.findByRole("button", { name: "Save" }).click(); @@ -27,11 +29,13 @@ context("List View Settings", () => { cy.get(".list-count").should("be.empty"); cy.get(".list-sidebar .list-tags").should("not.exist"); + cy.get("[href='#icon-small-message']").should("not.be.visible"); cy.get(".menu-btn-group button").click({ force: true }); cy.get(".dropdown-menu li").filter(":visible").contains("List Settings").click(); cy.get(".modal-dialog").should("contain", "DocType Settings"); cy.findByLabelText("Disable Count").uncheck({ force: true }); + cy.findByLabelText("Disable Comment Count").uncheck({ force: true }); cy.findByLabelText("Disable Sidebar Stats").uncheck({ force: true }); cy.findByRole("button", { name: "Save" }).click(); }); diff --git a/frappe/automation/doctype/reminder/__init__.py b/frappe/automation/doctype/reminder/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/automation/doctype/reminder/reminder.js b/frappe/automation/doctype/reminder/reminder.js new file mode 100644 index 0000000000..6d1a72bab2 --- /dev/null +++ b/frappe/automation/doctype/reminder/reminder.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Reminder", { +// refresh(frm) { + +// }, +// }); diff --git a/frappe/automation/doctype/reminder/reminder.json b/frappe/automation/doctype/reminder/reminder.json new file mode 100644 index 0000000000..a288f205a2 --- /dev/null +++ b/frappe/automation/doctype/reminder/reminder.json @@ -0,0 +1,90 @@ +{ + "actions": [], + "autoname": "hash", + "creation": "2023-02-22 11:23:58.183276", + "default_view": "List", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "user", + "remind_at", + "description", + "reminder_doctype", + "reminder_docname", + "notified" + ], + "fields": [ + { + "default": "__user", + "fieldname": "user", + "fieldtype": "Link", + "hidden": 1, + "label": "User", + "options": "User", + "reqd": 1, + "search_index": 1 + }, + { + "fieldname": "reminder_doctype", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Document Type", + "options": "DocType", + "read_only": 1 + }, + { + "fieldname": "reminder_docname", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Document Name", + "options": "reminder_doctype", + "read_only": 1 + }, + { + "default": "now", + "fieldname": "remind_at", + "fieldtype": "Datetime", + "in_list_view": 1, + "label": "Remind At", + "reqd": 1, + "search_index": 1 + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description", + "reqd": 1 + }, + { + "default": "0", + "fieldname": "notified", + "fieldtype": "Check", + "hidden": 1, + "label": "notified" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2023-02-24 13:47:50.419648", + "modified_by": "Administrator", + "module": "Automation", + "name": "Reminder", + "naming_rule": "Random", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "if_owner": 1, + "read": 1, + "role": "All", + "write": 1 + } + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "description" +} \ No newline at end of file diff --git a/frappe/automation/doctype/reminder/reminder.py b/frappe/automation/doctype/reminder/reminder.py new file mode 100644 index 0000000000..795cdfda69 --- /dev/null +++ b/frappe/automation/doctype/reminder/reminder.py @@ -0,0 +1,78 @@ +# Copyright (c) 2023, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import cint +from frappe.utils.data import add_to_date, get_datetime, now_datetime + + +class Reminder(Document): + @staticmethod + def clear_old_logs(days=30): + from frappe.query_builder import Interval + from frappe.query_builder.functions import Now + + table = frappe.qb.DocType("Reminder") + frappe.db.delete(table, filters=(table.remind_at < (Now() - Interval(days=days)))) + + def validate(self): + self.user = frappe.session.user + if get_datetime(self.remind_at) < now_datetime(): + frappe.throw(_("Reminder cannot be created in past.")) + + def send_reminder(self): + if self.notified: + return + + self.db_set("notified", 1, update_modified=False) + + try: + notification = frappe.new_doc("Notification Log") + notification.for_user = self.user + notification.set("type", "Alert") + notification.document_type = self.reminder_doctype + notification.document_name = self.reminder_docname + notification.subject = self.description + notification.insert() + except Exception: + self.log_error("Failed to send reminder") + + +@frappe.whitelist() +def create_new_reminder( + remind_at: str, + description: str, + reminder_doctype: str | None = None, + reminder_docname: str | None = None, +): + reminder = frappe.new_doc("Reminder") + + reminder.description = description + reminder.remind_at = remind_at + reminder.reminder_doctype = reminder_doctype + reminder.reminder_docname = reminder_docname + + return reminder.insert() + + +def send_reminders(): + # Ensure that we send all reminders that might be before next job execution. + job_freq = cint(frappe.get_conf().scheduler_interval) or 240 + upper_threshold = add_to_date(now_datetime(), seconds=job_freq, as_string=True, as_datetime=True) + + lower_threshold = add_to_date(now_datetime(), hours=-8, as_string=True, as_datetime=True) + + pending_reminders = frappe.get_all( + "Reminder", + filters=[ + ("remind_at", "<=", upper_threshold), + ("remind_at", ">=", lower_threshold), # dont send too old reminders if failed to send + ("notified", "=", 0), + ], + pluck="name", + ) + + for reminder in pending_reminders: + frappe.get_doc("Reminder", reminder).send_reminder() diff --git a/frappe/automation/doctype/reminder/test_reminder.py b/frappe/automation/doctype/reminder/test_reminder.py new file mode 100644 index 0000000000..84cc258701 --- /dev/null +++ b/frappe/automation/doctype/reminder/test_reminder.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023, Frappe Technologies and Contributors +# See license.txt + +import frappe +from frappe.automation.doctype.reminder.reminder import create_new_reminder, send_reminders +from frappe.desk.doctype.notification_log.notification_log import get_notification_logs +from frappe.tests.utils import FrappeTestCase +from frappe.utils import add_to_date, now_datetime + + +class TestReminder(FrappeTestCase): + def test_reminder(self): + + description = "TEST_REMINDER" + + create_new_reminder( + remind_at=add_to_date(now_datetime(), minutes=1, as_datetime=True, as_string=True), + description=description, + ) + + send_reminders() + + notifications = get_notification_logs()["notification_logs"] + self.assertIn( + description, + [n.subject for n in notifications], + msg=f"Failed to find reminder notification \n{notifications}", + ) diff --git a/frappe/boot.py b/frappe/boot.py index 7c43c68488..9594635c70 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -12,6 +12,7 @@ from frappe.desk.doctype.route_history.route_history import frequently_visited_l from frappe.desk.form.load import get_meta_bundle from frappe.email.inbox import get_email_accounts from frappe.model.base_document import get_controller +from frappe.permissions import has_permission from frappe.query_builder import DocType from frappe.query_builder.functions import Count from frappe.query_builder.terms import ParameterizedValueWrapper, SubQuery @@ -234,6 +235,9 @@ def get_user_pages_or_reports(parent, cache=False): has_role[p.name] = {"modified": p.modified, "title": p.title} elif parent == "Report": + if not has_permission("Report", raise_exception=False): + return {} + reports = frappe.get_list( "Report", fields=["name", "report_type"], diff --git a/frappe/contacts/doctype/address/address.json b/frappe/contacts/doctype/address/address.json index ce8e435bfa..c30299c7ad 100644 --- a/frappe/contacts/doctype/address/address.json +++ b/frappe/contacts/doctype/address/address.json @@ -204,7 +204,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 } diff --git a/frappe/contacts/doctype/address_template/address_template.json b/frappe/contacts/doctype/address_template/address_template.json index 48eacc0fc7..58b8210a49 100644 --- a/frappe/contacts/doctype/address_template/address_template.json +++ b/frappe/contacts/doctype/address_template/address_template.json @@ -53,7 +53,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 } @@ -62,4 +61,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/frappe/contacts/doctype/contact/contact.json b/frappe/contacts/doctype/contact/contact.json index c756a8ecb8..3090746657 100644 --- a/frappe/contacts/doctype/contact/contact.json +++ b/frappe/contacts/doctype/contact/contact.json @@ -275,7 +275,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 }, diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.json b/frappe/core/doctype/custom_docperm/custom_docperm.json index 2c594f5624..208b0beef9 100644 --- a/frappe/core/doctype/custom_docperm/custom_docperm.json +++ b/frappe/core/doctype/custom_docperm/custom_docperm.json @@ -27,7 +27,6 @@ "report", "export", "import", - "set_user_permissions", "column_break_19", "share", "print", @@ -179,13 +178,6 @@ "fieldtype": "Check", "label": "Import" }, - { - "default": "0", - "description": "This role update User Permissions for a user", - "fieldname": "set_user_permissions", - "fieldtype": "Check", - "label": "Set User Permissions" - }, { "fieldname": "column_break_19", "fieldtype": "Column Break" @@ -223,7 +215,7 @@ } ], "links": [], - "modified": "2020-12-03 15:20:48.296730", + "modified": "2023-02-20 13:19:04.889081", "modified_by": "Administrator", "module": "Core", "name": "Custom DocPerm", diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 0d8d7ea671..90b1c6cb77 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -304,6 +304,7 @@ }, { "default": "0", + "depends_on": "eval:!in_list(['Section Break', 'Column Break', 'Tab Break'], doc.fieldtype)", "fieldname": "permlevel", "fieldtype": "Int", "label": "Perm Level", @@ -555,7 +556,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-01-11 20:46:43.164926", + "modified": "2023-02-20 12:07:29.552523", "modified_by": "Administrator", "module": "Core", "name": "DocField", diff --git a/frappe/core/doctype/docperm/docperm.json b/frappe/core/doctype/docperm/docperm.json index 4411a67435..3ce49c4d6b 100644 --- a/frappe/core/doctype/docperm/docperm.json +++ b/frappe/core/doctype/docperm/docperm.json @@ -26,7 +26,6 @@ "report", "export", "import", - "set_user_permissions", "column_break_19", "share", "print", @@ -178,13 +177,6 @@ "fieldtype": "Check", "label": "Import" }, - { - "default": "0", - "description": "This role update User Permissions for a user", - "fieldname": "set_user_permissions", - "fieldtype": "Check", - "label": "Set User Permissions" - }, { "fieldname": "column_break_19", "fieldtype": "Column Break" @@ -218,7 +210,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2020-12-03 15:15:30.488212", + "modified": "2023-02-20 13:21:45.071310", "modified_by": "Administrator", "module": "Core", "name": "DocPerm", diff --git a/frappe/core/doctype/doctype/boilerplate/controller._py b/frappe/core/doctype/doctype/boilerplate/controller._py index 6db99def55..d8f02bf09c 100644 --- a/frappe/core/doctype/doctype/boilerplate/controller._py +++ b/frappe/core/doctype/doctype/boilerplate/controller._py @@ -4,5 +4,6 @@ # import frappe {base_class_import} + class {classname}({base_class}): {custom_controller} diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index d9c31d312e..d92277152c 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -55,7 +55,7 @@ frappe.ui.form.on("DocType", { msg += __("If you just want to customize for your site, use {0} instead.", [ customize_form_link, ]); - frm.dashboard.add_comment(msg, "yellow"); + frm.dashboard.add_comment(msg, "yellow", true); } if (frm.is_new()) { diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 0ac5533ea2..6cc0adcc87 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1604,11 +1604,6 @@ def validate_permissions(doctype, for_remove=False, alert=False): d.set("import", 0) d.set("export", 0) - for ptype, label in [["set_user_permissions", _("Set User Permissions")]]: - if d.get(ptype): - d.set(ptype, 0) - frappe.msgprint(_("{0} cannot be set for Single types").format(label)) - def check_if_submittable(d): if d.submit and not issubmittable: frappe.throw(_("{0}: Cannot set Assign Submit if not Submittable").format(get_txt(d))) diff --git a/frappe/core/doctype/document_naming_settings/document_naming_settings.json b/frappe/core/doctype/document_naming_settings/document_naming_settings.json index 4c86b2ec1d..9a12f3f77e 100644 --- a/frappe/core/doctype/document_naming_settings/document_naming_settings.json +++ b/frappe/core/doctype/document_naming_settings/document_naming_settings.json @@ -81,10 +81,10 @@ }, { "depends_on": "transaction_type", - "description": "Generate 3 preview of names generate by any valid series.", + "description": "Get a preview of generated names with a series.", "fieldname": "try_naming_series", "fieldtype": "Data", - "label": "Try a naming Series" + "label": "Try a Naming Series" }, { "fieldname": "transaction_type", @@ -111,7 +111,7 @@ "icon": "fa fa-sort-by-order", "issingle": 1, "links": [], - "modified": "2022-05-30 23:51:36.136535", + "modified": "2023-02-20 13:11:56.662100", "modified_by": "Administrator", "module": "Core", "name": "Document Naming Settings", @@ -130,4 +130,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} +} \ No newline at end of file diff --git a/frappe/core/doctype/log_settings/log_settings.py b/frappe/core/doctype/log_settings/log_settings.py index eaa55f4bca..4a3b457bcc 100644 --- a/frappe/core/doctype/log_settings/log_settings.py +++ b/frappe/core/doctype/log_settings/log_settings.py @@ -19,6 +19,8 @@ DEFAULT_LOGTYPES_RETENTION = { "Route History": 90, "Submission Queue": 30, "Prepared Report": 30, + "Webhook Request Log": 30, + "Reminder": 30, } diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 64982c5707..00e1cffa88 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -769,7 +769,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 }, @@ -793,4 +792,4 @@ "states": [], "title_field": "full_name", "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/core/page/permission_manager/permission_manager.js b/frappe/core/page/permission_manager/permission_manager.js index f29df0d3e5..bc27106068 100644 --- a/frappe/core/page/permission_manager/permission_manager.js +++ b/frappe/core/page/permission_manager/permission_manager.js @@ -320,7 +320,6 @@ frappe.PermissionEngine = class PermissionEngine { "report", "import", "export", - "set_user_permissions", "share", ]; } diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index 45c1e44fa1..5ed3014778 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -62,8 +62,8 @@ def get_roles_and_doctypes(): roles_list = [{"label": _(d.get("name")), "value": d.get("name")} for d in roles] return { - "doctypes": sorted(doctypes_list, key=lambda d: d["label"]), - "roles": sorted(roles_list, key=lambda d: d["label"]), + "doctypes": sorted(doctypes_list, key=lambda d: d["label"].casefold()), + "roles": sorted(roles_list, key=lambda d: d["label"].casefold()), } diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index 758d9c1e64..8953153be6 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -18,6 +18,18 @@ class CustomField(Document): self.name = self.dt + "-" + self.fieldname def set_fieldname(self): + restricted = ( + "name", + "parent", + "creation", + "modified", + "modified_by", + "parentfield", + "parenttype", + "file_list", + "flags", + "docstatus", + ) if not self.fieldname: label = self.label if not label: @@ -34,6 +46,9 @@ class CustomField(Document): # fieldnames should be lowercase self.fieldname = self.fieldname.lower() + if self.fieldname in restricted: + self.fieldname = self.fieldname + "1" + def before_insert(self): self.set_fieldname() diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 618186c0de..4ab693b415 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -314,22 +314,59 @@ frappe.ui.form.on("DocType State", { }, }); -frappe.customize_form.set_primary_action = function (frm) { - frm.page.set_primary_action(__("Update"), function () { - if (frm.doc.doc_type) { - return frm.call({ - doc: frm.doc, - freeze: true, - btn: frm.page.btn_primary, - method: "save_customization", - callback: function (r) { - if (!r.exc) { - frappe.customize_form.clear_locals_and_refresh(frm); - frm.script_manager.trigger("doc_type"); - } - }, - }); +frappe.customize_form.validate_fieldnames = async function (frm) { + for (let i = 0; i < frm.doc.fields.length; i++) { + let field = frm.doc.fields[i]; + + let fieldname = field.label && frappe.model.scrub(field.label).toLowerCase(); + if ( + field.label && + !field.fieldname && + in_list(frappe.model.restricted_fields, fieldname) + ) { + let message = __( + "For field {0} in row {1}, fieldname {2} is restricted it will be renamed as {2}1. Do you want to continue?", + [field.label, field.idx, fieldname] + ); + await pause_to_confirm(message); } + } + + function pause_to_confirm(message) { + return new Promise((resolve) => { + frappe.confirm( + message, + () => resolve(), + () => { + frm.page.btn_primary.prop("disabled", false); + } + ); + }); + } +}; + +frappe.customize_form.save_customization = function (frm) { + if (frm.doc.doc_type) { + return frm.call({ + doc: frm.doc, + freeze: true, + freeze_message: __("Saving Customization..."), + btn: frm.page.btn_primary, + method: "save_customization", + callback: function (r) { + if (!r.exc) { + frappe.customize_form.clear_locals_and_refresh(frm); + frm.script_manager.trigger("doc_type"); + } + }, + }); + } +}; + +frappe.customize_form.set_primary_action = function (frm) { + frm.page.set_primary_action(__("Update"), async () => { + await this.validate_fieldnames(frm); + this.save_customization(frm); }); }; 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 ad0d600a0b..d8da44101b 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -212,6 +212,7 @@ }, { "default": "0", + "depends_on": "eval:!in_list(['Section Break', 'Column Break', 'Tab Break'], doc.fieldtype)", "fieldname": "permlevel", "fieldtype": "Int", "in_list_view": 1, @@ -467,7 +468,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2022-11-30 14:25:50.649449", + "modified": "2023-02-20 12:07:40.242470", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/custom/fixtures/temp_doctype.json b/frappe/custom/fixtures/temp_doctype.json index 8c23227389..20b3d9caa9 100644 --- a/frappe/custom/fixtures/temp_doctype.json +++ b/frappe/custom/fixtures/temp_doctype.json @@ -57,7 +57,6 @@ "report": 1, "export": 1, "import": 0, - "set_user_permissions": 0, "share": 1, "print": 1, "email": 1, diff --git a/frappe/custom/fixtures/temp_singles.json b/frappe/custom/fixtures/temp_singles.json index d6ecd74420..723f47d7ac 100644 --- a/frappe/custom/fixtures/temp_singles.json +++ b/frappe/custom/fixtures/temp_singles.json @@ -57,7 +57,6 @@ "report": 1, "export": 1, "import": 0, - "set_user_permissions": 0, "share": 1, "print": 1, "email": 1, diff --git a/frappe/database/database.py b/frappe/database/database.py index 0ffda1af9d..a9d1ddc3bb 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -1046,7 +1046,7 @@ class Database: dt = dt.copy() # don't modify the original dict dt, dn = dt.pop("doctype"), dt - return self.get_value(dt, dn, ignore=True, cache=cache) + return self.get_value(dt, dn, ignore=True, cache=cache, order_by=None) def count(self, dt, filters=None, debug=False, cache=False, distinct: bool = True): """Returns `COUNT(*)` for given DocType and filters.""" diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index 8d2f1df973..5cbeb06e33 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -278,15 +278,14 @@ def get_group_by_chart_config(chart, filters): group_by_field = chart.group_by_based_on doctype = chart.document_type - data = frappe.db.get_list( + data = frappe.get_list( doctype, fields=[ f"{group_by_field} as name", - "{aggregate_function}({value_field}) as count".format( - aggregate_function=aggregate_function, value_field=value_field - ), + f"{aggregate_function}({value_field}) as count", ], filters=filters, + parent_doctype=chart.parent_document_type, group_by=group_by_field, order_by="count desc", ignore_ifnull=True, diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.json b/frappe/desk/doctype/list_view_settings/list_view_settings.json index 44761992f1..69ea379e61 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.json +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.json @@ -7,6 +7,7 @@ "engine": "InnoDB", "field_order": [ "disable_count", + "disable_comment_count", "disable_sidebar_stats", "disable_auto_refresh", "total_fields", @@ -49,13 +50,20 @@ "hidden": 1, "label": "Fields", "read_only": 1 + }, + { + "default": "0", + "fieldname": "disable_comment_count", + "fieldtype": "Check", + "label": "Disable Comment Count" } ], "links": [], - "modified": "2020-05-12 18:27:15.568199", + "modified": "2023-02-14 14:46:43.764229", "modified_by": "Administrator", "module": "Desk", "name": "List View Settings", + "naming_rule": "Set by user", "owner": "Administrator", "permissions": [ { @@ -72,5 +80,6 @@ "read_only": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index 84239fae6d..c5fe6407b7 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -59,7 +59,7 @@ def get_tags(doctype, txt): tag = frappe.get_list("Tag", filters=[["name", "like", f"%{txt}%"]]) tags = [t.name for t in tag] - return sorted(filter(lambda t: t and txt.lower() in t.lower(), list(set(tags)))) + return sorted(filter(lambda t: t and txt.casefold() in t.casefold(), list(set(tags)))) class DocTags: diff --git a/frappe/desk/search.py b/frappe/desk/search.py index 2af9b575be..ee63f67423 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -282,7 +282,7 @@ def scrub_custom_query(query, key, txt): def relevance_sorter(key, query, as_dict): value = _(key.name if as_dict else key[0]) - return (cstr(value).lower().startswith(query.lower()) is not True, value) + return (cstr(value).casefold().startswith(query.casefold()) is not True, value) def validate_and_sanitize_search_inputs(fn): diff --git a/frappe/email/doctype/email_account/email_account.json b/frappe/email/doctype/email_account/email_account.json index f9e4f95ff0..85241b8194 100644 --- a/frappe/email/doctype/email_account/email_account.json +++ b/frappe/email/doctype/email_account/email_account.json @@ -628,7 +628,6 @@ "delete": 1, "read": 1, "role": "System Manager", - "set_user_permissions": 1, "write": 1 }, { @@ -640,4 +639,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/email/doctype/email_domain/email_domain.json b/frappe/email/doctype/email_domain/email_domain.json index 18635e6dae..c162060436 100644 --- a/frappe/email/doctype/email_domain/email_domain.json +++ b/frappe/email/doctype/email_domain/email_domain.json @@ -145,7 +145,6 @@ "delete": 1, "read": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 } @@ -154,4 +153,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/email/doctype/newsletter/newsletter.json b/frappe/email/doctype/newsletter/newsletter.json index b42f4755cb..b757e95e36 100644 --- a/frappe/email/doctype/newsletter/newsletter.json +++ b/frappe/email/doctype/newsletter/newsletter.json @@ -251,7 +251,6 @@ "read": 1, "report": 1, "role": "Newsletter Manager", - "set_user_permissions": 1, "share": 1, "write": 1 } @@ -261,4 +260,4 @@ "sort_order": "ASC", "title_field": "subject", "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/exceptions.py b/frappe/exceptions.py index f09583e215..20e858c543 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -244,6 +244,10 @@ class InReadOnlyMode(ValidationError): http_status_code = 503 # temporarily not available +class SessionBootFailed(ValidationError): + http_status_code = 500 + + class TooManyWritesError(Exception): pass diff --git a/frappe/geo/doctype/country/country.json b/frappe/geo/doctype/country/country.json index 2cbd0a296f..8f62458ad1 100644 --- a/frappe/geo/doctype/country/country.json +++ b/frappe/geo/doctype/country/country.json @@ -69,7 +69,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 }, @@ -87,4 +86,4 @@ "states": [], "track_changes": 1, "translated_doctype": 1 -} \ No newline at end of file +} diff --git a/frappe/hooks.py b/frappe/hooks.py index 36ba699531..429640d6d5 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -192,6 +192,7 @@ scheduler_events = { "frappe.email.doctype.email_account.email_account.notify_unreplied", "frappe.utils.global_search.sync_global_search", "frappe.monitor.flush", + "frappe.automation.doctype.reminder.reminder.send_reminders", ], "hourly": [ "frappe.model.utils.link_count.update_link_count", @@ -390,6 +391,7 @@ ignore_links_on_delete = [ "Document Share Key", "Integration Request", "Unhandled Email", + "Webhook Request Log", ] # Request Hooks diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.py b/frappe/integrations/doctype/google_calendar/google_calendar.py index 534e3c1ac7..5056f536fc 100644 --- a/frappe/integrations/doctype/google_calendar/google_calendar.py +++ b/frappe/integrations/doctype/google_calendar/google_calendar.py @@ -422,7 +422,10 @@ def insert_event_in_google_calendar(doc, method=None): event = ( google_calendar.events() .insert( - calendarId=doc.google_calendar_id, body=event, conferenceDataVersion=conference_data_version + calendarId=doc.google_calendar_id, + body=event, + conferenceDataVersion=conference_data_version, + sendUpdates="all", ) .execute() ) @@ -504,6 +507,7 @@ def update_event_in_google_calendar(doc, method=None): eventId=doc.google_calendar_event_id, body=event, conferenceDataVersion=conference_data_version, + sendUpdates="all", ) .execute() ) diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index 6d2773a29c..9ab25f56b2 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -128,32 +128,40 @@ def enqueue_webhook(doc, webhook) -> None: ) r.raise_for_status() frappe.logger().debug({"webhook_success": r.text}) - log_request(webhook.request_url, headers, data, r) + log_request(webhook.name, doc.name, webhook.request_url, headers, data, r) break except requests.exceptions.ReadTimeout as e: frappe.logger().debug({"webhook_error": e, "try": i + 1}) - log_request(webhook.request_url, headers, data) + log_request(webhook.name, doc.name, webhook.request_url, headers, data) except Exception as e: frappe.logger().debug({"webhook_error": e, "try": i + 1}) - log_request(webhook.request_url, headers, data, r) + log_request(webhook.name, doc.name, webhook.request_url, headers, data, r) sleep(3 * i + 1) if i != 2: continue - else: - webhook.log_error("Webhook failed") -def log_request(url: str, headers: dict, data: dict, res: requests.Response | None = None): +def log_request( + webhook: str, + docname: str, + url: str, + headers: dict, + data: dict, + res: requests.Response | None = None, +): request_log = frappe.get_doc( { "doctype": "Webhook Request Log", + "webhook": webhook, + "reference_document": docname, "user": frappe.session.user if frappe.session.user else None, "url": url, "headers": frappe.as_json(headers) if headers else None, "data": frappe.as_json(data) if data else None, "response": frappe.as_json(res.json()) if res else None, + "error": frappe.get_traceback(), } ) diff --git a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.json b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.json index d9410a2f82..ed5201df1f 100644 --- a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.json +++ b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.json @@ -7,11 +7,14 @@ "engine": "InnoDB", "field_order": [ "user", + "webhook", + "reference_document", "headers", "data", "column_break_4", "url", - "response" + "response", + "error" ], "fields": [ { @@ -51,12 +54,32 @@ "label": "User", "options": "User", "read_only": 1 + }, + { + "fieldname": "reference_document", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Reference Document", + "read_only": 1 + }, + { + "fieldname": "error", + "fieldtype": "Text", + "label": "Error", + "read_only": 1 + }, + { + "fieldname": "webhook", + "fieldtype": "Link", + "label": "Webhook", + "options": "Webhook" } ], "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2022-05-03 09:33:49.240777", + "modified": "2023-02-24 14:59:24.743552", "modified_by": "Administrator", "module": "Integrations", "name": "Webhook Request Log", diff --git a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py index 8fbc73f5e5..175215f4d4 100644 --- a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py +++ b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py @@ -1,9 +1,15 @@ # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE -# import frappe +import frappe from frappe.model.document import Document class WebhookRequestLog(Document): - pass + @staticmethod + def clear_old_logs(days=30): + from frappe.query_builder import Interval + from frappe.query_builder.functions import Now + + table = frappe.qb.DocType("Webhook Request Log") + frappe.db.delete(table, filters=(table.modified < (Now() - Interval(days=days)))) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 893d349d70..8cc939a1ee 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -29,6 +29,7 @@ from frappe.utils import ( get_timespan_date_range, make_filter_tuple, ) +from frappe.utils.data import sbool LOCATE_PATTERN = re.compile(r"locate\([^,]+,\s*[`\"]?name[`\"]?\s*\)", flags=re.IGNORECASE) LOCATE_CAST_PATTERN = re.compile( @@ -74,6 +75,10 @@ class DatabaseQuery: self._doctype_meta = frappe.get_meta(self.doctype) return self._doctype_meta + @property + def query_tables(self): + return self.tables + [d.table_name for d in self.link_tables] + def execute( self, fields=None, @@ -196,7 +201,7 @@ class DatabaseQuery: result = self.build_and_run() - if with_comment_count and not as_list and self.doctype: + if sbool(with_comment_count) and not as_list and self.doctype: self.add_comment_count(result) if save_user_settings: @@ -472,9 +477,7 @@ class DatabaseQuery: table_name = table_name[13:] if not table_name[0] == "`": table_name = f"`{table_name}`" - if table_name not in self.tables and table_name not in ( - d.table_name for d in self.link_tables - ): + if table_name not in self.query_tables: self.append_table(table_name) def append_table(self, table_name): @@ -640,7 +643,7 @@ class DatabaseQuery: table, column = column.split(".", 1) ch_doctype = table.replace("`", "").replace("tab", "", 1) - if wrap_grave_quotes(table) in self.tables: + if wrap_grave_quotes(table) in self.query_tables: permitted_child_table_fields = get_permitted_fields( doctype=ch_doctype, parenttype=self.doctype ) diff --git a/frappe/model/document.py b/frappe/model/document.py index 8a99676b60..7fcb9ac335 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -676,7 +676,11 @@ class Document(BaseDocument): for df in self.meta.fields: if df.permlevel and hasattr(self, df.fieldname) and df.permlevel not in has_access_to: - delattr(self, df.fieldname) + try: + delattr(self, df.fieldname) + except AttributeError: + # hasattr might return True for class attribute which can't be delattr-ed. + continue for table_field in self.meta.get_table_fields(): for df in frappe.get_meta(table_field.options).fields or []: diff --git a/frappe/permissions.py b/frappe/permissions.py index 91517e774f..75a940233e 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -22,7 +22,6 @@ rights = ( "report", "import", "export", - "set_user_permissions", "share", ) @@ -459,29 +458,6 @@ def get_doctypes_with_custom_docperms(): return [d.parent for d in doctypes] -def can_set_user_permissions(doctype, docname=None): - # System Manager can always set user permissions - if frappe.session.user == "Administrator" or "System Manager" in frappe.get_roles(): - return True - - meta = frappe.get_meta(doctype) - - # check if current user has read permission for docname - if docname and not has_permission(doctype, "read", docname): - return False - - # check if current user has a role that can set permission - if get_role_permissions(meta).set_user_permissions != 1: - return False - - return True - - -def set_user_permission_if_allowed(doctype, name, user, with_message=False): - if get_role_permissions(frappe.get_meta(doctype), user).set_user_permissions != 1: - add_user_permission(doctype, name, user) - - def add_user_permission( doctype, name, diff --git a/frappe/printing/doctype/print_heading/print_heading.json b/frappe/printing/doctype/print_heading/print_heading.json index 418429f29e..9951b533cb 100644 --- a/frappe/printing/doctype/print_heading/print_heading.json +++ b/frappe/printing/doctype/print_heading/print_heading.json @@ -1,145 +1,143 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "field:print_heading", - "beta": 0, - "creation": "2013-01-10 16:34:24", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:print_heading", + "beta": 0, + "creation": "2013-01-10 16:34:24", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 0, "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "print_heading", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Print Heading", - "length": 0, - "no_copy": 0, - "oldfieldname": "print_heading", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "print_heading", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Print Heading", + "length": 0, + "no_copy": 0, + "oldfieldname": "print_heading", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Small Text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Description", + "length": 0, + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Small Text", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "300px" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-font", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-05-03 05:59:09.131569", - "modified_by": "Administrator", - "module": "Printing", - "name": "Print Heading", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "icon": "fa fa-font", + "idx": 1, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-05-03 05:59:09.131569", + "modified_by": "Administrator", + "module": "Printing", + "name": "Print Heading", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "All", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "All", + "share": 0, + "submit": 0, "write": 0 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "print_heading", - "show_name_in_global_search": 0, - "sort_order": "DESC", - "track_changes": 0, + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "search_fields": "print_heading", + "show_name_in_global_search": 0, + "sort_order": "DESC", + "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} diff --git a/frappe/public/js/form_builder/components/Column.vue b/frappe/public/js/form_builder/components/Column.vue index a9c4bf0ea1..acb1ff735e 100644 --- a/frappe/public/js/form_builder/components/Column.vue +++ b/frappe/public/js/form_builder/components/Column.vue @@ -85,7 +85,7 @@ function delete_column(with_children) { // remove column columns.splice(index, 1); - store.selected_field = null; + store.form.selected_field = null; } function move_columns_to_section() { @@ -101,7 +101,7 @@ function move_columns_to_section() { store.selected(column.df.name) ? 'selected' : '' ]" :title="column.df.fieldname" - @click.stop="store.selected_field = column.df" + @click.stop="store.form.selected_field = column.df" @mouseover.stop="hovered = true" @mouseout.stop="hovered = false" > diff --git a/frappe/public/js/form_builder/components/Field.vue b/frappe/public/js/form_builder/components/Field.vue index cf3e21c310..e0230765b5 100644 --- a/frappe/public/js/form_builder/components/Field.vue +++ b/frappe/public/js/form_builder/components/Field.vue @@ -19,7 +19,7 @@ function remove_field() { } let index = props.column.fields.indexOf(props.field); props.column.fields.splice(index, 1); - store.selected_field = null; + store.form.selected_field = null; } function move_fields_to_column() { @@ -51,7 +51,7 @@ function duplicate_field() { // push duplicate_field after props.field in the same column let index = props.column.fields.indexOf(props.field); props.column.fields.splice(index + 1, 0, duplicate_field); - store.selected_field = duplicate_field.df; + store.form.selected_field = duplicate_field.df; } @@ -63,7 +63,7 @@ function duplicate_field() { store.selected(field.df.name) ? 'selected' : '' ]" :title="field.df.fieldname" - @click.stop="store.selected_field = field.df" + @click.stop="store.form.selected_field = field.df" @mouseover.stop="hovered = true" @mouseout.stop="hovered = false" > diff --git a/frappe/public/js/form_builder/components/FieldProperties.vue b/frappe/public/js/form_builder/components/FieldProperties.vue index b5597d20c5..b8e687ac06 100644 --- a/frappe/public/js/form_builder/components/FieldProperties.vue +++ b/frappe/public/js/form_builder/components/FieldProperties.vue @@ -14,18 +14,18 @@ let docfield_df = computed(() => { if (in_list(frappe.model.layout_fields, df.fieldtype) || df.hidden) { return false; } - if (df.depends_on && !evaluate_depends_on_value(df.depends_on, store.selected_field)) { + if (df.depends_on && !evaluate_depends_on_value(df.depends_on, store.form.selected_field)) { return false; } if ( in_list(["fetch_from", "fetch_if_empty"], df.fieldname) && - in_list(frappe.model.no_value_type, store.selected_field.fieldtype) + in_list(frappe.model.no_value_type, store.form.selected_field.fieldtype) ) { return false; } - if (df.fieldname === "reqd" && store.selected_field.fieldtype === "Check") { + if (df.fieldname === "reqd" && store.form.selected_field.fieldtype === "Check") { return false; } @@ -34,11 +34,11 @@ let docfield_df = computed(() => { df.options = ""; args.value = {}; - if (in_list(["Table", "Link"], store.selected_field.fieldtype)) { + if (in_list(["Table", "Link"], store.form.selected_field.fieldtype)) { df.fieldtype = "Link"; df.options = "DocType"; - if (store.selected_field.fieldtype === "Table") { + if (store.form.selected_field.fieldtype === "Table") { args.value.is_table_field = 1; } } @@ -63,14 +63,14 @@ let docfield_df = computed(() => {