wbhuman_resources 1.58.4__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.
- wbhuman_resources/__init__.py +1 -0
- wbhuman_resources/admin/__init__.py +5 -0
- wbhuman_resources/admin/absence.py +113 -0
- wbhuman_resources/admin/calendars.py +37 -0
- wbhuman_resources/admin/employee.py +109 -0
- wbhuman_resources/admin/kpi.py +21 -0
- wbhuman_resources/admin/review.py +157 -0
- wbhuman_resources/apps.py +23 -0
- wbhuman_resources/dynamic_preferences_registry.py +119 -0
- wbhuman_resources/factories/__init__.py +38 -0
- wbhuman_resources/factories/absence.py +109 -0
- wbhuman_resources/factories/calendars.py +60 -0
- wbhuman_resources/factories/employee.py +80 -0
- wbhuman_resources/factories/kpi.py +155 -0
- wbhuman_resources/filters/__init__.py +20 -0
- wbhuman_resources/filters/absence.py +109 -0
- wbhuman_resources/filters/absence_graphs.py +85 -0
- wbhuman_resources/filters/calendars.py +28 -0
- wbhuman_resources/filters/employee.py +81 -0
- wbhuman_resources/filters/kpi.py +35 -0
- wbhuman_resources/filters/review.py +134 -0
- wbhuman_resources/filters/signals.py +27 -0
- wbhuman_resources/locale/de/LC_MESSAGES/django.mo +0 -0
- wbhuman_resources/locale/de/LC_MESSAGES/django.po +2207 -0
- wbhuman_resources/locale/de/LC_MESSAGES/django.po.translated +2456 -0
- wbhuman_resources/locale/en/LC_MESSAGES/django.mo +0 -0
- wbhuman_resources/locale/en/LC_MESSAGES/django.po +2091 -0
- wbhuman_resources/locale/fr/LC_MESSAGES/django.mo +0 -0
- wbhuman_resources/locale/fr/LC_MESSAGES/django.po +2093 -0
- wbhuman_resources/management/__init__.py +23 -0
- wbhuman_resources/migrations/0001_initial_squashed_squashed_0015_alter_absencerequest_calendaritem_ptr_and_more.py +949 -0
- wbhuman_resources/migrations/0016_alter_employeehumanresource_options.py +20 -0
- wbhuman_resources/migrations/0017_absencerequest_crossborder_country_and_more.py +55 -0
- wbhuman_resources/migrations/0018_remove_position_group_position_groups.py +32 -0
- wbhuman_resources/migrations/0019_alter_absencerequest_options_alter_kpi_options_and_more.py +44 -0
- wbhuman_resources/migrations/0020_alter_employeeyearbalance_year_alter_review_year.py +27 -0
- wbhuman_resources/migrations/0021_alter_position_color.py +18 -0
- wbhuman_resources/migrations/0022_remove_review_editable_mode.py +64 -0
- wbhuman_resources/migrations/__init__.py +0 -0
- wbhuman_resources/models/__init__.py +23 -0
- wbhuman_resources/models/absence.py +903 -0
- wbhuman_resources/models/calendars.py +370 -0
- wbhuman_resources/models/employee.py +1241 -0
- wbhuman_resources/models/kpi.py +199 -0
- wbhuman_resources/models/preferences.py +40 -0
- wbhuman_resources/models/review.py +982 -0
- wbhuman_resources/permissions/__init__.py +0 -0
- wbhuman_resources/permissions/backend.py +26 -0
- wbhuman_resources/serializers/__init__.py +49 -0
- wbhuman_resources/serializers/absence.py +308 -0
- wbhuman_resources/serializers/calendars.py +73 -0
- wbhuman_resources/serializers/employee.py +267 -0
- wbhuman_resources/serializers/kpi.py +80 -0
- wbhuman_resources/serializers/review.py +415 -0
- wbhuman_resources/signals.py +4 -0
- wbhuman_resources/tasks.py +195 -0
- wbhuman_resources/templates/review/review_report.html +322 -0
- wbhuman_resources/tests/__init__.py +1 -0
- wbhuman_resources/tests/conftest.py +96 -0
- wbhuman_resources/tests/models/__init__.py +0 -0
- wbhuman_resources/tests/models/test_absences.py +478 -0
- wbhuman_resources/tests/models/test_calendars.py +209 -0
- wbhuman_resources/tests/models/test_employees.py +502 -0
- wbhuman_resources/tests/models/test_review.py +103 -0
- wbhuman_resources/tests/models/test_utils.py +110 -0
- wbhuman_resources/tests/signals.py +108 -0
- wbhuman_resources/tests/test_permission.py +64 -0
- wbhuman_resources/tests/test_tasks.py +74 -0
- wbhuman_resources/urls.py +221 -0
- wbhuman_resources/utils.py +43 -0
- wbhuman_resources/viewsets/__init__.py +61 -0
- wbhuman_resources/viewsets/absence.py +312 -0
- wbhuman_resources/viewsets/absence_charts.py +328 -0
- wbhuman_resources/viewsets/buttons/__init__.py +7 -0
- wbhuman_resources/viewsets/buttons/absence.py +32 -0
- wbhuman_resources/viewsets/buttons/employee.py +44 -0
- wbhuman_resources/viewsets/buttons/kpis.py +16 -0
- wbhuman_resources/viewsets/buttons/review.py +195 -0
- wbhuman_resources/viewsets/calendars.py +103 -0
- wbhuman_resources/viewsets/display/__init__.py +39 -0
- wbhuman_resources/viewsets/display/absence.py +334 -0
- wbhuman_resources/viewsets/display/calendars.py +83 -0
- wbhuman_resources/viewsets/display/employee.py +254 -0
- wbhuman_resources/viewsets/display/kpis.py +92 -0
- wbhuman_resources/viewsets/display/review.py +429 -0
- wbhuman_resources/viewsets/employee.py +210 -0
- wbhuman_resources/viewsets/endpoints/__init__.py +42 -0
- wbhuman_resources/viewsets/endpoints/absence.py +57 -0
- wbhuman_resources/viewsets/endpoints/calendars.py +18 -0
- wbhuman_resources/viewsets/endpoints/employee.py +51 -0
- wbhuman_resources/viewsets/endpoints/kpis.py +53 -0
- wbhuman_resources/viewsets/endpoints/review.py +191 -0
- wbhuman_resources/viewsets/kpi.py +280 -0
- wbhuman_resources/viewsets/menu/__init__.py +22 -0
- wbhuman_resources/viewsets/menu/absence.py +50 -0
- wbhuman_resources/viewsets/menu/administration.py +15 -0
- wbhuman_resources/viewsets/menu/calendars.py +33 -0
- wbhuman_resources/viewsets/menu/employee.py +44 -0
- wbhuman_resources/viewsets/menu/kpis.py +18 -0
- wbhuman_resources/viewsets/menu/review.py +97 -0
- wbhuman_resources/viewsets/mixins.py +14 -0
- wbhuman_resources/viewsets/review.py +837 -0
- wbhuman_resources/viewsets/titles/__init__.py +18 -0
- wbhuman_resources/viewsets/titles/absence.py +30 -0
- wbhuman_resources/viewsets/titles/employee.py +18 -0
- wbhuman_resources/viewsets/titles/kpis.py +15 -0
- wbhuman_resources/viewsets/titles/review.py +62 -0
- wbhuman_resources/viewsets/utils.py +28 -0
- wbhuman_resources-1.58.4.dist-info/METADATA +8 -0
- wbhuman_resources-1.58.4.dist-info/RECORD +111 -0
- wbhuman_resources-1.58.4.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from wbcore.contrib.color.enums import WBColor
|
|
5
|
+
from wbcore.contrib.icons import WBIcon
|
|
6
|
+
from wbcore.enums import Unit
|
|
7
|
+
from wbcore.metadata.configs import display as dp
|
|
8
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
9
|
+
Display,
|
|
10
|
+
create_simple_display,
|
|
11
|
+
create_simple_section,
|
|
12
|
+
)
|
|
13
|
+
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
14
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
15
|
+
|
|
16
|
+
from wbhuman_resources.models import AbsenceRequest, AbsenceRequestType
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_type_legend():
|
|
20
|
+
"""
|
|
21
|
+
Dynamically create the request type list legend
|
|
22
|
+
"""
|
|
23
|
+
if AbsenceRequestType.objects.exists():
|
|
24
|
+
legend = []
|
|
25
|
+
for type in AbsenceRequestType.objects.all():
|
|
26
|
+
try:
|
|
27
|
+
legend.append(dp.LegendItem(icon=WBIcon[type.icon].icon, label=type.title, value=type.id))
|
|
28
|
+
except KeyError:
|
|
29
|
+
legend.append(dp.LegendItem(icon=type.icon, label=type.title, value=type.id))
|
|
30
|
+
|
|
31
|
+
return dp.Legend(key="type", items=legend)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AbsenceRequestDisplayConfig(DisplayViewConfig):
|
|
35
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
36
|
+
return dp.ListDisplay(
|
|
37
|
+
fields=[
|
|
38
|
+
dp.Field(key="type_icon", label=" ", width=Unit.PIXEL(50)),
|
|
39
|
+
dp.Field(key="employee", label=_("Employee"), width=Unit.PIXEL(200)),
|
|
40
|
+
dp.Field(key="period", label=_("Period"), width=Unit.PIXEL(250)),
|
|
41
|
+
dp.Field(key="_total_hours_in_days", label=_("Total Days"), width=Unit.PIXEL(125)),
|
|
42
|
+
dp.Field(key="_total_vacation_hours_in_days", label=_("Vacation Days"), width=Unit.PIXEL(125)),
|
|
43
|
+
dp.Field(key="department", label=_("Department"), width=Unit.PIXEL(350)),
|
|
44
|
+
dp.Field(key="created", label=_("Created"), width=Unit.PIXEL(150)),
|
|
45
|
+
],
|
|
46
|
+
formatting=[
|
|
47
|
+
dp.Formatting(
|
|
48
|
+
column="status",
|
|
49
|
+
formatting_rules=[
|
|
50
|
+
dp.FormattingRule(
|
|
51
|
+
style={"backgroundColor": WBColor.YELLOW_LIGHT.value},
|
|
52
|
+
condition=("==", AbsenceRequest.Status.DRAFT.name),
|
|
53
|
+
),
|
|
54
|
+
dp.FormattingRule(
|
|
55
|
+
style={"backgroundColor": WBColor.BLUE_LIGHT.value},
|
|
56
|
+
condition=("==", AbsenceRequest.Status.PENDING.name),
|
|
57
|
+
),
|
|
58
|
+
dp.FormattingRule(
|
|
59
|
+
style={"backgroundColor": WBColor.GREEN_LIGHT.value},
|
|
60
|
+
condition=("==", AbsenceRequest.Status.APPROVED.name),
|
|
61
|
+
),
|
|
62
|
+
dp.FormattingRule(
|
|
63
|
+
style={"backgroundColor": WBColor.RED_LIGHT.value},
|
|
64
|
+
condition=("==", AbsenceRequest.Status.DENIED.name),
|
|
65
|
+
),
|
|
66
|
+
dp.FormattingRule(
|
|
67
|
+
style={"backgroundColor": WBColor.RED_DARK.value},
|
|
68
|
+
condition=("==", AbsenceRequest.Status.CANCELLED.name),
|
|
69
|
+
),
|
|
70
|
+
],
|
|
71
|
+
),
|
|
72
|
+
],
|
|
73
|
+
legends=[
|
|
74
|
+
dp.Legend(
|
|
75
|
+
key="status",
|
|
76
|
+
items=[
|
|
77
|
+
dp.LegendItem(
|
|
78
|
+
icon=WBColor.YELLOW_LIGHT.value,
|
|
79
|
+
label=AbsenceRequest.Status.DRAFT.label,
|
|
80
|
+
value=AbsenceRequest.Status.DRAFT.value,
|
|
81
|
+
),
|
|
82
|
+
dp.LegendItem(
|
|
83
|
+
icon=WBColor.BLUE_LIGHT.value,
|
|
84
|
+
label=AbsenceRequest.Status.PENDING.label,
|
|
85
|
+
value=AbsenceRequest.Status.PENDING.value,
|
|
86
|
+
),
|
|
87
|
+
dp.LegendItem(
|
|
88
|
+
icon=WBColor.GREEN_LIGHT.value,
|
|
89
|
+
label=AbsenceRequest.Status.APPROVED.label,
|
|
90
|
+
value=AbsenceRequest.Status.APPROVED.value,
|
|
91
|
+
),
|
|
92
|
+
dp.LegendItem(
|
|
93
|
+
icon=WBColor.RED_LIGHT.value,
|
|
94
|
+
label=AbsenceRequest.Status.DENIED.label,
|
|
95
|
+
value=AbsenceRequest.Status.DENIED.value,
|
|
96
|
+
),
|
|
97
|
+
dp.LegendItem(
|
|
98
|
+
icon=WBColor.RED_DARK.value,
|
|
99
|
+
label=AbsenceRequest.Status.CANCELLED.label,
|
|
100
|
+
value=AbsenceRequest.Status.CANCELLED.value,
|
|
101
|
+
),
|
|
102
|
+
],
|
|
103
|
+
),
|
|
104
|
+
get_type_legend(),
|
|
105
|
+
],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def get_instance_display(self) -> Display:
|
|
109
|
+
grid_fields = [[repeat_field(3, "status")], ["period", "employee", "type"]]
|
|
110
|
+
try:
|
|
111
|
+
if self.view.get_object().status == AbsenceRequest.Status.DENIED.name:
|
|
112
|
+
grid_fields.append([repeat_field(3, "reason")])
|
|
113
|
+
except AssertionError:
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
grid_fields.extend(
|
|
117
|
+
[
|
|
118
|
+
["attachment", repeat_field(2, "crossborder_country")],
|
|
119
|
+
[repeat_field(3, "notes")],
|
|
120
|
+
[repeat_field(3, "hours_section")],
|
|
121
|
+
[repeat_field(3, "periods_section")],
|
|
122
|
+
]
|
|
123
|
+
)
|
|
124
|
+
return create_simple_display(
|
|
125
|
+
grid_fields,
|
|
126
|
+
[
|
|
127
|
+
create_simple_section(
|
|
128
|
+
"hours_section",
|
|
129
|
+
_("Hours"),
|
|
130
|
+
[
|
|
131
|
+
["_total_hours", "_total_hours_in_days"],
|
|
132
|
+
["_total_vacation_hours", "_total_vacation_hours_in_days"],
|
|
133
|
+
],
|
|
134
|
+
collapsed=False,
|
|
135
|
+
),
|
|
136
|
+
create_simple_section("periods_section", _("Periods"), [["periods"]], "periods", collapsed=True),
|
|
137
|
+
],
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class AbsenceRequestTypeDisplayConfig(DisplayViewConfig):
|
|
142
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
143
|
+
return dp.ListDisplay(
|
|
144
|
+
fields=[
|
|
145
|
+
dp.Field(key="title", label=_("Title")),
|
|
146
|
+
dp.Field(key="icon", label=_("Icon")),
|
|
147
|
+
dp.Field(key="color", label=_("Color")),
|
|
148
|
+
]
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
def get_instance_display(self) -> Display:
|
|
152
|
+
return create_simple_display(
|
|
153
|
+
[
|
|
154
|
+
[
|
|
155
|
+
"title",
|
|
156
|
+
"icon",
|
|
157
|
+
"color",
|
|
158
|
+
],
|
|
159
|
+
[repeat_field(3, "extra_notify_groups")],
|
|
160
|
+
[repeat_field(3, "settings_section")],
|
|
161
|
+
[repeat_field(3, "allowed_countries_section")],
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
create_simple_section(
|
|
165
|
+
"settings_section",
|
|
166
|
+
_("Settings"),
|
|
167
|
+
[
|
|
168
|
+
[
|
|
169
|
+
"is_vacation",
|
|
170
|
+
"is_timeoff",
|
|
171
|
+
"is_extensible",
|
|
172
|
+
],
|
|
173
|
+
["days_in_advance", "auto_approve", "is_country_necessary"],
|
|
174
|
+
],
|
|
175
|
+
collapsed=False,
|
|
176
|
+
),
|
|
177
|
+
create_simple_section(
|
|
178
|
+
"allowed_countries_section",
|
|
179
|
+
_("Allowed Countries (Cross-Border Rule)"),
|
|
180
|
+
[["crossbordercountries"]],
|
|
181
|
+
"crossbordercountries",
|
|
182
|
+
collapsed=False,
|
|
183
|
+
),
|
|
184
|
+
],
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class AbsenceRequestCrossBorderCountryDisplayConfig(DisplayViewConfig):
|
|
189
|
+
def get_instance_display(self) -> Display:
|
|
190
|
+
return create_simple_display([["geography"]])
|
|
191
|
+
|
|
192
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
193
|
+
return dp.ListDisplay(fields=(dp.Field(key="geography_repr", label=_("Country")),))
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class AbsenceRequestEmployeeHumanResourceDisplayConfig(AbsenceRequestDisplayConfig):
|
|
197
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
198
|
+
return dp.ListDisplay(
|
|
199
|
+
fields=[
|
|
200
|
+
dp.Field(key="type", label=_("Type")),
|
|
201
|
+
dp.Field(key="status", label=_("Status")),
|
|
202
|
+
dp.Field(key="period", label=_("Period")),
|
|
203
|
+
dp.Field(key="_total_hours_in_days", label=_("Total Days")),
|
|
204
|
+
dp.Field(key="_total_vacation_hours_in_days", label=_("Vacation Days")),
|
|
205
|
+
dp.Field(key="created", label=_("Created")),
|
|
206
|
+
]
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class AbsenceTypeCountEmployeeDisplayConfig(DisplayViewConfig):
|
|
211
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
212
|
+
return dp.ListDisplay(
|
|
213
|
+
fields=[
|
|
214
|
+
dp.Field(key="year", label=_("Year")),
|
|
215
|
+
dp.Field(key="absence_type", label=_("Type")),
|
|
216
|
+
dp.Field(key="hours_count", label=_("Count (hours)")),
|
|
217
|
+
dp.Field(key="days_count", label=_("Count (days)")),
|
|
218
|
+
]
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class AbsenceRequestPeriodsAbsenceRequestDisplayConfig(DisplayViewConfig):
|
|
223
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
224
|
+
return dp.ListDisplay(
|
|
225
|
+
fields=[
|
|
226
|
+
dp.Field(key="date", label=_("Date")),
|
|
227
|
+
dp.Field(key="default_period", label=_("Period")),
|
|
228
|
+
dp.Field(key="_total_hours", label=_("Total hours")),
|
|
229
|
+
dp.Field(key="balance", label=_("Balance")),
|
|
230
|
+
dp.Field(key="consecutive_hours_count", label=_("Consecutive hours count")),
|
|
231
|
+
]
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def get_instance_display(self) -> Display:
|
|
235
|
+
return create_simple_display(
|
|
236
|
+
[["date", repeat_field(2, "default_period")], ["_total_hours", "balance", "consecutive_hours_count"]]
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class AbsenceTablePandasDisplayConfig(DisplayViewConfig):
|
|
241
|
+
FORMATTING_CELL_RULE = [
|
|
242
|
+
dp.FormattingRule(
|
|
243
|
+
style={"backgroundColor": "#BA324F", "color": "#BA324F"},
|
|
244
|
+
condition=("==", -1), # Absent
|
|
245
|
+
),
|
|
246
|
+
dp.FormattingRule(
|
|
247
|
+
style={"backgroundColor": "#F0F7F4", "color": "#F0F7F4"},
|
|
248
|
+
condition=("==", 0), # Present
|
|
249
|
+
),
|
|
250
|
+
dp.FormattingRule(
|
|
251
|
+
style={"backgroundColor": "#6A8D73", "color": "#6A8D73"},
|
|
252
|
+
condition=("==", 1), # Partially Present
|
|
253
|
+
),
|
|
254
|
+
dp.FormattingRule(
|
|
255
|
+
style={"backgroundColor": "#1E91D6", "color": "#1E91D6"},
|
|
256
|
+
condition=("==", 2), # Partially Remote
|
|
257
|
+
),
|
|
258
|
+
dp.FormattingRule(
|
|
259
|
+
style={"backgroundColor": "#18206F", "color": "#18206F"},
|
|
260
|
+
condition=("==", 3), # Remote
|
|
261
|
+
),
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
265
|
+
return dp.ListDisplay(
|
|
266
|
+
fields=[
|
|
267
|
+
dp.Field(
|
|
268
|
+
key="employee_repr",
|
|
269
|
+
label=_("Employee"),
|
|
270
|
+
formatting_rules=[
|
|
271
|
+
dp.FormattingRule(
|
|
272
|
+
style={"fontWeight": "bold"},
|
|
273
|
+
condition=("!=", None),
|
|
274
|
+
)
|
|
275
|
+
],
|
|
276
|
+
width=Unit.PIXEL(200),
|
|
277
|
+
),
|
|
278
|
+
dp.Field(key="position", label=_("Department"), width=Unit.PIXEL(300)),
|
|
279
|
+
dp.Field(
|
|
280
|
+
key="monday", label=_("Monday"), formatting_rules=self.FORMATTING_CELL_RULE, width=Unit.PIXEL(150)
|
|
281
|
+
),
|
|
282
|
+
dp.Field(
|
|
283
|
+
key="tuesday",
|
|
284
|
+
label=_("Tuesday"),
|
|
285
|
+
formatting_rules=self.FORMATTING_CELL_RULE,
|
|
286
|
+
width=Unit.PIXEL(150),
|
|
287
|
+
),
|
|
288
|
+
dp.Field(
|
|
289
|
+
key="wednesday",
|
|
290
|
+
label=_("Wednesday"),
|
|
291
|
+
formatting_rules=self.FORMATTING_CELL_RULE,
|
|
292
|
+
width=Unit.PIXEL(150),
|
|
293
|
+
),
|
|
294
|
+
dp.Field(
|
|
295
|
+
key="thursday",
|
|
296
|
+
label=_("Thursday"),
|
|
297
|
+
formatting_rules=self.FORMATTING_CELL_RULE,
|
|
298
|
+
width=Unit.PIXEL(150),
|
|
299
|
+
),
|
|
300
|
+
dp.Field(
|
|
301
|
+
key="friday", label=_("Friday"), formatting_rules=self.FORMATTING_CELL_RULE, width=Unit.PIXEL(150)
|
|
302
|
+
),
|
|
303
|
+
dp.Field(
|
|
304
|
+
key="saturday",
|
|
305
|
+
label=_("Saturday"),
|
|
306
|
+
formatting_rules=self.FORMATTING_CELL_RULE,
|
|
307
|
+
width=Unit.PIXEL(150),
|
|
308
|
+
),
|
|
309
|
+
dp.Field(
|
|
310
|
+
key="sunday", label=_("Sunday"), formatting_rules=self.FORMATTING_CELL_RULE, width=Unit.PIXEL(150)
|
|
311
|
+
),
|
|
312
|
+
],
|
|
313
|
+
legends=[
|
|
314
|
+
dp.Legend(
|
|
315
|
+
items=[
|
|
316
|
+
dp.LegendItem(icon="#F0F7F4", label=_("Present")),
|
|
317
|
+
dp.LegendItem(icon="#6A8D73", label=_("Partially Present")),
|
|
318
|
+
dp.LegendItem(icon="#18206F", label=_("Remote")),
|
|
319
|
+
dp.LegendItem(icon="#1E91D6", label=_("Partially Remote")),
|
|
320
|
+
dp.LegendItem(icon="#BA324F", label=_("Absent")),
|
|
321
|
+
]
|
|
322
|
+
)
|
|
323
|
+
],
|
|
324
|
+
# formatting=[
|
|
325
|
+
# dp.Formatting(
|
|
326
|
+
# column="employee_repr",
|
|
327
|
+
# formatting_rules=[
|
|
328
|
+
# dp.FormattingRule(
|
|
329
|
+
# condition=("!=", None), style={"fontWeight": "bold"}
|
|
330
|
+
# )
|
|
331
|
+
# ]
|
|
332
|
+
# )
|
|
333
|
+
# ]
|
|
334
|
+
)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from wbcore.metadata.configs import display as dp
|
|
5
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
6
|
+
Display,
|
|
7
|
+
create_simple_display,
|
|
8
|
+
create_simple_section,
|
|
9
|
+
)
|
|
10
|
+
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
11
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DayOffDisplayConfig(DisplayViewConfig):
|
|
15
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
16
|
+
return dp.ListDisplay(
|
|
17
|
+
fields=[
|
|
18
|
+
dp.Field(key="title", label=_("Title")),
|
|
19
|
+
dp.Field(key="date", label=_("Date")),
|
|
20
|
+
dp.Field(key="count_as_holiday", label=_("Count as Holiday")),
|
|
21
|
+
dp.Field(key="calendar", label=_("Calendar")),
|
|
22
|
+
]
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def get_instance_display(self) -> Display:
|
|
26
|
+
return create_simple_display(
|
|
27
|
+
[[repeat_field(2, "title")], [repeat_field(2, "calendar")], ["date", "count_as_holiday"]]
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DayOffCalendarDisplayConfig(DisplayViewConfig):
|
|
32
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
33
|
+
return dp.ListDisplay(
|
|
34
|
+
fields=[
|
|
35
|
+
dp.Field(key="title", label=_("Title")),
|
|
36
|
+
dp.Field(key="resource", label=_("Resource")),
|
|
37
|
+
dp.Field(key="timezone", label=_("Timezone")),
|
|
38
|
+
]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def get_instance_display(self) -> Display:
|
|
42
|
+
return create_simple_display(
|
|
43
|
+
[
|
|
44
|
+
["title", "resource", "timezone"],
|
|
45
|
+
[repeat_field(3, "default_periods_section")],
|
|
46
|
+
[repeat_field(3, "days_off_section")],
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
create_simple_section(
|
|
50
|
+
"default_periods_section",
|
|
51
|
+
_("Default Periods"),
|
|
52
|
+
[["default_periods"]],
|
|
53
|
+
"default_periods",
|
|
54
|
+
collapsed=True,
|
|
55
|
+
),
|
|
56
|
+
create_simple_section("days_off_section", _("Day off"), [["days_off"]], "days_off", collapsed=False),
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class DayOffDayOffCalendarDisplayConfig(DayOffDisplayConfig):
|
|
62
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
63
|
+
return dp.ListDisplay(
|
|
64
|
+
fields=[
|
|
65
|
+
dp.Field(key="date", label=_("Date")),
|
|
66
|
+
dp.Field(key="title", label=_("Title")),
|
|
67
|
+
dp.Field(key="count_as_holiday", label=_("Count as Holiday")),
|
|
68
|
+
]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class DefaultDailyPeriodDayOffCalendarDisplayConfig(DisplayViewConfig):
|
|
73
|
+
def get_list_display(self):
|
|
74
|
+
return dp.ListDisplay(
|
|
75
|
+
fields=[
|
|
76
|
+
dp.Field(key="timespan", label=_("Time Range")),
|
|
77
|
+
dp.Field(key="title", label=_("Title")),
|
|
78
|
+
dp.Field(key="total_hours", label=_("Total Hours")),
|
|
79
|
+
]
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def get_instance_display(self) -> Display:
|
|
83
|
+
return create_simple_display([["title", "title"], ["timespan", "total_hours"]])
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from django.utils.translation import gettext as _
|
|
5
|
+
from wbcore.contrib.color.enums import WBColor
|
|
6
|
+
from wbcore.enums import Unit
|
|
7
|
+
from wbcore.metadata.configs import display as dp
|
|
8
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
9
|
+
Display,
|
|
10
|
+
create_simple_display,
|
|
11
|
+
create_simple_section,
|
|
12
|
+
)
|
|
13
|
+
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
14
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
15
|
+
|
|
16
|
+
from wbhuman_resources.models.preferences import (
|
|
17
|
+
get_previous_year_balance_expiration_date,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PositionDisplayConfig(DisplayViewConfig):
|
|
22
|
+
def get_instance_display(self) -> Display:
|
|
23
|
+
return create_simple_display(
|
|
24
|
+
[["name", "name", "color"], ["level", "parent", "manager"], [repeat_field(3, "groups")]]
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
28
|
+
return dp.ListDisplay(
|
|
29
|
+
fields=[
|
|
30
|
+
dp.Field(key="name", label=_("Name")),
|
|
31
|
+
dp.Field(key="level", label=_("Level")),
|
|
32
|
+
dp.Field(key="height", label=_("Height")),
|
|
33
|
+
dp.Field(key="parent", label=_("Parent Position")),
|
|
34
|
+
dp.Field(key="manager", label=_("Manager")),
|
|
35
|
+
dp.Field(key="groups", label=_("Groups")),
|
|
36
|
+
]
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class EmployeeBalanceDisplayConfig(DisplayViewConfig):
|
|
41
|
+
def get_instance_display(self) -> Display:
|
|
42
|
+
return create_simple_display(
|
|
43
|
+
[
|
|
44
|
+
["profile", "contract_type", "is_active"],
|
|
45
|
+
["calendar", "position", "enrollment_at"],
|
|
46
|
+
["extra_days_per_period", "extra_days_frequency", "occupancy_rate"],
|
|
47
|
+
[
|
|
48
|
+
"available_vacation_balance_previous_year",
|
|
49
|
+
"available_vacation_balance_current_year",
|
|
50
|
+
"available_vacation_balance_next_year",
|
|
51
|
+
],
|
|
52
|
+
[repeat_field(3, "periods_count_per_type_section")],
|
|
53
|
+
[repeat_field(3, "absencerequest_section")],
|
|
54
|
+
[repeat_field(3, "employeeyearbalance_section")],
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
create_simple_section(
|
|
58
|
+
"periods_count_per_type_section",
|
|
59
|
+
_("Absence Periods Count per type"),
|
|
60
|
+
[["periods_count_per_type"]],
|
|
61
|
+
"periods_count_per_type",
|
|
62
|
+
collapsed=True,
|
|
63
|
+
),
|
|
64
|
+
create_simple_section(
|
|
65
|
+
"absencerequest_section", _("Requests"), [["absencerequest"]], "absencerequest", collapsed=True
|
|
66
|
+
),
|
|
67
|
+
create_simple_section(
|
|
68
|
+
"employeeyearbalance_section",
|
|
69
|
+
_("Balances"),
|
|
70
|
+
[["employeeyearbalance"]],
|
|
71
|
+
"employeeyearbalance",
|
|
72
|
+
collapsed=True,
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
78
|
+
current_year = date.today().year
|
|
79
|
+
|
|
80
|
+
base_fields = [
|
|
81
|
+
dp.Field(key="profile", label=_("Profile"), width=Unit.PIXEL(250)),
|
|
82
|
+
dp.Field(key="position", label=_("Position"), width=Unit.PIXEL(350)),
|
|
83
|
+
dp.Field(key="contract_type", label=_("Contract Type"), width=Unit.PIXEL(140)),
|
|
84
|
+
dp.Field(key="is_active", label=_("Active"), width=Unit.PIXEL(100)),
|
|
85
|
+
dp.Field(key="occupancy_rate", label=_("Occupancy Rate"), width=Unit.PIXEL(120)),
|
|
86
|
+
dp.Field(key="calendar", label=_("Calendar"), width=Unit.PIXEL(140)),
|
|
87
|
+
dp.Field(key="extra_days_frequency", label=_("Frequency"), width=Unit.PIXEL(120)),
|
|
88
|
+
dp.Field(key="extra_days_per_period", label=_("Periodic days"), width=Unit.PIXEL(120)),
|
|
89
|
+
dp.Field(key="took_long_vacations", label=_("Long Vacation"), width=Unit.PIXEL(140)),
|
|
90
|
+
]
|
|
91
|
+
if date.today() < get_previous_year_balance_expiration_date(current_year):
|
|
92
|
+
base_fields.append(
|
|
93
|
+
dp.Field(
|
|
94
|
+
key="available_vacation_balance_previous_year",
|
|
95
|
+
label=_("Balance ({current_year})").format(current_year=current_year - 1),
|
|
96
|
+
formatting_rules=[
|
|
97
|
+
dp.FormattingRule(
|
|
98
|
+
style={"color": WBColor.RED.value, "fontWeight": "bold"},
|
|
99
|
+
condition=("<=", 0),
|
|
100
|
+
),
|
|
101
|
+
dp.FormattingRule(
|
|
102
|
+
style={"color": WBColor.GREEN.value, "fontWeight": "bold"},
|
|
103
|
+
condition=(">", 0),
|
|
104
|
+
),
|
|
105
|
+
],
|
|
106
|
+
width=Unit.PIXEL(175),
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
base_fields.append(
|
|
110
|
+
dp.Field(
|
|
111
|
+
key="available_vacation_balance_current_year",
|
|
112
|
+
label=_("Balance ({current_year})").format(current_year=current_year),
|
|
113
|
+
formatting_rules=[
|
|
114
|
+
dp.FormattingRule(
|
|
115
|
+
style={"color": WBColor.RED.value, "fontWeight": "bold"},
|
|
116
|
+
condition=("<=", 0),
|
|
117
|
+
),
|
|
118
|
+
dp.FormattingRule(
|
|
119
|
+
style={"color": WBColor.GREEN.value, "fontWeight": "bold"},
|
|
120
|
+
condition=(">", 0),
|
|
121
|
+
),
|
|
122
|
+
],
|
|
123
|
+
width=Unit.PIXEL(175),
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
if date.today().month == 12:
|
|
127
|
+
base_fields.append(
|
|
128
|
+
dp.Field(
|
|
129
|
+
key="available_vacation_balance_next_year",
|
|
130
|
+
label=_("Balance ({current_year})").format(current_year=current_year + 1),
|
|
131
|
+
formatting_rules=[
|
|
132
|
+
dp.FormattingRule(
|
|
133
|
+
style={"color": WBColor.RED.value, "fontWeight": "bold"},
|
|
134
|
+
condition=("<=", 0),
|
|
135
|
+
),
|
|
136
|
+
dp.FormattingRule(
|
|
137
|
+
style={"color": WBColor.GREEN.value, "fontWeight": "bold"},
|
|
138
|
+
condition=(">", 0),
|
|
139
|
+
),
|
|
140
|
+
],
|
|
141
|
+
width=Unit.PIXEL(175),
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
return dp.ListDisplay(fields=tuple(base_fields))
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class EmployeeDisplayConfig(DisplayViewConfig):
|
|
148
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
149
|
+
return dp.ListDisplay(
|
|
150
|
+
fields=[
|
|
151
|
+
dp.Field(key="profile", label=_("Name")),
|
|
152
|
+
dp.Field(key="calendar", label=_("Calendar")),
|
|
153
|
+
dp.Field(key="contract_type", label=_("Contract")),
|
|
154
|
+
dp.Field(key="position", label=_("Position")),
|
|
155
|
+
dp.Field(key="top_position_repr", label=_("Position N+1")),
|
|
156
|
+
dp.Field(key="position_manager", label=_("Department manager")),
|
|
157
|
+
dp.Field(key="direct_manager", label=_("Direct Manager")),
|
|
158
|
+
dp.Field(key="primary_telephone", label=_("Telephone")),
|
|
159
|
+
dp.Field(key="primary_email", label=_("Email")),
|
|
160
|
+
dp.Field(key="primary_address", label=_("Address")),
|
|
161
|
+
dp.Field(key="enrollment_at", label=_("Since")),
|
|
162
|
+
]
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def get_instance_display(self) -> Display:
|
|
166
|
+
return create_simple_display(
|
|
167
|
+
[
|
|
168
|
+
["profile", "is_active", "enrollment_at"],
|
|
169
|
+
["direct_manager", "calendar", "position"],
|
|
170
|
+
[repeat_field(3, "contract_info_section")],
|
|
171
|
+
],
|
|
172
|
+
[
|
|
173
|
+
create_simple_section(
|
|
174
|
+
"contract_info_section",
|
|
175
|
+
_("Contract Info"),
|
|
176
|
+
[
|
|
177
|
+
[
|
|
178
|
+
"extra_days_frequency",
|
|
179
|
+
"occupancy_rate",
|
|
180
|
+
"contract_type",
|
|
181
|
+
],
|
|
182
|
+
],
|
|
183
|
+
)
|
|
184
|
+
],
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class YearBalanceEmployeeHumanResourceDisplayConfig(DisplayViewConfig):
|
|
189
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
190
|
+
return dp.ListDisplay(
|
|
191
|
+
fields=[
|
|
192
|
+
dp.Field(key="year", label=_("Year")),
|
|
193
|
+
dp.Field(key="_balance", label="Given yearly balance (in hours)"),
|
|
194
|
+
dp.Field(key="_number_mandatory_days_off", label="Mandatory days off (in hours)"),
|
|
195
|
+
dp.Field(key="_total_vacation_hourly_usage", label="Hourly usage (in hours)"),
|
|
196
|
+
dp.Field(key="actual_total_vacation_hourly_balance", label="Hourly available balance (in hours)"),
|
|
197
|
+
dp.Field(key="_balance_in_days", label="Given yearly balance (in days)"),
|
|
198
|
+
dp.Field(key="_number_mandatory_days_off_in_days", label="Mandatory days off (in days)"),
|
|
199
|
+
dp.Field(key="_total_vacation_hourly_usage_in_days", label="Hourly usage (in days)"),
|
|
200
|
+
dp.Field(
|
|
201
|
+
key="actual_total_vacation_hourly_balance_in_days", label="Hourly available balance (in days)"
|
|
202
|
+
),
|
|
203
|
+
]
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def get_instance_display(self) -> Display:
|
|
207
|
+
return create_simple_display(
|
|
208
|
+
[
|
|
209
|
+
["year", "extra_balance"],
|
|
210
|
+
[repeat_field(2, "hourly_balance_section")],
|
|
211
|
+
[repeat_field(2, "daily_balance_section")],
|
|
212
|
+
],
|
|
213
|
+
[
|
|
214
|
+
create_simple_section(
|
|
215
|
+
"hourly_balance_section",
|
|
216
|
+
_("Balance (in Hours)"),
|
|
217
|
+
[
|
|
218
|
+
[
|
|
219
|
+
"_balance_in_days",
|
|
220
|
+
"_number_mandatory_days_off_in_days",
|
|
221
|
+
"_total_vacation_hourly_usage_in_days",
|
|
222
|
+
"actual_total_vacation_hourly_balance_in_days",
|
|
223
|
+
]
|
|
224
|
+
],
|
|
225
|
+
collapsed=False,
|
|
226
|
+
),
|
|
227
|
+
create_simple_section(
|
|
228
|
+
"daily_balance_section",
|
|
229
|
+
_("Balance (in Days)"),
|
|
230
|
+
[
|
|
231
|
+
[
|
|
232
|
+
"_balance",
|
|
233
|
+
"_number_mandatory_days_off",
|
|
234
|
+
"_total_vacation_hourly_usage",
|
|
235
|
+
"actual_total_vacation_hourly_balance",
|
|
236
|
+
]
|
|
237
|
+
],
|
|
238
|
+
collapsed=False,
|
|
239
|
+
),
|
|
240
|
+
],
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class WeeklyOffPeriodEmployeeHumanResourceDisplayConfig(DisplayViewConfig):
|
|
245
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
246
|
+
return dp.ListDisplay(
|
|
247
|
+
fields=[
|
|
248
|
+
dp.Field(key="period", label=_("Period")),
|
|
249
|
+
dp.Field(key="weekday", label=_("Weekday")),
|
|
250
|
+
]
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
def get_instance_display(self) -> Display:
|
|
254
|
+
return create_simple_display([["period", "weekday"]])
|