wbhuman_resources 2.2.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. wbhuman_resources/__init__.py +1 -0
  2. wbhuman_resources/admin/__init__.py +5 -0
  3. wbhuman_resources/admin/absence.py +113 -0
  4. wbhuman_resources/admin/calendars.py +37 -0
  5. wbhuman_resources/admin/employee.py +109 -0
  6. wbhuman_resources/admin/kpi.py +21 -0
  7. wbhuman_resources/admin/review.py +157 -0
  8. wbhuman_resources/apps.py +22 -0
  9. wbhuman_resources/dynamic_preferences_registry.py +118 -0
  10. wbhuman_resources/factories/__init__.py +38 -0
  11. wbhuman_resources/factories/absence.py +108 -0
  12. wbhuman_resources/factories/calendars.py +59 -0
  13. wbhuman_resources/factories/employee.py +79 -0
  14. wbhuman_resources/factories/kpi.py +154 -0
  15. wbhuman_resources/filters/__init__.py +20 -0
  16. wbhuman_resources/filters/absence.py +108 -0
  17. wbhuman_resources/filters/absence_graphs.py +84 -0
  18. wbhuman_resources/filters/calendars.py +28 -0
  19. wbhuman_resources/filters/employee.py +80 -0
  20. wbhuman_resources/filters/kpi.py +34 -0
  21. wbhuman_resources/filters/review.py +133 -0
  22. wbhuman_resources/filters/signals.py +26 -0
  23. wbhuman_resources/management/__init__.py +23 -0
  24. wbhuman_resources/migrations/0001_initial_squashed_squashed_0015_alter_absencerequest_calendaritem_ptr_and_more.py +949 -0
  25. wbhuman_resources/migrations/0016_alter_employeehumanresource_options.py +20 -0
  26. wbhuman_resources/migrations/0017_absencerequest_crossborder_country_and_more.py +55 -0
  27. wbhuman_resources/migrations/0018_remove_position_group_position_groups.py +32 -0
  28. wbhuman_resources/migrations/0019_alter_absencerequest_options_alter_kpi_options_and_more.py +44 -0
  29. wbhuman_resources/migrations/0020_alter_employeeyearbalance_year_alter_review_year.py +27 -0
  30. wbhuman_resources/migrations/0021_alter_position_color.py +18 -0
  31. wbhuman_resources/migrations/0022_remove_review_editable_mode.py +64 -0
  32. wbhuman_resources/migrations/__init__.py +0 -0
  33. wbhuman_resources/models/__init__.py +23 -0
  34. wbhuman_resources/models/absence.py +889 -0
  35. wbhuman_resources/models/calendars.py +370 -0
  36. wbhuman_resources/models/employee.py +1211 -0
  37. wbhuman_resources/models/kpi.py +199 -0
  38. wbhuman_resources/models/preferences.py +39 -0
  39. wbhuman_resources/models/review.py +978 -0
  40. wbhuman_resources/permissions/__init__.py +0 -0
  41. wbhuman_resources/permissions/backend.py +25 -0
  42. wbhuman_resources/serializers/__init__.py +49 -0
  43. wbhuman_resources/serializers/absence.py +296 -0
  44. wbhuman_resources/serializers/calendars.py +71 -0
  45. wbhuman_resources/serializers/employee.py +266 -0
  46. wbhuman_resources/serializers/kpi.py +79 -0
  47. wbhuman_resources/serializers/review.py +414 -0
  48. wbhuman_resources/tasks.py +189 -0
  49. wbhuman_resources/tests/__init__.py +1 -0
  50. wbhuman_resources/tests/conftest.py +96 -0
  51. wbhuman_resources/tests/models/__init__.py +0 -0
  52. wbhuman_resources/tests/models/test_absences.py +477 -0
  53. wbhuman_resources/tests/models/test_calendars.py +208 -0
  54. wbhuman_resources/tests/models/test_employees.py +501 -0
  55. wbhuman_resources/tests/models/test_review.py +102 -0
  56. wbhuman_resources/tests/models/test_utils.py +109 -0
  57. wbhuman_resources/tests/signals.py +107 -0
  58. wbhuman_resources/tests/test_permission.py +63 -0
  59. wbhuman_resources/tests/test_tasks.py +73 -0
  60. wbhuman_resources/urls.py +220 -0
  61. wbhuman_resources/utils.py +40 -0
  62. wbhuman_resources/viewsets/__init__.py +61 -0
  63. wbhuman_resources/viewsets/absence.py +327 -0
  64. wbhuman_resources/viewsets/absence_charts.py +327 -0
  65. wbhuman_resources/viewsets/buttons/__init__.py +7 -0
  66. wbhuman_resources/viewsets/buttons/absence.py +31 -0
  67. wbhuman_resources/viewsets/buttons/employee.py +43 -0
  68. wbhuman_resources/viewsets/buttons/kpis.py +16 -0
  69. wbhuman_resources/viewsets/buttons/review.py +194 -0
  70. wbhuman_resources/viewsets/calendars.py +102 -0
  71. wbhuman_resources/viewsets/display/__init__.py +39 -0
  72. wbhuman_resources/viewsets/display/absence.py +344 -0
  73. wbhuman_resources/viewsets/display/calendars.py +84 -0
  74. wbhuman_resources/viewsets/display/employee.py +253 -0
  75. wbhuman_resources/viewsets/display/kpis.py +91 -0
  76. wbhuman_resources/viewsets/display/review.py +427 -0
  77. wbhuman_resources/viewsets/employee.py +209 -0
  78. wbhuman_resources/viewsets/endpoints/__init__.py +42 -0
  79. wbhuman_resources/viewsets/endpoints/absence.py +74 -0
  80. wbhuman_resources/viewsets/endpoints/calendars.py +18 -0
  81. wbhuman_resources/viewsets/endpoints/employee.py +57 -0
  82. wbhuman_resources/viewsets/endpoints/kpis.py +58 -0
  83. wbhuman_resources/viewsets/endpoints/review.py +203 -0
  84. wbhuman_resources/viewsets/kpi.py +279 -0
  85. wbhuman_resources/viewsets/menu/__init__.py +22 -0
  86. wbhuman_resources/viewsets/menu/absence.py +50 -0
  87. wbhuman_resources/viewsets/menu/administration.py +15 -0
  88. wbhuman_resources/viewsets/menu/calendars.py +33 -0
  89. wbhuman_resources/viewsets/menu/employee.py +44 -0
  90. wbhuman_resources/viewsets/menu/kpis.py +18 -0
  91. wbhuman_resources/viewsets/menu/review.py +97 -0
  92. wbhuman_resources/viewsets/mixins.py +13 -0
  93. wbhuman_resources/viewsets/review.py +836 -0
  94. wbhuman_resources/viewsets/titles/__init__.py +18 -0
  95. wbhuman_resources/viewsets/titles/absence.py +29 -0
  96. wbhuman_resources/viewsets/titles/employee.py +18 -0
  97. wbhuman_resources/viewsets/titles/kpis.py +14 -0
  98. wbhuman_resources/viewsets/titles/review.py +61 -0
  99. wbhuman_resources/viewsets/utils.py +28 -0
  100. wbhuman_resources-2.2.1.dist-info/METADATA +9 -0
  101. wbhuman_resources-2.2.1.dist-info/RECORD +102 -0
  102. wbhuman_resources-2.2.1.dist-info/WHEEL +5 -0
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -0,0 +1,5 @@
1
+ from .absence import *
2
+ from .calendars import *
3
+ from .employee import *
4
+ from .kpi import *
5
+ from .review import *
@@ -0,0 +1,113 @@
1
+ from io import StringIO
2
+
3
+ import pandas as pd
4
+ from django.contrib import admin
5
+ from django.shortcuts import redirect, render
6
+ from django.utils.translation import gettext_lazy as _
7
+ from reversion.errors import RevertError
8
+ from wbcore.admin import CsvImportForm, ImportCsvMixin
9
+
10
+ from ..models.absence import AbsenceRequest, AbsenceRequestPeriods, AbsenceRequestType
11
+
12
+
13
+ class CustomImportCsvMixin(ImportCsvMixin):
14
+ def _import_csv(self, request, _sep=";"):
15
+ if request.method == "POST":
16
+ csv_file = request.FILES["csv_file"]
17
+
18
+ str_text = ""
19
+ for line in csv_file:
20
+ str_text = str_text + line.decode()
21
+ # Import csv as df
22
+ df = pd.read_csv(StringIO(str_text), sep=_sep)
23
+ # Sanitize dataframe
24
+ df = df.where(pd.notnull(df), None)
25
+ df = df.drop(df.columns.difference(self.get_import_fields()), axis=1)
26
+
27
+ # Overide this function if there is foreign key ids in the dataframe
28
+ df = self.manipulate_df(df)
29
+ errors = 0
30
+ revert_errors = 0
31
+ nb_added = 0
32
+ for model in df.to_dict("records"):
33
+ # by default, process the modela as a create request. Can be override to change the behavior
34
+ try:
35
+ nb_added += self.process_model(model)
36
+ # https://django-reversion.readthedocs.io/en/stable/common-problems.html
37
+ except RevertError:
38
+ revert_errors += 1
39
+ except Exception as e:
40
+ print(e) # noqa: T201
41
+ errors += 1
42
+ self.message_user(
43
+ request,
44
+ _(
45
+ "Your CSV file has been imported : {} imported ({} added, {} updated), {} errors, {} revert errors found due to failure to restore old versions"
46
+ ).format(
47
+ df.shape[0] - errors - revert_errors,
48
+ nb_added,
49
+ df.shape[0] - errors - revert_errors - nb_added,
50
+ errors,
51
+ revert_errors,
52
+ ),
53
+ )
54
+ return redirect("..")
55
+ form = CsvImportForm()
56
+ payload = {"form": form}
57
+ return render(request, "wbcore/admin/csv_form.html", payload)
58
+
59
+
60
+ @admin.register(AbsenceRequestType)
61
+ class AbsenceRequestTypeAdmin(admin.ModelAdmin):
62
+ list_display = [
63
+ "title",
64
+ "is_vacation",
65
+ "is_timeoff",
66
+ "is_extensible",
67
+ "auto_approve",
68
+ "days_in_advance",
69
+ ]
70
+
71
+ autocomplete_fields = ["crossborder_countries", "extra_notify_groups"]
72
+
73
+
74
+ class AbsenceRequestPeriodsInline(admin.TabularInline):
75
+ model = AbsenceRequestPeriods
76
+ ordering = ("timespan__startswith",)
77
+ extra = 0
78
+ raw_id_fields = ["balance", "request"]
79
+
80
+
81
+ @admin.register(AbsenceRequest)
82
+ class AbsenceRequestAdmin(admin.ModelAdmin):
83
+ list_display = ["status", "employee", "period", "type", "_total_hours", "_total_vacation_hours"]
84
+
85
+ fieldsets = (
86
+ (
87
+ "",
88
+ {
89
+ "fields": (
90
+ ("status", "type"),
91
+ ("period", "employee"),
92
+ "attachment",
93
+ )
94
+ },
95
+ ),
96
+ (
97
+ _("Notes"),
98
+ {"fields": ("notes", "reason")},
99
+ ),
100
+ )
101
+ inlines = (AbsenceRequestPeriodsInline,)
102
+ autocomplete_fields = ["employee"]
103
+ list_filter = ["type__is_vacation"]
104
+
105
+ def _total_hours(self, obj):
106
+ return obj._total_hours
107
+
108
+ def _total_vacation_hours(self, obj):
109
+ return obj._total_vacation_hours
110
+
111
+ #
112
+ # def get_queryset(self, request):
113
+ # return super().get_queryset().
@@ -0,0 +1,37 @@
1
+ from django.contrib import admin
2
+
3
+ from ..models import (
4
+ DayOff,
5
+ DayOffCalendar,
6
+ DefaultDailyPeriod,
7
+ EmployeeWeeklyOffPeriods,
8
+ )
9
+
10
+
11
+ @admin.register(DayOffCalendar)
12
+ class DayOffCalendarModelAdmin(admin.ModelAdmin):
13
+ pass
14
+
15
+
16
+ @admin.register(DayOff)
17
+ class DayOffAdmin(admin.ModelAdmin):
18
+ list_display = ["date", "title", "count_as_holiday", "calendar"]
19
+ ordering = ["date"]
20
+
21
+
22
+ @admin.register(DefaultDailyPeriod)
23
+ class DefaultDailyPeriodAdmin(admin.ModelAdmin):
24
+ list_display = ["lower_time", "upper_time", "title", "total_hours"]
25
+ ordering = ["lower_time"]
26
+
27
+
28
+ class EmployeeWeeklyOffPeriodsInLine(admin.TabularInline):
29
+ model = EmployeeWeeklyOffPeriods
30
+ fields = [
31
+ "period",
32
+ "weekday",
33
+ ]
34
+ fk_name = "employee"
35
+ extra = 0
36
+ raw_id_fields = ["employee"]
37
+ ordering = ("weekday", "period__lower_time")
@@ -0,0 +1,109 @@
1
+ from django.contrib import admin
2
+
3
+ from ..models.employee import (
4
+ BalanceHourlyAllowance,
5
+ EmployeeHumanResource,
6
+ EmployeeYearBalance,
7
+ Position,
8
+ )
9
+ from .calendars import EmployeeWeeklyOffPeriodsInLine
10
+
11
+
12
+ class PositionInline(admin.TabularInline):
13
+ model = Position
14
+ extra = 0
15
+
16
+
17
+ @admin.register(Position)
18
+ class PositionAdmin(admin.ModelAdmin):
19
+ search_fields = ("name",)
20
+ list_display = ("name", "height", "manager")
21
+
22
+ raw_id_fields = ["groups", "manager"]
23
+ autocomplete_fields = ["groups", "manager"]
24
+
25
+
26
+ class BalanceHourlyAllowanceTabularAdmin(admin.TabularInline):
27
+ model = BalanceHourlyAllowance
28
+ fk_name = "balance"
29
+
30
+
31
+ @admin.register(EmployeeYearBalance)
32
+ class EmployeeYearBalanceAdmin(admin.ModelAdmin):
33
+ inlines = [BalanceHourlyAllowanceTabularAdmin]
34
+
35
+
36
+ class EmployeeYearBalanceInline(admin.TabularInline):
37
+ model = EmployeeYearBalance
38
+ fields = (
39
+ "year",
40
+ "balance",
41
+ "daily_hours",
42
+ "number_mandatory_days_off",
43
+ "total_vacation_hourly_usage",
44
+ "total_vacation_hourly_balance",
45
+ "balance_in_days",
46
+ "number_mandatory_days_off_in_days",
47
+ "total_vacation_hourly_usage_in_days",
48
+ "total_vacation_hourly_balance_in_days",
49
+ )
50
+ readonly_fields = [
51
+ "balance",
52
+ "daily_hours",
53
+ "number_mandatory_days_off",
54
+ "total_vacation_hourly_usage",
55
+ "total_vacation_hourly_balance",
56
+ "balance_in_days",
57
+ "number_mandatory_days_off_in_days",
58
+ "total_vacation_hourly_usage_in_days",
59
+ "total_vacation_hourly_balance_in_days",
60
+ ]
61
+ extra = 0
62
+ ordering = ("-year",)
63
+ show_change_link = True
64
+
65
+ def _number_mandatory_days_off(self, obj):
66
+ return obj._number_mandatory_days_off
67
+
68
+ def _total_vacation_hourly_usage(self, obj):
69
+ return obj._total_vacation_hourly_usage
70
+
71
+ def _total_vacation_hourly_balance(self, obj):
72
+ return obj._total_vacation_hourly_balance
73
+
74
+ def _balance_in_days(self, obj):
75
+ return obj._balance_in_days
76
+
77
+ def _number_mandatory_days_off_in_days(self, obj):
78
+ return obj._number_mandatory_days_off_in_days
79
+
80
+ def _total_vacation_hourly_usage_in_days(self, obj):
81
+ return obj._total_vacation_hourly_usage_in_days
82
+
83
+ def _total_vacation_hourly_balance_in_days(self, obj):
84
+ return obj._total_vacation_hourly_balance_in_days
85
+
86
+
87
+ @admin.register(EmployeeHumanResource)
88
+ class EmployeeHumanResourceAdmin(admin.ModelAdmin):
89
+ fieldsets = (
90
+ (
91
+ "",
92
+ {
93
+ "fields": (
94
+ "profile",
95
+ "is_active",
96
+ "extra_days_frequency",
97
+ "occupancy_rate",
98
+ "contract_type",
99
+ "position",
100
+ "enrollment_at",
101
+ "calendar",
102
+ )
103
+ },
104
+ ),
105
+ )
106
+ raw_id_fields = ("profile",)
107
+ search_fields = ("profile__computed_str",)
108
+ list_display = ("profile", "contract_type", "position", "calendar")
109
+ inlines = (EmployeeYearBalanceInline, EmployeeWeeklyOffPeriodsInLine)
@@ -0,0 +1,21 @@
1
+ from django.contrib import admin
2
+
3
+ from ..models.kpi import KPI, Evaluation
4
+
5
+
6
+ @admin.register(Evaluation)
7
+ class KEvaluationAdmin(admin.ModelAdmin):
8
+ list_display = ["id", "person", "evaluated_score", "evaluation_date", "evaluated_period"]
9
+
10
+
11
+ class EvaluationInline(admin.TabularInline):
12
+ model = Evaluation
13
+ extra = 0
14
+ raw_id_fields = ["kpi", "person"]
15
+
16
+
17
+ @admin.register(KPI)
18
+ class KPIAdmin(admin.ModelAdmin):
19
+ list_display = ["name", "period", "goal"]
20
+ inlines = (EvaluationInline,)
21
+ raw_id_fields = ["evaluated_persons"]
@@ -0,0 +1,157 @@
1
+ from io import StringIO
2
+
3
+ import pandas as pd
4
+ from django.contrib import admin
5
+ from django.shortcuts import redirect, render
6
+ from django.utils.translation import gettext_lazy as _
7
+ from reversion.errors import RevertError
8
+ from wbcore.admin import CsvImportForm, ExportCsvMixin, ImportCsvMixin
9
+
10
+ from ..models.review import (
11
+ Review,
12
+ ReviewAnswer,
13
+ ReviewGroup,
14
+ ReviewQuestion,
15
+ ReviewQuestionCategory,
16
+ )
17
+
18
+
19
+ class CustomImportCsvMixin(ImportCsvMixin):
20
+ def _import_csv(self, request, _sep=";"):
21
+ if request.method == "POST":
22
+ csv_file = request.FILES["csv_file"]
23
+
24
+ str_text = ""
25
+ for line in csv_file:
26
+ str_text = str_text + line.decode()
27
+ # Import csv as df
28
+ df = pd.read_csv(StringIO(str_text), sep=_sep)
29
+ # Sanitize dataframe
30
+ df = df.where(pd.notnull(df), None)
31
+ df = df.drop(df.columns.difference(self.get_import_fields()), axis=1)
32
+
33
+ # Overide this function if there is foreign key ids in the dataframe
34
+ df = self.manipulate_df(df)
35
+ errors = 0
36
+ revert_errors = 0
37
+ nb_added = 0
38
+ for model in df.to_dict("records"):
39
+ # by default, process the modela as a create request. Can be override to change the behavior
40
+ try:
41
+ nb_added += self.process_model(model)
42
+ # https://django-reversion.readthedocs.io/en/stable/common-problems.html
43
+ except RevertError:
44
+ revert_errors += 1
45
+ except Exception as e:
46
+ print(e) # noqa: T201
47
+ errors += 1
48
+ self.message_user(
49
+ request,
50
+ _(
51
+ "Your CSV file has been imported : {} imported ({} added, {} updated), {} errors, {} revert errors found due to failure to restore old versions"
52
+ ).format(
53
+ df.shape[0] - errors - revert_errors,
54
+ nb_added,
55
+ df.shape[0] - errors - revert_errors - nb_added,
56
+ errors,
57
+ revert_errors,
58
+ ),
59
+ )
60
+ return redirect("..")
61
+ form = CsvImportForm()
62
+ payload = {"form": form}
63
+ return render(request, "wbcore/admin/csv_form.html", payload)
64
+
65
+
66
+ @admin.register(ReviewGroup)
67
+ class ReviewGroupAdmin(admin.ModelAdmin):
68
+ list_display = ["name"]
69
+
70
+
71
+ @admin.register(Review)
72
+ class ReviewAdmin(admin.ModelAdmin):
73
+ list_display = [
74
+ "id",
75
+ "year",
76
+ "type",
77
+ "from_date",
78
+ "to_date",
79
+ "review_deadline",
80
+ "review",
81
+ "auto_apply_deadline",
82
+ "status",
83
+ "reviewee",
84
+ "reviewer",
85
+ "moderator",
86
+ "review_group",
87
+ "is_template",
88
+ ]
89
+
90
+
91
+ @admin.register(ReviewQuestionCategory)
92
+ class ReviewQuestionCategoryAdmin(ExportCsvMixin, CustomImportCsvMixin, admin.ModelAdmin):
93
+ list_display = ["name", "order", "weight"]
94
+
95
+ def manipulate_df(self, df):
96
+ return df
97
+
98
+ def get_import_fields(self):
99
+ return ["name", "order", "weight"]
100
+
101
+ def process_model(self, model):
102
+ if category_name := model.get("name"):
103
+ _, created = self.model.objects.update_or_create(
104
+ name=category_name,
105
+ defaults={
106
+ "order": model.get("order"),
107
+ "weight": model.get("weight"),
108
+ },
109
+ )
110
+ return 1 if created else 0
111
+ return 0
112
+
113
+
114
+ @admin.register(ReviewQuestion)
115
+ class ReviewQuestion(ExportCsvMixin, CustomImportCsvMixin, admin.ModelAdmin):
116
+ list_display = [
117
+ "id",
118
+ "question",
119
+ "review",
120
+ "category",
121
+ "mandatory",
122
+ "answer_type",
123
+ "for_reviewee",
124
+ "for_reviewer",
125
+ "for_department_peers",
126
+ "for_company_peers",
127
+ "order",
128
+ "weight",
129
+ ]
130
+
131
+ def manipulate_df(self, df):
132
+ df["review"] = df["review_id"].apply(lambda x: Review.objects.get(id=x))
133
+ df["category"] = df["category_name"].apply(lambda x: ReviewQuestionCategory.objects.filter(name=x).first())
134
+ return df
135
+
136
+ def get_import_fields(self):
137
+ return ["review_id", "category_name", "answer_type", "order", "weight", "question"]
138
+
139
+ def process_model(self, model):
140
+ if review := model.get("review"):
141
+ _, created = self.model.objects.update_or_create(
142
+ review=review,
143
+ question=model.get("question"),
144
+ defaults={
145
+ "category": model.get("category"),
146
+ "answer_type": model.get("answer_type"),
147
+ "order": model.get("order"),
148
+ "weight": model.get("weight"),
149
+ },
150
+ )
151
+ return 1 if created else 0
152
+ return 0
153
+
154
+
155
+ @admin.register(ReviewAnswer)
156
+ class ReviewAnswerAdmin(admin.ModelAdmin):
157
+ list_display = ["question", "answered_by", "answer_number", "answered_anonymized"]
@@ -0,0 +1,22 @@
1
+ from django.apps import AppConfig, apps
2
+ from django.db.models.signals import post_migrate
3
+
4
+
5
+ class WbhumanResourcesConfig(AppConfig):
6
+ name = "wbhuman_resources"
7
+
8
+ def ready(self) -> None:
9
+ from wbcore.signals.filters import add_filters
10
+ from wbhuman_resources.management import initialize_task
11
+
12
+ from .filters.signals import add_position_filter
13
+
14
+ if apps.is_installed("wbcrm"):
15
+ from wbcrm.filters import ActivityFilter
16
+
17
+ add_filters.connect(add_position_filter, sender=ActivityFilter)
18
+
19
+ post_migrate.connect(
20
+ initialize_task,
21
+ dispatch_uid="wbhuman_resources.initialize_task",
22
+ )
@@ -0,0 +1,118 @@
1
+ from django.conf import settings
2
+ from django.forms import ValidationError
3
+ from django.utils.translation import gettext as _
4
+ from dynamic_preferences.preferences import Section
5
+ from dynamic_preferences.registries import global_preferences_registry
6
+ from dynamic_preferences.types import (
7
+ BooleanPreference,
8
+ IntegerPreference,
9
+ LongStringPreference,
10
+ ModelChoicePreference,
11
+ StringPreference,
12
+ )
13
+ from wbhuman_resources.models.calendars import DayOffCalendar
14
+
15
+ human_resources = Section("wbhuman_resources")
16
+
17
+ # Employee dynamic preferences
18
+
19
+
20
+ @global_preferences_registry.register
21
+ class EmployeeDefaultCalendarEntry(ModelChoicePreference):
22
+ section = human_resources
23
+ name = "employee_default_calendar"
24
+ queryset = DayOffCalendar.objects.all()
25
+ default = None
26
+
27
+
28
+ @global_preferences_registry.register
29
+ class DefaultVacationDaysPreference(IntegerPreference):
30
+ section = human_resources
31
+ name = "default_vacation_days"
32
+ default = 25
33
+
34
+ verbose_name = _("Default employee vacation days")
35
+ help_text = _("The number of vacation days allocated to an employee working full time")
36
+
37
+ def validate(self, value):
38
+ if not isinstance(value, int) or value <= 1:
39
+ raise ValidationError(_("Only positive natural numbers allowed."))
40
+
41
+
42
+ @global_preferences_registry.register
43
+ class DefaultFromEmailAddressPreference(StringPreference):
44
+ section = human_resources
45
+ name = "default_from_email_address"
46
+ default = settings.DEFAULT_FROM_EMAIL
47
+
48
+ verbose_name = "The default from email address"
49
+ help_text = "The default from email address used to send hr related emails"
50
+
51
+
52
+ @global_preferences_registry.register
53
+ class NumberOfMonthsBeforeBalanceExpiration(IntegerPreference):
54
+ section = human_resources
55
+ name = "number_of_month_before_balance_expiration"
56
+ default = 12 * 5 # Default to 5 years
57
+ verbose_name = _("The number of month before yearly balance expiration")
58
+ help_text = _(
59
+ "The number of months before any yearly balance is considered expired. The count starts the first day of the next balance year"
60
+ )
61
+
62
+
63
+ @global_preferences_registry.register
64
+ class LongVacationNumberOfDaysPreference(IntegerPreference):
65
+ section = human_resources
66
+ name = "long_vacation_number_of_days"
67
+ default = 10
68
+ help_text = _("The number of days after which a vacation is considered a long vacation.")
69
+ verbose_name = _("Long Vacation Number of days")
70
+
71
+
72
+ # Monthly report accounting preference
73
+
74
+
75
+ @global_preferences_registry.register
76
+ class AccountingCompanyEmails(LongStringPreference):
77
+ section = human_resources
78
+ name = "accounting_company_emails"
79
+ default = "no-reply@stainly-bench.com;"
80
+ verbose_name = _("Accounting email destination")
81
+ help_text = _("The accounting company emails to send automatic reports to, as a comma separated list")
82
+
83
+
84
+ # Calendar preferences
85
+
86
+
87
+ @global_preferences_registry.register
88
+ class CalendarDefaultPublicHolidayPackagePreference(StringPreference):
89
+ section = human_resources
90
+ name = "calendar_default_public_holiday_package"
91
+ default = "europe.Switzerland"
92
+
93
+ verbose_name = _("Default calendar Public holiday package")
94
+ help_text = _("Package where the correct public holidays are found. Defaults to Europe Switzerland")
95
+
96
+ def validate(self, value):
97
+ if len(value.split(".")) != 2:
98
+ raise ValidationError(_("The preference has to be in the format of <continent>.<region>"))
99
+
100
+
101
+ @global_preferences_registry.register
102
+ class CalendarDefaultTimezonePreference(StringPreference):
103
+ section = human_resources
104
+ name = "calendar_default_timezone"
105
+ default = "UTC"
106
+
107
+ verbose_name = _("Default calendar timezone")
108
+ help_text = _("The default calendar timezone")
109
+
110
+
111
+ @global_preferences_registry.register
112
+ class AreExternalEmployeesConsideredAsInternal(BooleanPreference):
113
+ section = human_resources
114
+ name = "is_external_considered_as_internal"
115
+ default = False
116
+
117
+ verbose_name = _("Are external employee considered as internal?")
118
+ help_text = _("If True, will consider the external employee (and any related logic) as internal employee")
@@ -0,0 +1,38 @@
1
+ from .absence import (
2
+ AbsenceRequestFactory,
3
+ AbsenceRequestPeriodsFactory,
4
+ AbsenceRequestTypeFactory,
5
+ TimeOffRequestFactory,
6
+ TimeOffTypeFactory,
7
+ VacationRequestFactory,
8
+ VacationTypeFactory,
9
+ )
10
+ from .calendars import (
11
+ BaseDayOffCalendarFactory,
12
+ DayOffCalendarFactory,
13
+ DayOffFactory,
14
+ DefaultDailyPeriodFactory,
15
+ )
16
+ from .employee import (
17
+ BalanceHourlyAllowanceFactory,
18
+ EmployeeHumanResourceFactory,
19
+ EmployeeWeeklyOffPeriodsFactory,
20
+ EmployeeYearBalanceFactory,
21
+ PositionFactory,
22
+ )
23
+ from .kpi import (
24
+ CompletedFilledReviewFactory,
25
+ DefaultPersonKPIFactory,
26
+ EvaluationFactory,
27
+ KPIFactory,
28
+ ReviewAbstractFactory,
29
+ ReviewAnswerFactory,
30
+ ReviewAnswerNoCategoryFactory,
31
+ ReviewFactory,
32
+ ReviewGroupFactory,
33
+ ReviewQuestionCategoryFactory,
34
+ ReviewQuestionFactory,
35
+ ReviewQuestionNoCategoryFactory,
36
+ ReviewTemplateFactory,
37
+ SignedReviewFactory,
38
+ )