diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 3a4f192656..9a4f63d618 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -123,7 +123,7 @@ "fieldtype": "Select", "in_global_search": 1, "label": "Repeat On", - "options": "\nDaily\nWeekly\nMonthly\nYearly" + "options": "\nDaily\nWeekly\nMonthly\nQuarterly\nHalf Yearly\nYearly" }, { "depends_on": "repeat_this_event", @@ -295,7 +295,7 @@ "icon": "fa fa-calendar", "idx": 1, "links": [], - "modified": "2023-06-23 10:33:15.685368", + "modified": "2024-01-11 07:11:17.467503", "modified_by": "Administrator", "module": "Desk", "name": "Event", @@ -336,4 +336,4 @@ "track_changes": 1, "track_seen": 1, "track_views": 1 -} +} \ No newline at end of file diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py index bf56498780..0442c73d23 100644 --- a/frappe/desk/doctype/event/event.py +++ b/frappe/desk/doctype/event/event.py @@ -21,6 +21,7 @@ from frappe.utils import ( format_datetime, get_datetime_str, getdate, + month_diff, now_datetime, nowdate, ) @@ -62,7 +63,7 @@ class Event(Document): google_meet_link: DF.Data | None monday: DF.Check pulled_from_google_calendar: DF.Check - repeat_on: DF.Literal["", "Daily", "Weekly", "Monthly", "Yearly"] + repeat_on: DF.Literal["", "Daily", "Weekly", "Monthly", "Quarterly", "Half Yearly", "Yearly"] repeat_this_event: DF.Check repeat_till: DF.Date | None saturday: DF.Check @@ -392,6 +393,62 @@ def get_events(start, end, user=None, for_reminder=False, filters=None) -> list[ remove_events.append(e) + if e.repeat_on == "Half Yearly": + # creates a string with date (27) and month (07) and year (2019) eg: 2019-07-27 + year, month = start.split("-", maxsplit=2)[:2] + date = f"{year}-{month}-" + event_start.split("-", maxsplit=3)[2] + + # last day of month issue, start from prev month! + try: + getdate(date) + except Exception: + date = date.split("-") + date = date[0] + "-" + str(cint(date[1]) - 1) + "-" + date[2] + + start_from = date + for i in range(int(date_diff(end, start) / 30) + 3): + diff = month_diff(date, event_start) - 1 + if diff % 6 != 0: + continue + if ( + getdate(date) >= getdate(start) + and getdate(date) <= getdate(end) + and getdate(date) <= getdate(repeat) + and getdate(date) >= getdate(event_start) + ): + add_event(e, date) + + date = add_months(start_from, i + 1) + remove_events.append(e) + + if e.repeat_on == "Quarterly": + # creates a string with date (27) and month (07) and year (2019) eg: 2019-07-27 + year, month = start.split("-", maxsplit=2)[:2] + date = f"{year}-{month}-" + event_start.split("-", maxsplit=3)[2] + + # last day of month issue, start from prev month! + try: + getdate(date) + except Exception: + date = date.split("-") + date = date[0] + "-" + str(cint(date[1]) - 1) + "-" + date[2] + + start_from = date + for i in range(int(date_diff(end, start) / 30) + 3): + diff = month_diff(date, event_start) - 1 + if diff % 3 != 0: + continue + if ( + getdate(date) >= getdate(start) + and getdate(date) <= getdate(end) + and getdate(date) <= getdate(repeat) + and getdate(date) >= getdate(event_start) + ): + add_event(e, date) + + date = add_months(start_from, i + 1) + remove_events.append(e) + if e.repeat_on == "Monthly": # creates a string with date (27) and month (07) and year (2019) eg: 2019-07-27 year, month = start.split("-", maxsplit=2)[:2] diff --git a/frappe/desk/doctype/event/test_event.py b/frappe/desk/doctype/event/test_event.py index 72eab8f416..0680167329 100644 --- a/frappe/desk/doctype/event/test_event.py +++ b/frappe/desk/doctype/event/test_event.py @@ -136,3 +136,77 @@ class TestEvent(FrappeTestCase): ev_list3 = get_events("2015-02-01", "2015-02-01", "Administrator", for_reminder=True) self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list3)))) + + def test_quaterly_repeat(self): + ev = frappe.get_doc( + { + "doctype": "Event", + "subject": "_Test Event", + "starts_on": "2023-02-17", + "repeat_till": "2024-02-17", + "event_type": "Public", + "repeat_this_event": 1, + "repeat_on": "Quarterly", + } + ) + ev.insert() + # Test Quaterly months + ev_list = get_events("2023-02-17", "2023-02-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list)))) + + ev_list1 = get_events("2023-05-17", "2023-05-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list1)))) + + ev_list2 = get_events("2023-08-17", "2023-08-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list2)))) + + ev_list3 = get_events("2023-11-17", "2023-11-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list3)))) + + # Test before event start date and after event end date + ev_list4 = get_events("2022-11-17", "2022-11-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + ev_list4 = get_events("2024-02-17", "2024-02-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + # Test months that aren't part of the quarterly cycle + ev_list4 = get_events("2023-12-17", "2023-12-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + ev_list4 = get_events("2023-03-17", "2023-03-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + def test_half_yearly_repeat(self): + ev = frappe.get_doc( + { + "doctype": "Event", + "subject": "_Test Event", + "starts_on": "2023-02-17", + "repeat_till": "2024-02-17", + "event_type": "Public", + "repeat_this_event": 1, + "repeat_on": "Half Yearly", + } + ) + ev.insert() + # Test Half Yearly months + ev_list = get_events("2023-02-17", "2023-02-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list)))) + + ev_list1 = get_events("2023-08-17", "2023-08-17", "Administrator", for_reminder=True) + self.assertTrue(bool(list(filter(lambda e: e.name == ev.name, ev_list1)))) + + # Test before event start date and after event end date + ev_list4 = get_events("2022-08-17", "2022-08-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + ev_list4 = get_events("2024-02-17", "2024-02-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + # Test months that aren't part of the half yearly cycle + ev_list4 = get_events("2023-12-17", "2023-12-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4)))) + + ev_list4 = get_events("2023-05-17", "2023-05-17", "Administrator", for_reminder=True) + self.assertFalse(bool(list(filter(lambda e: e.name == ev.name, ev_list4))))