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,92 @@
|
|
|
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
|
+
from wbhuman_resources.models.kpi import KPI
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class KPIDisplayConfig(DisplayViewConfig):
|
|
17
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
18
|
+
return dp.ListDisplay(
|
|
19
|
+
fields=[
|
|
20
|
+
dp.Field(key="name", label=_("Name")),
|
|
21
|
+
dp.Field(key="handler", label=_("KPI")),
|
|
22
|
+
dp.Field(key="evaluated_persons", label=_("Persons")),
|
|
23
|
+
dp.Field(key="period", label=_("Period")),
|
|
24
|
+
dp.Field(key="parameters", label=_("Parameters")),
|
|
25
|
+
dp.Field(key="is_active", label=_("Is Active")),
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def get_instance_display(self) -> Display:
|
|
30
|
+
sections = []
|
|
31
|
+
grid_fields = [
|
|
32
|
+
[repeat_field(2, "name")],
|
|
33
|
+
[repeat_field(2, "handler")],
|
|
34
|
+
[repeat_field(2, "evaluated_persons")],
|
|
35
|
+
["evaluated_intervals", "is_active"],
|
|
36
|
+
["goal", "individual_evaluation"],
|
|
37
|
+
["period", "last_update"],
|
|
38
|
+
]
|
|
39
|
+
if pk := self.view.kwargs.get("pk", None):
|
|
40
|
+
handler = KPI.objects.get(id=pk).get_handler()
|
|
41
|
+
sections = [
|
|
42
|
+
create_simple_section("parameters_section", _("Parameters"), handler.get_display_grid()),
|
|
43
|
+
create_simple_section("evaluation_section", _("Evaluations"), [["evaluations"]], "evaluations"),
|
|
44
|
+
]
|
|
45
|
+
grid_fields.extend([["parameters_section", "evaluation_section"]])
|
|
46
|
+
return create_simple_display(grid_fields, sections)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class KPIEvaluationDisplayConfig(DisplayViewConfig):
|
|
50
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
51
|
+
return dp.ListDisplay(
|
|
52
|
+
fields=[
|
|
53
|
+
dp.Field(key="person", label=_("Person")),
|
|
54
|
+
dp.Field(key="evaluated_score", label=_("Evaluated Score")),
|
|
55
|
+
dp.Field(key="goal", label=_("Goal")),
|
|
56
|
+
dp.Field(key="evaluation_date", label=_("Evaluation Date")),
|
|
57
|
+
dp.Field(key="evaluated_period", label=_("Evaluated Period")),
|
|
58
|
+
]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def get_instance_display(self) -> Display:
|
|
62
|
+
return create_simple_display(
|
|
63
|
+
[
|
|
64
|
+
[repeat_field(2, "kpi")],
|
|
65
|
+
[repeat_field(2, "person")],
|
|
66
|
+
[repeat_field(2, "evaluated_period")],
|
|
67
|
+
["evaluation_date", "last_update"],
|
|
68
|
+
[repeat_field(2, "evaluated_score")],
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class KPIEvaluationPandasDisplayConfig(DisplayViewConfig):
|
|
74
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
75
|
+
pandas_fields = [
|
|
76
|
+
dp.Field(key="person", label=_("Person")),
|
|
77
|
+
dp.Field(key="kpi_name", label=_("KPI")),
|
|
78
|
+
dp.Field(key="period", label=_("Period")),
|
|
79
|
+
dp.Field(key="evaluation_date", label=_("Evaluation Date")),
|
|
80
|
+
dp.Field(key="evaluated_score", label=_("Evaluated Score")),
|
|
81
|
+
dp.Field(
|
|
82
|
+
key="goal",
|
|
83
|
+
label=_("Goal"),
|
|
84
|
+
formatting_rules=[
|
|
85
|
+
dp.FormattingRule(
|
|
86
|
+
style={"fontWeight": "bold"},
|
|
87
|
+
),
|
|
88
|
+
],
|
|
89
|
+
),
|
|
90
|
+
dp.Field(key="progression", label=_("Progression")),
|
|
91
|
+
]
|
|
92
|
+
return dp.ListDisplay(fields=pandas_fields)
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from django.utils.translation import gettext_lazy
|
|
5
|
+
from wbcore.contrib.color.enums import WBColor
|
|
6
|
+
from wbcore.enums import Operator, Unit
|
|
7
|
+
from wbcore.metadata.configs import display as dp
|
|
8
|
+
from wbcore.metadata.configs.display.instance_display import (
|
|
9
|
+
Display,
|
|
10
|
+
Inline,
|
|
11
|
+
Layout,
|
|
12
|
+
Page,
|
|
13
|
+
Style,
|
|
14
|
+
create_simple_display,
|
|
15
|
+
create_simple_section,
|
|
16
|
+
)
|
|
17
|
+
from wbcore.metadata.configs.display.instance_display.operators import default
|
|
18
|
+
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
19
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
20
|
+
|
|
21
|
+
from wbhuman_resources.models import Review, ReviewQuestion
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from wbhuman_resources.viewsets.review import ReviewAnswerReviewPandasViewSet
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_legends(model=None):
|
|
28
|
+
list_format = []
|
|
29
|
+
if model:
|
|
30
|
+
for _status, color in model.Status.get_color_map():
|
|
31
|
+
list_format.append(dp.LegendItem(icon=color, label=_status.label, value=_status.value))
|
|
32
|
+
return [dp.Legend(key="status", items=list_format)]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_list_formatting(model=None):
|
|
36
|
+
color_conditions = []
|
|
37
|
+
if model:
|
|
38
|
+
for _status, color in model.Status.get_color_map():
|
|
39
|
+
color_conditions.append(
|
|
40
|
+
dp.FormattingRule(condition=("==", _status.name), style={"backgroundColor": color})
|
|
41
|
+
)
|
|
42
|
+
return [
|
|
43
|
+
dp.Formatting(column="status", formatting_rules=color_conditions),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ReviewGroupDisplayConfig(DisplayViewConfig):
|
|
48
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
49
|
+
return dp.ListDisplay(
|
|
50
|
+
fields=[
|
|
51
|
+
dp.Field(key="name", label=_("Name")),
|
|
52
|
+
]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def get_instance_display(self) -> Display:
|
|
56
|
+
return create_simple_display(
|
|
57
|
+
[["name", "employees"], [repeat_field(2, "review_section")]],
|
|
58
|
+
[create_simple_section("review_section", _("Review"), [["review"]], "review", collapsed=False)],
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ReviewDisplayConfig(DisplayViewConfig):
|
|
63
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
64
|
+
return dp.ListDisplay(
|
|
65
|
+
fields=[
|
|
66
|
+
dp.Field(key="year", label=gettext_lazy("Year"), width=Unit.PIXEL(80)),
|
|
67
|
+
dp.Field(key="type", label=gettext_lazy("Type"), width=Unit.PIXEL(100)),
|
|
68
|
+
dp.Field(key="reviewee", label=gettext_lazy("Reviewee"), width=Unit.PIXEL(150)),
|
|
69
|
+
dp.Field(key="reviewer", label=gettext_lazy("Reviewer"), width=Unit.PIXEL(150)),
|
|
70
|
+
dp.Field(key="moderator", label=gettext_lazy("Moderator"), width=Unit.PIXEL(150)),
|
|
71
|
+
dp.Field(key="from_date", label=gettext_lazy("From"), width=Unit.PIXEL(140)),
|
|
72
|
+
dp.Field(key="to_date", label=gettext_lazy("To"), width=Unit.PIXEL(140)),
|
|
73
|
+
dp.Field(key="review_deadline", label=gettext_lazy("Deadline"), width=Unit.PIXEL(140)),
|
|
74
|
+
dp.Field(key="status", label=gettext_lazy("Status"), width=Unit.PIXEL(150)),
|
|
75
|
+
dp.Field(key="review", label=gettext_lazy("Review date"), width=Unit.PIXEL(140)),
|
|
76
|
+
dp.Field(key="is_template", label=gettext_lazy("Is Template"), width=Unit.PIXEL(100)),
|
|
77
|
+
dp.Field(key="changed", label=gettext_lazy("Changed"), width=Unit.PIXEL(140)),
|
|
78
|
+
dp.Field(key="review_group", label=gettext_lazy("Group"), width=Unit.PIXEL(150)),
|
|
79
|
+
],
|
|
80
|
+
legends=get_legends(Review),
|
|
81
|
+
formatting=get_list_formatting(Review),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def get_main_information_page(self):
|
|
85
|
+
grid_areas = [
|
|
86
|
+
["year", "type", repeat_field(2, "status")],
|
|
87
|
+
["review_group", "is_template", "moderator", "auto_apply_deadline"],
|
|
88
|
+
]
|
|
89
|
+
if self.view.kwargs.get("pk"):
|
|
90
|
+
instance = self.view.get_object()
|
|
91
|
+
if not instance.is_template:
|
|
92
|
+
grid_areas = [
|
|
93
|
+
["year", "type", repeat_field(2, "status")],
|
|
94
|
+
["from_date", "to_date", "review_deadline", "review"],
|
|
95
|
+
["reviewee", "reviewer", "moderator", "auto_apply_deadline"],
|
|
96
|
+
]
|
|
97
|
+
if instance.status != Review.Status.PREPARATION_OF_REVIEW:
|
|
98
|
+
if self.request.user.profile in [instance.reviewer, instance.reviewee]:
|
|
99
|
+
grid_areas.append(
|
|
100
|
+
["completely_filled_reviewee", "completely_filled_reviewer", repeat_field(2, "global_rating")]
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
grid_areas.append(
|
|
104
|
+
["completely_filled_reviewee", "completely_filled_reviewer", repeat_field(2, ".")]
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if instance.status in [Review.Status.EVALUATION, Review.Status.VALIDATION]:
|
|
108
|
+
grid_areas.append([repeat_field(2, "signed_reviewee"), repeat_field(2, "signed_reviewer")])
|
|
109
|
+
grid_areas.append([repeat_field(2, "feedback_reviewee"), repeat_field(2, "feedback_reviewer")])
|
|
110
|
+
|
|
111
|
+
return Page(
|
|
112
|
+
title=_("Main Information"),
|
|
113
|
+
layouts={
|
|
114
|
+
default(): Layout(
|
|
115
|
+
grid_template_areas=grid_areas,
|
|
116
|
+
),
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def get_answers_page(self, instance):
|
|
121
|
+
nb_columns = 4
|
|
122
|
+
grid_areas = []
|
|
123
|
+
sections = []
|
|
124
|
+
inlines = []
|
|
125
|
+
grid_template_rows = []
|
|
126
|
+
if instance.status == Review.Status.PREPARATION_OF_REVIEW:
|
|
127
|
+
grid_areas.append([repeat_field(nb_columns, "category_section")])
|
|
128
|
+
sections.append(
|
|
129
|
+
create_simple_section(
|
|
130
|
+
"category_section", _("Question Categories"), [["category"]], "category", collapsed=True
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
categories = instance.get_question_categories()
|
|
134
|
+
total, count = categories.count() + 1, 0
|
|
135
|
+
for count, category in enumerate(categories, start=1):
|
|
136
|
+
category_key = f"questioncategory{category.id}"
|
|
137
|
+
grid_areas.append([repeat_field(nb_columns, f"{category_key}_section")])
|
|
138
|
+
sections.append(
|
|
139
|
+
create_simple_section(
|
|
140
|
+
f"{category_key}_section",
|
|
141
|
+
("({count}/{total}). {title}").format(count=count, total=total, title=category.name),
|
|
142
|
+
[[category_key]],
|
|
143
|
+
category_key,
|
|
144
|
+
collapsed=True,
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
grid_areas.append([repeat_field(nb_columns, "questionnocategory_section")])
|
|
149
|
+
sections.append(
|
|
150
|
+
create_simple_section(
|
|
151
|
+
"questionnocategory_section",
|
|
152
|
+
_("({count}/{total}). No Question Category").format(count=count + 1, total=total),
|
|
153
|
+
[["questionnocategory"]],
|
|
154
|
+
"questionnocategory",
|
|
155
|
+
collapsed=False,
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
elif instance.status in [Review.Status.FILL_IN_REVIEW, Review.Status.REVIEW]:
|
|
160
|
+
categories = instance.get_answer_categories_for_user(self.request.user)
|
|
161
|
+
total, count = categories.count(), 0
|
|
162
|
+
if no_category := ReviewQuestion.objects.filter(review=instance, category=None).exists():
|
|
163
|
+
total += 1
|
|
164
|
+
|
|
165
|
+
for count, category in enumerate(categories, start=1):
|
|
166
|
+
category_key = f"reviewanswerquestioncategory{category.id}"
|
|
167
|
+
grid_areas.append([repeat_field(nb_columns, f"{category_key}_section")])
|
|
168
|
+
sections.append(
|
|
169
|
+
create_simple_section(
|
|
170
|
+
f"{category_key}_section",
|
|
171
|
+
("({count}/{total}). {title}").format(count=count, total=total, title=category.name),
|
|
172
|
+
[[category_key]],
|
|
173
|
+
category_key,
|
|
174
|
+
collapsed=True,
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
if no_category:
|
|
179
|
+
grid_areas.append([repeat_field(nb_columns, "reviewanswerquestionnocategory_section")])
|
|
180
|
+
sections.append(
|
|
181
|
+
create_simple_section(
|
|
182
|
+
"reviewanswerquestionnocategory_section",
|
|
183
|
+
_("({count}/{total}). No Question Category").format(count=count + 1, total=total),
|
|
184
|
+
[["reviewanswerquestionnocategory"]],
|
|
185
|
+
"reviewanswerquestionnocategory",
|
|
186
|
+
collapsed=False,
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
elif instance.status in [Review.Status.EVALUATION, Review.Status.VALIDATION]:
|
|
191
|
+
grid_areas += [
|
|
192
|
+
[repeat_field(nb_columns, "rating_review_answer_section")],
|
|
193
|
+
[repeat_field(nb_columns, "text_review_answer_inline")],
|
|
194
|
+
]
|
|
195
|
+
sections.append(
|
|
196
|
+
create_simple_section(
|
|
197
|
+
key="rating_review_answer_section",
|
|
198
|
+
title=_("Review of questions to be answered on a scale of 1 to 4"),
|
|
199
|
+
grid_template_areas=[["rating_review_answer_key"]],
|
|
200
|
+
inline_key="rating_review_answer_key",
|
|
201
|
+
collapsed=False,
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
inlines.append(Inline(key="text_review_answer_inline", endpoint="text_review_answer_key"))
|
|
205
|
+
grid_template_rows += [Style.MAX_CONTENT, Style.fr(1)]
|
|
206
|
+
|
|
207
|
+
return Page(
|
|
208
|
+
title=_("Q&A"),
|
|
209
|
+
layouts={
|
|
210
|
+
default(): Layout(
|
|
211
|
+
grid_template_areas=grid_areas,
|
|
212
|
+
sections=sections,
|
|
213
|
+
inlines=inlines,
|
|
214
|
+
grid_template_rows=grid_template_rows,
|
|
215
|
+
),
|
|
216
|
+
},
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def get_instance_display(self) -> Display:
|
|
220
|
+
pages = []
|
|
221
|
+
if self.view.kwargs.get("pk"):
|
|
222
|
+
instance = self.view.get_object()
|
|
223
|
+
pages.append(self.get_answers_page(instance))
|
|
224
|
+
pages.append(self.get_main_information_page())
|
|
225
|
+
return Display(pages=pages)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class ReviewTemplateDisplayConfig(ReviewDisplayConfig):
|
|
229
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
230
|
+
return dp.ListDisplay(
|
|
231
|
+
fields=[
|
|
232
|
+
dp.Field(key="year", label=_("Year")),
|
|
233
|
+
dp.Field(key="type", label=_("Type")),
|
|
234
|
+
dp.Field(key="moderator", label=_("Moderator")),
|
|
235
|
+
dp.Field(key="auto_apply_deadline", label=_("Auto Apply Deadline")),
|
|
236
|
+
dp.Field(key="status", label=_("Status")),
|
|
237
|
+
dp.Field(key="review", label=_("Review")),
|
|
238
|
+
dp.Field(key="review_group", label=_("Group")),
|
|
239
|
+
dp.Field(key="changed", label=_("Changed")),
|
|
240
|
+
],
|
|
241
|
+
formatting=get_list_formatting(Review),
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class ReviewQuestionCategoryDisplayConfig(DisplayViewConfig):
|
|
246
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
247
|
+
return dp.ListDisplay(
|
|
248
|
+
fields=[
|
|
249
|
+
dp.Field(key="name", label=_("Name"), width=Unit.PIXEL(1000)),
|
|
250
|
+
dp.Field(key="weight", label=_("Weight"), width=Unit.PIXEL(150)),
|
|
251
|
+
]
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def get_instance_display(self) -> Display:
|
|
255
|
+
return create_simple_display(
|
|
256
|
+
[["name", "weight"], [repeat_field(2, "question_section")]],
|
|
257
|
+
[
|
|
258
|
+
create_simple_section(
|
|
259
|
+
"question_section", _("Question"), [["reviewquestion"]], "reviewquestion", collapsed=False
|
|
260
|
+
)
|
|
261
|
+
],
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class ReviewQuestionDisplayConfig(DisplayViewConfig):
|
|
266
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
267
|
+
return dp.ListDisplay(
|
|
268
|
+
fields=[
|
|
269
|
+
dp.Field(key="question", label=gettext_lazy("Question"), width=Unit.PIXEL(600)),
|
|
270
|
+
dp.Field(key="answer_type", label=gettext_lazy("Type"), width=Unit.PIXEL(200)),
|
|
271
|
+
dp.Field(key="mandatory", label=gettext_lazy("Mandatory"), width=Unit.PIXEL(200)),
|
|
272
|
+
dp.Field(
|
|
273
|
+
key="review_for",
|
|
274
|
+
label=gettext_lazy("Reviewee/ Reviewer/ Department/ Company"),
|
|
275
|
+
width=Unit.PIXEL(260),
|
|
276
|
+
),
|
|
277
|
+
dp.Field(key="weight", label=gettext_lazy("Weight")),
|
|
278
|
+
dp.Field(key="category", label=gettext_lazy("Category"), width=Unit.PIXEL(200), hide=True),
|
|
279
|
+
dp.Field(key="review", label=gettext_lazy("Review"), hide=True),
|
|
280
|
+
]
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
def get_instance_display(self) -> Display:
|
|
284
|
+
return create_simple_display(
|
|
285
|
+
[
|
|
286
|
+
["answer_type", "category", "review"],
|
|
287
|
+
["mandatory", "for_reviewee", "for_reviewer"],
|
|
288
|
+
["weight", "for_department_peers", "for_company_peers"],
|
|
289
|
+
[repeat_field(3, "question")],
|
|
290
|
+
]
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class ReviewQuestionReviewDisplayConfig(ReviewQuestionDisplayConfig):
|
|
295
|
+
def get_instance_display(self) -> Display:
|
|
296
|
+
if self.view.review.status in [Review.Status.EVALUATION, Review.Status.VALIDATION]:
|
|
297
|
+
return create_simple_display(
|
|
298
|
+
[["review_answers_table"]],
|
|
299
|
+
inlines=[Inline(key="review_answers_table", endpoint="review_answers_table")],
|
|
300
|
+
)
|
|
301
|
+
return super().get_instance_display()
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class ReviewAnswerDisplayConfig(DisplayViewConfig):
|
|
305
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
306
|
+
fields = [
|
|
307
|
+
dp.Field(key="question_name", label=_("Question"), width=Unit.PIXEL(720)),
|
|
308
|
+
dp.Field(key="mandatory", label=_("Mandatory"), width=Unit.PIXEL(80)),
|
|
309
|
+
]
|
|
310
|
+
if self.view.get_queryset().filter(question__answer_type=ReviewQuestion.ANSWERTYPE.RATING):
|
|
311
|
+
fields += [dp.Field(key="answer_number", label=_("Rating"), width=Unit.PIXEL(170))]
|
|
312
|
+
|
|
313
|
+
fields += [dp.Field(key="answer_text", label=_("Comment"), width=Unit.PIXEL(720))]
|
|
314
|
+
|
|
315
|
+
if review_id := self.view.kwargs.get("review_id"):
|
|
316
|
+
review = Review.objects.get(id=review_id)
|
|
317
|
+
if review.status in [Review.Status.EVALUATION, Review.Status.VALIDATION]:
|
|
318
|
+
fields = [
|
|
319
|
+
dp.Field(key="question_name", label=_("Question"), width=Unit.PIXEL(740)),
|
|
320
|
+
dp.Field(key="answered_by", label=_("Answered By"), width=Unit.PIXEL(140)),
|
|
321
|
+
dp.Field(key="answer_text", label=_("Comment"), width=Unit.PIXEL(740)),
|
|
322
|
+
]
|
|
323
|
+
return dp.ListDisplay(fields=fields)
|
|
324
|
+
|
|
325
|
+
def get_instance_display(self) -> Display:
|
|
326
|
+
grid_fields = [[repeat_field(2, "question_name")], ["mandatory", "."]]
|
|
327
|
+
if self.view.kwargs.get("pk", None):
|
|
328
|
+
instance = self.view.get_object()
|
|
329
|
+
if instance.question.answer_type == ReviewQuestion.ANSWERTYPE.RATING:
|
|
330
|
+
grid_fields += [[repeat_field(2, "answer_number")]]
|
|
331
|
+
grid_fields += [[repeat_field(2, "answer_text")]]
|
|
332
|
+
return create_simple_display(grid_fields)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
class ReviewProgressReviewPandasDisplayConfig(DisplayViewConfig):
|
|
336
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
337
|
+
_fields = [
|
|
338
|
+
dp.Field(key="answered_by_name", label=_("Answered By")),
|
|
339
|
+
dp.Field(key="progress", label=_("Progress")),
|
|
340
|
+
]
|
|
341
|
+
return dp.ListDisplay(fields=_fields)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class ReviewAnswerReviewPandasDisplayConfig(DisplayViewConfig):
|
|
345
|
+
view: "ReviewAnswerReviewPandasViewSet"
|
|
346
|
+
|
|
347
|
+
def _get_formatting_rules(self):
|
|
348
|
+
return [
|
|
349
|
+
dp.Formatting(
|
|
350
|
+
column="deviation",
|
|
351
|
+
formatting_rules=[
|
|
352
|
+
dp.FormattingRule(
|
|
353
|
+
style={
|
|
354
|
+
"backgroundColor": WBColor.YELLOW_LIGHT.value,
|
|
355
|
+
},
|
|
356
|
+
condition=dp.Condition(operator=Operator.EQUAL, value="LESS"),
|
|
357
|
+
),
|
|
358
|
+
dp.FormattingRule(
|
|
359
|
+
style={
|
|
360
|
+
"backgroundColor": WBColor.GREEN_LIGHT.value,
|
|
361
|
+
},
|
|
362
|
+
condition=dp.Condition(operator=Operator.EQUAL, value="EQUAL"),
|
|
363
|
+
),
|
|
364
|
+
dp.FormattingRule(
|
|
365
|
+
style={
|
|
366
|
+
"backgroundColor": WBColor.RED_LIGHT.value,
|
|
367
|
+
},
|
|
368
|
+
condition=dp.Condition(operator=Operator.EQUAL, value="GREAT"),
|
|
369
|
+
),
|
|
370
|
+
],
|
|
371
|
+
)
|
|
372
|
+
]
|
|
373
|
+
|
|
374
|
+
def _get_legends(self):
|
|
375
|
+
return [
|
|
376
|
+
dp.Legend(
|
|
377
|
+
key="deviation",
|
|
378
|
+
items=[
|
|
379
|
+
dp.LegendItem(
|
|
380
|
+
icon=WBColor.RED_LIGHT.value,
|
|
381
|
+
label=_("Great Difference"),
|
|
382
|
+
value="GREAT",
|
|
383
|
+
),
|
|
384
|
+
dp.LegendItem(
|
|
385
|
+
icon=WBColor.YELLOW_LIGHT.value,
|
|
386
|
+
label=_("Little Difference"),
|
|
387
|
+
value="LESS",
|
|
388
|
+
),
|
|
389
|
+
dp.LegendItem(
|
|
390
|
+
icon=WBColor.GREEN_LIGHT.value,
|
|
391
|
+
label=_("Equal"),
|
|
392
|
+
value="EQUAL",
|
|
393
|
+
),
|
|
394
|
+
],
|
|
395
|
+
),
|
|
396
|
+
]
|
|
397
|
+
|
|
398
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
399
|
+
hide_rating = self.request.GET.get("answer_type") == ReviewQuestion.ANSWERTYPE.TEXT
|
|
400
|
+
fields = [
|
|
401
|
+
dp.Field(key="category_question_name", label=_("Category"), width=Unit.PIXEL(200), hide=True),
|
|
402
|
+
dp.Field(key="question_name", label=_("Question"), width=Unit.PIXEL(780)),
|
|
403
|
+
]
|
|
404
|
+
if self.view.review.moderator == self.view.request.user.profile:
|
|
405
|
+
fields.append(dp.Field(key="weight", label=_("Weight")))
|
|
406
|
+
fields += [
|
|
407
|
+
dp.Field(key="reviewee", label=_("Reviewee"), hide=hide_rating),
|
|
408
|
+
dp.Field(key="reviewer", label=_("Reviewer"), hide=hide_rating),
|
|
409
|
+
dp.Field(key="peers", label=_("Peers"), hide=True),
|
|
410
|
+
dp.Field(key="comment_reviewee", label=_("Reviewee"), width=Unit.PIXEL(450)),
|
|
411
|
+
dp.Field(key="comment_reviewer", label=_("Reviewer"), width=Unit.PIXEL(450)),
|
|
412
|
+
dp.Field(key="comment_peers", label=_("Peers"), width=Unit.PIXEL(450), hide=True),
|
|
413
|
+
]
|
|
414
|
+
return (
|
|
415
|
+
dp.ListDisplay(fields=fields)
|
|
416
|
+
if hide_rating
|
|
417
|
+
else dp.ListDisplay(fields=fields, formatting=self._get_formatting_rules(), legends=self._get_legends())
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class ReviewProgressPandasDisplayConfig(DisplayViewConfig):
|
|
422
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
423
|
+
_fields = [
|
|
424
|
+
dp.Field(key="review_name", label=_("Review"), width=Unit.PIXEL(800)),
|
|
425
|
+
dp.Field(key="reviewee", label=_("Reviewee")),
|
|
426
|
+
dp.Field(key="reviewer", label=_("Reviewer")),
|
|
427
|
+
dp.Field(key="peers", label=_("Peers")),
|
|
428
|
+
]
|
|
429
|
+
return dp.ListDisplay(fields=_fields)
|