From 5bdeea8c564602b5d929efd88470fe13d3127597 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:29:02 +0200 Subject: [PATCH 1/6] refactor(Working Time): insert_timesheet --- .../doctype/working_time/working_time.py | 81 ++++++++++++------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index 3d26d7f..dab0102 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -210,40 +210,65 @@ def create_timesheets(self): aggregated_time_logs = aggregate_time_logs(self.time_logs) for (project, task, key), data in aggregated_time_logs.items(): - costing_rate = get_costing_rate(self.employee) customer, billing_rate, jira_site = frappe.get_value( "Project", project, ["customer", "billing_rate", "jira_site"], ) - frappe.get_doc( - { - "doctype": "Timesheet", - "time_logs": [ - { - "is_billable": int(data["billable_hours"] > 0), - "project": project, - "task": task, - "activity_type": "Default", - "base_billing_rate": billing_rate, - "base_costing_rate": costing_rate, - "costing_rate": costing_rate, - "billing_rate": billing_rate, - "hours": data["hours"], - "from_time": self.date, - "billing_hours": data["billable_hours"], - "description": get_description(jira_site, key, "; ".join(data["customer_notes"])), - "jira_issue_url": get_jira_issue_url(jira_site, key), - } - ], - "note": ",\n".join(data["internal_notes"]), - "parent_project": project, - "customer": customer, - "employee": self.employee, - "working_time": self.name, - } - ).insert() + self.insert_timesheet( + project=project, + customer=customer, + task=task, + billing_rate=billing_rate, + hours=data["hours"], + billing_hours=data["billable_hours"], + description=get_description(jira_site, key, "; ".join(data["customer_notes"])), + jira_issue_url=get_jira_issue_url(jira_site, key), + internal_notes=data["internal_notes"], + ) + + def insert_timesheet( + self, + project, + customer, + task, + billing_rate, + hours, + billing_hours, + description, + jira_issue_url, + internal_notes, + ): + costing_rate = get_costing_rate(self.employee) + + frappe.get_doc( + { + "doctype": "Timesheet", + "time_logs": [ + { + "is_billable": int(billing_hours > 0), + "project": project, + "task": task, + "activity_type": "Default", + "base_billing_rate": billing_rate, + "base_costing_rate": costing_rate, + "costing_rate": costing_rate, + "billing_rate": billing_rate, + "hours": hours, + "from_time": self.date, + "billing_hours": billing_hours, + "description": description, + "jira_issue_url": jira_issue_url, + } + ], + "note": ",\n".join(internal_notes), + "parent_project": project, + "customer": customer, + "employee": self.employee, + "working_time": self.name, + } + ).insert() def delete_draft_timesheets(self): for timesheet in frappe.get_list( From aeaef6a652584adf91c52732f98b6fd2e356a0ec Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:29:37 +0200 Subject: [PATCH 2/6] feat(Working Time): whole day timesheets --- working_time/hooks.py | 8 +++ working_time/patches.txt | 2 +- .../doctype/working_time/working_time.json | 22 ++++++- .../doctype/working_time/working_time.py | 61 ++++++++++++++++++- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/working_time/hooks.py b/working_time/hooks.py index 4b8c341..751f6d4 100644 --- a/working_time/hooks.py +++ b/working_time/hooks.py @@ -209,6 +209,14 @@ "insert_after": "cost_center", "translatable": 0, }, + { + "fieldname": "billing_rate_per_day", + "label": "Billing Rate per Day", + "fieldtype": "Currency", + "options": "currency", + "insert_after": "billing_rate", + "translatable": 0, + }, { "fieldname": "jira_section", "label": "Jira", diff --git a/working_time/patches.txt b/working_time/patches.txt index 495241f..3cc0e3b 100644 --- a/working_time/patches.txt +++ b/working_time/patches.txt @@ -5,6 +5,6 @@ working_time.patches.link_timesheet_and_attendance_to_working_time # 2023-08-14 [post_model_sync] working_time.patches.billable_time_pct # 1 working_time.patches.add_total_to_old_freelancer_time -execute:from working_time.install import make_custom_fields; make_custom_fields() # 2026-03-27 +execute:from working_time.install import make_custom_fields; make_custom_fields() # 2026-06-11 working_time.patches.rename_max_working_time_to_productive_time working_time.patches.backfill_productive_and_paid_break_time # 1 diff --git a/working_time/working_time/doctype/working_time/working_time.json b/working_time/working_time/doctype/working_time/working_time.json index 5526be9..e7eac09 100644 --- a/working_time/working_time/doctype/working_time/working_time.json +++ b/working_time/working_time/doctype/working_time/working_time.json @@ -8,8 +8,11 @@ "employee", "column_break_2", "employee_name", - "section_break_4", + "section_break_caqe", "date", + "column_break_lyny", + "whole_day_project", + "section_break_4", "time_logs", "note_explainer", "section_break_7", @@ -171,6 +174,21 @@ "hide_seconds": 1, "label": "Productive Time", "read_only": 1 + }, + { + "fieldname": "section_break_caqe", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_lyny", + "fieldtype": "Column Break" + }, + { + "description": "If set, all time logs for this project will be merged into a single 8-hour timesheet.", + "fieldname": "whole_day_project", + "fieldtype": "Link", + "label": "Whole Day Project", + "options": "Project" } ], "grid_page_length": 50, @@ -185,7 +203,7 @@ "link_fieldname": "working_time" } ], - "modified": "2026-05-26 23:20:02.508838", + "modified": "2026-06-11 14:44:20.957196", "modified_by": "Administrator", "module": "Working Time", "name": "Working Time", diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index dab0102..ae85188 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -18,6 +18,7 @@ MAX_HALF_DAY = HALF_DAY * OVERTIME_FACTOR * 60 * 60 FIVE_MINUTES = 5 * 60 ONE_HOUR = 60 * 60 +WHOLE_DAY_HOURS = 8 class WorkingTime(Document): @@ -207,7 +208,14 @@ def create_attendance(self): attendance.submit() def create_timesheets(self): - aggregated_time_logs = aggregate_time_logs(self.time_logs) + regular_logs = self.time_logs + if self.whole_day_project: + whole_day_logs = [log for log in self.time_logs if log.project == self.whole_day_project] + regular_logs = [log for log in self.time_logs if log.project != self.whole_day_project] + if whole_day_logs: + self.create_whole_day_timesheet(whole_day_logs) + + aggregated_time_logs = aggregate_time_logs(regular_logs) for (project, task, key), data in aggregated_time_logs.items(): customer, billing_rate, jira_site = frappe.get_value( @@ -228,6 +236,57 @@ def create_timesheets(self): internal_notes=data["internal_notes"], ) + def create_whole_day_timesheet(self, logs): + """Merge all time logs for the whole day project into a single 8-hour timesheet.""" + customer_notes_by_key = {} + internal_notes = [] + tasks = set() + for log in logs: + customer_note, internal_note = parse_note(log.note) + if internal_note and (not internal_notes or internal_notes[-1] != internal_note): + internal_notes.append(internal_note) + + customer_notes = customer_notes_by_key.setdefault(log.key, []) + if customer_note and (not customer_notes or customer_notes[-1] != customer_note): + customer_notes.append(customer_note) + + if log.task: + tasks.add(log.task) + + customer, billing_rate_per_day, jira_site = frappe.get_value( + "Project", + self.whole_day_project, + ["customer", "billing_rate_per_day", "jira_site"], + ) + billing_rate = flt(billing_rate_per_day) / WHOLE_DAY_HOURS + + lines = [] + for key, customer_notes in customer_notes_by_key.items(): + note = "; ".join(customer_notes) + if key: + line = get_description(jira_site, key, None) + if note: + line += f": {note}" + lines.append(line) + elif note: + lines.append(note) + + description = "\n".join(lines) or "-" + keys = [key for key in customer_notes_by_key if key] + hours = sum(log.duration or 0 for log in logs) / ONE_HOUR + + self.insert_timesheet( + project=self.whole_day_project, + customer=customer, + task=tasks.pop() if len(tasks) == 1 else None, + billing_rate=billing_rate, + hours=hours, + billing_hours=WHOLE_DAY_HOURS, + description=description, + jira_issue_url=get_jira_issue_url(jira_site, keys[0]) if len(keys) == 1 else None, + internal_notes=internal_notes, + ) + def insert_timesheet( self, project, From 62e17f97d4aec12a843bf416153120fd74f4e078 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:06:36 +0200 Subject: [PATCH 3/6] fix(Working Time): fall back to hourly rate --- .../working_time/doctype/working_time/working_time.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index ae85188..28b9508 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -253,12 +253,14 @@ def create_whole_day_timesheet(self, logs): if log.task: tasks.add(log.task) - customer, billing_rate_per_day, jira_site = frappe.get_value( + customer, billing_rate_per_day, billing_rate_per_hour, jira_site = frappe.get_value( "Project", self.whole_day_project, - ["customer", "billing_rate_per_day", "jira_site"], + ["customer", "billing_rate_per_day", "billing_rate", "jira_site"], + ) + billing_rate = ( + flt(billing_rate_per_day) / WHOLE_DAY_HOURS if billing_rate_per_day else billing_rate_per_hour ) - billing_rate = flt(billing_rate_per_day) / WHOLE_DAY_HOURS lines = [] for key, customer_notes in customer_notes_by_key.items(): From 1320ed684a24493d594286e9c62f8f72e80d213b Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:09:28 +0200 Subject: [PATCH 4/6] refactor: shared get_project_details --- .../doctype/working_time/working_time.py | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index 28b9508..0dc44fb 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -218,21 +218,17 @@ def create_timesheets(self): aggregated_time_logs = aggregate_time_logs(regular_logs) for (project, task, key), data in aggregated_time_logs.items(): - customer, billing_rate, jira_site = frappe.get_value( - "Project", - project, - ["customer", "billing_rate", "jira_site"], - ) + details = get_project_details(project) self.insert_timesheet( project=project, - customer=customer, + customer=details.customer, task=task, - billing_rate=billing_rate, + billing_rate=details.billing_rate, hours=data["hours"], billing_hours=data["billable_hours"], - description=get_description(jira_site, key, "; ".join(data["customer_notes"])), - jira_issue_url=get_jira_issue_url(jira_site, key), + description=get_description(details.jira_site, key, "; ".join(data["customer_notes"])), + jira_issue_url=get_jira_issue_url(details.jira_site, key), internal_notes=data["internal_notes"], ) @@ -253,20 +249,18 @@ def create_whole_day_timesheet(self, logs): if log.task: tasks.add(log.task) - customer, billing_rate_per_day, billing_rate_per_hour, jira_site = frappe.get_value( - "Project", - self.whole_day_project, - ["customer", "billing_rate_per_day", "billing_rate", "jira_site"], - ) + details = get_project_details(self.whole_day_project) billing_rate = ( - flt(billing_rate_per_day) / WHOLE_DAY_HOURS if billing_rate_per_day else billing_rate_per_hour + flt(details.billing_rate_per_day) / WHOLE_DAY_HOURS + if details.billing_rate_per_day + else details.billing_rate ) lines = [] for key, customer_notes in customer_notes_by_key.items(): note = "; ".join(customer_notes) if key: - line = get_description(jira_site, key, None) + line = get_description(details.jira_site, key, None) if note: line += f": {note}" lines.append(line) @@ -279,13 +273,13 @@ def create_whole_day_timesheet(self, logs): self.insert_timesheet( project=self.whole_day_project, - customer=customer, + customer=details.customer, task=tasks.pop() if len(tasks) == 1 else None, billing_rate=billing_rate, hours=hours, billing_hours=WHOLE_DAY_HOURS, description=description, - jira_issue_url=get_jira_issue_url(jira_site, keys[0]) if len(keys) == 1 else None, + jira_issue_url=get_jira_issue_url(details.jira_site, keys[0]) if len(keys) == 1 else None, internal_notes=internal_notes, ) @@ -361,6 +355,15 @@ def get_costing_rate(employee): ) +def get_project_details(project: str): + return frappe.get_value( + "Project", + project, + ["customer", "billing_rate", "billing_rate_per_day", "jira_site"], + as_dict=True, + ) + + def get_billable_duration(log): if log.billable == "0%": return 0 From 1c6193d74fad3e03087fa10627112092bc97c4b7 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:08:43 +0200 Subject: [PATCH 5/6] feat(Working Time): enforce time log requirement for whole day projects before submission --- .../working_time/doctype/working_time/working_time.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index 0dc44fb..f243eb6 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -177,6 +177,17 @@ def validate_min_rest_between_days(self, policy): ) ) + def before_submit(self): + if self.whole_day_project and not any( + log.project == self.whole_day_project for log in self.time_logs + ): + frappe.throw( + _("Please add at least one time log for the whole day project {0}.").format( + frappe.bold(self.whole_day_project) + ), + title=_("Missing Time Log"), + ) + def on_submit(self): self.create_attendance() self.create_timesheets() From 896abc421fae42c895ebf4386c9e39c350fee113 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 11 Jun 2026 18:02:00 +0200 Subject: [PATCH 6/6] chore: update translations --- working_time/locale/de.po | 35 ++++++++++++++++++++++++++-------- working_time/locale/main.pot | 37 +++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/working_time/locale/de.po b/working_time/locale/de.po index 5d22390..dbc3f55 100644 --- a/working_time/locale/de.po +++ b/working_time/locale/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Working Time VERSION\n" "Report-Msgid-Bugs-To: hallo@alyf.de\n" -"POT-Creation-Date: 2026-05-26 23:08+0053\n" +"POT-Creation-Date: 2026-06-11 17:09+0053\n" "PO-Revision-Date: 2026-03-27 14:57+0053\n" "Last-Translator: hallo@alyf.de\n" "Language-Team: hallo@alyf.de\n" @@ -217,6 +217,12 @@ msgstr "Freelancer-Zeit" msgid "Freelancer Time Log" msgstr "Freelancer-Zeiteintrag" +#. Description of the 'Whole Day Project' (Link) field in DocType 'Working +#. Time' +#: working_time/working_time/doctype/working_time/working_time.json +msgid "If set, all time logs for this project will be merged into a single 8-hour timesheet." +msgstr "Wenn gesetzt, werden alle Einträge für dieses Projekt in ein 8-Stunden-Timesheet zusammengefasst." + #. Description of the 'Note' (Small Text) field in DocType 'Working Time Log' #: working_time/working_time/doctype/working_time_log/working_time_log.json msgid "If the Issue Key is missing or needs additional explanation. Start with a \"+\" to get this printed on the invoice." @@ -258,6 +264,10 @@ msgstr "Maximale produktive Arbeitszeit pro Tag" msgid "Min Rest Between Days" msgstr "Mindest-Ruhezeit zwischen Tagen" +#: working_time/working_time/doctype/working_time/working_time.py:188 +msgid "Missing Time Log" +msgstr "Fehlender Zeiteintrag" + #. Label of a shortcut in the Time Tracking Workspace #: working_time/working_time/workspace/time_tracking/time_tracking.json msgid "New Freelancer Time" @@ -286,11 +296,15 @@ msgstr "Bezahlte Pausenzeit" msgid "Paid Working Time" msgstr "Bezahlte Arbeitszeit" -#: working_time/working_time/doctype/working_time/working_time.py:64 +#: working_time/working_time/doctype/working_time/working_time.py:65 msgid "Please add an issue key or invoice note to the billable row {0}" msgstr "Bitte einen Issue-Key oder eine Rechnungsnotiz zur abrechenbaren Zeile {0} hinzufügen" -#: working_time/working_time/doctype/working_time/working_time.py:55 +#: working_time/working_time/doctype/working_time/working_time.py:185 +msgid "Please add at least one time log for the whole day project {0}." +msgstr "Bitte mindestens einen Zeiteintrag für das Ganztagesprojekt {0} hinzufügen." + +#: working_time/working_time/doctype/working_time/working_time.py:56 msgid "Please fix negative duration in row {0}" msgstr "Bitte negative Dauer in Zeile {0} korrigieren" @@ -299,11 +313,11 @@ msgstr "Bitte negative Dauer in Zeile {0} korrigieren" msgid "Productive Time" msgstr "Produktive Arbeitszeit" -#: working_time/working_time/doctype/working_time/working_time.py:116 +#: working_time/working_time/doctype/working_time/working_time.py:117 msgid "Productive time ({0}) exceeds the maximum allowed ({1}) per day" msgstr "Produktive Arbeitszeit ({0}) überschreitet die maximal erlaubte ({1}) pro Tag" -#: working_time/working_time/doctype/working_time/working_time.py:129 +#: working_time/working_time/doctype/working_time/working_time.py:130 msgid "Productive time of {0} or more requires at least {1} of break time" msgstr "Produktive Arbeitszeit von {0} oder mehr benötigt mindestens {1} Pausenzeit" @@ -326,7 +340,7 @@ msgstr "Erinnerung: Arbeitszeit einreichen" msgid "Required Break Minutes" msgstr "Erforderliche Pausenminuten" -#: working_time/working_time/doctype/working_time/working_time.py:173 +#: working_time/working_time/doctype/working_time/working_time.py:174 msgid "Rest time since previous day ({0}) is less than the required minimum ({1})" msgstr "Die Ruhezeit seit dem Vortag ({0}) ist kürzer als das erforderliche Minimum ({1})" @@ -357,6 +371,11 @@ msgstr "Das Datum in Zeile {0} liegt vor dem Startdatum." msgid "Total Duration" msgstr "Gesamtdauer" +#. Label of a Link field in DocType 'Working Time' +#: working_time/working_time/doctype/working_time/working_time.json +msgid "Whole Day Project" +msgstr "Ganztagesprojekt" + #. Label of a Duration field in DocType 'Working Time Break Policy' #: working_time/working_time/doctype/working_time_break_policy/working_time_break_policy.json msgid "Work Threshold" @@ -405,11 +424,11 @@ msgstr "Arbeitszeit Zusammenfassung" msgid "e.g. your-domain.atlassian.net" msgstr "z.B. your-domain.atlassian.net" -#: working_time/working_time/doctype/working_time/working_time.py:89 +#: working_time/working_time/doctype/working_time/working_time.py:90 msgid "{0} is a blocked day according to the Working Time Policy" msgstr "{0} ist laut Arbeitszeitrichtlinie ein gesperrter Tag" -#: working_time/working_time/doctype/working_time/working_time.py:105 +#: working_time/working_time/doctype/working_time/working_time.py:106 msgid "{0} is a holiday according to your holiday list" msgstr "{0} ist laut Ihrer Feiertagsliste ein Feiertag" diff --git a/working_time/locale/main.pot b/working_time/locale/main.pot index e5934c2..15bd0f5 100644 --- a/working_time/locale/main.pot +++ b/working_time/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Working Time VERSION\n" "Report-Msgid-Bugs-To: hallo@alyf.de\n" -"POT-Creation-Date: 2026-05-26 23:08+0053\n" -"PO-Revision-Date: 2026-05-26 23:08+0053\n" +"POT-Creation-Date: 2026-06-11 17:09+0053\n" +"PO-Revision-Date: 2026-06-11 17:09+0053\n" "Last-Translator: hallo@alyf.de\n" "Language-Team: hallo@alyf.de\n" "MIME-Version: 1.0\n" @@ -207,6 +207,12 @@ msgstr "" msgid "Freelancer Time Log" msgstr "" +#. Description of the 'Whole Day Project' (Link) field in DocType 'Working +#. Time' +#: working_time/working_time/doctype/working_time/working_time.json +msgid "If set, all time logs for this project will be merged into a single 8-hour timesheet." +msgstr "" + #. Description of the 'Note' (Small Text) field in DocType 'Working Time Log' #: working_time/working_time/doctype/working_time_log/working_time_log.json msgid "If the Issue Key is missing or needs additional explanation. Start with a \"+\" to get this printed on the invoice." @@ -248,6 +254,10 @@ msgstr "" msgid "Min Rest Between Days" msgstr "" +#: working_time/working_time/doctype/working_time/working_time.py:188 +msgid "Missing Time Log" +msgstr "" + #. Label of a shortcut in the Time Tracking Workspace #: working_time/working_time/workspace/time_tracking/time_tracking.json msgid "New Freelancer Time" @@ -276,11 +286,15 @@ msgstr "" msgid "Paid Working Time" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:64 +#: working_time/working_time/doctype/working_time/working_time.py:65 msgid "Please add an issue key or invoice note to the billable row {0}" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:55 +#: working_time/working_time/doctype/working_time/working_time.py:185 +msgid "Please add at least one time log for the whole day project {0}." +msgstr "" + +#: working_time/working_time/doctype/working_time/working_time.py:56 msgid "Please fix negative duration in row {0}" msgstr "" @@ -289,11 +303,11 @@ msgstr "" msgid "Productive Time" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:116 +#: working_time/working_time/doctype/working_time/working_time.py:117 msgid "Productive time ({0}) exceeds the maximum allowed ({1}) per day" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:129 +#: working_time/working_time/doctype/working_time/working_time.py:130 msgid "Productive time of {0} or more requires at least {1} of break time" msgstr "" @@ -316,7 +330,7 @@ msgstr "" msgid "Required Break Minutes" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:173 +#: working_time/working_time/doctype/working_time/working_time.py:174 msgid "Rest time since previous day ({0}) is less than the required minimum ({1})" msgstr "" @@ -347,6 +361,11 @@ msgstr "" msgid "Total Duration" msgstr "" +#. Label of a Link field in DocType 'Working Time' +#: working_time/working_time/doctype/working_time/working_time.json +msgid "Whole Day Project" +msgstr "" + #. Label of a Duration field in DocType 'Working Time Break Policy' #: working_time/working_time/doctype/working_time_break_policy/working_time_break_policy.json msgid "Work Threshold" @@ -395,11 +414,11 @@ msgstr "" msgid "e.g. your-domain.atlassian.net" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:89 +#: working_time/working_time/doctype/working_time/working_time.py:90 msgid "{0} is a blocked day according to the Working Time Policy" msgstr "" -#: working_time/working_time/doctype/working_time/working_time.py:105 +#: working_time/working_time/doctype/working_time/working_time.py:106 msgid "{0} is a holiday according to your holiday list" msgstr ""