wbintegrator_office365 1.43.1__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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