wbintegrator_office365 1.43.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 (42) hide show
  1. wbintegrator_office365/__init__.py +1 -0
  2. wbintegrator_office365/admin.py +209 -0
  3. wbintegrator_office365/apps.py +5 -0
  4. wbintegrator_office365/configurations/__init__.py +0 -0
  5. wbintegrator_office365/configurations/configurations/__init__.py +23 -0
  6. wbintegrator_office365/dynamic_preferences_registry.py +15 -0
  7. wbintegrator_office365/factories.py +102 -0
  8. wbintegrator_office365/filters.py +237 -0
  9. wbintegrator_office365/importer/__init__.py +3 -0
  10. wbintegrator_office365/importer/api.py +403 -0
  11. wbintegrator_office365/importer/disable_signals.py +43 -0
  12. wbintegrator_office365/importer/parser.py +135 -0
  13. wbintegrator_office365/kpi_handlers/__init__.py +1 -0
  14. wbintegrator_office365/kpi_handlers/calls.py +114 -0
  15. wbintegrator_office365/migrations/0001_initial_squashed_squashed_0003_alter_calendar_owner_alter_calendarevent_organizer_and_more.py +677 -0
  16. wbintegrator_office365/migrations/0002_remove_calendar_owner_remove_calendarevent_activity_and_more.py +85 -0
  17. wbintegrator_office365/migrations/0003_alter_event_options.py +20 -0
  18. wbintegrator_office365/migrations/__init__.py +0 -0
  19. wbintegrator_office365/models/__init__.py +3 -0
  20. wbintegrator_office365/models/event.py +623 -0
  21. wbintegrator_office365/models/subscription.py +144 -0
  22. wbintegrator_office365/models/tenant.py +62 -0
  23. wbintegrator_office365/serializers.py +266 -0
  24. wbintegrator_office365/tasks.py +108 -0
  25. wbintegrator_office365/templates/admin/tenant_change_list.html +12 -0
  26. wbintegrator_office365/tests/__init__.py +0 -0
  27. wbintegrator_office365/tests/conftest.py +28 -0
  28. wbintegrator_office365/tests/test_admin.py +86 -0
  29. wbintegrator_office365/tests/test_models.py +65 -0
  30. wbintegrator_office365/tests/test_tasks.py +318 -0
  31. wbintegrator_office365/tests/test_views.py +128 -0
  32. wbintegrator_office365/tests/tests.py +12 -0
  33. wbintegrator_office365/urls.py +46 -0
  34. wbintegrator_office365/viewsets/__init__.py +31 -0
  35. wbintegrator_office365/viewsets/display.py +306 -0
  36. wbintegrator_office365/viewsets/endpoints.py +52 -0
  37. wbintegrator_office365/viewsets/menu.py +65 -0
  38. wbintegrator_office365/viewsets/titles.py +49 -0
  39. wbintegrator_office365/viewsets/viewsets.py +745 -0
  40. wbintegrator_office365-1.43.1.dist-info/METADATA +10 -0
  41. wbintegrator_office365-1.43.1.dist-info/RECORD +42 -0
  42. wbintegrator_office365-1.43.1.dist-info/WHEEL +5 -0
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -0,0 +1,209 @@
1
+ from django.contrib import admin
2
+ from django.shortcuts import redirect
3
+ from django.urls import path
4
+ from wbcore.admin import ExportCsvMixin, ImportCsvMixin
5
+ from wbintegrator_office365.models.event import fetch_tenantusers
6
+ from wbintegrator_office365.models.subscription import (
7
+ resubscribe_as_task,
8
+ verification_subscriptions,
9
+ )
10
+
11
+ from .models import CallEvent, CallUser, Event, EventLog, Subscription, TenantUser
12
+
13
+
14
+ @admin.register(TenantUser)
15
+ class TenantUserAdmin(admin.ModelAdmin, ImportCsvMixin, ExportCsvMixin):
16
+ search_fields = ("tenant_id", "display_name", "mail", "phone", "profile__computed_str", "tenant_organization_id")
17
+ list_display = (
18
+ "tenant_id",
19
+ "display_name",
20
+ "mail",
21
+ "phone",
22
+ "profile",
23
+ "tenant_organization_id",
24
+ )
25
+ change_list_template = "admin/tenant_change_list.html"
26
+ list_filter = ("is_internal_organization",)
27
+ readonly_fields = ("is_internal_organization",)
28
+
29
+ def get_urls(self):
30
+ urls = super().get_urls()
31
+ my_urls = [path("fetch_tenantusers/", self._fetch_tenantusers)]
32
+ return my_urls + urls
33
+
34
+ def _fetch_tenantusers(self, request):
35
+ datum, count_added = fetch_tenantusers()
36
+ self.message_user(
37
+ request, str(len(datum)) + " tenants users found " + str(count_added) + " new tenants users added"
38
+ )
39
+ return redirect("..")
40
+
41
+
42
+ @admin.register(EventLog)
43
+ class EventLogAdmin(admin.ModelAdmin):
44
+ search_fields = ("id", "change_type", "last_event__resource", "last_event__subscription_id", "id_event")
45
+ list_display = (
46
+ "id",
47
+ "order_received",
48
+ "change_type",
49
+ "is_handled",
50
+ "resource",
51
+ "created",
52
+ "changed",
53
+ "last_event",
54
+ "id_event",
55
+ )
56
+ ordering = ["-id", "-order_received"]
57
+ list_filter = ("change_type", "created", "changed")
58
+
59
+
60
+ class EventLogTabularInline(admin.TabularInline):
61
+ model = EventLog
62
+ fields = ["id", "order_received", "change_type", "is_handled", "resource", "created", "changed"]
63
+ readonly_fields = ("id", "order_received", "change_type", "resource", "created", "changed")
64
+ extra = 0
65
+ autocomplete_fields = ["last_event"]
66
+ ordering = ["-id", "-order_received"]
67
+
68
+
69
+ @admin.register(Event)
70
+ class EventAdmin(admin.ModelAdmin):
71
+ search_fields = (
72
+ "id",
73
+ "id_event",
74
+ "resource",
75
+ "subscription_id",
76
+ "tenant_user__display_name",
77
+ "tenant_user__mail",
78
+ "tenant_user__phone",
79
+ "tenant_user__profile__computed_str",
80
+ "tenant_user__tenant_organization_id",
81
+ )
82
+ list_display = (
83
+ "id",
84
+ "auto_inc_id",
85
+ "nb_received",
86
+ "type",
87
+ "change_type",
88
+ "tenant_user",
89
+ "is_handled",
90
+ "created",
91
+ "changed",
92
+ "uuid_event",
93
+ "id_event",
94
+ "subscription_id",
95
+ )
96
+ raw_id_fields = ["tenant_user"]
97
+ ordering = ["-auto_inc_id"]
98
+ inlines = [EventLogTabularInline]
99
+ list_filter = ("type", "change_type", "created", "changed")
100
+
101
+
102
+ @admin.register(CallEvent)
103
+ class CallEventAdmin(admin.ModelAdmin):
104
+ search_fields = (
105
+ "id",
106
+ "event__id",
107
+ "organizer__tenant_user__display_name",
108
+ "organizer__tenant_user__mail",
109
+ "organizer__tenant_user__phone",
110
+ "organizer__tenant_user__profile__computed_str",
111
+ "organizer__tenant_user__tenant_organization_id",
112
+ )
113
+ list_display = (
114
+ "id",
115
+ "event",
116
+ "organizer",
117
+ "version",
118
+ "start",
119
+ "end",
120
+ "created",
121
+ "last_modified",
122
+ "is_internal_call",
123
+ )
124
+ list_filter = ("is_internal_call", "created", "last_modified", "start", "end")
125
+
126
+
127
+ @admin.register(CallUser)
128
+ class CallUserAdmin(admin.ModelAdmin):
129
+ search_fields = (
130
+ "tenant_user__display_name",
131
+ "tenant_user__mail",
132
+ "tenant_user__phone",
133
+ "tenant_user__profile__computed_str",
134
+ "tenant_user__tenant_organization_id",
135
+ )
136
+ list_display = ("id", "tenant_user", "is_guest", "is_phone")
137
+ list_filter = ("is_guest", "is_phone")
138
+
139
+
140
+ @admin.register(Subscription)
141
+ class SubscriptionAdmin(admin.ModelAdmin):
142
+ search_fields = (
143
+ "id",
144
+ "subscription_id",
145
+ "resource",
146
+ "tenant_user__display_name",
147
+ "tenant_user__mail",
148
+ "tenant_user__phone",
149
+ "tenant_user__profile__computed_str",
150
+ "tenant_user__tenant_organization_id",
151
+ )
152
+ list_display = (
153
+ "id",
154
+ "subscription_id",
155
+ "expiration_date",
156
+ "type_resource",
157
+ "tenant_user",
158
+ "is_enable",
159
+ "created",
160
+ "change_type",
161
+ "resource",
162
+ "notification_url",
163
+ )
164
+ list_filter = ("is_enable", "type_resource", "expiration_date", "created")
165
+
166
+ def disable_selected_subscriptions(self, request, queryset):
167
+ for subscription in queryset:
168
+ subscription.is_enable = False
169
+ subscription.save()
170
+
171
+ self.message_user(
172
+ request,
173
+ "Operation completed, we unsubscribe the subscriptions selected",
174
+ )
175
+
176
+ def verification_selected_subscriptions(self, request, queryset):
177
+ for subscription in queryset:
178
+ verification_subscriptions.delay(subscription.id)
179
+ self.message_user(
180
+ request,
181
+ "Verification completed for the subscriptions selected",
182
+ )
183
+
184
+ def renew_selected_subscriptions(self, request, queryset):
185
+ for subscription in queryset:
186
+ resubscribe_as_task.delay(subscription.id)
187
+ self.message_user(request, "Active subscriptions are renewed on microsoft")
188
+ return redirect("..")
189
+
190
+ actions = [disable_selected_subscriptions, verification_selected_subscriptions, renew_selected_subscriptions]
191
+
192
+ readonly_fields = [
193
+ "subscription_id",
194
+ "change_type",
195
+ "expiration_date",
196
+ "notification_url",
197
+ "resource",
198
+ "application_id",
199
+ "creator_id",
200
+ "client_state",
201
+ "latest_supported_tls_version",
202
+ "notification_content_type",
203
+ "odata_context",
204
+ "encryption_certificate_id",
205
+ "encryption_certificate",
206
+ "include_resource_data",
207
+ "notification_query_options",
208
+ "is_enable",
209
+ ]
@@ -0,0 +1,5 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class WbintegratorOffice365Config(AppConfig):
5
+ name = "wbintegrator_office365"
File without changes
@@ -0,0 +1,23 @@
1
+ from os import environ
2
+
3
+ from configurations import values
4
+
5
+
6
+ class Office365:
7
+ WBINTEGRATOR_OFFICE365_TENANT_ID = values.Value("", environ_prefix=None)
8
+ WBINTEGRATOR_OFFICE365_CLIENT_ID = values.Value("", environ_prefix=None)
9
+ WBINTEGRATOR_OFFICE365_CLIENT_SECRET = values.Value("", environ_prefix=None)
10
+ WBINTEGRATOR_OFFICE365_REDIRECT_URI = values.Value("", environ_prefix=None)
11
+ WBINTEGRATOR_OFFICE365_TOKEN_ENDPOINT = values.Value("", environ_prefix=None)
12
+ WBINTEGRATOR_OFFICE365_NOTIFICATION_URL = values.Value("", environ_prefix=None)
13
+ WBINTEGRATOR_OFFICE365_GRAPH_API_VERSION = values.Value("", environ_prefix=None)
14
+ WBINTEGRATOR_OFFICE365_AUTHORITY_PREFIX = values.Value("", environ_prefix=None)
15
+ WBINTEGRATOR_OFFICE365_GRAPH_URL_PREFIX = values.Value("", environ_prefix=None)
16
+
17
+ @property
18
+ def WBINTEGRATOR_OFFICE365_AUTHORITY(self):
19
+ return self.WBINTEGRATOR_OFFICE365_AUTHORITY_PREFIX + self.WBINTEGRATOR_OFFICE365_TENANT_ID
20
+
21
+ @property
22
+ def WBINTEGRATOR_OFFICE365_GRAPH_URL(self):
23
+ return self.WBINTEGRATOR_OFFICE365_GRAPH_URL_PREFIX + self.WBINTEGRATOR_OFFICE365_GRAPH_API_VERSION
@@ -0,0 +1,15 @@
1
+ from dynamic_preferences.preferences import Section
2
+ from dynamic_preferences.registries import global_preferences_registry
3
+ from dynamic_preferences.types import StringPreference
4
+
5
+ general = Section("wbintegrator_office365")
6
+
7
+
8
+ @global_preferences_registry.register
9
+ class AccesTokenPreference(StringPreference):
10
+ section = general
11
+ name = "access_token"
12
+ default = "0"
13
+
14
+ verbose_name = "Access Token"
15
+ help_text = "The access token obtained from subscriptions Microsoft for authentication"
@@ -0,0 +1,102 @@
1
+ import random
2
+
3
+ import factory
4
+ import pytz
5
+
6
+
7
+ class TenantUserFactory(factory.django.DjangoModelFactory):
8
+ class Meta:
9
+ model = "wbintegrator_office365.TenantUser"
10
+
11
+ tenant_id = factory.Sequence(lambda n: "user_tenant_%d" % n)
12
+ display_name = factory.Faker("name")
13
+ mail = factory.Faker("email")
14
+ phone = factory.Faker("phone_number")
15
+ profile = factory.SubFactory("wbcore.contrib.directory.factories.PersonFactory")
16
+ tenant_organization_id = factory.Faker("pystr")
17
+
18
+
19
+ class SubscriptionFactory(factory.django.DjangoModelFactory):
20
+ class Meta:
21
+ model = "wbintegrator_office365.Subscription"
22
+
23
+ subscription_id = factory.Sequence(lambda n: "subscription%d" % n)
24
+ expiration_date = factory.Faker("date_time_between", start_date="+2d", end_date="+3d", tzinfo=pytz.utc)
25
+ change_type = factory.Faker("pystr")
26
+ notification_url = factory.Faker("url")
27
+ resource = factory.Faker("uri")
28
+ application_id = factory.Faker("pystr")
29
+ creator_id = factory.Faker("pystr")
30
+ client_state = factory.Faker("pystr")
31
+ latest_supported_tls_version = factory.Faker("pystr")
32
+ notification_content_type = factory.Faker("pystr")
33
+ odata_context = factory.Faker("pystr")
34
+ encryption_certificate_id = factory.Faker("pystr")
35
+ encryption_certificate = factory.Faker("pystr")
36
+ include_resource_data = factory.Faker("pystr")
37
+ notification_query_options = factory.Faker("pystr")
38
+ tenant_user = factory.SubFactory(TenantUserFactory)
39
+
40
+
41
+ class EventFactory(factory.django.DjangoModelFactory):
42
+ class Meta:
43
+ model = "wbintegrator_office365.Event"
44
+
45
+ uuid_event = factory.Sequence(lambda n: "UID%d" % n)
46
+ id_event = factory.Sequence(lambda n: "ID%d" % n)
47
+ # type = "CALLRECORD"
48
+ subscription_id = factory.Sequence(lambda n: "subscription%d" % n)
49
+ # change_type = "CREATED" #"UPDATED"
50
+ resource = factory.Faker("uri")
51
+ tenant_user = factory.SubFactory(TenantUserFactory)
52
+
53
+
54
+ class EventLogFactory(factory.django.DjangoModelFactory):
55
+ class Meta:
56
+ model = "wbintegrator_office365.EventLog"
57
+
58
+ last_event = factory.SubFactory(EventFactory)
59
+ id_event = factory.Sequence(lambda n: "event%d" % n)
60
+
61
+
62
+ class CallUserFactory(factory.django.DjangoModelFactory):
63
+ class Meta:
64
+ model = "wbintegrator_office365.CallUser"
65
+
66
+ acs_user = factory.Faker("pystr")
67
+ splool_user = factory.Faker("pystr")
68
+ encrypted = factory.Faker("pystr")
69
+ on_premises = factory.Faker("pystr")
70
+ acs_application_instance = factory.Faker("pystr")
71
+ spool_application_instance = factory.Faker("pystr")
72
+ application_instance = factory.Faker("pystr")
73
+ application = factory.Faker("pystr")
74
+ device = factory.Faker("pystr")
75
+ tenant_user = factory.SubFactory(TenantUserFactory)
76
+ is_guest = factory.Faker("pybool")
77
+ is_phone = factory.Faker("pybool")
78
+
79
+
80
+ class CallEventFactory(factory.django.DjangoModelFactory):
81
+ class Meta:
82
+ model = "wbintegrator_office365.CallEvent"
83
+ django_get_or_create = ["activity"]
84
+
85
+ event = factory.SubFactory(EventFactory)
86
+ version = random.randint(1, 4)
87
+ type = factory.Faker("pystr")
88
+ start = factory.Faker("date_time_between", start_date="+2d", end_date="+3d", tzinfo=pytz.utc)
89
+ end = factory.Faker("date_time_between", start_date="+2d", end_date="+3d", tzinfo=pytz.utc)
90
+ last_modified = factory.Faker("date_time_between", start_date="+4d", end_date="+5d", tzinfo=pytz.utc)
91
+ join_web_url = factory.Faker("url")
92
+ organizer = factory.SubFactory(CallUserFactory)
93
+ activity = factory.SubFactory("wbcrm.factories.ActivityFactory")
94
+ is_internal_call = factory.Faker("pybool")
95
+
96
+ @factory.post_generation
97
+ def participants(self, create, extracted, **kwargs):
98
+ if not create:
99
+ return
100
+ if extracted:
101
+ for participant in extracted:
102
+ self.participants.add(participant)
@@ -0,0 +1,237 @@
1
+ from datetime import date, timedelta
2
+
3
+ from psycopg.types.range import DateRange
4
+ from wbcore import filters as wb_filters
5
+ from wbhuman_resources.models import EmployeeHumanResource
6
+ from wbintegrator_office365.models import (
7
+ CallEvent,
8
+ CallUser,
9
+ Event,
10
+ EventLog,
11
+ Subscription,
12
+ TenantUser,
13
+ )
14
+
15
+
16
+ class TenantUserFilter(wb_filters.FilterSet):
17
+ class Meta:
18
+ model = TenantUser
19
+ fields = {
20
+ "profile": ["exact"],
21
+ "display_name": ["exact", "icontains"],
22
+ "mail": ["exact", "icontains"],
23
+ "phone": ["exact", "icontains"],
24
+ "tenant_id": ["exact", "icontains"],
25
+ "tenant_organization_id": ["exact", "icontains"],
26
+ "is_internal_organization": ["exact"],
27
+ }
28
+
29
+
30
+ class SubscriptionFilter(wb_filters.FilterSet):
31
+ class Meta:
32
+ model = Subscription
33
+ fields = {
34
+ "change_type": ["exact", "icontains"],
35
+ "subscription_id": ["exact", "icontains"],
36
+ "expiration_date": ["lte", "gte"],
37
+ "type_resource": ["exact"],
38
+ "tenant_user": ["exact"],
39
+ "is_enable": ["exact"],
40
+ "created": ["lte", "gte"],
41
+ }
42
+
43
+
44
+ def current_year(field, request, view):
45
+ today = date.today()
46
+ return date(today.year, 1, 1)
47
+
48
+
49
+ class EventFilter(wb_filters.FilterSet):
50
+ created__gte = wb_filters.DateFilter(
51
+ label="Created",
52
+ lookup_expr="gte",
53
+ field_name="created",
54
+ method="created_filter",
55
+ default=current_year,
56
+ )
57
+
58
+ def created_filter(self, queryset, name, value):
59
+ if value:
60
+ return queryset.filter(created__gte=value)
61
+ return queryset
62
+
63
+ class Meta:
64
+ model = Event
65
+ fields = {
66
+ "id": ["exact"],
67
+ "nb_received": ["exact"],
68
+ "type": ["exact"],
69
+ "change_type": ["exact"],
70
+ "created": ["gte", "lte"],
71
+ "changed": ["gte", "lte"],
72
+ "tenant_user": ["exact"],
73
+ "subscription_id": ["icontains", "exact"],
74
+ "id_event": ["icontains", "exact"],
75
+ "is_handled": ["exact"],
76
+ }
77
+
78
+
79
+ class EventLogFilter(wb_filters.FilterSet):
80
+ class Meta:
81
+ model = EventLog
82
+ fields = {
83
+ "id": ["exact"],
84
+ "order_received": ["exact"],
85
+ "last_event": ["exact"],
86
+ "change_type": ["exact"],
87
+ "id_event": ["icontains", "exact"],
88
+ "created": ["gte", "lte"],
89
+ "changed": ["gte", "lte"],
90
+ }
91
+
92
+
93
+ class CallEventFilter(wb_filters.FilterSet):
94
+ change_type = wb_filters.CharFilter(label="Type", lookup_expr="icontains")
95
+ participants = wb_filters.ModelMultipleChoiceFilter(
96
+ label="Participants",
97
+ queryset=CallUser.objects.all(),
98
+ endpoint=CallUser.get_representation_endpoint(),
99
+ value_key=CallUser.get_representation_value_key(),
100
+ label_key=CallUser.get_representation_label_key(),
101
+ method="filter_participants",
102
+ )
103
+ start__gte = wb_filters.DateFilter(
104
+ label="Start",
105
+ lookup_expr="gte",
106
+ field_name="start",
107
+ method="start_filter",
108
+ default=current_year,
109
+ )
110
+
111
+ def filter_participants(self, queryset, name, value):
112
+ if value:
113
+ return queryset.filter(participants__in=value)
114
+ return queryset
115
+
116
+ def start_filter(self, queryset, name, value):
117
+ if value:
118
+ return queryset.filter(start__gte=value)
119
+ return queryset
120
+
121
+ class Meta:
122
+ model = CallEvent
123
+ fields = {
124
+ "event": ["exact"],
125
+ "organizer": ["exact"],
126
+ "start": ["gte", "exact", "lte"],
127
+ "end": ["gte", "exact", "lte"],
128
+ "created": ["gte", "exact", "lte"],
129
+ "is_internal_call": ["exact"],
130
+ }
131
+
132
+
133
+ class CallUserFilter(wb_filters.FilterSet):
134
+ name_user = wb_filters.CharFilter(label="Question", lookup_expr="icontains")
135
+ phone = wb_filters.CharFilter(label="Question", lookup_expr="icontains")
136
+ mail = wb_filters.CharFilter(label="Question", lookup_expr="icontains")
137
+
138
+ class Meta:
139
+ model = CallUser
140
+ fields = {
141
+ "tenant_user": ["exact"],
142
+ "is_phone": ["exact"],
143
+ "is_guest": ["exact"],
144
+ }
145
+
146
+
147
+ def previous_month(*args, **kwargs):
148
+ return date.today() - timedelta(days=30)
149
+
150
+
151
+ def next_day(*args, **kwargs):
152
+ return date.today() + timedelta(days=1)
153
+
154
+
155
+ class CallEventSummaryGraphFilter(wb_filters.FilterSet):
156
+ date_range = wb_filters.DateTimeRangeFilter(
157
+ method="filter_date_range",
158
+ label="Date Range",
159
+ required=True,
160
+ clearable=False,
161
+ default=lambda f, v, q: DateRange(previous_month(f, v, q), next_day(f, v, q)),
162
+ )
163
+
164
+ employee = wb_filters.ModelChoiceFilter(
165
+ label="Employee",
166
+ queryset=EmployeeHumanResource.objects.all(),
167
+ endpoint=EmployeeHumanResource.get_representation_endpoint(),
168
+ value_key=EmployeeHumanResource.get_representation_value_key(),
169
+ label_key=EmployeeHumanResource.get_representation_label_key(),
170
+ method="filter_employee",
171
+ )
172
+
173
+ call_type = wb_filters.ChoiceFilter(
174
+ label="Type of call",
175
+ choices=[("groupCall", "Group Call"), ("peerToPeer", "Peer To Peer")],
176
+ method="filter_call_type",
177
+ )
178
+
179
+ call_area = wb_filters.ChoiceFilter(
180
+ label="Call area",
181
+ choices=[("True", "Internal Call"), ("False", "External Call")],
182
+ method="filter_call_area",
183
+ )
184
+
185
+ compare_employee = wb_filters.ModelChoiceFilter(
186
+ label="Compare to an employee",
187
+ queryset=EmployeeHumanResource.objects.all(),
188
+ endpoint=EmployeeHumanResource.get_representation_endpoint(),
189
+ value_key=EmployeeHumanResource.get_representation_value_key(),
190
+ label_key=EmployeeHumanResource.get_representation_label_key(),
191
+ method="filter_compare_employee",
192
+ )
193
+
194
+ call_duration = wb_filters.NumberFilter(
195
+ label="Include calls of at least how many secondes", default=30, method="filter_call_duration", required=False
196
+ )
197
+
198
+ business_day_without_call = wb_filters.BooleanFilter(
199
+ label="Include business day without call", default=False, method="filter_business_day_without_call"
200
+ )
201
+
202
+ def filter_date_range(self, queryset, name, value):
203
+ if value:
204
+ return queryset.filter(start__gte=value.lower, end__lte=value.upper)
205
+ return queryset
206
+
207
+ def filter_employee(self, queryset, name, value):
208
+ if value:
209
+ return queryset.filter(
210
+ participants__tenant_user__profile__computed_str__icontains=value.profile.computed_str
211
+ )
212
+ return queryset
213
+
214
+ def filter_call_duration(self, queryset, name, value):
215
+ if value:
216
+ return queryset.filter(duration_seconds__gte=timedelta(seconds=float(value)))
217
+ return queryset
218
+
219
+ def filter_call_type(self, queryset, name, value):
220
+ if value:
221
+ return queryset.filter(type=value)
222
+ return queryset
223
+
224
+ def filter_call_area(self, queryset, name, value):
225
+ if value is not None:
226
+ return queryset.filter(is_internal_call=value)
227
+ return queryset
228
+
229
+ def filter_compare_employee(self, queryset, name, value):
230
+ return queryset
231
+
232
+ def filter_business_day_without_call(self, queryset, name, value):
233
+ return queryset
234
+
235
+ class Meta:
236
+ model = CallEvent
237
+ fields = {}
@@ -0,0 +1,3 @@
1
+ from .api import MicrosoftGraphAPI
2
+ from .disable_signals import DisableSignals
3
+ from .parser import parse