wbcompliance 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 (129) hide show
  1. wbcompliance/__init__.py +1 -0
  2. wbcompliance/admin/__init__.py +16 -0
  3. wbcompliance/admin/compliance_form.py +56 -0
  4. wbcompliance/admin/compliance_task.py +135 -0
  5. wbcompliance/admin/compliance_type.py +8 -0
  6. wbcompliance/admin/risk_management/__init__.py +3 -0
  7. wbcompliance/admin/risk_management/checks.py +7 -0
  8. wbcompliance/admin/risk_management/incidents.py +50 -0
  9. wbcompliance/admin/risk_management/rules.py +63 -0
  10. wbcompliance/admin/utils.py +46 -0
  11. wbcompliance/apps.py +14 -0
  12. wbcompliance/factories/__init__.py +21 -0
  13. wbcompliance/factories/compliance.py +246 -0
  14. wbcompliance/factories/risk_management/__init__.py +12 -0
  15. wbcompliance/factories/risk_management/backends.py +42 -0
  16. wbcompliance/factories/risk_management/checks.py +12 -0
  17. wbcompliance/factories/risk_management/incidents.py +84 -0
  18. wbcompliance/factories/risk_management/rules.py +100 -0
  19. wbcompliance/filters/__init__.py +2 -0
  20. wbcompliance/filters/compliances.py +189 -0
  21. wbcompliance/filters/risk_management/__init__.py +3 -0
  22. wbcompliance/filters/risk_management/checks.py +22 -0
  23. wbcompliance/filters/risk_management/incidents.py +113 -0
  24. wbcompliance/filters/risk_management/rules.py +110 -0
  25. wbcompliance/filters/risk_management/tables.py +112 -0
  26. wbcompliance/filters/risk_management/utils.py +3 -0
  27. wbcompliance/management/__init__.py +10 -0
  28. wbcompliance/migrations/0001_initial_squashed_squashed_0010_alter_checkedobjectincidentrelationship_resolved_by_and_more.py +1744 -0
  29. wbcompliance/migrations/0011_alter_riskrule_parameters.py +21 -0
  30. wbcompliance/migrations/0012_alter_compliancetype_options.py +20 -0
  31. wbcompliance/migrations/0013_alter_riskrule_unique_together.py +16 -0
  32. wbcompliance/migrations/0014_alter_reviewcompliancetask_year.py +27 -0
  33. wbcompliance/migrations/0015_auto_20240103_0957.py +43 -0
  34. wbcompliance/migrations/0016_checkedobjectincidentrelationship_report_details_and_more.py +37 -0
  35. wbcompliance/migrations/0017_alter_rulebackend_incident_report_template.py +20 -0
  36. wbcompliance/migrations/0018_alter_rulecheckedobjectrelationship_unique_together.py +39 -0
  37. wbcompliance/migrations/0019_rulegroup_riskrule_activation_date_and_more.py +60 -0
  38. wbcompliance/migrations/__init__.py +0 -0
  39. wbcompliance/models/__init__.py +20 -0
  40. wbcompliance/models/compliance_form.py +626 -0
  41. wbcompliance/models/compliance_task.py +800 -0
  42. wbcompliance/models/compliance_type.py +133 -0
  43. wbcompliance/models/enums.py +13 -0
  44. wbcompliance/models/risk_management/__init__.py +4 -0
  45. wbcompliance/models/risk_management/backend.py +139 -0
  46. wbcompliance/models/risk_management/checks.py +194 -0
  47. wbcompliance/models/risk_management/dispatch.py +41 -0
  48. wbcompliance/models/risk_management/incidents.py +619 -0
  49. wbcompliance/models/risk_management/mixins.py +115 -0
  50. wbcompliance/models/risk_management/rules.py +654 -0
  51. wbcompliance/permissions.py +32 -0
  52. wbcompliance/serializers/__init__.py +30 -0
  53. wbcompliance/serializers/compliance_form.py +320 -0
  54. wbcompliance/serializers/compliance_task.py +463 -0
  55. wbcompliance/serializers/compliance_type.py +26 -0
  56. wbcompliance/serializers/risk_management/__init__.py +19 -0
  57. wbcompliance/serializers/risk_management/checks.py +53 -0
  58. wbcompliance/serializers/risk_management/incidents.py +227 -0
  59. wbcompliance/serializers/risk_management/rules.py +158 -0
  60. wbcompliance/tasks.py +112 -0
  61. wbcompliance/tests/__init__.py +0 -0
  62. wbcompliance/tests/conftest.py +63 -0
  63. wbcompliance/tests/disable_signals.py +82 -0
  64. wbcompliance/tests/mixins.py +17 -0
  65. wbcompliance/tests/risk_management/__init__.py +0 -0
  66. wbcompliance/tests/risk_management/models/__init__.py +0 -0
  67. wbcompliance/tests/risk_management/models/test_backends.py +0 -0
  68. wbcompliance/tests/risk_management/models/test_checks.py +55 -0
  69. wbcompliance/tests/risk_management/models/test_incidents.py +327 -0
  70. wbcompliance/tests/risk_management/models/test_rules.py +255 -0
  71. wbcompliance/tests/signals.py +89 -0
  72. wbcompliance/tests/test_filters.py +23 -0
  73. wbcompliance/tests/test_models.py +57 -0
  74. wbcompliance/tests/test_serializers.py +48 -0
  75. wbcompliance/tests/test_views.py +377 -0
  76. wbcompliance/tests/tests.py +21 -0
  77. wbcompliance/urls.py +238 -0
  78. wbcompliance/viewsets/__init__.py +40 -0
  79. wbcompliance/viewsets/buttons/__init__.py +9 -0
  80. wbcompliance/viewsets/buttons/compliance_form.py +78 -0
  81. wbcompliance/viewsets/buttons/compliance_task.py +149 -0
  82. wbcompliance/viewsets/buttons/risk_managment/__init__.py +3 -0
  83. wbcompliance/viewsets/buttons/risk_managment/checks.py +11 -0
  84. wbcompliance/viewsets/buttons/risk_managment/incidents.py +51 -0
  85. wbcompliance/viewsets/buttons/risk_managment/rules.py +35 -0
  86. wbcompliance/viewsets/compliance_form.py +425 -0
  87. wbcompliance/viewsets/compliance_task.py +513 -0
  88. wbcompliance/viewsets/compliance_type.py +38 -0
  89. wbcompliance/viewsets/display/__init__.py +22 -0
  90. wbcompliance/viewsets/display/compliance_form.py +317 -0
  91. wbcompliance/viewsets/display/compliance_task.py +453 -0
  92. wbcompliance/viewsets/display/compliance_type.py +22 -0
  93. wbcompliance/viewsets/display/risk_managment/__init__.py +11 -0
  94. wbcompliance/viewsets/display/risk_managment/checks.py +46 -0
  95. wbcompliance/viewsets/display/risk_managment/incidents.py +155 -0
  96. wbcompliance/viewsets/display/risk_managment/rules.py +146 -0
  97. wbcompliance/viewsets/display/risk_managment/tables.py +51 -0
  98. wbcompliance/viewsets/endpoints/__init__.py +27 -0
  99. wbcompliance/viewsets/endpoints/compliance_form.py +207 -0
  100. wbcompliance/viewsets/endpoints/compliance_task.py +193 -0
  101. wbcompliance/viewsets/endpoints/compliance_type.py +9 -0
  102. wbcompliance/viewsets/endpoints/risk_managment/__init__.py +12 -0
  103. wbcompliance/viewsets/endpoints/risk_managment/checks.py +16 -0
  104. wbcompliance/viewsets/endpoints/risk_managment/incidents.py +36 -0
  105. wbcompliance/viewsets/endpoints/risk_managment/rules.py +32 -0
  106. wbcompliance/viewsets/endpoints/risk_managment/tables.py +14 -0
  107. wbcompliance/viewsets/menu/__init__.py +17 -0
  108. wbcompliance/viewsets/menu/compliance_form.py +49 -0
  109. wbcompliance/viewsets/menu/compliance_task.py +130 -0
  110. wbcompliance/viewsets/menu/compliance_type.py +17 -0
  111. wbcompliance/viewsets/menu/risk_management.py +56 -0
  112. wbcompliance/viewsets/risk_management/__init__.py +21 -0
  113. wbcompliance/viewsets/risk_management/checks.py +49 -0
  114. wbcompliance/viewsets/risk_management/incidents.py +204 -0
  115. wbcompliance/viewsets/risk_management/mixins.py +52 -0
  116. wbcompliance/viewsets/risk_management/rules.py +179 -0
  117. wbcompliance/viewsets/risk_management/tables.py +96 -0
  118. wbcompliance/viewsets/titles/__init__.py +17 -0
  119. wbcompliance/viewsets/titles/compliance_form.py +101 -0
  120. wbcompliance/viewsets/titles/compliance_task.py +60 -0
  121. wbcompliance/viewsets/titles/compliance_type.py +13 -0
  122. wbcompliance/viewsets/titles/risk_managment/__init__.py +1 -0
  123. wbcompliance/viewsets/titles/risk_managment/checks.py +0 -0
  124. wbcompliance/viewsets/titles/risk_managment/incidents.py +0 -0
  125. wbcompliance/viewsets/titles/risk_managment/rules.py +0 -0
  126. wbcompliance/viewsets/titles/risk_managment/tables.py +7 -0
  127. wbcompliance-2.2.1.dist-info/METADATA +7 -0
  128. wbcompliance-2.2.1.dist-info/RECORD +129 -0
  129. wbcompliance-2.2.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,30 @@
1
+ from .compliance_form import (
2
+ ComplianceFormModelSerializer,
3
+ ComplianceFormRepresentationSerializer,
4
+ ComplianceFormRuleModelSerializer,
5
+ ComplianceFormSectionModelSerializer,
6
+ ComplianceFormSectionRepresentationSerializer,
7
+ ComplianceFormSignatureModelSerializer,
8
+ ComplianceFormSignatureRuleModelSerializer,
9
+ ComplianceFormSignatureSectionRepresentationSerializer,
10
+ ComplianceFormTypeModelSerializer,
11
+ ComplianceFormTypeRepresentationSerializer,
12
+ )
13
+ from .compliance_task import (
14
+ ComplianceActionModelSerializer,
15
+ ComplianceEventModelSerializer,
16
+ ComplianceTaskGroupModelSerializer,
17
+ ComplianceTaskGroupRepresentationSerializer,
18
+ ComplianceTaskInstanceListModelSerializer,
19
+ ComplianceTaskInstanceModelSerializer,
20
+ ComplianceTaskModelSerializer,
21
+ ComplianceTaskRepresentationSerializer,
22
+ ComplianceTaskReviewModelSerializer,
23
+ ReviewComplianceTaskModelSerializer,
24
+ ReviewComplianceTaskRepresentationSerializer,
25
+ )
26
+ from .compliance_type import (
27
+ ComplianceTypeModelSerializer,
28
+ ComplianceTypeRepresentationSerializer,
29
+ )
30
+ from .risk_management import *
@@ -0,0 +1,320 @@
1
+ from django.utils import timezone
2
+ from django.utils.functional import cached_property
3
+ from django.utils.translation import gettext_lazy as _
4
+ from rest_framework import serializers
5
+ from rest_framework.reverse import reverse
6
+ from wbcompliance.models import (
7
+ ComplianceForm,
8
+ ComplianceFormRule,
9
+ ComplianceFormSection,
10
+ ComplianceFormSignature,
11
+ ComplianceFormSignatureRule,
12
+ ComplianceFormSignatureSection,
13
+ ComplianceFormType,
14
+ ComplianceType,
15
+ )
16
+ from wbcore import serializers as wb_serializers
17
+ from wbcore.contrib.authentication.serializers import GroupRepresentationSerializer
18
+ from wbcore.contrib.directory.models import Person
19
+ from wbcore.contrib.directory.serializers import PersonRepresentationSerializer
20
+ from wbcore.permissions.shortcuts import get_internal_groups
21
+
22
+ from .compliance_type import ComplianceTypeRepresentationSerializer
23
+
24
+
25
+ class ComplianceFormTypeRepresentationSerializer(wb_serializers.RepresentationSerializer):
26
+ class Meta:
27
+ model = ComplianceFormType
28
+ fields = ("id", "name", "type")
29
+
30
+
31
+ class ComplianceFormTypeModelSerializer(wb_serializers.ModelSerializer):
32
+ class Meta:
33
+ model = ComplianceFormType
34
+ fields = ("id", "name", "type")
35
+
36
+
37
+ # COMPLIANCE FORM
38
+ class ComplianceFormRepresentationSerializer(wb_serializers.RepresentationSerializer):
39
+ # _detail = wb_serializers.HyperlinkField(reverse_name="wbcompliance:complianceform-detail")
40
+ class Meta:
41
+ model = ComplianceForm
42
+ fields = (
43
+ "id",
44
+ "title",
45
+ "form_type",
46
+ "version",
47
+ "status",
48
+ "start",
49
+ "end",
50
+ )
51
+
52
+
53
+ class ComplianceFormModelSerializer(wb_serializers.ModelSerializer):
54
+ creator = wb_serializers.PrimaryKeyRelatedField(
55
+ default=wb_serializers.CurrentUserDefault("profile"),
56
+ many=False,
57
+ read_only=True,
58
+ )
59
+ start = wb_serializers.DateField(default=timezone.now().date(), label=_("Start"))
60
+ _creator = PersonRepresentationSerializer(source="creator")
61
+ _changer = PersonRepresentationSerializer(source="changer")
62
+ current_signed = wb_serializers.CharField(
63
+ label=_("Current Signed"),
64
+ read_only=True,
65
+ help_text=_("The number of signatures of the compliance form over the number of total to be signed"),
66
+ )
67
+ is_signed = wb_serializers.BooleanField(required=False, read_only=True)
68
+ _assigned_to = GroupRepresentationSerializer(source="assigned_to", many=True)
69
+ _form_type = ComplianceFormTypeRepresentationSerializer(source="form_type")
70
+ compliance_type = wb_serializers.PrimaryKeyRelatedField(
71
+ label=_("Administrator"), queryset=ComplianceType.objects.all()
72
+ )
73
+ _compliance_type = ComplianceTypeRepresentationSerializer(source="compliance_type")
74
+
75
+ @cached_property
76
+ def user_profile(self) -> Person | None:
77
+ if request := self.context.get("request"):
78
+ return request.user.profile
79
+ return None
80
+
81
+ class Meta:
82
+ model = ComplianceForm
83
+ fields = (
84
+ "id",
85
+ "creator",
86
+ "_creator",
87
+ "created",
88
+ "changer",
89
+ "_changer",
90
+ "changed",
91
+ "title",
92
+ "policy",
93
+ "status",
94
+ "version",
95
+ "_additional_resources",
96
+ "assigned_to",
97
+ "_assigned_to",
98
+ "is_signed",
99
+ "current_signed",
100
+ "only_internal",
101
+ "start",
102
+ "end",
103
+ "form_type",
104
+ "_form_type",
105
+ "compliance_type",
106
+ "_compliance_type",
107
+ )
108
+
109
+ read_only_fields = ("creator", "created", "changer", "changed", "version")
110
+
111
+ def create(self, validated_data):
112
+ validated_data["creator"] = self.user_profile
113
+ if len(validated_data["assigned_to"]) == 0:
114
+ validated_data["assigned_to"] = get_internal_groups()
115
+ return super().create(validated_data)
116
+
117
+ def update(self, instance, validated_data):
118
+ profile = self.user_profile
119
+ validated_data["changer"] = profile
120
+ validated_data.pop("creator", None)
121
+ validated_data.pop("created", None)
122
+ persons = validated_data.pop("assigned_to", None)
123
+
124
+ instance = super().update(instance, validated_data)
125
+
126
+ # now update manytomany field assigned_to
127
+ if persons is not None:
128
+ instance.assigned_to.clear()
129
+ for person in persons:
130
+ instance.assigned_to.add(person)
131
+ instance.save()
132
+
133
+ return instance
134
+
135
+ def validate(self, data):
136
+ obj = self.instance
137
+ start = data.get("start", obj.start if obj else None)
138
+ end = data.get("end", obj.end if obj else None)
139
+ title = data.get("title", obj.start if obj else None)
140
+ errors = {}
141
+ if not title:
142
+ errors["title"] = ["This field is required."]
143
+ if start and end:
144
+ if start > end:
145
+ errors["start"] = ["end date cannot be before start date"]
146
+ errors["end"] = ["end date cannot be before start date"]
147
+
148
+ if len(errors.keys()) > 0:
149
+ raise serializers.ValidationError(errors)
150
+
151
+ return data
152
+
153
+ @wb_serializers.register_resource()
154
+ def list_additional_resources(self, instance, request, user):
155
+ return {
156
+ "signatures": reverse(
157
+ "wbcompliance:complianceform-signatures-list",
158
+ args=[instance.id],
159
+ request=request,
160
+ ),
161
+ "sections": reverse(
162
+ "wbcompliance:complianceform-sections-list",
163
+ args=[instance.id],
164
+ request=request,
165
+ ),
166
+ }
167
+
168
+ @wb_serializers.register_only_instance_resource()
169
+ def instance_additional_resources(self, instance, request, user, view, **kwargs):
170
+ additional_resources = dict()
171
+ for section in ComplianceFormSection.objects.filter(compliance_form=instance.id).order_by("id"):
172
+ additional_resources[f"rules{section.id}"] = reverse(
173
+ "wbcompliance:complianceformsection-rules-list",
174
+ args=[section.id],
175
+ request=request,
176
+ )
177
+
178
+ if (
179
+ view.user_has_compliance_admin_permission
180
+ and instance.status == ComplianceForm.Status.ACTIVE
181
+ and hasattr(instance, "is_signed")
182
+ ):
183
+ if not instance.is_signed:
184
+ additional_resources["send_compliance_form_notification"] = reverse(
185
+ "wbcompliance:complianceform-sendcomplianceformnotification",
186
+ args=[instance.id],
187
+ request=request,
188
+ )
189
+ if view.user_has_compliance_admin_permission:
190
+ additional_resources["regenerate_document"] = reverse(
191
+ "wbcompliance:complianceform-regenerate-document", args=[instance.id], request=request
192
+ )
193
+ return additional_resources
194
+
195
+
196
+ # COMPLIANCE FORM SIGNATURE
197
+ class ComplianceFormSignatureModelSerializer(wb_serializers.ModelSerializer):
198
+ compliance_form = wb_serializers.PrimaryKeyRelatedField(read_only=True)
199
+ _compliance_form = ComplianceFormRepresentationSerializer(source="compliance_form")
200
+ person = wb_serializers.PrimaryKeyRelatedField(read_only=True)
201
+ _person = PersonRepresentationSerializer(source="person")
202
+ is_signed = wb_serializers.BooleanField(required=False, read_only=True)
203
+
204
+ class Meta:
205
+ model = ComplianceFormSignature
206
+ fields = (
207
+ "id",
208
+ "compliance_form",
209
+ "_compliance_form",
210
+ "version",
211
+ "start",
212
+ "end",
213
+ "policy",
214
+ "signed",
215
+ "person",
216
+ "_person",
217
+ "remark",
218
+ "is_signed",
219
+ "_additional_resources",
220
+ )
221
+
222
+ read_only_fields = ("compliance_form", "version", "policy", "person", "signed", "start", "end")
223
+
224
+ @wb_serializers.register_only_instance_resource()
225
+ def additional_resources(self, instance, request, user, **kwargs):
226
+ additional_resources = dict()
227
+ if not instance.signed and instance.person == user.profile:
228
+ additional_resources["signature"] = reverse(
229
+ "wbcompliance:complianceformsignature-signature",
230
+ args=[instance.id],
231
+ request=request,
232
+ )
233
+ for section in ComplianceFormSignatureSection.objects.filter(compliance_form_signature=instance.id).order_by(
234
+ "id"
235
+ ):
236
+ additional_resources[f"rules{section.id}"] = reverse(
237
+ "wbcompliance:complianceformsignaturesection-rules-list",
238
+ args=[section.id],
239
+ request=request,
240
+ )
241
+ if user.has_perm("wbcompliance.administrate_compliance") or user.profile == instance.person:
242
+ additional_resources["regenerate_document"] = reverse(
243
+ "wbcompliance:complianceformsignature-regenerate-document", args=[instance.id], request=request
244
+ )
245
+ return additional_resources
246
+
247
+
248
+ # SECION OF THE COMPLIANCE FORM
249
+ class ComplianceFormSectionRepresentationSerializer(wb_serializers.RepresentationSerializer):
250
+ class Meta:
251
+ model = ComplianceFormSection
252
+ fields = ("id", "name")
253
+
254
+
255
+ class ComplianceFormSectionModelSerializer(wb_serializers.ModelSerializer):
256
+ _compliance_form = ComplianceFormRepresentationSerializer(many=False, source="compliance_form")
257
+
258
+ class Meta:
259
+ model = ComplianceFormSection
260
+ fields = ("id", "name", "compliance_form", "_compliance_form", "_additional_resources")
261
+ read_only_fields = ("compliance_form",)
262
+
263
+ @wb_serializers.register_resource()
264
+ def additional_resources(self, instance, request, user):
265
+ additional_resources = dict()
266
+ additional_resources["rules"] = reverse(
267
+ "wbcompliance:complianceformsection-rules-list",
268
+ args=[instance.id],
269
+ request=request,
270
+ )
271
+ return additional_resources
272
+
273
+ def create(self, validated_data):
274
+ if request := self.context.get("request"):
275
+ compliance_form_id = request.data.get("compliance_form")
276
+ validated_data["compliance_form"] = ComplianceForm.objects.get(id=compliance_form_id)
277
+ else:
278
+ validated_data["compliance_form"] = None
279
+ return super().create(validated_data)
280
+
281
+
282
+ # RULES OF THE SECTION OF THE COMPLIANCE
283
+ class ComplianceFormRuleModelSerializer(wb_serializers.ModelSerializer):
284
+ _section = ComplianceFormSectionRepresentationSerializer(many=False, source="section")
285
+ text = wb_serializers.TextField(allow_null=False)
286
+
287
+ class Meta:
288
+ model = ComplianceFormRule
289
+ fields = ("id", "text", "ticked", "section", "_section")
290
+ read_only_fields = ("section",)
291
+
292
+ def create(self, validated_data):
293
+ if request := self.context.get("request"):
294
+ section_id = request.data.get("section")
295
+ validated_data["section"] = ComplianceFormSection.objects.get(id=section_id)
296
+ else:
297
+ validated_data["section"] = None
298
+ return super().create(validated_data)
299
+
300
+
301
+ # REPRESENTATION SECTION OF THE COMPLIANCE FORM SIGNATURE
302
+ class ComplianceFormSignatureSectionRepresentationSerializer(wb_serializers.RepresentationSerializer):
303
+ class Meta:
304
+ model = ComplianceFormSignatureSection
305
+ fields = ("id", "name")
306
+
307
+
308
+ # RULES OF THE SECTION OF THE COMPLIANCE FORM SIGNATURE
309
+ class ComplianceFormSignatureRuleModelSerializer(wb_serializers.ModelSerializer):
310
+ _section = ComplianceFormSignatureSectionRepresentationSerializer(many=False, source="section")
311
+ comments = wb_serializers.TextAreaField(label=_("Comments"), allow_blank=True, allow_null=True)
312
+
313
+ expected_result = wb_serializers.BooleanField(read_only=True)
314
+ same_answer = wb_serializers.BooleanField(read_only=True)
315
+
316
+ class Meta:
317
+ model = ComplianceFormSignatureRule
318
+ fields = ("id", "text", "ticked", "comments", "section", "_section", "expected_result", "same_answer")
319
+
320
+ read_only_fields = ("section", "text")