wbcompliance 1.59.0__py2.py3-none-any.whl → 1.59.2__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.
@@ -0,0 +1,39 @@
1
+ # Generated by Django 5.0.12 on 2025-11-28 09:18
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+ from django.db.models import Exists, OuterRef
6
+
7
+
8
+ def handle_data(apps, schema_editor):
9
+ CheckedObjectIncidentRelationship = apps.get_model('wbcompliance', 'CheckedObjectIncidentRelationship')
10
+ RiskIncident = apps.get_model('wbcompliance', 'RiskIncident')
11
+ CheckedObjectIncidentRelationship.objects.filter(incident__isnull=True).delete()
12
+ RiskIncident.objects.filter(checked_object_relationships__isnull=True).delete()
13
+ RiskIncident.objects.annotate(
14
+ is_precheck=Exists(CheckedObjectIncidentRelationship.objects.filter(incident=OuterRef("id"), rule_check__activator_id__isnull=False))
15
+ ).filter(is_precheck=True).update(precheck=True)
16
+
17
+ class Migration(migrations.Migration):
18
+
19
+ dependencies = [
20
+ ('wbcompliance', '0021_riskcheck_passive_check'),
21
+ ]
22
+
23
+ operations = [
24
+ migrations.AddField(
25
+ model_name='riskincident',
26
+ name='precheck',
27
+ field=models.BooleanField(default=False, help_text='If true, this incident was created during a precheck evaluation', verbose_name='Precheck Incident'),
28
+ ),
29
+ migrations.RunSQL(sql="SET CONSTRAINTS ALL IMMEDIATE;"),
30
+ migrations.RunPython(handle_data),
31
+ migrations.RunSQL(sql="SET CONSTRAINTS ALL DEFERRED;"),
32
+ migrations.AlterField(
33
+ model_name='checkedobjectincidentrelationship',
34
+ name='incident',
35
+ field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE,
36
+ related_name='checked_object_relationships', to='wbcompliance.riskincident'),
37
+ preserve_default=False,
38
+ ),
39
+ ]
@@ -1,6 +1,7 @@
1
1
  from contextlib import suppress
2
+ from datetime import date, timedelta
2
3
  from types import DynamicClassAttribute
3
- from typing import Self
4
+ from typing import Any, Self
4
5
 
5
6
  from celery import shared_task
6
7
  from django.contrib.contenttypes.fields import GenericForeignKey
@@ -8,12 +9,14 @@ from django.contrib.contenttypes.models import ContentType
8
9
  from django.db import models
9
10
  from django.template import Context, Template
10
11
  from django.utils.translation import gettext_lazy as _
12
+ from pandas._libs.tslibs.offsets import BDay
13
+ from psycopg.types.range import DateRange
11
14
  from wbcore.contrib.color.enums import WBColor
12
15
  from wbcore.contrib.icons import WBIcon
13
16
  from wbcore.models import WBModel
14
17
  from wbcore.utils.models import ComplexToStringMixin
15
18
 
16
- from .incidents import CheckedObjectIncidentRelationship
19
+ from .incidents import CheckedObjectIncidentRelationship, RiskIncident, RiskIncidentType
17
20
 
18
21
 
19
22
  class RiskCheckManager(models.Manager):
@@ -103,9 +106,13 @@ class RiskCheck(ComplexToStringMixin, WBModel):
103
106
  self.rule.checked_object_relationships.filter(
104
107
  checked_object_content_type=self.checked_object_content_type, checked_object_id=self.checked_object_id
105
108
  ).exists()
106
- or self.activator_id is not None
109
+ or self.precheck
107
110
  )
108
111
 
112
+ @property
113
+ def precheck(self) -> bool:
114
+ return self.activator_id is not None
115
+
109
116
  @property
110
117
  def previous_check(self) -> Self | None:
111
118
  """
@@ -130,6 +137,20 @@ class RiskCheck(ComplexToStringMixin, WBModel):
130
137
  self.checked_object_repr = str(self.checked_object)
131
138
  super().save(*args, **kwargs)
132
139
 
140
+ def delete(self, *args, **kwargs):
141
+ incidents = RiskIncident.all_objects.filter(
142
+ id__in=list(
143
+ CheckedObjectIncidentRelationship.objects.filter(rule_check_id=self.id).values_list(
144
+ "incident", flat=True
145
+ )
146
+ )
147
+ )
148
+ super().delete(*args, **kwargs)
149
+ # ensure that incident without subincidents are deleted automatically
150
+ for incident in incidents:
151
+ if not incident.checked_object_relationships.exists():
152
+ incident.delete()
153
+
133
154
  def compute_str(self) -> str:
134
155
  return _("{} - {}").format(
135
156
  self.checked_object,
@@ -167,7 +188,7 @@ class RiskCheck(ComplexToStringMixin, WBModel):
167
188
  # If the check is passive, we aggregated incident per breached object and return it for further processing
168
189
  if self.needs_incident:
169
190
  report = report_template.render(Context({"report_details": incident_result.report_details}))
170
- incident, created = self.rule.get_or_create_incident(
191
+ incident, created = self.get_or_create_incident(
171
192
  self.evaluation_date,
172
193
  incident_result.severity,
173
194
  incident_result.breached_object,
@@ -195,6 +216,68 @@ class RiskCheck(ComplexToStringMixin, WBModel):
195
216
  self.save()
196
217
  return incidents
197
218
 
219
+ def get_or_create_incident(
220
+ self,
221
+ evaluation_date: date,
222
+ incident_severity: "RiskIncidentType",
223
+ breached_object: Any,
224
+ breached_object_repr: str,
225
+ ) -> tuple[RiskIncident, bool]:
226
+ """
227
+ Utility function to get or create incident base on the given breached object
228
+
229
+ Args:
230
+ evaluation_date: The incident date
231
+ incident_severity: The incident severity
232
+ breached_object: The breached object (i.e. the object that triggers the incident)
233
+ breached_object_repr: Its string representation
234
+
235
+ Returns:
236
+ A tuple (incident, is_created)
237
+ """
238
+
239
+ # Consider that if an incident happens one business day in the future or past, it is continue
240
+ date_range = DateRange( # type: ignore
241
+ (evaluation_date - BDay(1)).date(), (evaluation_date + BDay(1)).date(), "[]"
242
+ )
243
+ incidents = RiskIncident.objects.filter(rule=self.rule, date_range__overlap=date_range, precheck=self.precheck)
244
+ if breached_object:
245
+ # If a breached_object is provided, we lookup over it
246
+ incidents = incidents.filter(
247
+ breached_content_type=ContentType.objects.get_for_model(breached_object),
248
+ breached_object_id=breached_object.id,
249
+ )
250
+ else:
251
+ # Otherwise, we lookup over its string representation. Might need to change as this is not very robust
252
+ incidents = incidents.filter(
253
+ breached_object_repr=breached_object_repr,
254
+ )
255
+ created = False
256
+ if incident := incidents.first():
257
+ incident.date_range = DateRange( # type: ignore
258
+ lower=incident.date_range.lower, upper=(evaluation_date + timedelta(days=1))
259
+ )
260
+ incident.severity = incident_severity
261
+ else:
262
+ incident = RiskIncident(
263
+ rule=self.rule,
264
+ date_range=DateRange(lower=evaluation_date, upper=(evaluation_date + timedelta(days=1))), # type: ignore
265
+ breached_content_type=ContentType.objects.get_for_model(breached_object) if breached_object else None,
266
+ breached_object_id=breached_object.id if breached_object else None,
267
+ breached_object_repr=breached_object_repr,
268
+ severity=incident_severity,
269
+ status=RiskIncident.Status.OPEN,
270
+ )
271
+ created = True
272
+
273
+ if self.rule.automatically_close_incident:
274
+ incident.status = RiskIncident.Status.CLOSED
275
+ elif self.precheck:
276
+ incident.status = RiskIncident.Status.IGNORED
277
+ incident.precheck = self.precheck
278
+ incident.save()
279
+ return incident, created
280
+
198
281
  class Meta:
199
282
  verbose_name = "Risk Check"
200
283
  verbose_name_plural = "Risk Checks"
@@ -112,9 +112,7 @@ class CheckedObjectIncidentRelationship(ComplexToStringMixin, RiskIncidentMixin)
112
112
  incident = models.ForeignKey(
113
113
  to="wbcompliance.RiskIncident",
114
114
  related_name="checked_object_relationships",
115
- null=True,
116
- blank=True,
117
- on_delete=models.SET_NULL,
115
+ on_delete=models.CASCADE,
118
116
  )
119
117
 
120
118
  rule_check = models.ForeignKey(
@@ -248,8 +246,12 @@ class CheckedObjectIncidentRelationship(ComplexToStringMixin, RiskIncidentMixin)
248
246
 
249
247
 
250
248
  class RiskIncidentDefaultManager(models.Manager):
249
+ def __init__(self, only_passive_checks: bool = True):
250
+ self.only_passive_checks = only_passive_checks
251
+ super().__init__()
252
+
251
253
  def get_queryset(self):
252
- return (
254
+ qs = (
253
255
  super()
254
256
  .get_queryset()
255
257
  .annotate(
@@ -259,6 +261,9 @@ class RiskIncidentDefaultManager(models.Manager):
259
261
  ignore_until=TruncDate("ignore_until_time"),
260
262
  )
261
263
  )
264
+ if self.only_passive_checks:
265
+ qs = qs.filter(precheck=False)
266
+ return qs
262
267
 
263
268
 
264
269
  class RiskIncident(ComplexToStringMixin, RiskIncidentMixin):
@@ -297,6 +302,11 @@ class RiskIncident(ComplexToStringMixin, RiskIncidentMixin):
297
302
  ignore_duration = models.DurationField(
298
303
  blank=True, null=True, help_text=_("If set, will ignore the forthcoming incidents for the specified duration")
299
304
  )
305
+ precheck = models.BooleanField(
306
+ default=False,
307
+ verbose_name=_("Precheck Incident"),
308
+ help_text="If true, this incident was created during a precheck evaluation",
309
+ )
300
310
 
301
311
  def get_ignore_until_date(self) -> date | None:
302
312
  if self.last_ignored_date and self.ignore_duration:
@@ -367,6 +377,7 @@ class RiskIncident(ComplexToStringMixin, RiskIncidentMixin):
367
377
  return dict()
368
378
 
369
379
  objects = RiskIncidentDefaultManager()
380
+ all_objects = RiskIncidentDefaultManager(only_passive_checks=False)
370
381
 
371
382
  class Meta:
372
383
  verbose_name = "Risk Incident"
@@ -22,7 +22,6 @@ from django.template.loader import get_template
22
22
  from django.utils.functional import cached_property
23
23
  from django.utils.translation import gettext_lazy as _
24
24
  from pandas.tseries.offsets import BDay
25
- from psycopg.types.range import DateRange
26
25
  from rest_framework.reverse import reverse
27
26
  from wbcore.contrib.directory.models import Person
28
27
  from wbcore.contrib.guardian.models.mixins import PermissionObjectModelMixin
@@ -33,7 +32,7 @@ from wbcore.utils.rrules import convert_rrulestr_to_dict
33
32
 
34
33
  from .backend import AbstractRuleBackend
35
34
  from .checks import RiskCheck
36
- from .incidents import CheckedObjectIncidentRelationship, RiskIncident, RiskIncidentType
35
+ from .incidents import CheckedObjectIncidentRelationship, RiskIncident
37
36
 
38
37
  User: BaseUser = get_user_model()
39
38
 
@@ -511,69 +510,6 @@ class RiskRule(PermissionObjectModelMixin, WBModel):
511
510
 
512
511
  return permissions
513
512
 
514
- def get_or_create_incident(
515
- self,
516
- evaluation_date: date,
517
- incident_severity: "RiskIncidentType",
518
- breached_object: Any,
519
- breached_object_repr: str,
520
- ) -> tuple[RiskIncident, bool]:
521
- """
522
- Utility function to get or create incident base on the given breached object
523
-
524
- Args:
525
- rule: The rule this incident happens
526
- evaluation_date: The incident date
527
- incident_severity: The incident severity
528
- breached_object: The breached object (i.e. the object that triggers the incident)
529
- breached_object_repr: Its string representation
530
-
531
- Returns:
532
- A tuple (incident, is_created)
533
- """
534
-
535
- # Consider that if an incident happens one business day in the future or past, it is continue
536
- date_range = DateRange( # type: ignore
537
- (evaluation_date - BDay(1)).date(), (evaluation_date + BDay(1)).date(), "[]"
538
- )
539
- incidents = RiskIncident.objects.filter(rule=self, date_range__overlap=date_range)
540
- if breached_object:
541
- # If a breached_object is provided, we lookup over it
542
- incidents = incidents.filter(
543
- breached_content_type=ContentType.objects.get_for_model(breached_object),
544
- breached_object_id=breached_object.id,
545
- )
546
- else:
547
- # Otherwise, we lookup over its string representation. Might need to change as this is not very robust
548
- incidents = incidents.filter(
549
- breached_object_repr=breached_object_repr,
550
- )
551
- if incident := incidents.first():
552
- incident.date_range = DateRange(
553
- lower=incident.date_range.lower, upper=(evaluation_date + timedelta(days=1))
554
- ) # type: ignore
555
- if self.automatically_close_incident:
556
- incident.status = RiskIncident.Status.CLOSED
557
- incident.save()
558
- return incident, False
559
- else:
560
- return (
561
- RiskIncident.objects.create(
562
- rule=self,
563
- date_range=DateRange(lower=evaluation_date, upper=(evaluation_date + timedelta(days=1))), # type: ignore
564
- breached_content_type=ContentType.objects.get_for_model(breached_object)
565
- if breached_object
566
- else None,
567
- breached_object_id=breached_object.id if breached_object else None,
568
- breached_object_repr=breached_object_repr,
569
- severity=incident_severity,
570
- status=RiskIncident.Status.CLOSED
571
- if self.automatically_close_incident
572
- else RiskIncident.Status.OPEN,
573
- ),
574
- True,
575
- )
576
-
577
513
  def notify(self, evaluation_date: date):
578
514
  """
579
515
  Create the notification for this rule relationship and all implied persons
@@ -662,7 +598,7 @@ class RiskRule(PermissionObjectModelMixin, WBModel):
662
598
  def pre_save_risk_threshold(sender, instance, **kwargs):
663
599
  with suppress(RuleThreshold.DoesNotExist):
664
600
  pre_save_instance = RuleThreshold.objects.get(id=instance.id)
665
- RiskIncident.objects.filter(rule=instance.rule, severity=pre_save_instance.severity).update(
601
+ RiskIncident.all_objects.filter(rule=instance.rule, severity=pre_save_instance.severity).update(
666
602
  severity=instance.severity
667
603
  )
668
604
  CheckedObjectIncidentRelationship.objects.filter(
@@ -672,7 +608,7 @@ def pre_save_risk_threshold(sender, instance, **kwargs):
672
608
 
673
609
  @receiver(pre_delete, sender="wbcompliance.RuleThreshold")
674
610
  def pre_delete_risk_threshold(sender, instance, **kwargs):
675
- RiskIncident.objects.filter(rule=instance.rule, severity=instance.severity).delete()
611
+ RiskIncident.all_objects.filter(rule=instance.rule, severity=instance.severity).delete()
676
612
  CheckedObjectIncidentRelationship.objects.filter(incident__rule=instance.rule, severity=instance.severity).delete()
677
613
 
678
614
 
@@ -85,7 +85,7 @@ class TestRiskIncidentFactory:
85
85
  (fake.date_object(), False),
86
86
  ],
87
87
  )
88
- def test_get_or_create_incident(self, risk_rule, risk_incident_type, evaluation_date, is_breached_object):
88
+ def test_get_or_create_incident(self, risk_check, risk_incident_type, evaluation_date, is_breached_object):
89
89
  if is_breached_object:
90
90
  breached_object = get_anonymous_user()
91
91
  breached_object_repr = str(get_anonymous_user())
@@ -94,11 +94,11 @@ class TestRiskIncidentFactory:
94
94
  breached_object_repr = fake.text(max_nb_chars=125)
95
95
 
96
96
  assert not RiskIncident.objects.exists()
97
- risk_rule.get_or_create_incident(evaluation_date, risk_incident_type, breached_object, breached_object_repr)
97
+ risk_check.get_or_create_incident(evaluation_date, risk_incident_type, breached_object, breached_object_repr)
98
98
  if breached_object:
99
99
  assert (
100
100
  RiskIncident.objects.filter(
101
- rule=risk_rule,
101
+ rule=risk_check.rule,
102
102
  date_range__contains=evaluation_date,
103
103
  breached_content_type=ContentType.objects.get_for_model(breached_object),
104
104
  breached_object_id=breached_object.id,
@@ -108,19 +108,21 @@ class TestRiskIncidentFactory:
108
108
  else:
109
109
  assert (
110
110
  RiskIncident.objects.filter(
111
- rule=risk_rule, date_range__contains=evaluation_date, breached_object_repr=breached_object_repr
111
+ rule=risk_check.rule,
112
+ date_range__contains=evaluation_date,
113
+ breached_object_repr=breached_object_repr,
112
114
  ).count()
113
115
  == 1
114
116
  )
115
117
  assert RiskIncident.objects.count() == 1
116
118
  # Check if we reevaluate this incident one business day later, the incident is consider the same
117
- risk_rule.get_or_create_incident(
119
+ risk_check.get_or_create_incident(
118
120
  (evaluation_date + BDay(1)).date(), risk_incident_type, breached_object, breached_object_repr
119
121
  )
120
122
  assert RiskIncident.objects.count() == 1
121
123
 
122
124
  # Check if we reevaluate this incident three business day later, the incident is consider the discontinue, and then a new incident is created
123
- risk_rule.get_or_create_incident(
125
+ risk_check.get_or_create_incident(
124
126
  (evaluation_date + BDay(3)).date(), risk_incident_type, breached_object, breached_object_repr
125
127
  )
126
128
 
@@ -135,7 +137,7 @@ class TestRiskIncidentFactory:
135
137
  risk_incident.save()
136
138
  assert risk_incident.status == RiskIncident.Status.RESOLVED
137
139
  new_evaluation_date = subincident.rule_check.evaluation_date + timedelta(days=1)
138
- incident, created = risk_incident.rule.get_or_create_incident(
140
+ incident, created = subincident.rule_check.get_or_create_incident(
139
141
  new_evaluation_date,
140
142
  subincident.severity,
141
143
  risk_incident.breached_content_object,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbcompliance
3
- Version: 1.59.0
3
+ Version: 1.59.2
4
4
  Summary: A workbench module for managing compliance.
5
5
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
6
6
  Requires-Dist: wbcore
@@ -47,6 +47,7 @@ wbcompliance/migrations/0018_alter_rulecheckedobjectrelationship_unique_together
47
47
  wbcompliance/migrations/0019_rulegroup_riskrule_activation_date_and_more.py,sha256=OZsIfILAl1u2dTLd_kffTov5US3HWOtkeoXyHodjQQ0,2011
48
48
  wbcompliance/migrations/0020_rename_trigger_content_type_riskcheck_checked_object_content_type_and_more.py,sha256=XZVSSrk-71tSp9_VO6M0S9jaFJy5azyJEMYvO7e_Ut8,3135
49
49
  wbcompliance/migrations/0021_riskcheck_passive_check.py,sha256=8P0ELPz-_UmnBOY_AyjkAtRJyXD9AOqYUhUB_9FW27Y,836
50
+ wbcompliance/migrations/0022_riskincident_precheck.py,sha256=H2l9REAsogn7EsUMWcE_A7ldZ6QUZ9UnfhhJpioyyhk,1756
50
51
  wbcompliance/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
52
  wbcompliance/models/__init__.py,sha256=gk3D0yZ3ZpJh1Nl-Kyc1PWm67t0Gj7t47Jl2xm9Lisk,534
52
53
  wbcompliance/models/compliance_form.py,sha256=6xWJ5cEt0mfNsZjLYXI8GcP1Jb4MsFsvPhtVITmE0yI,24879
@@ -55,11 +56,11 @@ wbcompliance/models/compliance_type.py,sha256=Euevn9BRt7_R7lv49kTDlkMoL1uTQuUKWn
55
56
  wbcompliance/models/enums.py,sha256=id1m8trG7b6Sw3Sa9VrLgD104GC2nG9A8ngJzaRqIIQ,424
56
57
  wbcompliance/models/risk_management/__init__.py,sha256=DJXoHheA5REDpPYP0uyRmFWyNKP-ir_z5YB61CN6N-E,247
57
58
  wbcompliance/models/risk_management/backend.py,sha256=pbszChXMxA36JjK0nIkrz0k7w9ImKUTGMVlokgA1R-w,4736
58
- wbcompliance/models/risk_management/checks.py,sha256=S9MkG3kmMzixx9bi2P2SEREj9b25dstiPeThGx6jeHI,8601
59
+ wbcompliance/models/risk_management/checks.py,sha256=cVDSiHd41y0HBp6ujNvRqvWcruYmi_gByZdj3CEYMIA,12143
59
60
  wbcompliance/models/risk_management/dispatch.py,sha256=cLi63vSGbk9xhCoVgr4UmVk2kfYmGiyohKINSvCodb0,1423
60
- wbcompliance/models/risk_management/incidents.py,sha256=RNYjsFK87JLUByF4hcWk5W8eYL6sdlojfPuLdXCgYcE,23803
61
+ wbcompliance/models/risk_management/incidents.py,sha256=4xKTDvhfruWJEZ7axgnKW2_sbUbtchjnLerjZVq4Uzg,24267
61
62
  wbcompliance/models/risk_management/mixins.py,sha256=KsdjpM1Cl235z8h57USVcYSBKtO2VRH1S0FCuJOEMH0,3762
62
- wbcompliance/models/risk_management/rules.py,sha256=u6Mo2jxojY1EEJ2-3TaAKB4OXz9s4AF8sQCE0wc0x8Q,28507
63
+ wbcompliance/models/risk_management/rules.py,sha256=ra7XkBuDCPknTCamEIdRhxSs6Fo1P9tJnvhjTT7xZ8g,25660
63
64
  wbcompliance/serializers/__init__.py,sha256=OhRIuUrexqQePCISpu-BKry9dfioYGfpO8RwlcwhHtI,1122
64
65
  wbcompliance/serializers/compliance_form.py,sha256=OxPILlup_CP4Qwvu864oMqz7QUZsk2QOkOGFifWP3gM,11615
65
66
  wbcompliance/serializers/compliance_task.py,sha256=euTQya2LdexoRblew9zMkv40kU7wkW9nU2uLTI-lwow,17035
@@ -86,7 +87,7 @@ wbcompliance/tests/risk_management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
86
87
  wbcompliance/tests/risk_management/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
88
  wbcompliance/tests/risk_management/models/test_backends.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
89
  wbcompliance/tests/risk_management/models/test_checks.py,sha256=F4Pbn7q4PBmWx5fjvkwEclioG1mEt2M53maegSI9hYU,2467
89
- wbcompliance/tests/risk_management/models/test_incidents.py,sha256=wy7dkm1c2klnU_FUzDuz2i3oVWMbqoJ2zHiMTxQIbIY,15046
90
+ wbcompliance/tests/risk_management/models/test_incidents.py,sha256=BYhBbD6M83poo5VrLzULG9xXpbtOlw9ObhzLwm31KAE,15107
90
91
  wbcompliance/tests/risk_management/models/test_rules.py,sha256=j3g2gK6SV0F9a7U2eh2bEzPLI2wtZZoueQpzH6NTxpw,11177
91
92
  wbcompliance/viewsets/__init__.py,sha256=JVv3mT5i-9dSYIC_lrvJqcFCPI92KQp9AZ21lR-eqEg,1498
92
93
  wbcompliance/viewsets/compliance_form.py,sha256=2DKB72gzHQ9W3P3n7Al50awVLhMKBfkEEUZeMHASfGw,17295
@@ -137,6 +138,6 @@ wbcompliance/viewsets/titles/risk_managment/checks.py,sha256=47DEQpj8HBSa-_TImW-
137
138
  wbcompliance/viewsets/titles/risk_managment/incidents.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
139
  wbcompliance/viewsets/titles/risk_managment/rules.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
140
  wbcompliance/viewsets/titles/risk_managment/tables.py,sha256=x_9mr6JWZ9GVNAEvfdNCeFZtGGYSG0-sXrR9pwTyocU,256
140
- wbcompliance-1.59.0.dist-info/METADATA,sha256=8RXxxWBjoI56DxAGyX25eIMnOEs3K2PE9mTgUdIUzWI,196
141
- wbcompliance-1.59.0.dist-info/WHEEL,sha256=aha0VrrYvgDJ3Xxl3db_g_MDIW-ZexDdrc_m-Hk8YY4,105
142
- wbcompliance-1.59.0.dist-info/RECORD,,
141
+ wbcompliance-1.59.2.dist-info/METADATA,sha256=sJhCLSF5pLurkOr1QX4OWQ_FpidTrpJdF4gs1d8Tb-8,196
142
+ wbcompliance-1.59.2.dist-info/WHEEL,sha256=aha0VrrYvgDJ3Xxl3db_g_MDIW-ZexDdrc_m-Hk8YY4,105
143
+ wbcompliance-1.59.2.dist-info/RECORD,,