Merge pull request #36116 from barredterra/local-holidays

This commit is contained in:
Rucha Mahabal 2023-07-14 17:46:18 +05:30 committed by GitHub
commit 692bfccb6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 207 additions and 404 deletions

View File

@ -6,13 +6,41 @@ frappe.ui.form.on("Holiday List", {
if (frm.doc.holidays) { if (frm.doc.holidays) {
frm.set_value("total_holidays", frm.doc.holidays.length); frm.set_value("total_holidays", frm.doc.holidays.length);
} }
frm.call("get_supported_countries").then(r => {
frm.subdivisions_by_country = r.message.subdivisions_by_country;
frm.fields_dict.country.set_data(
r.message.countries.sort((a, b) => a.label.localeCompare(b.label))
);
if (frm.doc.country) {
frm.trigger("set_subdivisions");
}
});
}, },
from_date: function(frm) { from_date: function(frm) {
if (frm.doc.from_date && !frm.doc.to_date) { if (frm.doc.from_date && !frm.doc.to_date) {
var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12); var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12);
frm.set_value("to_date", frappe.datetime.add_days(a_year_from_start, -1)); frm.set_value("to_date", frappe.datetime.add_days(a_year_from_start, -1));
} }
} },
country: function(frm) {
frm.set_value("subdivision", "");
if (frm.doc.country) {
frm.trigger("set_subdivisions");
}
},
set_subdivisions: function(frm) {
const subdivisions = [...frm.subdivisions_by_country[frm.doc.country]];
if (subdivisions && subdivisions.length > 0) {
frm.fields_dict.subdivision.set_data(subdivisions);
frm.set_df_property("subdivision", "hidden", 0);
} else {
frm.fields_dict.subdivision.set_data([]);
frm.set_df_property("subdivision", "hidden", 1);
}
},
}); });
frappe.tour["Holiday List"] = [ frappe.tour["Holiday List"] = [

View File

@ -1,480 +1,166 @@
{ {
"allow_copy": 0, "actions": [],
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"autoname": "field:holiday_list_name", "autoname": "field:holiday_list_name",
"beta": 0,
"creation": "2013-01-10 16:34:14", "creation": "2013-01-10 16:34:14",
"custom": 0,
"docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "Setup", "document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [
"holiday_list_name",
"from_date",
"to_date",
"column_break_4",
"total_holidays",
"add_weekly_holidays",
"weekly_off",
"get_weekly_off_dates",
"add_local_holidays",
"country",
"subdivision",
"get_local_holidays",
"holidays_section",
"holidays",
"clear_table",
"section_break_9",
"color"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "holiday_list_name", "fieldname": "holiday_list_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Holiday List Name", "label": "Holiday List Name",
"length": 0,
"no_copy": 0,
"oldfieldname": "holiday_list_name", "oldfieldname": "holiday_list_name",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1 "unique": 1
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_date", "fieldname": "from_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "From Date", "label": "From Date",
"length": 0, "reqd": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "to_date", "fieldname": "to_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "To Date", "label": "To Date",
"length": 0, "reqd": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4", "fieldname": "column_break_4",
"fieldtype": "Column Break", "fieldtype": "Column Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_holidays", "fieldname": "total_holidays",
"fieldtype": "Int", "fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Total Holidays", "label": "Total Holidays",
"length": 0, "read_only": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1, "collapsible": 1,
"columns": 0, "depends_on": "eval: doc.from_date && doc.to_date",
"fieldname": "add_weekly_holidays", "fieldname": "add_weekly_holidays",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "label": "Add Weekly Holidays"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Add Weekly Holidays",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "weekly_off", "fieldname": "weekly_off",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Weekly Off", "label": "Weekly Off",
"length": 0,
"no_copy": 1, "no_copy": 1,
"options": "\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday", "options": "\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
"permlevel": 0,
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "report_hide": 1
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_weekly_off_dates", "fieldname": "get_weekly_off_dates",
"fieldtype": "Button", "fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Add to Holidays", "label": "Add to Holidays",
"length": 0, "options": "get_weekly_off_dates"
"no_copy": 0,
"options": "get_weekly_off_dates",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "holidays_section", "fieldname": "holidays_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "label": "Holidays"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Holidays",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "holidays", "fieldname": "holidays",
"fieldtype": "Table", "fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Holidays", "label": "Holidays",
"length": 0,
"no_copy": 0,
"oldfieldname": "holiday_list_details", "oldfieldname": "holiday_list_details",
"oldfieldtype": "Table", "oldfieldtype": "Table",
"options": "Holiday", "options": "Holiday"
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "clear_table", "fieldname": "clear_table",
"fieldtype": "Button", "fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Clear Table", "label": "Clear Table",
"length": 0, "options": "clear_table"
"no_copy": 0,
"options": "clear_table",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_9", "fieldname": "section_break_9",
"fieldtype": "Section Break", "fieldtype": "Section Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "color", "fieldname": "color",
"fieldtype": "Color", "fieldtype": "Color",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Color", "label": "Color",
"length": 0, "print_hide": 1
"no_copy": 0, },
"permlevel": 0, {
"precision": "", "fieldname": "country",
"print_hide": 1, "fieldtype": "Autocomplete",
"print_hide_if_no_value": 0, "label": "Country"
"read_only": 0, },
"remember_last_selected_value": 0, {
"report_hide": 0, "depends_on": "country",
"reqd": 0, "fieldname": "subdivision",
"search_index": 0, "fieldtype": "Autocomplete",
"set_only_once": 0, "label": "Subdivision"
"translatable": 0, },
"unique": 0 {
"collapsible": 1,
"depends_on": "eval: doc.from_date && doc.to_date",
"fieldname": "add_local_holidays",
"fieldtype": "Section Break",
"label": "Add Local Holidays"
},
{
"fieldname": "get_local_holidays",
"fieldtype": "Button",
"label": "Add to Holidays",
"options": "get_local_holidays"
} }
], ],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-calendar", "icon": "fa fa-calendar",
"idx": 1, "idx": 1,
"image_view": 0, "links": [],
"in_create": 0, "modified": "2023-07-14 13:28:53.156421",
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-07-03 07:22:46.474096",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Setup", "module": "Setup",
"name": "Holiday List", "name": "Holiday List",
"naming_rule": "By fieldname",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {
"amend": 0,
"cancel": 0,
"create": 1, "create": 1,
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "HR Manager", "role": "HR Manager",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 0,
"write": 1 "write": 1
} }
], ],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 0, "states": []
"track_seen": 0,
"track_views": 0
} }

View File

@ -3,11 +3,15 @@
import json import json
from datetime import date
import frappe import frappe
from babel import Locale
from frappe import _, throw from frappe import _, throw
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cint, formatdate, getdate, today from frappe.utils import formatdate, getdate, today
from holidays import country_holidays
from holidays.utils import list_supported_countries
class OverlapError(frappe.ValidationError): class OverlapError(frappe.ValidationError):
@ -21,25 +25,66 @@ class HolidayList(Document):
@frappe.whitelist() @frappe.whitelist()
def get_weekly_off_dates(self): def get_weekly_off_dates(self):
self.validate_values()
date_list = self.get_weekly_off_date_list(self.from_date, self.to_date)
last_idx = max(
[cint(d.idx) for d in self.get("holidays")]
or [
0,
]
)
for i, d in enumerate(date_list):
ch = self.append("holidays", {})
ch.description = _(self.weekly_off)
ch.holiday_date = d
ch.weekly_off = 1
ch.idx = last_idx + i + 1
def validate_values(self):
if not self.weekly_off: if not self.weekly_off:
throw(_("Please select weekly off day")) throw(_("Please select weekly off day"))
existing_holidays = self.get_holidays()
for d in self.get_weekly_off_date_list(self.from_date, self.to_date):
if d in existing_holidays:
continue
self.append("holidays", {"description": _(self.weekly_off), "holiday_date": d, "weekly_off": 1})
self.sort_holidays()
@frappe.whitelist()
def get_supported_countries(self):
subdivisions_by_country = list_supported_countries()
countries = [
{"value": country, "label": local_country_name(country)}
for country in subdivisions_by_country.keys()
]
return {
"countries": countries,
"subdivisions_by_country": subdivisions_by_country,
}
@frappe.whitelist()
def get_local_holidays(self):
if not self.country:
throw(_("Please select a country"))
existing_holidays = self.get_holidays()
from_date = getdate(self.from_date)
to_date = getdate(self.to_date)
for holiday_date, holiday_name in country_holidays(
self.country,
subdiv=self.subdivision,
years=[from_date.year, to_date.year],
language=frappe.local.lang,
).items():
if holiday_date in existing_holidays:
continue
if holiday_date < from_date or holiday_date > to_date:
continue
self.append(
"holidays", {"description": holiday_name, "holiday_date": holiday_date, "weekly_off": 0}
)
self.sort_holidays()
def sort_holidays(self):
self.holidays.sort(key=lambda x: getdate(x.holiday_date))
for i in range(len(self.holidays)):
self.holidays[i].idx = i + 1
def get_holidays(self) -> list[date]:
return [getdate(holiday.holiday_date) for holiday in self.holidays]
def validate_days(self): def validate_days(self):
if getdate(self.from_date) > getdate(self.to_date): if getdate(self.from_date) > getdate(self.to_date):
throw(_("To Date cannot be before From Date")) throw(_("To Date cannot be before From Date"))
@ -120,3 +165,8 @@ def is_holiday(holiday_list, date=None):
) )
else: else:
return False return False
def local_country_name(country_code: str) -> str:
"""Return the localized country name for the given country code."""
return Locale.parse(frappe.local.lang).territories.get(country_code, country_code)

View File

@ -3,7 +3,7 @@
import unittest import unittest
from contextlib import contextmanager from contextlib import contextmanager
from datetime import timedelta from datetime import date, timedelta
import frappe import frappe
from frappe.utils import getdate from frappe.utils import getdate
@ -23,6 +23,41 @@ class TestHolidayList(unittest.TestCase):
fetched_holiday_list = frappe.get_value("Holiday List", holiday_list.name) fetched_holiday_list = frappe.get_value("Holiday List", holiday_list.name)
self.assertEqual(holiday_list.name, fetched_holiday_list) self.assertEqual(holiday_list.name, fetched_holiday_list)
def test_weekly_off(self):
holiday_list = frappe.new_doc("Holiday List")
holiday_list.from_date = "2023-01-01"
holiday_list.to_date = "2023-02-28"
holiday_list.weekly_off = "Sunday"
holiday_list.get_weekly_off_dates()
holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
self.assertNotIn(date(2022, 12, 25), holidays)
self.assertIn(date(2023, 1, 1), holidays)
self.assertIn(date(2023, 1, 8), holidays)
self.assertIn(date(2023, 1, 15), holidays)
self.assertIn(date(2023, 1, 22), holidays)
self.assertIn(date(2023, 1, 29), holidays)
self.assertIn(date(2023, 2, 5), holidays)
self.assertIn(date(2023, 2, 12), holidays)
self.assertIn(date(2023, 2, 19), holidays)
self.assertIn(date(2023, 2, 26), holidays)
self.assertNotIn(date(2023, 3, 5), holidays)
def test_local_holidays(self):
holiday_list = frappe.new_doc("Holiday List")
holiday_list.from_date = "2023-04-01"
holiday_list.to_date = "2023-04-30"
holiday_list.country = "DE"
holiday_list.subdivision = "SN"
holiday_list.get_local_holidays()
holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
self.assertNotIn(date(2023, 1, 1), holidays)
self.assertIn(date(2023, 4, 7), holidays)
self.assertIn(date(2023, 4, 10), holidays)
self.assertNotIn(date(2023, 5, 1), holidays)
def make_holiday_list( def make_holiday_list(
name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None

View File

@ -1219,7 +1219,7 @@ High Sensitivity,Hohe Empfindlichkeit,
Hold,Anhalten, Hold,Anhalten,
Hold Invoice,Rechnung zurückhalten, Hold Invoice,Rechnung zurückhalten,
Holiday,Urlaub, Holiday,Urlaub,
Holiday List,Urlaubsübersicht, Holiday List,Feiertagsliste,
Hotel Rooms of type {0} are unavailable on {1},Hotelzimmer vom Typ {0} sind auf {1} nicht verfügbar, Hotel Rooms of type {0} are unavailable on {1},Hotelzimmer vom Typ {0} sind auf {1} nicht verfügbar,
Hotels,Hotels, Hotels,Hotels,
Hourly,Stündlich, Hourly,Stündlich,
@ -3317,7 +3317,7 @@ Workflow,Workflow,
Working,In Bearbeitung, Working,In Bearbeitung,
Working Hours,Arbeitszeit, Working Hours,Arbeitszeit,
Workstation,Arbeitsplatz, Workstation,Arbeitsplatz,
Workstation is closed on the following dates as per Holiday List: {0},Arbeitsplatz ist an folgenden Tagen gemäß der Urlaubsliste geschlossen: {0}, Workstation is closed on the following dates as per Holiday List: {0},Arbeitsplatz ist an folgenden Tagen gemäß der Feiertagsliste geschlossen: {0},
Wrapping up,Aufwickeln, Wrapping up,Aufwickeln,
Wrong Password,Falsches Passwort, Wrong Password,Falsches Passwort,
Year start date or end date is overlapping with {0}. To avoid please set company,"Jahresbeginn oder Enddatum überlappt mit {0}. Bitte ein Unternehmen wählen, um dies zu verhindern", Year start date or end date is overlapping with {0}. To avoid please set company,"Jahresbeginn oder Enddatum überlappt mit {0}. Bitte ein Unternehmen wählen, um dies zu verhindern",
@ -3583,6 +3583,7 @@ Accounting Period overlaps with {0},Abrechnungszeitraum überschneidet sich mit
Activity,Aktivität, Activity,Aktivität,
Add / Manage Email Accounts.,Hinzufügen/Verwalten von E-Mail-Konten, Add / Manage Email Accounts.,Hinzufügen/Verwalten von E-Mail-Konten,
Add Child,Unterpunkt hinzufügen, Add Child,Unterpunkt hinzufügen,
Add Local Holidays,Lokale Feiertage hinzufügen,
Add Multiple,Mehrere hinzufügen, Add Multiple,Mehrere hinzufügen,
Add Participants,Teilnehmer hinzufügen, Add Participants,Teilnehmer hinzufügen,
Add to Featured Item,Zum empfohlenen Artikel hinzufügen, Add to Featured Item,Zum empfohlenen Artikel hinzufügen,
@ -4046,6 +4047,7 @@ Stock Ledger ID,Bestandsbuch-ID,
Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.,Der Bestandswert ({0}) und der Kontostand ({1}) sind für das Konto {2} und die verknüpften Lager nicht synchron., Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.,Der Bestandswert ({0}) und der Kontostand ({1}) sind für das Konto {2} und die verknüpften Lager nicht synchron.,
Stores - {0},Stores - {0}, Stores - {0},Stores - {0},
Student with email {0} does not exist,Der Student mit der E-Mail-Adresse {0} existiert nicht, Student with email {0} does not exist,Der Student mit der E-Mail-Adresse {0} existiert nicht,
Subdivision,Teilgebiet,
Submit Review,Bewertung abschicken, Submit Review,Bewertung abschicken,
Submitted,Gebucht, Submitted,Gebucht,
Supplier Addresses And Contacts,Lieferanten-Adressen und Kontaktdaten, Supplier Addresses And Contacts,Lieferanten-Adressen und Kontaktdaten,
@ -4192,6 +4194,7 @@ Mode Of Payment,Zahlungsart,
No students Found,Keine Schüler gefunden, No students Found,Keine Schüler gefunden,
Not in Stock,Nicht lagernd, Not in Stock,Nicht lagernd,
Please select a Customer,Bitte wählen Sie einen Kunden aus, Please select a Customer,Bitte wählen Sie einen Kunden aus,
Please select a country,Bitte wählen Sie ein Land aus,
Printed On,Gedruckt auf, Printed On,Gedruckt auf,
Received From,Erhalten von, Received From,Erhalten von,
Sales Person,Verkäufer, Sales Person,Verkäufer,
@ -6497,7 +6500,7 @@ Reports to,Vorgesetzter,
Attendance and Leave Details,Anwesenheits- und Urlaubsdetails, Attendance and Leave Details,Anwesenheits- und Urlaubsdetails,
Leave Policy,Urlaubsrichtlinie, Leave Policy,Urlaubsrichtlinie,
Attendance Device ID (Biometric/RF tag ID),Anwesenheitsgeräte-ID (biometrische / RF-Tag-ID), Attendance Device ID (Biometric/RF tag ID),Anwesenheitsgeräte-ID (biometrische / RF-Tag-ID),
Applicable Holiday List,Geltende Urlaubsliste, Applicable Holiday List,Geltende Feiertagsliste,
Default Shift,Standardverschiebung, Default Shift,Standardverschiebung,
Salary Details,Gehaltsdetails, Salary Details,Gehaltsdetails,
Salary Mode,Gehaltsmodus, Salary Mode,Gehaltsmodus,
@ -6662,12 +6665,12 @@ Unclaimed amount,Nicht beanspruchter Betrag,
Expense Claim Detail,Auslage, Expense Claim Detail,Auslage,
Expense Date,Datum der Auslage, Expense Date,Datum der Auslage,
Expense Claim Type,Art der Auslagenabrechnung, Expense Claim Type,Art der Auslagenabrechnung,
Holiday List Name,Urlaubslistenname, Holiday List Name,Name der Feiertagsliste,
Total Holidays,Insgesamt Feiertage, Total Holidays,Insgesamt freie Tage,
Add Weekly Holidays,Wöchentliche Feiertage hinzufügen, Add Weekly Holidays,Wöchentlich freie Tage hinzufügen,
Weekly Off,Wöchentlich frei, Weekly Off,Wöchentlich frei,
Add to Holidays,Zu Feiertagen hinzufügen, Add to Holidays,Zu freien Tagen hinzufügen,
Holidays,Ferien, Holidays,Arbeitsfreie Tage,
Clear Table,Tabelle leeren, Clear Table,Tabelle leeren,
HR Settings,Einstellungen zum Modul Personalwesen, HR Settings,Einstellungen zum Modul Personalwesen,
Employee Settings,Mitarbeitereinstellungen, Employee Settings,Mitarbeitereinstellungen,
@ -6777,7 +6780,7 @@ Transaction Name,Transaktionsname,
Is Carry Forward,Ist Übertrag, Is Carry Forward,Ist Übertrag,
Is Expired,Ist abgelaufen, Is Expired,Ist abgelaufen,
Is Leave Without Pay,Ist unbezahlter Urlaub, Is Leave Without Pay,Ist unbezahlter Urlaub,
Holiday List for Optional Leave,Urlaubsliste für optionalen Urlaub, Holiday List for Optional Leave,Feiertagsliste für optionalen Urlaub,
Leave Allocations,Zuteilungen verlassen, Leave Allocations,Zuteilungen verlassen,
Leave Policy Details,Urlaubsrichtliniendetails, Leave Policy Details,Urlaubsrichtliniendetails,
Leave Policy Detail,Urlaubsrichtliniendetail, Leave Policy Detail,Urlaubsrichtliniendetail,
@ -7646,7 +7649,7 @@ Legal Entity / Subsidiary with a separate Chart of Accounts belonging to the Org
Change Abbreviation,Abkürzung ändern, Change Abbreviation,Abkürzung ändern,
Parent Company,Muttergesellschaft, Parent Company,Muttergesellschaft,
Default Values,Standardwerte, Default Values,Standardwerte,
Default Holiday List,Standard-Urlaubsliste, Default Holiday List,Standard Feiertagsliste,
Default Selling Terms,Standardverkaufsbedingungen, Default Selling Terms,Standardverkaufsbedingungen,
Default Buying Terms,Standard-Einkaufsbedingungen, Default Buying Terms,Standard-Einkaufsbedingungen,
Create Chart Of Accounts Based On,"Kontenplan erstellen, basierend auf", Create Chart Of Accounts Based On,"Kontenplan erstellen, basierend auf",

Can't render this file because it is too large.

View File

@ -13,6 +13,7 @@ dependencies = [
"Unidecode~=1.3.6", "Unidecode~=1.3.6",
"barcodenumber~=0.5.0", "barcodenumber~=0.5.0",
"rapidfuzz~=2.15.0", "rapidfuzz~=2.15.0",
"holidays~=0.28",
# integration dependencies # integration dependencies
"gocardless-pro~=1.22.0", "gocardless-pro~=1.22.0",