From 5f8d19133ed8de0027df336066753fe016e57016 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 17 Dec 2018 10:06:12 +0530 Subject: [PATCH 01/11] fix(Chat): Show red indicator for unread threads (#6629) - Mark messages as read in background --- .../chat/doctype/chat_message/chat_message.py | 30 +++++++++++++++---- frappe/public/js/frappe/chat.js | 15 ++++++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/frappe/chat/doctype/chat_message/chat_message.py b/frappe/chat/doctype/chat_message/chat_message.py index 3c58a6c07d..06127b3148 100644 --- a/frappe/chat/doctype/chat_message/chat_message.py +++ b/frappe/chat/doctype/chat_message/chat_message.py @@ -39,7 +39,7 @@ def get_message_urls(content): urls.append(text) return urls - + def get_message_mentions(content): mentions = [ ] tokens = content.split(' ') @@ -68,12 +68,12 @@ def get_message_meta(content): meta.content = content meta.urls = get_message_urls(content) meta.mentions = get_message_mentions(content) - + return meta def sanitize_message_content(content): emojis = get_emojis() - + tokens = content.split(' ') for token in tokens: if token.startswith(':') and token.endswith(':'): @@ -131,7 +131,7 @@ def get_new_chat_message(user, room, content, type = "Content"): @frappe.whitelist(allow_guest = True) def send(user, room, content, type = "Content"): mess = get_new_chat_message(user, room, content, type) - + frappe.publish_realtime('frappe.chat.message:create', mess, room = room, after_commit = True) @@ -144,7 +144,7 @@ def seen(message, user = None): room = mess.room resp = dict(message = message, data = dict(seen = json.loads(mess._seen))) - + frappe.publish_realtime('frappe.chat.message:update', resp, room = room, after_commit = True) def history(room, fields = None, limit = 10, start = None, end = None): @@ -159,7 +159,7 @@ def history(room, fields = None, limit = 10, start = None, end = None): ], order_by = 'creation' ) - + if not fields or 'seen' in fields: for m in mess: m['seen'] = json.loads(m._seen) if m._seen else [ ] @@ -168,8 +168,26 @@ def history(room, fields = None, limit = 10, start = None, end = None): for m in mess: m['content'] = json.loads(m.content) if m.type in ["File"] else m.content + frappe.enqueue('frappe.chat.doctype.chat_message.chat_message.mark_messages_as_seen', + message_names=[m.name for m in mess], user=frappe.session.user) + return mess +def mark_messages_as_seen(message_names, user): + ''' + Marks chat messages as seen, updates the _seen for each message + (should be run in background process) + ''' + for name in message_names: + seen = frappe.db.get_value('Chat Message', name, '_seen') or '[]' + seen = json.loads(seen) + seen.append(user) + seen = json.dumps(seen) + frappe.db.set_value('Chat Message', name, '_seen', seen, update_modified=False) + + frappe.db.commit() + + @frappe.whitelist() def get(name, rooms = None, fields = None): rooms, fields = safe_json_loads(rooms, fields) diff --git a/frappe/public/js/frappe/chat.js b/frappe/public/js/frappe/chat.js index 18275c688e..e6d289b2d3 100644 --- a/frappe/public/js/frappe/chat.js +++ b/frappe/public/js/frappe/chat.js @@ -1982,18 +1982,27 @@ class extends Component { } } - if ( props.last_message ) + let is_unread = false + if ( props.last_message ) { item.timestamp = frappe.chat.pretty_datetime(props.last_message.creation) + is_unread = !props.last_message.seen.includes(frappe.session.user) + } return ( h("li", null, - h("a", { class: props.active ? "active": "", onclick: () => props.click(props) }, + h("a", { class: props.active ? "active": "", onclick: () => { + props.last_message.seen.push(frappe.session.user) + props.click(props) + } }, h("div", { class: "row" }, h("div", { class: "col-xs-9" }, h(frappe.Chat.Widget.MediaProfile, { ...item }) ), h("div", { class: "col-xs-3 text-right" }, - h("div", { class: "text-muted", style: { "font-size": "9px" } }, item.timestamp) + [ + h("div", { class: "text-muted", style: { "font-size": "9px" } }, item.timestamp), + is_unread ? h("span", { class: "indicator red" }) : null + ] ), ) ) From 09077ae327f502a5db13a682f771c8a6c6e81a22 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 17 Dec 2018 13:48:02 +0530 Subject: [PATCH 02/11] fix: Update DataTable (#6622) - Now vertical scrollbar is shown always --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 73a33157c6..c0246539bc 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "awesomplete": "^1.1.2", "cookie": "^0.3.1", "express": "^4.16.2", - "frappe-datatable": "^1.7.0", + "frappe-datatable": "^1.7.1", "frappe-gantt": "^0.1.0", "fuse.js": "^3.2.0", "highlight.js": "^9.12.0", diff --git a/yarn.lock b/yarn.lock index d1a0f9ab14..b6c07445c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1219,10 +1219,10 @@ forwarded@~0.1.2: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= -frappe-datatable@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.7.0.tgz#6cc950a69bdfd514fb61ab25b85fa68c3b33aee0" - integrity sha512-CcCIf36eJMqzobc4rMT75zCCFKjfghJAR9rXiAP6h2uWdDKhb0U+rDjiFPweS54lv19tpTYF7Q/1SSx0Ih+Mfg== +frappe-datatable@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.7.1.tgz#5badb1138c7019e9dce50d6cbbd81c2fdc97e391" + integrity sha512-ePD4IDaLDCZCrchqT+TsPquOdnm72oYxh/KYMPfYBxUGSzWUoi2uRgzQD4MBR+uq1WxJhFQNoXe/fD3yOqNNUQ== dependencies: hyperlist "^1.0.0-beta" lodash "^4.17.5" From d6833996d3c0e04e84b88dcb0197823fb6edcb47 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 17 Dec 2018 13:55:32 +0530 Subject: [PATCH 03/11] fix: Include meta_block in Web Page (#6627) --- frappe/templates/includes/meta_block.html | 8 ++++---- frappe/website/doctype/web_page/templates/web_page.html | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frappe/templates/includes/meta_block.html b/frappe/templates/includes/meta_block.html index 6f8a6a3a73..0ab3c2a4a7 100644 --- a/frappe/templates/includes/meta_block.html +++ b/frappe/templates/includes/meta_block.html @@ -1,11 +1,11 @@ {%- if metatags -%} {%- for name in metatags %} - + {%- endfor -%} - - - + + + {%- endif -%} diff --git a/frappe/website/doctype/web_page/templates/web_page.html b/frappe/website/doctype/web_page/templates/web_page.html index ab0ec87650..0295c9ec1c 100644 --- a/frappe/website/doctype/web_page/templates/web_page.html +++ b/frappe/website/doctype/web_page/templates/web_page.html @@ -2,6 +2,10 @@ {%- block header -%} {{ header or "" }} {%- endblock -%} +{% block meta_block %} + {% include "templates/includes/meta_block.html" %} +{% endblock %} + {% block hero %}{{ hero or "" }}{% endblock %} {% block breadcrumbs %} From baa906c547d0a1de4b41ba92c112497c8f16064c Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 17 Dec 2018 14:30:27 +0530 Subject: [PATCH 04/11] fix: Remove redundant import (#6614) * fix: Remove redundant import * fix: import only required class using {reference} --- frappe/public/less/chat.less | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/frappe/public/less/chat.less b/frappe/public/less/chat.less index e9ea77d843..74fd78c01b 100644 --- a/frappe/public/less/chat.less +++ b/frappe/public/less/chat.less @@ -2,8 +2,8 @@ // http://codeguide.co - @mdo (Author of Bootstrap) -@import "common.less"; @import "flex.less"; +@import {reference} "common.less"; // Typography @font-weight-bold: 700; @@ -55,7 +55,7 @@ margin: @fab-margin; width: @fab-size; height: @fab-size; - + &.frappe-fab-lg { width: @fab-size-lg; @@ -80,10 +80,10 @@ { position: fixed; bottom: 0px; - right: 0px; + right: 0px; margin: @chat-popper-margin; z-index: @chat-popper-z-index; - + & > .frappe-chat-popper-collapse { & > .panel @@ -175,7 +175,7 @@ right: 0px; overflow: auto; border-radius: 0px; - + .panel-heading { border-radius: 0px; @@ -194,19 +194,19 @@ { font-size: @chat-form-font-size; } - + .dropdown-menu { border-radius: @chat-form-menu-border-radius; } - + // Hints .hint-list.list-group { margin: 0px; max-height: @chat-form-list-group-height; overflow-y: auto; - + .hint-list-item.list-group-item:first-child, .hint-list-item.list-group-item:last-child { border-radius: 0px !important; @@ -269,7 +269,7 @@ { margin-right: @chat-base-spacing; } - + .avatar { width: 32px; height: 32px; @@ -285,7 +285,7 @@ .chat-form { border-top: @chat-form-border; - + .input-group-btn { .btn @@ -294,7 +294,7 @@ border-radius: 0px; } } - + .form-control { line-height: 27px; // HACK: Makes input and placeholder centered within textarea. Also takes care of the input-btn @@ -305,7 +305,7 @@ padding-right: 0px; overflow: hidden; } - + .fa { font-size: @chat-base-font-size-lg; @@ -317,7 +317,7 @@ .chat-list { - height: 100%; + height: 100%; // background: @chat-list-bg-color; overflow-y: scroll; @@ -334,22 +334,22 @@ } .cursor-pointer; - + border: none !important; padding: @chat-list-item-padding; background: transparent; - + .chat-bubble { max-width: @chat-bubble-max-width; display: inline-block; padding: @chat-bubble-padding; border-radius: @chat-bubble-border-radius; - + -webkit-box-shadow: @chat-bubble-box-shadow; -moz-box-shadow: @chat-bubble-box-shadow; box-shadow: @chat-bubble-box-shadow; - + @media (max-width : 768px) { min-width: @chat-bubble-min-width; } @@ -372,7 +372,7 @@ } } } - + &.chat-bubble-r { text-align: right; @@ -386,33 +386,33 @@ } } } - + .chat-bubble-author { font-size: @chat-bubble-author-font-size; - + a { .font-bold; - + text-decoration: none !important; } } - + .chat-bubble-content { margin-bottom: @chat-bubble-content-margin-bottom; word-wrap: break-word; } - + .chat-bubble-meta { font-size: @chat-bubble-meta-font-size; - + & > .chat-bubble-check { margin-left: @chat-base-spacing; - + i { font-size: @chat-bubble-check-font-size; @@ -439,4 +439,4 @@ font-size: 10px; padding: 5px; // background-color: white; -} \ No newline at end of file +} From 52073a2b59ddee2c1700c3ca38cca75e7198d510 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 17 Dec 2018 16:06:56 +0530 Subject: [PATCH 05/11] [minor][fix] get_notifications_for_doctypes (#6634) --- frappe/desk/notifications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py index f0b0cd62b6..7a5676cca6 100644 --- a/frappe/desk/notifications.py +++ b/frappe/desk/notifications.py @@ -28,7 +28,7 @@ def get_notifications(): notification_count[name] = count return { - "open_count_doctype": {}, + "open_count_doctype": get_notifications_for_doctypes(config, notification_count), "open_count_module": get_notifications_for_modules(config, notification_count), "open_count_other": get_notifications_for_other(config, notification_count), "targets": get_notifications_for_targets(config, notification_percent), From 50ad6bcdf6025a77b0ddaa3a470be0be51b9a9e4 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 17 Dec 2018 21:21:04 +0530 Subject: [PATCH 06/11] fix(website): Correctly generate route for list item (#6620) Since route string for list-item in website list view was generated from frappe.local.request.path, page part that is acquired by ajax call used to contain incorrect route e.g. /api/frappe.www.list.get/CC-SINV-2018-00006 instead of /invoices/ACC-SINV-2018-00006 --- frappe/templates/includes/list/list.js | 1 + frappe/www/list.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/templates/includes/list/list.js b/frappe/templates/includes/list/list.js index ee1006326d..6bd3a155f2 100644 --- a/frappe/templates/includes/list/list.js +++ b/frappe/templates/includes/list/list.js @@ -11,6 +11,7 @@ frappe.ready(function() { pathname: location.pathname, }); data.web_form_name = frappe.web_form_name; + data.pathname = location.pathname; btn.prop("disabled", true); return $.ajax({ url:"/api/method/frappe.www.list.get", diff --git a/frappe/www/list.py b/frappe/www/list.py index 159983aa72..e0d8bd895a 100644 --- a/frappe/www/list.py +++ b/frappe/www/list.py @@ -24,7 +24,7 @@ def get_context(context, **dict_params): context.update(get(**frappe.local.form_dict)) @frappe.whitelist(allow_guest=True) -def get(doctype, txt=None, limit_start=0, limit=20, **kwargs): +def get(doctype, txt=None, limit_start=0, limit=20, pathname=None, **kwargs): """Returns processed HTML page for a standard listing.""" limit_start = cint(limit_start) raw_result = get_list_data(doctype, txt, limit_start, limit=limit + 1, **kwargs) @@ -54,7 +54,8 @@ def get(doctype, txt=None, limit_start=0, limit=20, **kwargs): new_context.update(new_context.doc.as_dict()) if not frappe.flags.in_test: - new_context["pathname"] = frappe.local.request.path.strip("/ ") + pathname = pathname or frappe.local.request.path + new_context["pathname"] = pathname.strip("/ ") new_context.update(list_context) set_route(new_context) rendered_row = frappe.render_template(row_template, new_context, is_path=True) From b247cae12e364e6d405b7f2e19d572b7415fd2fc Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Tue, 18 Dec 2018 08:54:26 +0530 Subject: [PATCH 07/11] fix: pass parameters as list (#6626) * fix: pass parameters as list * test: Add test case * test: Add json file for test data --- frappe/core/doctype/report/report.py | 2 +- frappe/core/doctype/report/test_report.py | 15 +++++++++++++++ .../user_activity_report_without_sort.json | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 frappe/core/doctype/report/user_activity_report_without_sort.json diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index a7b1c4d4dc..197e781843 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -149,7 +149,7 @@ class Report(Document): if params.get('sort_by'): order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order') else: - order_by = _format(self.ref_doctype, 'modified') + ' desc' + order_by = _format([self.ref_doctype, 'modified']) + ' desc' if params.get('sort_by_next'): order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next') diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 1689d99716..5591035c08 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -53,3 +53,18 @@ class TestReport(unittest.TestCase): report = frappe.get_doc('Report', 'Test Report') self.assertNotEquals(report.is_permitted(), True) + + # test for the `_format` method if report data doesn't have sort_by parameter + def test_format_method(self): + if frappe.db.exists('Report', 'User Activity Report Without Sort'): + frappe.delete_doc('Report', 'User Activity Report Without Sort') + with open(os.path.join(os.path.dirname(__file__), 'user_activity_report_without_sort.json'), 'r') as f: + frappe.get_doc(json.loads(f.read())).insert() + + report = frappe.get_doc('Report', 'User Activity Report Without Sort') + # this would raise an error without the fix added along with this test case + columns, data = report.get_data() + self.assertEqual(columns[0].get('label'), 'ID') + self.assertEqual(columns[1].get('label'), 'User Type') + self.assertTrue('Administrator' in [d[0] for d in data]) + frappe.delete_doc('Report', 'User Activity Report Without Sort') diff --git a/frappe/core/doctype/report/user_activity_report_without_sort.json b/frappe/core/doctype/report/user_activity_report_without_sort.json new file mode 100644 index 0000000000..bb520a25e2 --- /dev/null +++ b/frappe/core/doctype/report/user_activity_report_without_sort.json @@ -0,0 +1,17 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "is_standard": "No", + "javascript": null, + "json": "{\"filters\":[],\"columns\":[[\"name\",\"User\"],[\"user_type\",\"User\"],[\"first_name\",\"User\"],[\"last_name\",\"User\"],[\"last_active\",\"User\"],[\"role\",\"Has Role\"]],\"sort_order\":\"desc\",\"sort_by_next\":null,\"sort_order_next\":\"desc\"}", + "modified": "2018-12-17 18:27:07.728890", + "module": "Core", + "name": "User Activity Report Without Sort", + "query": null, + "ref_doctype": "User", + "report_name": "User Activity Report Without Sort", + "report_type": "Report Builder" + } \ No newline at end of file From 863c54b0fa14332a3bed0021b496534eba320082 Mon Sep 17 00:00:00 2001 From: Zarrar Date: Tue, 18 Dec 2018 08:56:10 +0530 Subject: [PATCH 08/11] [Fix] Json data for Report Builder based reports (#6624) * replace doctype name if already present * patch to update json data for report builder based reports * minor fix for auto email --- frappe/patches.txt | 3 ++- .../v11_0/fix_order_by_in_reports_json.py | 22 +++++++++++++++++++ frappe/utils/data.py | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 frappe/patches/v11_0/fix_order_by_in_reports_json.py diff --git a/frappe/patches.txt b/frappe/patches.txt index d8ed1fd82b..c3799ccca9 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -231,4 +231,5 @@ frappe.patches.v10_0.enhance_security frappe.patches.v11_0.multiple_references_in_events frappe.patches.v11_0.set_allow_self_approval_in_workflow frappe.patches.v11_0.migrate_report_settings_for_new_listview -frappe.patches.v11_0.delete_all_prepared_reports \ No newline at end of file +frappe.patches.v11_0.delete_all_prepared_reports +frappe.patches.v11_0.fix_order_by_in_reports_json \ No newline at end of file diff --git a/frappe/patches/v11_0/fix_order_by_in_reports_json.py b/frappe/patches/v11_0/fix_order_by_in_reports_json.py new file mode 100644 index 0000000000..28558ef4fb --- /dev/null +++ b/frappe/patches/v11_0/fix_order_by_in_reports_json.py @@ -0,0 +1,22 @@ +import frappe, json + +def execute(): + reports_data = frappe.get_all('Report', + filters={'json': ['not like', '%%%"order_by": "`tab%%%'], + 'report_type': 'Report Builder', 'is_standard': 'No'}, fields=['name']) + + for d in reports_data: + doc = frappe.get_doc('Report', d.get('name')) + json_data = json.loads(doc.get('json')) + + parts = [] + if ('order_by' in json_data) and ('.' in json_data.get('order_by')): + parts = json_data.get('order_by').split('.') + + sort_by = parts[1].split(' ') + + json_data['order_by'] = '`tab{0}`.`{1}`'.format(doc.ref_doctype, sort_by[0]) + json_data['order_by'] += ' {0}'.format(sort_by[1]) if len(sort_by) > 1 else '' + + doc.json = json.dumps(json_data) + doc.save() diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 8f5961d775..a09f9a1354 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -824,7 +824,8 @@ def get_filter(doctype, f): if len(f) == 3: f = (doctype, f[0], f[1], f[2]) - + elif len(f) > 4: + f = f[0:4] elif len(f) != 4: frappe.throw(frappe._("Filter must have 4 values (doctype, fieldname, operator, value): {0}").format(str(f))) From ac82c04c2bfb436967eeaa05d98e8c66464a5473 Mon Sep 17 00:00:00 2001 From: Rohan Date: Tue, 18 Dec 2018 08:59:26 +0530 Subject: [PATCH 09/11] fix(report): Only show generate button if it is a prepared report (#6619) * fix(report): Only show generate button if it is a prepared report * Update query_report.js --- .../public/js/frappe/views/reports/query_report.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 26f346618a..3bd8a9b83c 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -974,16 +974,16 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { toggle_nothing_to_show(flag) { - let message = __('Nothing to show'); - if(this.prepared_report) { - message = __(`This is a background report. - Please set the appropriate filters and then generate a new one.`); - } + let message = this.prepared_report + ? __('This is a background report. Please set the appropriate filters and then generate a new one.') + : __('Nothing to show') + this.toggle_message(flag, message); - if(flag){ + + if (flag && this.prepared_report) { this.prepared_report_action = "New"; + this.add_prepared_report_buttons(); } - this.add_prepared_report_buttons(); } toggle_message(flag, message) { From a0b2709a680ba164bfd03dd07759db72c74d3953 Mon Sep 17 00:00:00 2001 From: Saif Date: Tue, 18 Dec 2018 08:31:09 +0500 Subject: [PATCH 10/11] fix: bug in total row calculation for Currency field for list of dict values (#6615) --- frappe/desk/query_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index 37a076aa19..451e9da55c 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -314,7 +314,7 @@ def add_total_row(result, columns, meta = None): if fieldtype=="Link" and options == "Currency": - total_row[i] = result[0][i] + total_row[i] = result[0].get(fieldname) if isinstance(result[0], dict) else result[0][i] for i in has_percent: total_row[i] = flt(total_row[i]) / len(result) From a62cac8ab71770643c82cbbfa4f7bcfe2013bd65 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 18 Dec 2018 10:49:37 +0600 Subject: [PATCH 11/11] bumped to version 11.0.3-beta.38 --- frappe/hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/hooks.py b/frappe/hooks.py index dd4bdc6c91..5c7c45861c 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe" app_license = "MIT" develop_version = '12.x.x-develop' -staging_version = '11.0.3-beta.37' +staging_version = '11.0.3-beta.38' app_email = "info@frappe.io"