From 688829efa52a3dd940181ddbe2e7c89d6deb0920 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Tue, 28 Dec 2021 15:51:17 +0530 Subject: [PATCH 01/22] fix: time zone info in web form --- frappe/website/doctype/web_form/templates/web_form.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/website/doctype/web_form/templates/web_form.html b/frappe/website/doctype/web_form/templates/web_form.html index f511b3c27d..743c094314 100644 --- a/frappe/website/doctype/web_form/templates/web_form.html +++ b/frappe/website/doctype/web_form/templates/web_form.html @@ -78,6 +78,10 @@ frappe.boot = { sysdefaults: { float_precision: parseInt("{{ frappe.get_system_settings('float_precision') or 3 }}"), date_format: "{{ frappe.get_system_settings('date_format') or 'yyyy-mm-dd' }}", + }, + time_zone: { + system: "{{ frappe.utils.get_time_zone() }}", + user: "{{ frappe.db.get_value('User', frappe.session.user, 'time_zone') or frappe.utils.get_time_zone() }}" } }; // for backward compatibility of some libs From 950f60ef69ad1ed8b5567619b511a589503de8e6 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Wed, 29 Dec 2021 22:41:24 +0530 Subject: [PATCH 02/22] fix: sr no column alignment --- frappe/public/js/frappe/form/grid_row.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 96e502663d..a40f428969 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -196,7 +196,7 @@ export default class GridRow { // REDESIGN-TODO: Make translation contextual, this No is Number var txt = (this.doc ? this.doc.idx : __("No.")); this.row_index = $( - `
+ `
${this.row_check_html}
`) .appendTo(this.row) From 063cc293a950392ff2002c6d9b823f233793f69f Mon Sep 17 00:00:00 2001 From: Saif Ur Rehman Date: Fri, 31 Dec 2021 13:30:02 +0500 Subject: [PATCH 03/22] fix(Migrate): add unique and index for new columns --- frappe/database/schema.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frappe/database/schema.py b/frappe/database/schema.py index ce9fcb4147..10582eff8f 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -206,6 +206,12 @@ class DbColumn: if not current_def: self.fieldname = validate_column_name(self.fieldname) self.table.add_column.append(self) + + if column_type not in ('text', 'longtext'): + if self.unique: + self.table.add_unique.append(self) + if self.set_index: + self.table.add_index.append(self) return # type From b5e2f78a883d13e5acd477130aab7dc59e1fc0c2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 3 Jan 2022 13:36:32 +0530 Subject: [PATCH 04/22] fix: Start week from Sunday instead of Monday - Like we do in client-side --- frappe/utils/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 206f0eac64..7a65a6f18a 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -246,7 +246,7 @@ def get_quarter_start(dt, as_str=False): def get_first_day_of_week(dt, as_str=False): dt = getdate(dt) - date = dt - datetime.timedelta(days=dt.weekday()) + date = dt - datetime.timedelta(days=(dt.weekday() + 1) % 7) return date.strftime(DATE_FORMAT) if as_str else date def get_year_start(dt, as_str=False): From 85360ef4c0c4204cf79c6248e122924993310f19 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 3 Jan 2022 13:37:11 +0530 Subject: [PATCH 05/22] test: Add cases to check date utilities --- frappe/tests/test_utils.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 599a638ce2..67586719c8 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -306,3 +306,16 @@ class TestDiffUtils(unittest.TestCase): diff = get_version_diff(old_version, latest_version) self.assertIn('-2;', diff) self.assertIn('+42;', diff) + +class TestDateUtils(unittest.TestCase): + def test_first_day_of_week(self): + self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-25"), + frappe.utils.getdate("2020-12-20")) + self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-21"), + frappe.utils.getdate("2020-12-20")) + + def test_last_day_of_week(self): + self.assertEqual(frappe.utils.get_last_day_of_week("2020-12-24"), + frappe.utils.getdate("2020-12-26")) + self.assertEqual(frappe.utils.get_last_day_of_week("2020-12-28"), + frappe.utils.getdate("2021-01-02")) \ No newline at end of file From 42e1c15c18f72e447f1b7b5e4227963abbc90249 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:00:31 +0530 Subject: [PATCH 06/22] feat: Add setting to configure the day on which week starts --- .../system_settings/system_settings.json | 13 ++++++-- .../doctype/system_console/system_console.js | 4 +++ frappe/public/js/frappe/desk.js | 19 ++++++++---- frappe/public/js/frappe/utils/datetime.js | 5 ++++ frappe/utils/data.py | 30 ++++++++++++++++++- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/frappe/core/doctype/system_settings/system_settings.json b/frappe/core/doctype/system_settings/system_settings.json index 3e04643256..0af8f2e4be 100644 --- a/frappe/core/doctype/system_settings/system_settings.json +++ b/frappe/core/doctype/system_settings/system_settings.json @@ -17,10 +17,11 @@ "date_and_number_format", "date_format", "time_format", - "column_break_7", "number_format", + "column_break_7", "float_precision", "currency_precision", + "week_starts_on", "sec_backup_limit", "backup_limit", "encrypt_backup", @@ -477,12 +478,19 @@ "fieldname": "disable_system_update_notification", "fieldtype": "Check", "label": "Disable System Update Notification" + }, + { + "default": "Sunday", + "fieldname": "week_starts_on", + "fieldtype": "Select", + "label": "Week Starts On", + "options": "Sunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday" } ], "icon": "fa fa-cog", "issingle": 1, "links": [], - "modified": "2021-11-29 18:09:53.601629", + "modified": "2022-01-04 11:28:34.881192", "modified_by": "Administrator", "module": "Core", "name": "System Settings", @@ -499,5 +507,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "ASC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/frappe/desk/doctype/system_console/system_console.js b/frappe/desk/doctype/system_console/system_console.js index 0fe3932671..06f04e8b32 100644 --- a/frappe/desk/doctype/system_console/system_console.js +++ b/frappe/desk/doctype/system_console/system_console.js @@ -100,5 +100,9 @@ frappe.ui.form.on('System Console', { ${rows}`); }); + }, + + week_starts_on() { + frappe.app.setup_moment() } }); diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index 64767e1232..f9a9931c4c 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -275,11 +275,7 @@ frappe.Application = class Application { this.set_globals(); this.sync_pages(); frappe.router.setup(); - moment.locale("en"); - moment.user_utc_offset = moment().utcOffset(); - if(frappe.boot.timezone_info) { - moment.tz.add(frappe.boot.timezone_info); - } + this.setup_moment(); if(frappe.boot.print_css) { frappe.dom.set_style(frappe.boot.print_css, "print-style"); } @@ -628,6 +624,19 @@ frappe.Application = class Application { } }); } + + setup_moment() { + moment.updateLocale('en', { + week : { + dow : frappe.datetime.get_week_starts_on_index(), + } + }); + moment.locale("en"); + moment.user_utc_offset = moment().utcOffset(); + if(frappe.boot.timezone_info) { + moment.tz.add(frappe.boot.timezone_info); + } + } } frappe.get_module = function(m, default_module) { diff --git a/frappe/public/js/frappe/utils/datetime.js b/frappe/public/js/frappe/utils/datetime.js index 7bb6076b72..09e44d917d 100644 --- a/frappe/public/js/frappe/utils/datetime.js +++ b/frappe/public/js/frappe/utils/datetime.js @@ -254,6 +254,11 @@ $.extend(frappe.datetime, { ], true).isValid(); }, + get_week_starts_on_index() { + const week_starts_on = frappe.sys_defaults.week_starts_on || "Sunday"; + return moment.weekdays().indexOf(week_starts_on); + } + }); // Proxy for dateutil and get_today diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 7a65a6f18a..9f9391b1fc 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -11,11 +11,26 @@ from code import compile_command from urllib.parse import quote, urljoin from frappe.desk.utils import slug from click import secho +from enum import Enum DATE_FORMAT = "%Y-%m-%d" TIME_FORMAT = "%H:%M:%S.%f" DATETIME_FORMAT = DATE_FORMAT + " " + TIME_FORMAT +class Weekday(Enum): + Sunday = 0 + Monday = 1 + Tuesday = 2 + Wednesday = 3 + Thursday = 4 + Friday = 5 + Saturday = 6 + +def get_week_starts_on(): + return frappe.get_system_settings('week_starts_on') or "Sunday" + +def get_start_of_week_index(): + return Weekday[get_week_starts_on()].value def is_invalid_date_string(date_string): # dateutil parser does not agree with dates like "0001-01-01" or "0000-00-00" @@ -246,9 +261,22 @@ def get_quarter_start(dt, as_str=False): def get_first_day_of_week(dt, as_str=False): dt = getdate(dt) - date = dt - datetime.timedelta(days=(dt.weekday() + 1) % 7) + date = dt - datetime.timedelta(days=get_week_start_offset_days(dt)) return date.strftime(DATE_FORMAT) if as_str else date +def get_week_start_offset_days(dt): + current_day_index = get_normalized_weekday_index(dt) + start_of_week_index = get_start_of_week_index() + + if current_day_index >= start_of_week_index: + return current_day_index - start_of_week_index + else: + return 7 - (start_of_week_index - current_day_index) + +def get_normalized_weekday_index(dt): + # starts Sunday with 0 + return (dt.weekday() + 1) % 7 + def get_year_start(dt, as_str=False): dt = getdate(dt) date = datetime.date(dt.year, 1, 1) From 9c75336ea0e11d31adcf23b129f351d148b2569a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:02:09 +0530 Subject: [PATCH 07/22] fix: Set start of the week for date control based on configuration --- frappe/public/js/frappe/form/controls/date.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/form/controls/date.js b/frappe/public/js/frappe/form/controls/date.js index 28e7f2a478..b03ea53239 100644 --- a/frappe/public/js/frappe/form/controls/date.js +++ b/frappe/public/js/frappe/form/controls/date.js @@ -62,6 +62,7 @@ frappe.ui.form.ControlDate = class ControlDate extends frappe.ui.form.ControlDat dateFormat: date_format, startDate: this.get_start_date(), keyboardNav: false, + firstDay: frappe.datetime.get_week_starts_on_index(), onSelect: () => { this.$input.trigger('change'); }, From 4a5d9a02e3b74b5c430f45514dc6fc5ccb3b7aa8 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:04:10 +0530 Subject: [PATCH 08/22] test: Update date utils test cases --- frappe/tests/test_utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 67586719c8..5d2b8a918f 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -15,6 +15,8 @@ import io from mimetypes import guess_type from datetime import datetime, timedelta, date +from unittest.mock import patch + class TestFilters(unittest.TestCase): def test_simple_dict(self): self.assertTrue(evaluate_filters({'doctype': 'User', 'status': 'Open'}, {'status': 'Open'})) @@ -309,6 +311,14 @@ class TestDiffUtils(unittest.TestCase): class TestDateUtils(unittest.TestCase): def test_first_day_of_week(self): + # Monday as start of the week + with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-25"), + frappe.utils.getdate("2020-12-21")) + self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-20"), + frappe.utils.getdate("2020-12-14")) + + # Sunday as start of the week self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-25"), frappe.utils.getdate("2020-12-20")) self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-21"), From ca9b2a953d13a3c2b67a37c9aaba2da0d93fb8cc Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:25:19 +0530 Subject: [PATCH 09/22] fix: Add patch to set week_starts_on as "Monday" --- frappe/patches.txt | 1 + frappe/patches/v13_0/set_week_starts_on.py | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 frappe/patches/v13_0/set_week_starts_on.py diff --git a/frappe/patches.txt b/frappe/patches.txt index 27ba1a145d..3bd883aa6d 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -182,6 +182,7 @@ frappe.patches.v13_0.queryreport_columns execute:frappe.reload_doc('core', 'doctype', 'doctype') frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty +frappe.patches.v13_0.set_week_starts_on frappe.patches.v14_0.drop_data_import_legacy frappe.patches.v14_0.rename_cancelled_documents frappe.patches.v14_0.copy_mail_data #08.03.21 diff --git a/frappe/patches/v13_0/set_week_starts_on.py b/frappe/patches/v13_0/set_week_starts_on.py new file mode 100644 index 0000000000..8f90a6b2a8 --- /dev/null +++ b/frappe/patches/v13_0/set_week_starts_on.py @@ -0,0 +1,7 @@ +import frappe + +def execute(): + frappe.reload_doctype("System Settings") + # setting week_starts_on value as "Monday" to avoid breaking change + # because before the configuration was introduced, system used to consider "Monday" as start of the week + frappe.db.set_value("System Settings", "System Settings", "week_starts_on", "Monday") \ No newline at end of file From 5821a7bc9176ad8fb11d39bf89212d29066f327d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:40:30 +0530 Subject: [PATCH 10/22] test: Fix dashboard chart tests --- .../dashboard_chart/test_dashboard_chart.py | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py index 5562f2fc92..6e96c58464 100644 --- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py @@ -8,6 +8,7 @@ from frappe.desk.doctype.dashboard_chart.dashboard_chart import get from datetime import datetime from dateutil.relativedelta import relativedelta +from unittest.mock import patch class TestDashboardChart(unittest.TestCase): def test_period_ending(self): @@ -15,8 +16,9 @@ class TestDashboardChart(unittest.TestCase): getdate('2019-04-10')) # week starts on monday - self.assertEqual(get_period_ending('2019-04-10', 'Weekly'), - getdate('2019-04-14')) + with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + self.assertEqual(get_period_ending('2019-04-10', 'Weekly'), + getdate('2019-04-14')) self.assertEqual(get_period_ending('2019-04-10', 'Monthly'), getdate('2019-04-30')) @@ -200,13 +202,14 @@ class TestDashboardChart(unittest.TestCase): timeseries = 1 )).insert() - result = get(chart_name ='Test Weekly Dashboard Chart', refresh = 1) + with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + result = get(chart_name ='Test Weekly Dashboard Chart', refresh = 1) - self.assertEqual(result.get('datasets')[0].get('values'), [50.0, 300.0, 800.0, 0.0]) - self.assertEqual( - result.get('labels'), - ['30-12-18', '06-01-19', '13-01-19', '20-01-19'] - ) + self.assertEqual(result.get('datasets')[0].get('values'), [50.0, 300.0, 800.0, 0.0]) + self.assertEqual( + result.get('labels'), + ['30-12-18', '06-01-19', '13-01-19', '20-01-19'] + ) frappe.db.rollback() @@ -231,13 +234,13 @@ class TestDashboardChart(unittest.TestCase): timeseries = 1 )).insert() - result = get(chart_name='Test Average Dashboard Chart', refresh = 1) - - self.assertEqual(result.get('datasets')[0].get('values'), [50.0, 150.0, 266.6666666666667, 0.0]) - self.assertEqual( - result.get('labels'), - ['30-12-18', '06-01-19', '13-01-19', '20-01-19'] - ) + with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + result = get(chart_name='Test Average Dashboard Chart', refresh = 1) + self.assertEqual( + result.get('labels'), + ['30-12-18', '06-01-19', '13-01-19', '20-01-19'] + ) + self.assertEqual(result.get('datasets')[0].get('values'), [50.0, 150.0, 266.6666666666667, 0.0]) frappe.db.rollback() From ea2101d537cab6541f047f9fe1879f8303474a5a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 13:42:52 +0530 Subject: [PATCH 11/22] style: Fix formatting issues --- frappe/desk/doctype/system_console/system_console.js | 2 +- frappe/public/js/frappe/desk.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/desk/doctype/system_console/system_console.js b/frappe/desk/doctype/system_console/system_console.js index 06f04e8b32..ad0e9d638e 100644 --- a/frappe/desk/doctype/system_console/system_console.js +++ b/frappe/desk/doctype/system_console/system_console.js @@ -103,6 +103,6 @@ frappe.ui.form.on('System Console', { }, week_starts_on() { - frappe.app.setup_moment() + frappe.app.setup_moment(); } }); diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index f9a9931c4c..3668f0d3e7 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -627,13 +627,13 @@ frappe.Application = class Application { setup_moment() { moment.updateLocale('en', { - week : { - dow : frappe.datetime.get_week_starts_on_index(), + week: { + dow: frappe.datetime.get_week_starts_on_index(), } }); moment.locale("en"); moment.user_utc_offset = moment().utcOffset(); - if(frappe.boot.timezone_info) { + if (frappe.boot.timezone_info) { moment.tz.add(frappe.boot.timezone_info); } } From 6b77ed68e9b74b85cf5bbee1c05630a8e36d2ebb Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 14:07:17 +0530 Subject: [PATCH 12/22] fix: Revert unnecessary code --- frappe/desk/doctype/system_console/system_console.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frappe/desk/doctype/system_console/system_console.js b/frappe/desk/doctype/system_console/system_console.js index ad0e9d638e..fc83069fd2 100644 --- a/frappe/desk/doctype/system_console/system_console.js +++ b/frappe/desk/doctype/system_console/system_console.js @@ -101,8 +101,4 @@ frappe.ui.form.on('System Console', { ${rows}`); }); }, - - week_starts_on() { - frappe.app.setup_moment(); - } }); From 53b2c472a6f4576ef7fbeea478d54b1ec54ba7ae Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 4 Jan 2022 14:14:06 +0530 Subject: [PATCH 13/22] fix: Re-setup moment object whenever `week_starts_on` is changed --- frappe/core/doctype/system_settings/system_settings.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/system_settings/system_settings.js b/frappe/core/doctype/system_settings/system_settings.js index 4eeab0274b..cb1686df39 100644 --- a/frappe/core/doctype/system_settings/system_settings.js +++ b/frappe/core/doctype/system_settings/system_settings.js @@ -10,6 +10,10 @@ frappe.ui.form.on("System Settings", { frm.set_value(key, val); frappe.sys_defaults[key] = val; }); + if (frm.re_setup_moment) { + frappe.app.setup_moment(); + delete frm.re_setup_moment; + } } }); }, @@ -38,5 +42,8 @@ frappe.ui.form.on("System Settings", { // Clear cache after saving to refresh the values of boot. frappe.ui.toolbar.clear_cache(); } - } + }, + week_starts_on(frm) { + frm.re_setup_moment = true; + }, }); From 5d5ad78789738e6c9ddd3a368f44badc9022ce5a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 5 Jan 2022 14:54:46 +0530 Subject: [PATCH 14/22] refactor: Rename `week_starts_on` to `first_day_of_the_week` For consistency --- frappe/core/doctype/system_settings/system_settings.js | 2 +- frappe/core/doctype/system_settings/system_settings.json | 6 +++--- frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py | 6 +++--- frappe/patches.txt | 2 +- .../{set_week_starts_on.py => set_first_day_of_the_week.py} | 4 ++-- frappe/public/js/frappe/desk.js | 2 +- frappe/public/js/frappe/form/controls/date.js | 2 +- frappe/public/js/frappe/utils/datetime.js | 6 +++--- frappe/tests/test_utils.py | 2 +- frappe/utils/data.py | 6 +++--- 10 files changed, 19 insertions(+), 19 deletions(-) rename frappe/patches/v13_0/{set_week_starts_on.py => set_first_day_of_the_week.py} (51%) diff --git a/frappe/core/doctype/system_settings/system_settings.js b/frappe/core/doctype/system_settings/system_settings.js index cb1686df39..5128ae24cb 100644 --- a/frappe/core/doctype/system_settings/system_settings.js +++ b/frappe/core/doctype/system_settings/system_settings.js @@ -43,7 +43,7 @@ frappe.ui.form.on("System Settings", { frappe.ui.toolbar.clear_cache(); } }, - week_starts_on(frm) { + first_day_of_the_week(frm) { frm.re_setup_moment = true; }, }); diff --git a/frappe/core/doctype/system_settings/system_settings.json b/frappe/core/doctype/system_settings/system_settings.json index 0af8f2e4be..61410fb1a8 100644 --- a/frappe/core/doctype/system_settings/system_settings.json +++ b/frappe/core/doctype/system_settings/system_settings.json @@ -21,7 +21,7 @@ "column_break_7", "float_precision", "currency_precision", - "week_starts_on", + "first_day_of_the_week", "sec_backup_limit", "backup_limit", "encrypt_backup", @@ -481,9 +481,9 @@ }, { "default": "Sunday", - "fieldname": "week_starts_on", + "fieldname": "first_day_of_the_week", "fieldtype": "Select", - "label": "Week Starts On", + "label": "First Day of the Week", "options": "Sunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday" } ], diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py index 6e96c58464..5c986b5b7c 100644 --- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py @@ -16,7 +16,7 @@ class TestDashboardChart(unittest.TestCase): getdate('2019-04-10')) # week starts on monday - with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + with patch.object(frappe.utils.data, "get_first_day_of_the_week", return_value="Monday"): self.assertEqual(get_period_ending('2019-04-10', 'Weekly'), getdate('2019-04-14')) @@ -202,7 +202,7 @@ class TestDashboardChart(unittest.TestCase): timeseries = 1 )).insert() - with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + with patch.object(frappe.utils.data, "get_first_day_of_the_week", return_value="Monday"): result = get(chart_name ='Test Weekly Dashboard Chart', refresh = 1) self.assertEqual(result.get('datasets')[0].get('values'), [50.0, 300.0, 800.0, 0.0]) @@ -234,7 +234,7 @@ class TestDashboardChart(unittest.TestCase): timeseries = 1 )).insert() - with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + with patch.object(frappe.utils.data, "get_first_day_of_the_week", return_value="Monday"): result = get(chart_name='Test Average Dashboard Chart', refresh = 1) self.assertEqual( result.get('labels'), diff --git a/frappe/patches.txt b/frappe/patches.txt index 2e94185179..af7e4d6e3f 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -182,7 +182,7 @@ frappe.patches.v13_0.queryreport_columns execute:frappe.reload_doc('core', 'doctype', 'doctype') frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty -frappe.patches.v13_0.set_week_starts_on +frappe.patches.v13_0.set_first_day_of_the_week frappe.patches.v14_0.drop_data_import_legacy frappe.patches.v14_0.rename_cancelled_documents frappe.patches.v14_0.copy_mail_data #08.03.21 diff --git a/frappe/patches/v13_0/set_week_starts_on.py b/frappe/patches/v13_0/set_first_day_of_the_week.py similarity index 51% rename from frappe/patches/v13_0/set_week_starts_on.py rename to frappe/patches/v13_0/set_first_day_of_the_week.py index 8f90a6b2a8..cfb694bbf1 100644 --- a/frappe/patches/v13_0/set_week_starts_on.py +++ b/frappe/patches/v13_0/set_first_day_of_the_week.py @@ -2,6 +2,6 @@ import frappe def execute(): frappe.reload_doctype("System Settings") - # setting week_starts_on value as "Monday" to avoid breaking change + # setting first_day_of_the_week value as "Monday" to avoid breaking change # because before the configuration was introduced, system used to consider "Monday" as start of the week - frappe.db.set_value("System Settings", "System Settings", "week_starts_on", "Monday") \ No newline at end of file + frappe.db.set_value("System Settings", "System Settings", "first_day_of_the_week", "Monday") \ No newline at end of file diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index 3668f0d3e7..202cee645a 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -628,7 +628,7 @@ frappe.Application = class Application { setup_moment() { moment.updateLocale('en', { week: { - dow: frappe.datetime.get_week_starts_on_index(), + dow: frappe.datetime.get_first_day_of_the_week_index(), } }); moment.locale("en"); diff --git a/frappe/public/js/frappe/form/controls/date.js b/frappe/public/js/frappe/form/controls/date.js index b03ea53239..78eb3832cc 100644 --- a/frappe/public/js/frappe/form/controls/date.js +++ b/frappe/public/js/frappe/form/controls/date.js @@ -62,7 +62,7 @@ frappe.ui.form.ControlDate = class ControlDate extends frappe.ui.form.ControlDat dateFormat: date_format, startDate: this.get_start_date(), keyboardNav: false, - firstDay: frappe.datetime.get_week_starts_on_index(), + firstDay: frappe.datetime.get_first_day_of_the_week_index(), onSelect: () => { this.$input.trigger('change'); }, diff --git a/frappe/public/js/frappe/utils/datetime.js b/frappe/public/js/frappe/utils/datetime.js index 09e44d917d..196bdf68a3 100644 --- a/frappe/public/js/frappe/utils/datetime.js +++ b/frappe/public/js/frappe/utils/datetime.js @@ -254,9 +254,9 @@ $.extend(frappe.datetime, { ], true).isValid(); }, - get_week_starts_on_index() { - const week_starts_on = frappe.sys_defaults.week_starts_on || "Sunday"; - return moment.weekdays().indexOf(week_starts_on); + get_first_day_of_the_week_index() { + const first_day_of_the_week = frappe.sys_defaults.first_day_of_the_week || "Sunday"; + return moment.weekdays().indexOf(first_day_of_the_week); } }); diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 5d2b8a918f..5c1541e0de 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -312,7 +312,7 @@ class TestDiffUtils(unittest.TestCase): class TestDateUtils(unittest.TestCase): def test_first_day_of_week(self): # Monday as start of the week - with patch.object(frappe.utils.data, "get_week_starts_on", return_value="Monday"): + with patch.object(frappe.utils.data, "get_first_day_of_the_week", return_value="Monday"): self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-25"), frappe.utils.getdate("2020-12-21")) self.assertEqual(frappe.utils.get_first_day_of_week("2020-12-20"), diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 9f9391b1fc..545d49054a 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -26,11 +26,11 @@ class Weekday(Enum): Friday = 5 Saturday = 6 -def get_week_starts_on(): - return frappe.get_system_settings('week_starts_on') or "Sunday" +def get_first_day_of_the_week(): + return frappe.get_system_settings('first_day_of_the_week') or "Sunday" def get_start_of_week_index(): - return Weekday[get_week_starts_on()].value + return Weekday[get_first_day_of_the_week()].value def is_invalid_date_string(date_string): # dateutil parser does not agree with dates like "0001-01-01" or "0000-00-00" From d73428df919dc98e7ee13af92af5fd8a66da66d4 Mon Sep 17 00:00:00 2001 From: Navdeep Date: Mon, 26 Apr 2021 11:09:22 -0400 Subject: [PATCH 15/22] feat(fixes): for frappeclient post_api(POST) request being redirected to GET request on calling server --- frappe/frappeclient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py index ab58979203..cf6afde4a6 100644 --- a/frappe/frappeclient.py +++ b/frappe/frappeclient.py @@ -296,7 +296,7 @@ class FrappeClient(object): def post_api(self, method, params=None): if params is None: params = {} - res = self.session.post(self.url + "/api/method/" + method + "/", + res = self.session.post(self.url + "/api/method/" + method, params=params, verify=self.verify, headers=self.headers) return self.post_process(res) From 984420363a9aa8d60f95b197e0750e1766347ddf Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 5 Jan 2022 20:37:33 +0530 Subject: [PATCH 16/22] fix: Use params instead of data for client login --- frappe/frappeclient.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py index cf6afde4a6..59db38584c 100644 --- a/frappe/frappeclient.py +++ b/frappe/frappeclient.py @@ -1,11 +1,13 @@ -import requests -import json -import frappe -import base64 - ''' FrappeClient is a library that helps you connect with other frappe systems ''' +import base64 +import json + +import requests + +import frappe + class AuthError(Exception): pass @@ -46,7 +48,7 @@ class FrappeClient(object): def _login(self, username, password): '''Login/start a sesion. Called internally on init''' - r = self.session.post(self.url, data={ + r = self.session.post(self.url, params={ 'cmd': 'login', 'usr': username, 'pwd': password @@ -289,14 +291,14 @@ class FrappeClient(object): def get_api(self, method, params=None): if params is None: params = {} - res = self.session.get(self.url + "/api/method/" + method + "/", + res = self.session.get(f"{self.url}/api/method/{method}", params=params, verify=self.verify, headers=self.headers) return self.post_process(res) def post_api(self, method, params=None): if params is None: params = {} - res = self.session.post(self.url + "/api/method/" + method, + res = self.session.post(f"{self.url}/api/method/{method}", params=params, verify=self.verify, headers=self.headers) return self.post_process(res) From 54fbd0b5e6239398e0833557e718ff5bf96d578d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Jan 2022 09:05:08 +0530 Subject: [PATCH 17/22] test: UI test cases for "First Day of the Week" --- cypress/integration/first_day_of_the_week.js | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 cypress/integration/first_day_of_the_week.js diff --git a/cypress/integration/first_day_of_the_week.js b/cypress/integration/first_day_of_the_week.js new file mode 100644 index 0000000000..7099d3fddc --- /dev/null +++ b/cypress/integration/first_day_of_the_week.js @@ -0,0 +1,48 @@ +context("First Day of the Week", () => { + before(() => { + cy.login(); + }); + + beforeEach(() => { + cy.visit('/app/system-settings'); + cy.findByText('Date and Number Format').click(); + cy.fill_field('first_day_of_the_week', 'Sunday', 'Select'); + cy.findByRole('button', {name: 'Save'}).click(); + cy.findByText('Date and Number Format').click(); + }); + + it("Date control starts with same day as selected in System Settings", () => { + cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings") + cy.fill_field('first_day_of_the_week', 'Tuesday', 'Select'); + cy.findByRole('button', {name: 'Save'}).click(); + cy.wait("@load_settings"); + cy.dialog({ + title: 'Date', + fields: [ + { + label: 'Date', + fieldname: 'date', + fieldtype: 'Date' + } + ] + }); + cy.get_field('date').click(); + cy.get('.datepicker--day-name').eq(0).should('have.text', 'Tu'); + }); + + it("Calendar view starts with same day as selected in System Settings", () => { + cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings") + cy.fill_field('first_day_of_the_week', 'Monday', 'Select'); + cy.findByRole('button', {name: 'Save'}).click(); + cy.wait("@load_settings"); + cy.visit("app/todo/view/calendar/default"); + cy.get('.fc-day-header > span').eq(0).should('have.text', 'Mon'); + }); + + after(() => { + cy.visit('/app/system-settings'); + cy.findByText('Date and Number Format').click(); + cy.fill_field('first_day_of_the_week', 'Sunday', 'Select'); + cy.findByRole('button', {name: 'Save'}).click(); + }); +}) \ No newline at end of file From ed2e37eaf7c61e0687d9d817505b10b2654c8f4a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Jan 2022 09:18:42 +0530 Subject: [PATCH 18/22] style: Fix sider issues --- .eslintrc | 1 + cypress/integration/first_day_of_the_week.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.eslintrc b/.eslintrc index cc7f555669..937f11586c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -148,6 +148,7 @@ "context": true, "before": true, "beforeEach": true, + "after": true, "qz": true, "localforage": true, "extend_cscript": true diff --git a/cypress/integration/first_day_of_the_week.js b/cypress/integration/first_day_of_the_week.js index 7099d3fddc..2626905f5b 100644 --- a/cypress/integration/first_day_of_the_week.js +++ b/cypress/integration/first_day_of_the_week.js @@ -12,7 +12,7 @@ context("First Day of the Week", () => { }); it("Date control starts with same day as selected in System Settings", () => { - cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings") + cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings"); cy.fill_field('first_day_of_the_week', 'Tuesday', 'Select'); cy.findByRole('button', {name: 'Save'}).click(); cy.wait("@load_settings"); @@ -31,7 +31,7 @@ context("First Day of the Week", () => { }); it("Calendar view starts with same day as selected in System Settings", () => { - cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings") + cy.intercept('POST', '/api/method/frappe.core.doctype.system_settings.system_settings.load').as("load_settings"); cy.fill_field('first_day_of_the_week', 'Monday', 'Select'); cy.findByRole('button', {name: 'Save'}).click(); cy.wait("@load_settings"); @@ -45,4 +45,4 @@ context("First Day of the Week", () => { cy.fill_field('first_day_of_the_week', 'Sunday', 'Select'); cy.findByRole('button', {name: 'Save'}).click(); }); -}) \ No newline at end of file +}); \ No newline at end of file From 30591720f868e924973c2fd458448752d8a5295c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Jan 2022 10:18:12 +0530 Subject: [PATCH 19/22] test: Fix flaky grid flaky test Simplified test case as bit --- cypress/integration/grid_keyboard_shortcut.js | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/cypress/integration/grid_keyboard_shortcut.js b/cypress/integration/grid_keyboard_shortcut.js index dee056e03e..189ed0812c 100644 --- a/cypress/integration/grid_keyboard_shortcut.js +++ b/cypress/integration/grid_keyboard_shortcut.js @@ -1,48 +1,39 @@ context('Grid Keyboard Shortcut', () => { let total_count = 0; - beforeEach(() => { - cy.login(); - cy.visit('/app/doctype/User'); - }); before(() => { cy.login(); - cy.visit('/app/doctype/User'); - return cy.window().its('frappe').then(frappe => { - frappe.db.count('DocField', { - filters: { - 'parent': 'User', 'parentfield': 'fields', 'parenttype': 'DocType' - } - }).then((r) => { - total_count = r; - }); - }); + }) + beforeEach(() => { + cy.reload(); + cy.visit('/app/contact/new-contact-1'); + cy.get('.frappe-control[data-fieldname="email_ids"]').find(".grid-add-row").click() }); it('Insert new row at the end', () => { cy.add_new_row_in_grid('{ctrl}{shift}{downarrow}', (cy, total_count) => { - cy.get('[data-name="new-docfield-1"]').should('have.attr', 'data-idx', `${total_count+1}`); + cy.get('[data-name="new-contact-email-1"]').should('have.attr', 'data-idx', `${total_count+1}`); }, total_count); }); it('Insert new row at the top', () => { cy.add_new_row_in_grid('{ctrl}{shift}{uparrow}', (cy) => { - cy.get('[data-name="new-docfield-1"]').should('have.attr', 'data-idx', '1'); + cy.get('[data-name="new-contact-email-1"]').should('have.attr', 'data-idx', '2'); }); }); it('Insert new row below', () => { cy.add_new_row_in_grid('{ctrl}{downarrow}', (cy) => { - cy.get('[data-name="new-docfield-1"]').should('have.attr', 'data-idx', '2'); + cy.get('[data-name="new-contact-email-1"]').should('have.attr', 'data-idx', '1'); }); }); it('Insert new row above', () => { cy.add_new_row_in_grid('{ctrl}{uparrow}', (cy) => { - cy.get('[data-name="new-docfield-1"]').should('have.attr', 'data-idx', '1'); + cy.get('[data-name="new-contact-email-1"]').should('have.attr', 'data-idx', '2'); }); }); }); Cypress.Commands.add('add_new_row_in_grid', (shortcut_keys, callbackFn, total_count) => { - cy.get('.frappe-control[data-fieldname="fields"]').as('table'); - cy.get('@table').find('.grid-body .col-xs-2').first().click(); - cy.get('@table').find('.grid-body .col-xs-2') + cy.get('.frappe-control[data-fieldname="email_ids"]').as('table'); + cy.get('@table').find('.grid-body [data-fieldname="email_id"]').first().click(); + cy.get('@table').find('.grid-body [data-fieldname="email_id"]') .first().type(shortcut_keys); callbackFn(cy, total_count); From 454a08aa183d81cbaed1c3ff789a5943c92ddd82 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Jan 2022 10:43:04 +0530 Subject: [PATCH 20/22] test: Remove unnecessary code --- cypress/integration/first_day_of_the_week.js | 3 --- cypress/integration/grid_keyboard_shortcut.js | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cypress/integration/first_day_of_the_week.js b/cypress/integration/first_day_of_the_week.js index 2626905f5b..1e65b78990 100644 --- a/cypress/integration/first_day_of_the_week.js +++ b/cypress/integration/first_day_of_the_week.js @@ -6,9 +6,6 @@ context("First Day of the Week", () => { beforeEach(() => { cy.visit('/app/system-settings'); cy.findByText('Date and Number Format').click(); - cy.fill_field('first_day_of_the_week', 'Sunday', 'Select'); - cy.findByRole('button', {name: 'Save'}).click(); - cy.findByText('Date and Number Format').click(); }); it("Date control starts with same day as selected in System Settings", () => { diff --git a/cypress/integration/grid_keyboard_shortcut.js b/cypress/integration/grid_keyboard_shortcut.js index 189ed0812c..9cf39165ad 100644 --- a/cypress/integration/grid_keyboard_shortcut.js +++ b/cypress/integration/grid_keyboard_shortcut.js @@ -2,11 +2,11 @@ context('Grid Keyboard Shortcut', () => { let total_count = 0; before(() => { cy.login(); - }) + }); beforeEach(() => { cy.reload(); cy.visit('/app/contact/new-contact-1'); - cy.get('.frappe-control[data-fieldname="email_ids"]').find(".grid-add-row").click() + cy.get('.frappe-control[data-fieldname="email_ids"]').find(".grid-add-row").click(); }); it('Insert new row at the end', () => { cy.add_new_row_in_grid('{ctrl}{shift}{downarrow}', (cy, total_count) => { From 997c0e25cbb6df999ef51251d13ec790bfaf17ec Mon Sep 17 00:00:00 2001 From: harshpwctech <84438948+harshpwctech@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:24:58 +0530 Subject: [PATCH 21/22] Updating the get_payment_gateway_url method (#15423) This change is proposed as on_payment_authorized method defined in any doctype for which the payment is made isn't getting triggered. https://github.com/frappe/frappe/pull/12756 --- frappe/website/doctype/web_form/web_form.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index eb7ee90826..cef1a8d8a3 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -216,8 +216,8 @@ def get_context(context): "amount": amount, "title": title, "description": title, - "reference_doctype": "Web Form", - "reference_docname": self.name, + "reference_doctype": doc.doctype, + "reference_docname": doc.name, "payer_email": frappe.session.user, "payer_name": frappe.utils.get_fullname(frappe.session.user), "order_id": doc.name, From 0a8b5fe7857c875c6b08b728887d93ba96dd2cd4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 6 Jan 2022 13:38:48 +0530 Subject: [PATCH 22/22] test: Fix get_field command for select fields --- cypress/support/commands.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 4fe315c372..758b3cde2b 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -193,7 +193,8 @@ Cypress.Commands.add('fill_field', (fieldname, value, fieldtype = 'Data') => { }); Cypress.Commands.add('get_field', (fieldname, fieldtype = 'Data') => { - let selector = `[data-fieldname="${fieldname}"] input:visible`; + let field_element = fieldtype === 'Select' ? 'select': 'input'; + let selector = `[data-fieldname="${fieldname}"] ${field_element}:visible`; if (fieldtype === 'Text Editor') { selector = `[data-fieldname="${fieldname}"] .ql-editor[contenteditable=true]:visible`;