diff --git a/admin.py b/admin.py index c7723b1..dd07a58 100644 --- a/admin.py +++ b/admin.py @@ -132,7 +132,7 @@ def page_admin(): def update_month_and_year(): current_user = user(time_user.value) # Archivstatus - + days_with_errors = current_user.archiving_validity_check(int(select_year.value), int(select_month.value)) with ui.grid(columns='auto auto auto 1fr 1fr 1fr 1fr') as table_grid: if int(select_month.value) > 1: archive_status = current_user.get_archive_status(int(select_year.value), @@ -310,22 +310,26 @@ Dies kann nicht rückgängig gemacht werden!''') timestamp_button = ui.button(datetime.datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M'), on_click=lambda t_stamp=timestamps_dict[day][i], day=day: edit_entry(t_stamp, day)) if archive_status: timestamp_button.disable() + with ui.row(): + # Fehlerhinweis + if day in days_with_errors: + ui.icon('warning', color='red').tooltip("Keine Schlussbuchung").classes('text-2xl') - # Notizen anzeigen - days_notes = current_user.get_day_notes(select_year.value, select_month.value, day) - if days_notes != { }: - with ui.icon('o_description').classes('text-2xl'): - with ui.tooltip(): - with ui.grid(columns='auto auto'): - for username, text in days_notes.items(): - admins_name = load_adminsettings()["admin_user"] - if username == admins_name: - ui.markdown('Administrator:') - else: - ui.markdown(current_user.fullname) - ui.markdown(text) - else: - ui.space() + # Notizen anzeigen + days_notes = current_user.get_day_notes(select_year.value, select_month.value, day) + if days_notes != { }: + with ui.icon('o_description').classes('text-2xl'): + with ui.tooltip(): + with ui.grid(columns='auto auto'): + for username, text in days_notes.items(): + admins_name = load_adminsettings()["admin_user"] + if username == admins_name: + ui.markdown('Administrator:') + else: + ui.markdown(current_user.fullname) + ui.markdown(text) + else: + ui.space() # Arbeitszeit Ist bestimmen @@ -586,6 +590,7 @@ Dies kann nicht rückgängig gemacht werden!''') current_user = user(time_user.value) month_header.set_content(f"###Buchungen für **{current_user.fullname}** für **{calendar.month_name[int(select_month.value)]} {select_year.value}**") + month_header.set_content(f"###Buchungen für **{current_user.fullname}** für **{calendar.month_name[int(select_month.value)]} {select_year.value}**") timetable() button_update = ui.button("Aktualisieren", on_click=timetable.refresh) button_update.move(timetable_header) diff --git a/api.py b/api.py index b636999..508c091 100644 --- a/api.py +++ b/api.py @@ -21,6 +21,7 @@ def page_overview_month(username: str, year: int, month: int): try: current_user = user(username) + days_with_errors = current_user.archiving_validity_check(year, month) ui.page_title(f"Bericht für {current_user.fullname} für {calendar.month_name[month]} {year}") if current_user.get_archive_status(year, month): with ui.column().classes('w-full items-end gap-0'): @@ -80,7 +81,8 @@ def page_overview_month(username: str, year: int, month: int): color_day = color_weekend current_day_date = f"{datetime(year, month, day).strftime('%a')}, {day}.{month}.{year}" - day_text_element = ui.markdown(current_day_date).classes(f'border px-{pad_x} py-{pad_y} bg-{color_day}') + with ui.link_target(day): + ui.markdown(current_day_date).classes(f'border px-{pad_x} py-{pad_y} bg-{color_day}') # Abwesenheitseinträge @@ -100,11 +102,11 @@ def page_overview_month(username: str, year: int, month: int): for i in range(0, len(timestamps_dict[day]), 2): try: temp_pair = [timestamps_dict[day][i], timestamps_dict[day][i + 1]] - booking_text = booking_text + str(datetime.fromtimestamp(temp_pair[0]).strftime('%H:%M')) + "-" + str(datetime.fromtimestamp(temp_pair[1]).strftime('%H:%M')) + "
" + booking_text = booking_text + str(datetime.fromtimestamp(temp_pair[0]).strftime('%H:%M')) + " - " + str(datetime.fromtimestamp(temp_pair[1]).strftime('%H:%M')) + "
" except: if len(timestamps_dict[day]) % 2 != 0: - booking_text += datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M') + booking_text += datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M') + " - ***Buchung fehlt!***" booking_text_element = ui.markdown(booking_text).classes(f'border px-{pad_x} py-{pad_y} bg-{booking_color} text-{booking_text_color}') @@ -258,7 +260,15 @@ def page_overview_month(username: str, year: int, month: int): dialog.open() if archivable == True: - ui.button("Archivieren", on_click=archive_dialog) + if len(days_with_errors) > 0: + ui.label("Es gibt Inkonsistenzen in den Buchungen. Folgende Tage müssen überprüft werden:") + with ui.grid(columns=len(days_with_errors)): + for i in days_with_errors: + ui.link(f"{i}.", f'#{i}') + + archive_button = ui.button("Archivieren", on_click=archive_dialog) + if len(days_with_errors) > 0: + archive_button.disable() archive() diff --git a/users.py b/users.py index b57f2a9..9d9f2ff 100644 --- a/users.py +++ b/users.py @@ -3,6 +3,7 @@ import hashlib # User bezogene Funktionen import os +from calendar import monthrange from stat import S_IREAD, S_IWUSR import datetime import time @@ -223,6 +224,25 @@ class user: except: return -1 + def archiving_validity_check(self, year: int, month: int): + timestampfilename = f"{self.userfolder}/{year}-{month}.txt" + try: + with open(timestampfilename) as timestampfile: + timestamps = timestampfile.readlines() + timestamps.sort() + days_with_errors = [ ] + for day in range(1, monthrange(year, month)[1] + 1): + day_dt = datetime.datetime(year, month, day) + timestamps_of_this_day = [ ] + for i in timestamps: + i_dt = datetime.datetime.fromtimestamp(int(i)) + if day_dt.year == i_dt.year and day_dt.month == i_dt.month and day_dt.day == i_dt.day: + timestamps_of_this_day.append(i) + if len(timestamps_of_this_day) % 2 != 0: + days_with_errors.append(day) + return days_with_errors + except: + return [ ] def archive_hours(self, year, month, overtime: int): filename = f"{self.userfolder}/{year}-{month}.json" diff --git a/users/testuser1/2025-3.json b/users/testuser1/2025-3.json old mode 100644 new mode 100755 index 27c5b37..d438ef3 --- a/users/testuser1/2025-3.json +++ b/users/testuser1/2025-3.json @@ -1 +1 @@ -{"archived": 1, "overtime": -528928} \ No newline at end of file +{"archived": 0, "overtime": -528928} \ No newline at end of file diff --git a/users/testuser1/2025-3.txt b/users/testuser1/2025-3.txt old mode 100644 new mode 100755 index 7350e03..da7ed21 --- a/users/testuser1/2025-3.txt +++ b/users/testuser1/2025-3.txt @@ -1,30 +1,4 @@ -1743965819 -1743965909 -1743966022 -1743966045 -1743966047 -1743966049 -1743967346 -1744889948 -1744889966 -1744989797 -1744989827 -1744989830 -1744989883 -1744989909 -1744989914 -1744989916 -1744991169 -1744991171 -1744991288 -1744991291 -1744991473 -1744991477 -1744991770 -1744991777 -1745181046 -1745181050 -1745240760 -1745240762 1740996000 -1740997800 +1742460540 +1741038540 +1742464500 diff --git a/users/testuser1/2025-4.json b/users/testuser1/2025-4.json old mode 100755 new mode 100644 index 1883f9d..48da952 --- a/users/testuser1/2025-4.json +++ b/users/testuser1/2025-4.json @@ -1 +1,12 @@ -{"archived": 0, "overtime": -860821, "absence": {"7": "U", "8": "K", "9": "KK", "10": "UU", "11": "F", "14": "EZ"}} \ No newline at end of file +{ + "archived": 1, + "overtime": -877154, + "absence": { + "7": "U", + "8": "K", + "9": "KK", + "10": "UU", + "11": "F", + "14": "EZ" + } +} \ No newline at end of file diff --git a/users/testuser1/2025-4.txt b/users/testuser1/2025-4.txt old mode 100755 new mode 100644 index ad67cca..bd42eec --- a/users/testuser1/2025-4.txt +++ b/users/testuser1/2025-4.txt @@ -1,21 +1,5 @@ 1744889948 1744890300 -1744989797 -1744989827 -1744989830 -1744989883 -1744989909 -1744989914 -1744989916 -1744991169 -1744991171 -1744991288 -1744991291 -1744991473 -1744991477 -1744991770 -1745215200 -1745229600 1745390818 1745390894 1745390894 diff --git a/users/testuser1/2025-5.json b/users/testuser1/2025-5.json index d3b1f01..7ec0e06 100644 --- a/users/testuser1/2025-5.json +++ b/users/testuser1/2025-5.json @@ -2,7 +2,6 @@ "archived": 0, "overtime": 0, "absence": { - "14": "U", "2": "SO" }, "notes": { diff --git a/users/testuser1/2025-5.txt b/users/testuser1/2025-5.txt index 5098bdd..58cd3a9 100644 --- a/users/testuser1/2025-5.txt +++ b/users/testuser1/2025-5.txt @@ -6,3 +6,6 @@ 1746608922 1746609024 1746609037 +1747206908 +1747207022 +1747813500