wbcrm 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.
Potentially problematic release.
This version of wbcrm might be problematic. Click here for more details.
- wbcrm/__init__.py +1 -0
- wbcrm/admin/__init__.py +4 -0
- wbcrm/admin/accounts.py +59 -0
- wbcrm/admin/activities.py +101 -0
- wbcrm/admin/groups.py +7 -0
- wbcrm/admin/products.py +8 -0
- wbcrm/apps.py +5 -0
- wbcrm/configurations/__init__.py +1 -0
- wbcrm/configurations/base.py +16 -0
- wbcrm/dynamic_preferences_registry.py +38 -0
- wbcrm/factories/__init__.py +14 -0
- wbcrm/factories/accounts.py +56 -0
- wbcrm/factories/activities.py +125 -0
- wbcrm/factories/groups.py +23 -0
- wbcrm/factories/products.py +10 -0
- wbcrm/filters/__init__.py +10 -0
- wbcrm/filters/accounts.py +67 -0
- wbcrm/filters/activities.py +181 -0
- wbcrm/filters/groups.py +20 -0
- wbcrm/filters/products.py +37 -0
- wbcrm/filters/signals.py +94 -0
- wbcrm/migrations/0001_initial_squashed_squashed_0032_productcompanyrelationship_alter_product_prospects_and_more.py +3948 -0
- wbcrm/migrations/0002_alter_activity_repeat_choice.py +32 -0
- wbcrm/migrations/0003_remove_activity_external_id_and_more.py +63 -0
- wbcrm/migrations/0004_alter_activity_status.py +28 -0
- wbcrm/migrations/0005_account_accountrole_accountroletype_and_more.py +182 -0
- wbcrm/migrations/0006_alter_activity_location.py +17 -0
- wbcrm/migrations/0007_alter_account_status.py +23 -0
- wbcrm/migrations/0008_alter_activity_options.py +16 -0
- wbcrm/migrations/0009_alter_account_is_public.py +19 -0
- wbcrm/migrations/0010_alter_account_reference_id.py +17 -0
- wbcrm/migrations/0011_activity_summary.py +22 -0
- wbcrm/migrations/0012_alter_activity_summary.py +17 -0
- wbcrm/migrations/0013_account_action_plan_account_relationship_status_and_more.py +34 -0
- wbcrm/migrations/0014_alter_account_relationship_status.py +24 -0
- wbcrm/migrations/0015_alter_activity_type.py +23 -0
- wbcrm/migrations/0016_auto_20241205_1015.py +106 -0
- wbcrm/migrations/__init__.py +0 -0
- wbcrm/models/__init__.py +4 -0
- wbcrm/models/accounts.py +637 -0
- wbcrm/models/activities.py +1335 -0
- wbcrm/models/groups.py +118 -0
- wbcrm/models/products.py +83 -0
- wbcrm/models/recurrence.py +279 -0
- wbcrm/preferences.py +14 -0
- wbcrm/serializers/__init__.py +23 -0
- wbcrm/serializers/accounts.py +126 -0
- wbcrm/serializers/activities.py +526 -0
- wbcrm/serializers/groups.py +30 -0
- wbcrm/serializers/products.py +57 -0
- wbcrm/serializers/recurrence.py +90 -0
- wbcrm/serializers/signals.py +70 -0
- wbcrm/synchronization/__init__.py +0 -0
- wbcrm/synchronization/activity/__init__.py +0 -0
- wbcrm/synchronization/activity/admin.py +72 -0
- wbcrm/synchronization/activity/backend.py +207 -0
- wbcrm/synchronization/activity/backends/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/google/__init__.py +2 -0
- wbcrm/synchronization/activity/backends/google/google_calendar_backend.py +399 -0
- wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
- wbcrm/synchronization/activity/backends/google/tasks.py +21 -0
- wbcrm/synchronization/activity/backends/google/tests/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/google/tests/conftest.py +1 -0
- wbcrm/synchronization/activity/backends/google/tests/test_data.py +81 -0
- wbcrm/synchronization/activity/backends/google/tests/test_google_backend.py +319 -0
- wbcrm/synchronization/activity/backends/google/tests/test_utils.py +274 -0
- wbcrm/synchronization/activity/backends/google/typing_informations.py +139 -0
- wbcrm/synchronization/activity/backends/google/utils.py +216 -0
- wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/outlook/backend.py +576 -0
- wbcrm/synchronization/activity/backends/outlook/msgraph.py +438 -0
- wbcrm/synchronization/activity/backends/outlook/parser.py +423 -0
- wbcrm/synchronization/activity/backends/outlook/tests/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/outlook/tests/conftest.py +1 -0
- wbcrm/synchronization/activity/backends/outlook/tests/fixtures.py +606 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_admin.py +117 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +269 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +237 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +173 -0
- wbcrm/synchronization/activity/controller.py +545 -0
- wbcrm/synchronization/activity/dynamic_preferences_registry.py +107 -0
- wbcrm/synchronization/activity/preferences.py +21 -0
- wbcrm/synchronization/activity/shortcuts.py +9 -0
- wbcrm/synchronization/activity/signals.py +28 -0
- wbcrm/synchronization/activity/tasks.py +21 -0
- wbcrm/synchronization/activity/urls.py +6 -0
- wbcrm/synchronization/activity/utils.py +46 -0
- wbcrm/synchronization/activity/views.py +37 -0
- wbcrm/synchronization/admin.py +1 -0
- wbcrm/synchronization/apps.py +15 -0
- wbcrm/synchronization/dynamic_preferences_registry.py +1 -0
- wbcrm/synchronization/management.py +36 -0
- wbcrm/synchronization/tasks.py +1 -0
- wbcrm/synchronization/urls.py +5 -0
- wbcrm/tasks.py +312 -0
- wbcrm/tests/__init__.py +0 -0
- wbcrm/tests/accounts/__init__.py +0 -0
- wbcrm/tests/accounts/test_models.py +380 -0
- wbcrm/tests/accounts/test_viewsets.py +87 -0
- wbcrm/tests/conftest.py +76 -0
- wbcrm/tests/disable_signals.py +52 -0
- wbcrm/tests/e2e/__init__.py +1 -0
- wbcrm/tests/e2e/e2e_wbcrm_utility.py +82 -0
- wbcrm/tests/e2e/test_e2e.py +369 -0
- wbcrm/tests/test_assignee_methods.py +39 -0
- wbcrm/tests/test_chartviewsets.py +111 -0
- wbcrm/tests/test_dto.py +63 -0
- wbcrm/tests/test_filters.py +51 -0
- wbcrm/tests/test_models.py +216 -0
- wbcrm/tests/test_recurrence.py +291 -0
- wbcrm/tests/test_report.py +20 -0
- wbcrm/tests/test_serializers.py +170 -0
- wbcrm/tests/test_tasks.py +94 -0
- wbcrm/tests/test_viewsets.py +967 -0
- wbcrm/tests/tests.py +120 -0
- wbcrm/typings.py +107 -0
- wbcrm/urls.py +67 -0
- wbcrm/viewsets/__init__.py +22 -0
- wbcrm/viewsets/accounts.py +121 -0
- wbcrm/viewsets/activities.py +315 -0
- wbcrm/viewsets/buttons/__init__.py +7 -0
- wbcrm/viewsets/buttons/accounts.py +27 -0
- wbcrm/viewsets/buttons/activities.py +68 -0
- wbcrm/viewsets/buttons/signals.py +17 -0
- wbcrm/viewsets/display/__init__.py +12 -0
- wbcrm/viewsets/display/accounts.py +110 -0
- wbcrm/viewsets/display/activities.py +443 -0
- wbcrm/viewsets/display/groups.py +22 -0
- wbcrm/viewsets/display/products.py +105 -0
- wbcrm/viewsets/endpoints/__init__.py +8 -0
- wbcrm/viewsets/endpoints/accounts.py +32 -0
- wbcrm/viewsets/endpoints/activities.py +30 -0
- wbcrm/viewsets/endpoints/groups.py +7 -0
- wbcrm/viewsets/endpoints/products.py +9 -0
- wbcrm/viewsets/groups.py +37 -0
- wbcrm/viewsets/menu/__init__.py +8 -0
- wbcrm/viewsets/menu/accounts.py +18 -0
- wbcrm/viewsets/menu/activities.py +61 -0
- wbcrm/viewsets/menu/groups.py +16 -0
- wbcrm/viewsets/menu/products.py +20 -0
- wbcrm/viewsets/mixins.py +34 -0
- wbcrm/viewsets/previews/__init__.py +1 -0
- wbcrm/viewsets/previews/activities.py +10 -0
- wbcrm/viewsets/products.py +56 -0
- wbcrm/viewsets/recurrence.py +26 -0
- wbcrm/viewsets/titles/__init__.py +13 -0
- wbcrm/viewsets/titles/accounts.py +22 -0
- wbcrm/viewsets/titles/activities.py +61 -0
- wbcrm/viewsets/titles/products.py +13 -0
- wbcrm/viewsets/titles/utils.py +46 -0
- wbcrm/workflows/__init__.py +1 -0
- wbcrm/workflows/assignee_methods.py +25 -0
- wbcrm-2.2.1.dist-info/METADATA +11 -0
- wbcrm-2.2.1.dist-info/RECORD +155 -0
- wbcrm-2.2.1.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from psycopg.types.range import TimestamptzRange
|
|
5
|
+
from wbcore.contrib.agenda.factories import ConferenceRoomFactory
|
|
6
|
+
from wbcrm.models.recurrence import Recurrence
|
|
7
|
+
from wbcrm.synchronization.activity.backends.outlook.parser import OutlookParser
|
|
8
|
+
|
|
9
|
+
from .fixtures import TestOutlookSyncFixture
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.django_db
|
|
13
|
+
class TestOutlookSyncParser(TestOutlookSyncFixture):
|
|
14
|
+
def test_convert_string_to_datetime(self, organizer_event_fixture_parsed):
|
|
15
|
+
start = OutlookParser.convert_string_to_datetime(
|
|
16
|
+
organizer_event_fixture_parsed["start.date_time"], organizer_event_fixture_parsed["start.time_zone"]
|
|
17
|
+
)
|
|
18
|
+
assert isinstance(start, datetime)
|
|
19
|
+
|
|
20
|
+
def test_convert_to_all_day_period(self, organizer_event_fixture_parsed):
|
|
21
|
+
start = OutlookParser.convert_string_to_datetime(
|
|
22
|
+
organizer_event_fixture_parsed["start.date_time"], organizer_event_fixture_parsed["start.time_zone"]
|
|
23
|
+
)
|
|
24
|
+
end = OutlookParser.convert_string_to_datetime(
|
|
25
|
+
organizer_event_fixture_parsed["end.date_time"], organizer_event_fixture_parsed["end.time_zone"]
|
|
26
|
+
)
|
|
27
|
+
period = OutlookParser.convert_to_all_day_period(TimestamptzRange(start, end))
|
|
28
|
+
assert period
|
|
29
|
+
assert isinstance(period, TimestamptzRange)
|
|
30
|
+
|
|
31
|
+
def test_deserialize_participants(self, organizer_event_fixture_parsed):
|
|
32
|
+
participants, conference_rooms = OutlookParser.deserialize_participants(organizer_event_fixture_parsed)
|
|
33
|
+
assert len(conference_rooms) == 0
|
|
34
|
+
assert len(participants) == len(organizer_event_fixture_parsed["attendees"]) + 1 # include the organizer
|
|
35
|
+
|
|
36
|
+
def test_deserialize_recurring_activities(
|
|
37
|
+
self, organizer_event_fixture_parsed, organizer_master_event_fixture_parsed
|
|
38
|
+
):
|
|
39
|
+
assert OutlookParser.deserialize_recurring_activities(organizer_event_fixture_parsed) == {
|
|
40
|
+
"recurrence_count": 0,
|
|
41
|
+
"recurrence_end": None,
|
|
42
|
+
"repeat_choice": "NEVER",
|
|
43
|
+
}
|
|
44
|
+
assert OutlookParser.deserialize_recurring_activities(organizer_master_event_fixture_parsed) != {
|
|
45
|
+
"recurrence_count": 0,
|
|
46
|
+
"recurrence_end": None,
|
|
47
|
+
"repeat_choice": "NEVER",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def test_deserialize_person(self, organizer_event_fixture_parsed):
|
|
51
|
+
person_dto = OutlookParser.deserialize_person("test@test.ch", "test")
|
|
52
|
+
person_dto1 = OutlookParser.deserialize_person("test@test.ch", "first_name_test last_name_test")
|
|
53
|
+
person_dto2 = OutlookParser.deserialize_person(
|
|
54
|
+
organizer_event_fixture_parsed["organizer.email_address.address"],
|
|
55
|
+
organizer_event_fixture_parsed["organizer.email_address.name"],
|
|
56
|
+
)
|
|
57
|
+
assert person_dto.email == person_dto1.email == "test@test.ch"
|
|
58
|
+
assert person_dto2.email == organizer_event_fixture_parsed["organizer.email_address.address"]
|
|
59
|
+
assert person_dto.first_name == person_dto.last_name == "test"
|
|
60
|
+
assert person_dto1.first_name == "first_name_test"
|
|
61
|
+
assert person_dto1.last_name == "last_name_test"
|
|
62
|
+
|
|
63
|
+
@pytest.mark.parametrize(
|
|
64
|
+
"visibility, sensitivity",
|
|
65
|
+
[("PUBLIC", "normal"), ("PRIVATE", "private"), ("CONFIDENTIAL", "confidential"), ("PUBLIC", None)],
|
|
66
|
+
)
|
|
67
|
+
def test_convert_sensitivity_to_visibility(self, visibility, sensitivity):
|
|
68
|
+
assert OutlookParser.convert_sensitivity_to_visibility(sensitivity) == visibility
|
|
69
|
+
|
|
70
|
+
@pytest.mark.parametrize(
|
|
71
|
+
"visibility, sensitivity",
|
|
72
|
+
[("PUBLIC", "normal"), ("PRIVATE", "private"), ("CONFIDENTIAL", "confidential"), (None, "normal")],
|
|
73
|
+
)
|
|
74
|
+
def test_convert_visibility_to_sensitivity(self, visibility, sensitivity):
|
|
75
|
+
assert OutlookParser.convert_visibility_to_sensitivity(visibility) == sensitivity
|
|
76
|
+
|
|
77
|
+
@pytest.mark.parametrize(
|
|
78
|
+
"reminder_choice, reminder_minute",
|
|
79
|
+
[
|
|
80
|
+
("NEVER", -1),
|
|
81
|
+
("EVENT_TIME", 0),
|
|
82
|
+
("MINUTES_5", 5),
|
|
83
|
+
("MINUTES_15", 15),
|
|
84
|
+
("MINUTES_30", 30),
|
|
85
|
+
("HOURS_1", 60),
|
|
86
|
+
("HOURS_2", 120),
|
|
87
|
+
("HOURS_12", 720),
|
|
88
|
+
("WEEKS_1", 10080),
|
|
89
|
+
("MINUTES_15", None),
|
|
90
|
+
],
|
|
91
|
+
)
|
|
92
|
+
def test_convert_reminder_minutes_to_choice(self, reminder_choice, reminder_minute):
|
|
93
|
+
assert OutlookParser.convert_reminder_minutes_to_choice(reminder_minute) == reminder_choice
|
|
94
|
+
|
|
95
|
+
@pytest.mark.parametrize(
|
|
96
|
+
"reminder_choice, reminder_minute",
|
|
97
|
+
[
|
|
98
|
+
("NEVER", -1),
|
|
99
|
+
("EVENT_TIME", 0),
|
|
100
|
+
("MINUTES_5", 5),
|
|
101
|
+
("MINUTES_15", 15),
|
|
102
|
+
("MINUTES_30", 30),
|
|
103
|
+
("HOURS_1", 60),
|
|
104
|
+
("HOURS_2", 120),
|
|
105
|
+
("HOURS_12", 720),
|
|
106
|
+
("WEEKS_1", 10080),
|
|
107
|
+
],
|
|
108
|
+
)
|
|
109
|
+
def test_convert_reminder_choice_to_minutes(self, reminder_choice, reminder_minute):
|
|
110
|
+
assert OutlookParser.convert_reminder_choice_to_minutes(reminder_choice) == reminder_minute
|
|
111
|
+
|
|
112
|
+
def test_serialize_person(self, person_factory):
|
|
113
|
+
person_dto = person_factory()._build_dto()
|
|
114
|
+
person_dict = OutlookParser.serialize_person(person_dto)
|
|
115
|
+
assert set(person_dict.keys()) == {"emailAddress"}
|
|
116
|
+
assert person_dict["emailAddress"]["address"] == person_dto.email
|
|
117
|
+
assert person_dict["emailAddress"]["name"] == f"{person_dto.first_name} {person_dto.last_name}"
|
|
118
|
+
|
|
119
|
+
@pytest.mark.parametrize(
|
|
120
|
+
"participant_status, attendee_status",
|
|
121
|
+
[
|
|
122
|
+
("NOTRESPONDED", "notResponded"),
|
|
123
|
+
("ATTENDS", "accepted"),
|
|
124
|
+
("CANCELLED", "declined"),
|
|
125
|
+
("MAYBE", "tentativelyAccepted"),
|
|
126
|
+
("ATTENDS_DIGITALLY", "accepted"),
|
|
127
|
+
],
|
|
128
|
+
)
|
|
129
|
+
def test_convert_participant_status_to_attendee_status(self, participant_status, attendee_status):
|
|
130
|
+
assert OutlookParser.convert_participant_status_to_attendee_status(participant_status) == attendee_status
|
|
131
|
+
|
|
132
|
+
@pytest.mark.parametrize(
|
|
133
|
+
"participant_status, attendee_status",
|
|
134
|
+
[
|
|
135
|
+
("NOTRESPONDED", "notResponded"),
|
|
136
|
+
("ATTENDS", "accepted"),
|
|
137
|
+
("CANCELLED", "declined"),
|
|
138
|
+
("MAYBE", "tentativelyAccepted"),
|
|
139
|
+
("NOTRESPONDED", None),
|
|
140
|
+
("ATTENDS", "organizer"),
|
|
141
|
+
],
|
|
142
|
+
)
|
|
143
|
+
def test_convert_attendee_status_to_participant_status(self, participant_status, attendee_status):
|
|
144
|
+
assert OutlookParser.convert_attendee_status_to_participant_status(attendee_status) == participant_status
|
|
145
|
+
|
|
146
|
+
def test_serialize_participants(self, activity_factory, person_factory):
|
|
147
|
+
activity = activity_factory(preceded_by=None, participants=(person_factory(),))
|
|
148
|
+
activity_dto = activity._build_dto()
|
|
149
|
+
assert activity_dto.participants
|
|
150
|
+
attendees = OutlookParser.serialize_participants(activity_dto.participants)
|
|
151
|
+
assert attendees
|
|
152
|
+
assert attendees[0]
|
|
153
|
+
|
|
154
|
+
def test_serialize_conference_room(self):
|
|
155
|
+
cf_dto = ConferenceRoomFactory()._build_dto()
|
|
156
|
+
cf_dict = OutlookParser.serialize_conference_room(cf_dto)
|
|
157
|
+
assert set(cf_dict.keys()) == {"emailAddress", "type"}
|
|
158
|
+
assert cf_dict["type"] == "resource"
|
|
159
|
+
assert cf_dict["emailAddress"]["address"] == cf_dto.email
|
|
160
|
+
assert cf_dict["emailAddress"]["name"] == cf_dto.name
|
|
161
|
+
|
|
162
|
+
def test_serialize_recurring_activities(self, activity_factory):
|
|
163
|
+
act_dto0 = activity_factory()._build_dto()
|
|
164
|
+
act_dto = activity_factory(
|
|
165
|
+
repeat_choice=Recurrence.ReoccuranceChoice.DAILY, recurrence_count=3, preceded_by=None
|
|
166
|
+
)._build_dto()
|
|
167
|
+
reccurence_dict = OutlookParser.serialize_recurring_activities(act_dto)
|
|
168
|
+
assert OutlookParser.serialize_recurring_activities(act_dto0) == {}
|
|
169
|
+
assert set(reccurence_dict.keys()) == {"recurrence"}
|
|
170
|
+
assert reccurence_dict["recurrence"]["pattern"]["type"] == "daily"
|
|
171
|
+
assert reccurence_dict["recurrence"]["range"]["type"] == "numbered"
|
|
172
|
+
assert reccurence_dict["recurrence"]["range"]["numberOfOccurrences"] == 4
|
|
173
|
+
assert reccurence_dict["recurrence"]["range"]["startDate"] == act_dto.period.lower.strftime("%Y-%m-%d")
|