dashboard_segment.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. """Decode legacy dashboard links into the regular editable list filters."""
  2. import json
  3. from datetime import date
  4. from .query_filter import EMPTY_FILTER_VALUE, encode_filter_values
  5. VIEWS = ("Altersstaffel", "Standort", "Verursacher", "Wiedervorlage")
  6. DASHBOARD_VIEWS = VIEWS[:-1] # Old Wiedervorlage list selections remain valid.
  7. def _date_key(key):
  8. if key is None:
  9. return
  10. if not isinstance(key, dict) or set(key) != {"from", "to"} or not any(key.values()):
  11. raise ValueError("Ungültiger Datumsfilter")
  12. for value in key.values():
  13. if value is not None and (not isinstance(value, str) or date.fromisoformat(value).isoformat() != value):
  14. raise ValueError("Ungültiges Datum")
  15. if key["from"] and key["to"] and key["from"] > key["to"]:
  16. raise ValueError("Ungültiger Zeitraum")
  17. if key["to"] == "9999-12-31":
  18. raise ValueError("Zeitraum außerhalb des unterstützten Bereichs")
  19. def _value(value):
  20. if value is not None and (
  21. not isinstance(value, str)
  22. or len(value) > 500
  23. or any(ord(char) < 32 or ord(char) == 127 or 0xD800 <= ord(char) <= 0xDFFF for char in value)
  24. ):
  25. raise ValueError("Ungültiger Gruppenschlüssel")
  26. def parse_segment(raw):
  27. if not raw:
  28. return None
  29. if not isinstance(raw, str) or len(raw) > 4096:
  30. raise ValueError("Ungültiger Dashboardfilter")
  31. try:
  32. segment = json.loads(raw)
  33. except (ValueError, TypeError, RecursionError) as error:
  34. raise ValueError("Ungültiger Dashboardfilter") from error
  35. if (
  36. not isinstance(segment, dict)
  37. or set(segment) - {"view", "key", "department", "only_invoices", "follow_up"}
  38. or not {"view", "key"} <= set(segment)
  39. or segment["view"] not in VIEWS
  40. ):
  41. raise ValueError("Ungültiger Dashboardfilter")
  42. key, view = segment["key"], segment["view"]
  43. if "only_invoices" in segment and type(segment["only_invoices"]) is not bool:
  44. raise ValueError("Ungültiger Rechnungsfilter")
  45. if "department" in segment:
  46. _value(segment["department"])
  47. if "follow_up" in segment:
  48. _date_key(segment["follow_up"])
  49. if view == "Altersstaffel":
  50. _value(key)
  51. elif view == "Standort":
  52. if not isinstance(key, dict) or set(key) != {"client", "site"} or not key["client"]:
  53. raise ValueError("Ungültiger Standortfilter")
  54. _value(key["client"])
  55. _value(key["site"])
  56. elif view == "Verursacher":
  57. if not isinstance(key, dict) or set(key) not in ({"id"}, {"text"}):
  58. raise ValueError("Ungültiger Verursacherfilter")
  59. _value(next(iter(key.values())))
  60. if "id" in key and not key["id"]:
  61. raise ValueError("Benutzer-ID fehlt")
  62. else:
  63. _date_key(key)
  64. return segment
  65. def pack_segment(segment):
  66. return json.dumps(segment, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
  67. def segment_filters(segment, person_values=None):
  68. """Translate old dashboard URLs into editable list filters, never hidden predicates."""
  69. if not segment:
  70. return {}
  71. values = {}
  72. key, view = segment["key"], segment["view"]
  73. if view == "Standort":
  74. values.update(Mandant=[key["client"]], Filiale=[key["site"]])
  75. elif view == "Altersstaffel":
  76. values["Staffel"] = [key]
  77. elif view == "Verursacher":
  78. values["Verursacher"] = person_values if person_values is not None else [key.get("text", key.get("id"))]
  79. if "department" in segment:
  80. values["Abteilung"] = [segment["department"]]
  81. if segment.get("only_invoices"):
  82. values["RechnungGutschrift"] = ["Rechnung"]
  83. # Both the old Wiedervorlage rubric and follow_up stacks are deliberately ignored.
  84. return {
  85. name: encode_filter_values([EMPTY_FILTER_VALUE if value in (None, "") else value for value in items])
  86. for name, items in values.items()
  87. }