Merge branch 'develop' into app-switcher
This commit is contained in:
commit
11b699c60d
17 changed files with 174 additions and 132 deletions
|
|
@ -239,8 +239,7 @@
|
|||
"options": "Has Role",
|
||||
"permlevel": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"show_on_timeline": 1
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
|
|
@ -431,8 +430,7 @@
|
|||
"hidden": 1,
|
||||
"label": "Block Modules",
|
||||
"options": "Block Module",
|
||||
"permlevel": 1,
|
||||
"show_on_timeline": 1
|
||||
"permlevel": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "home_settings",
|
||||
|
|
@ -813,7 +811,7 @@
|
|||
"link_fieldname": "user"
|
||||
}
|
||||
],
|
||||
"modified": "2024-08-08 19:09:17.399748",
|
||||
"modified": "2024-08-12 15:23:38.996646",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "User",
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class Database:
|
|||
def _transform_query(self, query: Query, values: QueryValues) -> tuple:
|
||||
return query, values
|
||||
|
||||
def _transform_result(self, result: list[tuple]) -> list[tuple]:
|
||||
def _transform_result(self, result: list[tuple] | tuple[tuple]) -> tuple[tuple]:
|
||||
return result
|
||||
|
||||
def _clean_up(self):
|
||||
|
|
|
|||
|
|
@ -225,6 +225,9 @@ class PostgresDatabase(PostgresExceptionUtil, Database):
|
|||
)
|
||||
return db_size[0].get("database_size")
|
||||
|
||||
def _transform_result(self, result: list[tuple] | tuple[tuple]) -> tuple[tuple]:
|
||||
return tuple(result) if isinstance(result, list) else result
|
||||
|
||||
# pylint: disable=W0221
|
||||
def sql(self, query, values=EmptyQueryValues, *args, **kwargs):
|
||||
return super().sql(modify_query(query), modify_values(values), *args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -175,11 +175,17 @@ frappe.ui.form.on("Email Account", {
|
|||
delete locals["User"][frappe.route_flags.linked_user];
|
||||
}
|
||||
|
||||
if (frappe.boot.developer_mode && !frm.is_dirty() && frm.doc.enable_incoming) {
|
||||
if (!frm.is_dirty() && frm.doc.enable_incoming) {
|
||||
frm.add_custom_button(__("Pull Emails"), () => {
|
||||
frappe.dom.freeze(__("Pulling emails..."));
|
||||
frm.call({
|
||||
method: "pull_emails",
|
||||
args: { email_account: frm.doc.name },
|
||||
}).then((r) => {
|
||||
frappe.dom.unfreeze();
|
||||
if (!(r._server_messages && r._server_messages.length)) {
|
||||
frappe.show_alert({ message: __("Emails Pulled"), indicator: "green" });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -916,7 +916,13 @@ def pull_emails(email_account: str) -> None:
|
|||
"""Pull emails from given email account."""
|
||||
frappe.has_permission("Email Account", "read", throw=True)
|
||||
|
||||
pull_from_email_account(email_account)
|
||||
job_name = f"pull_from_email_account|{email_account}"
|
||||
queued_jobs = get_jobs(site=frappe.local.site, key="job_name")[frappe.local.site]
|
||||
|
||||
if job_name not in queued_jobs:
|
||||
pull_from_email_account(email_account)
|
||||
else:
|
||||
frappe.msgprint(_("Emails are already being pulled from this account."))
|
||||
|
||||
|
||||
def pull_from_email_account(email_account):
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ frappe.ui.form.on("Notification", {
|
|||
},
|
||||
};
|
||||
});
|
||||
frm.preview_fields = frm.doc.__onload.preview_fields;
|
||||
},
|
||||
refresh: function (frm) {
|
||||
frappe.notification.setup_fieldname_select(frm);
|
||||
|
|
@ -185,7 +184,15 @@ frappe.ui.form.on("Notification", {
|
|||
const args = {
|
||||
doc: frm.doc,
|
||||
doctype: frm.doc.document_type,
|
||||
preview_fields: frm.preview_fields,
|
||||
preview_fields: [
|
||||
{
|
||||
label: __("Meets Condition?"),
|
||||
fieldtype: "Data",
|
||||
method: "preview_meets_condition",
|
||||
},
|
||||
{ label: __("Subject"), fieldtype: "Data", method: "preview_subject" },
|
||||
{ label: __("Message"), fieldtype: "Code", method: "preview_message" },
|
||||
],
|
||||
};
|
||||
let dialog = new frappe.views.RenderPreviewer(args);
|
||||
return dialog;
|
||||
|
|
|
|||
|
|
@ -73,14 +73,6 @@ class Notification(Document):
|
|||
"""load message"""
|
||||
if self.is_standard:
|
||||
self.message = self.get_template()
|
||||
self.set_onload(
|
||||
"preview_fields",
|
||||
[
|
||||
{"label": _("Meets Condition?"), "fieldtype": "Data", "method": "preview_meets_condition"},
|
||||
{"label": _("Subject"), "fieldtype": "Data", "method": "preview_subject"},
|
||||
{"label": _("Message"), "fieldtype": "Code", "method": "preview_message"},
|
||||
],
|
||||
)
|
||||
|
||||
def autoname(self):
|
||||
if not self.name:
|
||||
|
|
|
|||
|
|
@ -85,6 +85,29 @@ frappe.ui.form.on("Webhook", {
|
|||
"background_jobs_queue",
|
||||
"frappe.integrations.doctype.webhook.webhook.get_all_queues"
|
||||
);
|
||||
|
||||
if (frm.doc.webhook_doctype) {
|
||||
frm.add_custom_button(__("Preview"), () => {
|
||||
const args = {
|
||||
doc: frm.doc,
|
||||
doctype: frm.doc.webhook_doctype,
|
||||
preview_fields: [
|
||||
{
|
||||
label: __("Meets Condition?"),
|
||||
fieldtype: "Data",
|
||||
method: "preview_meets_condition",
|
||||
},
|
||||
{
|
||||
label: __("Request Body"),
|
||||
fieldtype: "Code",
|
||||
method: "preview_request_body",
|
||||
},
|
||||
],
|
||||
};
|
||||
let dialog = new frappe.views.RenderPreviewer(args);
|
||||
return dialog;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
request_structure: (frm) => {
|
||||
|
|
@ -98,17 +121,6 @@ frappe.ui.form.on("Webhook", {
|
|||
enable_security: (frm) => {
|
||||
frm.toggle_reqd("webhook_secret", frm.doc.enable_security);
|
||||
},
|
||||
|
||||
preview_document: (frm) => {
|
||||
frappe.call({
|
||||
method: "generate_preview",
|
||||
doc: frm.doc,
|
||||
callback: (r) => {
|
||||
frm.refresh_field("meets_condition");
|
||||
frm.refresh_field("preview_request_body");
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Webhook Data", {
|
||||
|
|
|
|||
|
|
@ -30,13 +30,7 @@
|
|||
"webhook_headers",
|
||||
"sb_webhook_data",
|
||||
"webhook_data",
|
||||
"webhook_json",
|
||||
"preview_tab",
|
||||
"preview_document",
|
||||
"column_break_26",
|
||||
"meets_condition",
|
||||
"section_break_28",
|
||||
"preview_request_body"
|
||||
"webhook_json"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
|
|
@ -169,37 +163,6 @@
|
|||
"options": "POST\nPUT\nDELETE",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "preview_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Preview"
|
||||
},
|
||||
{
|
||||
"fieldname": "preview_document",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Select Document",
|
||||
"options": "webhook_doctype"
|
||||
},
|
||||
{
|
||||
"fieldname": "preview_request_body",
|
||||
"fieldtype": "Code",
|
||||
"is_virtual": 1,
|
||||
"label": "Request Body"
|
||||
},
|
||||
{
|
||||
"fieldname": "meets_condition",
|
||||
"fieldtype": "Data",
|
||||
"is_virtual": 1,
|
||||
"label": "Meets Condition?"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_26",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_28",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "On checking this option, URL will be treated like a jinja template string",
|
||||
|
|
@ -226,7 +189,7 @@
|
|||
"link_fieldname": "webhook"
|
||||
}
|
||||
],
|
||||
"modified": "2024-03-23 16:04:03.108172",
|
||||
"modified": "2024-07-22 09:23:32.642172",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Webhook",
|
||||
|
|
@ -250,4 +213,4 @@
|
|||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ class Webhook(Document):
|
|||
enable_security: DF.Check
|
||||
enabled: DF.Check
|
||||
is_dynamic_url: DF.Check
|
||||
meets_condition: DF.Data | None
|
||||
preview_document: DF.DynamicLink | None
|
||||
preview_request_body: DF.Code | None
|
||||
request_method: DF.Literal["POST", "PUT", "DELETE"]
|
||||
request_structure: DF.Literal["", "Form URL-Encoded", "JSON"]
|
||||
request_url: DF.SmallText
|
||||
|
|
@ -119,35 +116,24 @@ class Webhook(Document):
|
|||
frappe.throw(_("Invalid Webhook Secret"))
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_preview(self):
|
||||
# This function doesn't need to do anything specific as virtual fields
|
||||
# get evaluated automatically.
|
||||
pass
|
||||
|
||||
@property
|
||||
def meets_condition(self):
|
||||
def preview_meets_condition(self, preview_document):
|
||||
if not self.condition:
|
||||
return _("Yes")
|
||||
|
||||
if not (self.preview_document and self.webhook_doctype):
|
||||
return _("Select a document to check if it meets conditions.")
|
||||
|
||||
try:
|
||||
doc = frappe.get_cached_doc(self.webhook_doctype, self.preview_document)
|
||||
doc = frappe.get_cached_doc(self.webhook_doctype, preview_document)
|
||||
met_condition = frappe.safe_eval(self.condition, eval_locals=get_context(doc))
|
||||
except Exception as e:
|
||||
frappe.local.message_log = []
|
||||
return _("Failed to evaluate conditions: {}").format(e)
|
||||
return _("Yes") if met_condition else _("No")
|
||||
|
||||
@property
|
||||
def preview_request_body(self):
|
||||
if not (self.preview_document and self.webhook_doctype):
|
||||
return _("Select a document to preview request data")
|
||||
|
||||
@frappe.whitelist()
|
||||
def preview_request_body(self, preview_document):
|
||||
try:
|
||||
doc = frappe.get_cached_doc(self.webhook_doctype, self.preview_document)
|
||||
doc = frappe.get_cached_doc(self.webhook_doctype, preview_document)
|
||||
return frappe.as_json(get_webhook_data(doc, self))
|
||||
except Exception as e:
|
||||
frappe.local.message_log = []
|
||||
return _("Failed to compute request body: {}").format(e)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,15 @@ frappe.ui.form.make_quick_entry = (doctype, after_insert, init_callback, doc, fo
|
|||
return frappe.quick_entry.setup();
|
||||
};
|
||||
|
||||
frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
||||
frappe.ui.form.QuickEntryForm = class QuickEntryForm extends frappe.ui.Dialog {
|
||||
constructor(doctype, after_insert, init_callback, doc, force) {
|
||||
super({ auto_make: false });
|
||||
this.doctype = doctype;
|
||||
this.after_insert = after_insert;
|
||||
this.init_callback = init_callback;
|
||||
this.doc = doc;
|
||||
this.force = force ? force : false;
|
||||
this.dialog = this; // for backward compatibility
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
|
@ -132,29 +134,39 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
this.script_manager.setup();
|
||||
}
|
||||
|
||||
get mandatory() {
|
||||
// Backwards compatibility
|
||||
console.warn("QuickEntryForm: .mandatory is deprecated, use .docfields instead");
|
||||
return this.docfields;
|
||||
}
|
||||
|
||||
set mandatory(value) {
|
||||
// Backwards compatibility
|
||||
console.warn("QuickEntryForm: .mandatory is deprecated, use .docfields instead");
|
||||
this.docfields = value;
|
||||
}
|
||||
|
||||
render_dialog() {
|
||||
var me = this;
|
||||
|
||||
this.dialog = new frappe.ui.Dialog({
|
||||
title: this.get_title(),
|
||||
fields: this.docfields,
|
||||
doc: this.doc,
|
||||
});
|
||||
this.fields = this.docfields;
|
||||
this.title = this.get_title();
|
||||
|
||||
super.make();
|
||||
this.register_primary_action();
|
||||
this.render_edit_in_full_page_link();
|
||||
this.setup_cmd_enter_for_save();
|
||||
|
||||
this.dialog.onhide = () => (frappe.quick_entry = null);
|
||||
this.dialog.show();
|
||||
this.onhide = () => (frappe.quick_entry = null);
|
||||
this.show();
|
||||
|
||||
this.dialog.refresh_dependency();
|
||||
this.refresh_dependency();
|
||||
this.set_defaults();
|
||||
|
||||
this.script_manager.trigger("refresh");
|
||||
|
||||
if (this.init_callback) {
|
||||
this.init_callback(this.dialog);
|
||||
this.init_callback(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +182,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
|
||||
register_primary_action() {
|
||||
var me = this;
|
||||
this.dialog.set_primary_action(__("Save"), function () {
|
||||
this.set_primary_action(__("Save"), function () {
|
||||
if (me.dialog.working) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -247,14 +259,14 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
|
||||
process_after_insert(r) {
|
||||
// delete the old doc
|
||||
frappe.model.clear_doc(this.dialog.doc.doctype, this.dialog.doc.name);
|
||||
this.dialog.doc = r.message;
|
||||
frappe.model.clear_doc(this.doc.doctype, this.doc.name);
|
||||
this.doc = r.message;
|
||||
if (this.script_manager.has_handler("after_save")) {
|
||||
return this.script_manager.trigger("after_save");
|
||||
} else if (frappe._from_link) {
|
||||
frappe.ui.form.update_calling_link(this.dialog.doc);
|
||||
frappe.ui.form.update_calling_link(this.doc);
|
||||
} else if (this.after_insert) {
|
||||
this.after_insert(this.dialog.doc);
|
||||
this.after_insert(this.doc);
|
||||
} else {
|
||||
this.open_form_if_not_list();
|
||||
}
|
||||
|
|
@ -263,7 +275,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
setup_cmd_enter_for_save() {
|
||||
var me = this;
|
||||
// ctrl+enter to save
|
||||
this.dialog.wrapper.keydown(function (e) {
|
||||
this.wrapper.keydown(function (e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.which == 13) {
|
||||
if (!frappe.request.ajax_count) {
|
||||
// not already working -- double entry
|
||||
|
|
@ -278,7 +290,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
open_form_if_not_list() {
|
||||
if (this.meta.issingle) return;
|
||||
let route = frappe.get_route();
|
||||
let doc = this.dialog.doc;
|
||||
let doc = this.doc;
|
||||
if (route && !(route[0] === "List" && route[1] === doc.doctype)) {
|
||||
frappe.run_serially([() => frappe.set_route("Form", doc.doctype, doc.name)]);
|
||||
}
|
||||
|
|
@ -286,17 +298,17 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
|
||||
update_doc() {
|
||||
var me = this;
|
||||
var data = this.dialog.get_values(true);
|
||||
var data = this.get_values(true);
|
||||
$.each(data, function (key, value) {
|
||||
if (!is_null(value)) {
|
||||
me.dialog.doc[key] = value;
|
||||
}
|
||||
});
|
||||
return this.dialog.doc;
|
||||
return this.doc;
|
||||
}
|
||||
|
||||
open_doc(set_hooks) {
|
||||
this.dialog.hide();
|
||||
this.hide();
|
||||
this.update_doc();
|
||||
if (set_hooks && this.after_insert) {
|
||||
frappe.route_options = frappe.route_options || {};
|
||||
|
|
@ -309,13 +321,13 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm {
|
|||
|
||||
render_edit_in_full_page_link() {
|
||||
if (this.force || this.hide_full_form_button) return;
|
||||
this.dialog.add_custom_action(__("Edit Full Form"), () => this.open_doc(true));
|
||||
this.add_custom_action(__("Edit Full Form"), () => this.open_doc(true));
|
||||
}
|
||||
|
||||
set_defaults() {
|
||||
var me = this;
|
||||
// set defaults
|
||||
$.each(this.dialog.fields_dict, function (fieldname, field) {
|
||||
$.each(this.fields_dict, function (fieldname, field) {
|
||||
field.doctype = me.doc.doctype;
|
||||
field.docname = me.doc.name;
|
||||
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ frappe.ui.form.ScriptManager = class ScriptManager {
|
|||
|
||||
this.trigger("setup");
|
||||
}
|
||||
|
||||
log_error(caller, e) {
|
||||
frappe.show_alert({ message: __("Error in Client Script."), indicator: "error" });
|
||||
console.group && console.group();
|
||||
|
|
|
|||
|
|
@ -790,7 +790,9 @@ $.extend(frappe.model, {
|
|||
}
|
||||
for (var i = 0, j = fieldnames.length; i < j; i++) {
|
||||
var fieldname = fieldnames[i];
|
||||
doc[fieldname] = flt(doc[fieldname], precision(fieldname, doc));
|
||||
if (doc[fieldname]) {
|
||||
doc[fieldname] = flt(doc[fieldname], precision(fieldname, doc));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
this.display = false;
|
||||
this.is_dialog = true;
|
||||
|
||||
$.extend(this, { animate: true, size: null }, opts);
|
||||
this.make();
|
||||
$.extend(this, { animate: true, size: null, auto_make: true }, opts);
|
||||
if (this.auto_make) {
|
||||
this.make();
|
||||
}
|
||||
}
|
||||
|
||||
make() {
|
||||
|
|
@ -127,10 +129,6 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
});
|
||||
}
|
||||
|
||||
get $backdrop() {
|
||||
return $(this.$wrapper.data("bs.modal")?._backdrop);
|
||||
}
|
||||
|
||||
set_modal_size() {
|
||||
if (!this.fields) {
|
||||
this.size = "";
|
||||
|
|
@ -259,7 +257,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
this.$wrapper.removeClass("modal-minimize");
|
||||
|
||||
if (this.minimizable && this.is_minimized) {
|
||||
this.$backdrop.show();
|
||||
$(".modal-backdrop").toggle();
|
||||
this.is_minimized = false;
|
||||
}
|
||||
|
||||
|
|
@ -272,10 +270,6 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
}
|
||||
|
||||
hide() {
|
||||
if (this.animate && this.animation_speed === "slow") {
|
||||
this.$wrapper.addClass("slow");
|
||||
this.$backdrop.addClass("slow");
|
||||
}
|
||||
this.$wrapper.modal("hide");
|
||||
this.is_visible = false;
|
||||
}
|
||||
|
|
@ -297,7 +291,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
}
|
||||
|
||||
toggle_minimize() {
|
||||
this.$backdrop.toggle();
|
||||
$(".modal-backdrop").toggle();
|
||||
let modal = this.$wrapper.closest(".modal").toggleClass("modal-minimize");
|
||||
modal.attr("tabindex") ? modal.removeAttr("tabindex") : modal.attr("tabindex", -1);
|
||||
this.is_minimized = !this.is_minimized;
|
||||
|
|
@ -323,6 +317,8 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
|
||||
action && action_button.click(action);
|
||||
}
|
||||
|
||||
add_custom_button() {}
|
||||
};
|
||||
|
||||
frappe.ui.hide_open_dialog = () => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout {
|
|||
constructor(opts) {
|
||||
super(opts);
|
||||
this.dirty = false;
|
||||
this.fetch_dict = {};
|
||||
|
||||
$.each(this.fields || [], function (i, f) {
|
||||
if (!f.fieldname && f.label) {
|
||||
f.fieldname = f.label.replace(/ /g, "_").toLowerCase();
|
||||
|
|
@ -197,4 +199,43 @@ frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout {
|
|||
field.df[prop] = value;
|
||||
field.refresh();
|
||||
}
|
||||
|
||||
set_query(fieldname, opt1, opt2) {
|
||||
if (opt2) {
|
||||
// on child table
|
||||
// set_query(fieldname, parent fieldname, query)
|
||||
if (this.fields_dict[opt1])
|
||||
this.fields_dict[opt1].grid.get_field(fieldname).get_query = opt2;
|
||||
} else {
|
||||
// on parent table
|
||||
// set_query(fieldname, query)
|
||||
if (this.fields_dict[fieldname]) {
|
||||
this.fields_dict[fieldname].get_query = opt1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UTILITIES
|
||||
add_fetch(link_field, source_field, target_field, target_doctype) {
|
||||
/*
|
||||
Example fetch dict to get sender_email from email_id field in sender:
|
||||
{
|
||||
"Notification": {
|
||||
"sender": {
|
||||
"sender_email": "email_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!target_doctype) target_doctype = "*";
|
||||
|
||||
// Target field kept as key because source field could be non-unique
|
||||
this.fetch_dict.setDefault(target_doctype, {}).setDefault(link_field, {})[target_field] =
|
||||
source_field;
|
||||
}
|
||||
|
||||
is_new() {
|
||||
return this.doc.__islocal;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -572,6 +572,20 @@ class TestDB(FrappeTestCase):
|
|||
|
||||
frappe.db.rollback()
|
||||
|
||||
def test_get_list_return_value_data_type(self):
|
||||
frappe.db.delete("Note")
|
||||
|
||||
frappe.get_doc(doctype="Note", title="note1", content="something").insert()
|
||||
frappe.get_doc(doctype="Note", title="note2", content="someting else").insert()
|
||||
|
||||
note_docs = frappe.db.sql("select * from `tabNote`")
|
||||
|
||||
# should return both records
|
||||
self.assertEqual(len(note_docs), 2)
|
||||
|
||||
# data-type should be list
|
||||
self.assertIsInstance(note_docs, tuple)
|
||||
|
||||
@run_only_if(db_type_is.POSTGRES)
|
||||
def test_modify_query(self):
|
||||
from frappe.database.postgres.database import modify_query
|
||||
|
|
@ -1111,9 +1125,9 @@ class TestPostgresSchemaQueryIndependence(ExtFrappeTestCase):
|
|||
|
||||
if frappe.db.sql(
|
||||
"""SELECT 1
|
||||
FROM information_schema.schemata
|
||||
WHERE schema_name = 'alt_schema'
|
||||
limit 1 """
|
||||
FROM information_schema.schemata
|
||||
WHERE schema_name = 'alt_schema'
|
||||
LIMIT 1 """
|
||||
):
|
||||
self.cleanup()
|
||||
|
||||
|
|
@ -1244,19 +1258,19 @@ class TestPostgresSchemaQueryIndependence(ExtFrappeTestCase):
|
|||
rows = frappe.db.sql(f'select * from "tab{self.test_table_name}"')
|
||||
self.assertEqual(
|
||||
rows,
|
||||
[
|
||||
(
|
||||
(
|
||||
"a",
|
||||
"b",
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
) # there should be a single row in the public table
|
||||
|
||||
# when schema is changed to alt_schema, the alt_schema tables should be addressed by search path
|
||||
frappe.conf["db_schema"] = "alt_schema"
|
||||
frappe.db.connect()
|
||||
rows = frappe.db.sql(f'select * from "tab{self.test_table_name}"')
|
||||
self.assertEqual(rows, []) # there are no records in the alt_schema table
|
||||
self.assertEqual(rows, ()) # there are no records in the alt_schema table
|
||||
|
||||
del frappe.conf["db_schema"]
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,9 @@ def schedule_jobs_based_on_activity(check_time=None):
|
|||
|
||||
|
||||
def is_dormant(check_time=None):
|
||||
# Assume never dormant if developer_mode is enabled
|
||||
if frappe.conf.developer_mode:
|
||||
return False
|
||||
last_activity_log_timestamp = _get_last_creation_timestamp("Activity Log")
|
||||
since = (frappe.get_system_settings("dormant_days") or 4) * 86400
|
||||
if not last_activity_log_timestamp:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue