wbcrm 1.56.8__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.
- wbcrm/__init__.py +1 -0
- wbcrm/admin/__init__.py +5 -0
- wbcrm/admin/accounts.py +60 -0
- wbcrm/admin/activities.py +104 -0
- wbcrm/admin/events.py +43 -0
- wbcrm/admin/groups.py +8 -0
- wbcrm/admin/products.py +9 -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 +57 -0
- wbcrm/factories/activities.py +124 -0
- wbcrm/factories/groups.py +24 -0
- wbcrm/factories/products.py +11 -0
- wbcrm/filters/__init__.py +10 -0
- wbcrm/filters/accounts.py +80 -0
- wbcrm/filters/activities.py +204 -0
- wbcrm/filters/groups.py +21 -0
- wbcrm/filters/products.py +38 -0
- wbcrm/filters/signals.py +95 -0
- wbcrm/fixtures/wbcrm.json +1215 -0
- wbcrm/kpi_handlers/activities.py +171 -0
- wbcrm/locale/de/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/de/LC_MESSAGES/django.po +1557 -0
- wbcrm/locale/de/LC_MESSAGES/django.po.translated +1630 -0
- wbcrm/locale/en/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/en/LC_MESSAGES/django.po +1466 -0
- wbcrm/locale/fr/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/fr/LC_MESSAGES/django.po +1467 -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/0017_event.py +40 -0
- wbcrm/migrations/0018_activity_search_vector.py +24 -0
- wbcrm/migrations/__init__.py +0 -0
- wbcrm/models/__init__.py +5 -0
- wbcrm/models/accounts.py +648 -0
- wbcrm/models/activities.py +1419 -0
- wbcrm/models/events.py +15 -0
- wbcrm/models/groups.py +119 -0
- wbcrm/models/llm/activity_summaries.py +41 -0
- wbcrm/models/llm/analyze_relationship.py +50 -0
- wbcrm/models/products.py +86 -0
- wbcrm/models/recurrence.py +280 -0
- wbcrm/preferences.py +13 -0
- wbcrm/report/activity_report.py +110 -0
- wbcrm/serializers/__init__.py +23 -0
- wbcrm/serializers/accounts.py +141 -0
- wbcrm/serializers/activities.py +525 -0
- wbcrm/serializers/groups.py +30 -0
- wbcrm/serializers/products.py +58 -0
- wbcrm/serializers/recurrence.py +91 -0
- wbcrm/serializers/signals.py +71 -0
- wbcrm/static/wbcrm/markdown/documentation/activity.md +86 -0
- wbcrm/static/wbcrm/markdown/documentation/activitytype.md +20 -0
- wbcrm/static/wbcrm/markdown/documentation/group.md +2 -0
- wbcrm/static/wbcrm/markdown/documentation/product.md +11 -0
- wbcrm/synchronization/__init__.py +0 -0
- wbcrm/synchronization/activity/__init__.py +0 -0
- wbcrm/synchronization/activity/admin.py +73 -0
- wbcrm/synchronization/activity/backend.py +214 -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 +406 -0
- wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/create.py +75 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/delete.py +78 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/update.py +155 -0
- wbcrm/synchronization/activity/backends/google/request_utils/internal_to_external/update.py +181 -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 +217 -0
- wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/outlook/backend.py +593 -0
- wbcrm/synchronization/activity/backends/outlook/msgraph.py +436 -0
- wbcrm/synchronization/activity/backends/outlook/parser.py +432 -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 +118 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +274 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +249 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +174 -0
- wbcrm/synchronization/activity/controller.py +627 -0
- wbcrm/synchronization/activity/dynamic_preferences_registry.py +119 -0
- wbcrm/synchronization/activity/preferences.py +27 -0
- wbcrm/synchronization/activity/shortcuts.py +16 -0
- wbcrm/synchronization/activity/tasks.py +21 -0
- wbcrm/synchronization/activity/urls.py +7 -0
- wbcrm/synchronization/activity/utils.py +46 -0
- wbcrm/synchronization/activity/views.py +41 -0
- wbcrm/synchronization/admin.py +1 -0
- wbcrm/synchronization/apps.py +14 -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 +264 -0
- wbcrm/templates/email/activity.html +98 -0
- wbcrm/templates/email/activity_report.html +6 -0
- wbcrm/templates/email/daily_summary.html +72 -0
- wbcrm/templates/email/global_daily_summary.html +85 -0
- wbcrm/tests/__init__.py +0 -0
- wbcrm/tests/accounts/__init__.py +0 -0
- wbcrm/tests/accounts/test_models.py +393 -0
- wbcrm/tests/accounts/test_viewsets.py +88 -0
- wbcrm/tests/conftest.py +76 -0
- wbcrm/tests/disable_signals.py +62 -0
- wbcrm/tests/e2e/__init__.py +1 -0
- wbcrm/tests/e2e/e2e_wbcrm_utility.py +83 -0
- wbcrm/tests/e2e/test_e2e.py +370 -0
- wbcrm/tests/test_assignee_methods.py +40 -0
- wbcrm/tests/test_chartviewsets.py +112 -0
- wbcrm/tests/test_dto.py +64 -0
- wbcrm/tests/test_filters.py +52 -0
- wbcrm/tests/test_models.py +217 -0
- wbcrm/tests/test_recurrence.py +292 -0
- wbcrm/tests/test_report.py +21 -0
- wbcrm/tests/test_serializers.py +171 -0
- wbcrm/tests/test_tasks.py +95 -0
- wbcrm/tests/test_viewsets.py +967 -0
- wbcrm/tests/tests.py +121 -0
- wbcrm/typings.py +109 -0
- wbcrm/urls.py +67 -0
- wbcrm/viewsets/__init__.py +22 -0
- wbcrm/viewsets/accounts.py +122 -0
- wbcrm/viewsets/activities.py +341 -0
- wbcrm/viewsets/buttons/__init__.py +7 -0
- wbcrm/viewsets/buttons/accounts.py +27 -0
- wbcrm/viewsets/buttons/activities.py +89 -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 +444 -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 +25 -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 +38 -0
- wbcrm/viewsets/menu/__init__.py +8 -0
- wbcrm/viewsets/menu/accounts.py +18 -0
- wbcrm/viewsets/menu/activities.py +49 -0
- wbcrm/viewsets/menu/groups.py +16 -0
- wbcrm/viewsets/menu/products.py +20 -0
- wbcrm/viewsets/mixins.py +35 -0
- wbcrm/viewsets/previews/__init__.py +1 -0
- wbcrm/viewsets/previews/activities.py +10 -0
- wbcrm/viewsets/products.py +57 -0
- wbcrm/viewsets/recurrence.py +27 -0
- wbcrm/viewsets/titles/__init__.py +13 -0
- wbcrm/viewsets/titles/accounts.py +23 -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-1.56.8.dist-info/METADATA +11 -0
- wbcrm-1.56.8.dist-info/RECORD +182 -0
- wbcrm-1.56.8.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from django.utils.translation import pgettext
|
|
5
|
+
from wbcore.contrib.color.enums import WBColor
|
|
6
|
+
from wbcore.metadata.configs import display as dp
|
|
7
|
+
from wbcore.metadata.configs.display.instance_display import (
|
|
8
|
+
Display,
|
|
9
|
+
Inline,
|
|
10
|
+
Layout,
|
|
11
|
+
Page,
|
|
12
|
+
Section,
|
|
13
|
+
Style,
|
|
14
|
+
create_simple_display,
|
|
15
|
+
)
|
|
16
|
+
from wbcore.metadata.configs.display.instance_display.operators import default
|
|
17
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
18
|
+
|
|
19
|
+
from wbcrm.models import Activity
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_activity_legend() -> list[dp.Legend]:
|
|
23
|
+
"""Dynamically creates the activity legend based on the activity status enum"""
|
|
24
|
+
|
|
25
|
+
legend_items = []
|
|
26
|
+
for status, color in Activity.Status.get_color_map():
|
|
27
|
+
legend_items.append(dp.LegendItem(icon=color, label=status.label, value=status.value))
|
|
28
|
+
return [dp.Legend(key="status", items=legend_items)]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def get_activity_list_formatting() -> list[dp.Formatting]:
|
|
32
|
+
"""Dynamically creates the activity list formatting based on the activity status enum"""
|
|
33
|
+
|
|
34
|
+
formatting_rules = []
|
|
35
|
+
for status, color in Activity.Status.get_color_map():
|
|
36
|
+
formatting_rules.append(dp.FormattingRule(condition=("==", status.name), style={"backgroundColor": color}))
|
|
37
|
+
|
|
38
|
+
return [dp.Formatting(column="status", formatting_rules=formatting_rules)]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ActivityTypeDisplay(DisplayViewConfig):
|
|
42
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
43
|
+
return dp.ListDisplay(
|
|
44
|
+
fields=[
|
|
45
|
+
dp.Field(key="title", label=_("Title")),
|
|
46
|
+
dp.Field(key="icon", label=_("Icon")),
|
|
47
|
+
dp.Field(key="color", label=_("Color")),
|
|
48
|
+
dp.Field(key="score", label=_("Multiplier")),
|
|
49
|
+
dp.Field(key="default", label=_("Is Default")),
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def get_instance_display(self) -> Display:
|
|
54
|
+
return create_simple_display([["default", "."], ["title", "score"], ["color", "icon"]])
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ActivityDisplay(DisplayViewConfig):
|
|
58
|
+
@classmethod
|
|
59
|
+
def _get_activity_instance_display(cls, instance: Activity) -> Display:
|
|
60
|
+
"""Returns an activity instance's display
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
instance: The activity instance that will be displayed
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Display: The display instance
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
participants_section = Section(
|
|
70
|
+
key="participants_section",
|
|
71
|
+
collapsible=False,
|
|
72
|
+
title=_("Participants"),
|
|
73
|
+
display=Display(
|
|
74
|
+
pages=[
|
|
75
|
+
Page(
|
|
76
|
+
title=_("Participants"),
|
|
77
|
+
layouts={
|
|
78
|
+
default(): Layout(
|
|
79
|
+
grid_template_areas=[["participants_table"]],
|
|
80
|
+
inlines=[Inline(key="participants_table", endpoint="activity_participants_table")],
|
|
81
|
+
)
|
|
82
|
+
},
|
|
83
|
+
),
|
|
84
|
+
]
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if instance.status == Activity.Status.PLANNED:
|
|
89
|
+
display = Display(
|
|
90
|
+
pages=[
|
|
91
|
+
Page(
|
|
92
|
+
title=_("Main Information"),
|
|
93
|
+
layouts={
|
|
94
|
+
default(): Layout(
|
|
95
|
+
grid_template_areas=[
|
|
96
|
+
[
|
|
97
|
+
"status",
|
|
98
|
+
"status",
|
|
99
|
+
"participants_section",
|
|
100
|
+
"participants_section",
|
|
101
|
+
],
|
|
102
|
+
[
|
|
103
|
+
"title",
|
|
104
|
+
"type",
|
|
105
|
+
"participants_section",
|
|
106
|
+
"participants_section",
|
|
107
|
+
],
|
|
108
|
+
[
|
|
109
|
+
"period",
|
|
110
|
+
"all_day",
|
|
111
|
+
"participants_section",
|
|
112
|
+
"participants_section",
|
|
113
|
+
],
|
|
114
|
+
[
|
|
115
|
+
"participants",
|
|
116
|
+
"groups",
|
|
117
|
+
"participants_section",
|
|
118
|
+
"participants_section",
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
"companies",
|
|
122
|
+
"disable_participant_check",
|
|
123
|
+
"participants_section",
|
|
124
|
+
"participants_section",
|
|
125
|
+
],
|
|
126
|
+
[
|
|
127
|
+
"description",
|
|
128
|
+
"description",
|
|
129
|
+
"result",
|
|
130
|
+
"result",
|
|
131
|
+
],
|
|
132
|
+
["summary", "summary", "summary", "summary"],
|
|
133
|
+
],
|
|
134
|
+
grid_auto_columns="1fr",
|
|
135
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
136
|
+
sections=(participants_section,),
|
|
137
|
+
),
|
|
138
|
+
},
|
|
139
|
+
),
|
|
140
|
+
Page(
|
|
141
|
+
title=_("Recurrence"),
|
|
142
|
+
layouts={
|
|
143
|
+
default(): Layout(grid_template_areas=[["propagate_for_all_children", "repeat_choice"]])
|
|
144
|
+
},
|
|
145
|
+
),
|
|
146
|
+
Page(
|
|
147
|
+
title=_("Additional Information"),
|
|
148
|
+
layouts={
|
|
149
|
+
default(): Layout(
|
|
150
|
+
grid_template_areas=[
|
|
151
|
+
[
|
|
152
|
+
"assigned_to",
|
|
153
|
+
"assigned_to",
|
|
154
|
+
"reminder_choice",
|
|
155
|
+
"visibility",
|
|
156
|
+
],
|
|
157
|
+
["conference_room", "online_meeting", "location", "importance"],
|
|
158
|
+
[
|
|
159
|
+
"created",
|
|
160
|
+
"edited",
|
|
161
|
+
".",
|
|
162
|
+
".",
|
|
163
|
+
],
|
|
164
|
+
],
|
|
165
|
+
grid_template_columns=[
|
|
166
|
+
"minmax(min-content, 1fr)",
|
|
167
|
+
"minmax(min-content, 1fr)",
|
|
168
|
+
"minmax(min-content, 2fr)",
|
|
169
|
+
"minmax(min-content, 2fr)",
|
|
170
|
+
],
|
|
171
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
),
|
|
175
|
+
]
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
display = Display(
|
|
179
|
+
pages=[
|
|
180
|
+
Page(
|
|
181
|
+
title=_("Main Information"),
|
|
182
|
+
layouts={
|
|
183
|
+
default(): Layout(
|
|
184
|
+
grid_template_areas=[
|
|
185
|
+
[
|
|
186
|
+
"status",
|
|
187
|
+
".",
|
|
188
|
+
],
|
|
189
|
+
[
|
|
190
|
+
"title",
|
|
191
|
+
"type",
|
|
192
|
+
],
|
|
193
|
+
[
|
|
194
|
+
"period",
|
|
195
|
+
"all_day",
|
|
196
|
+
],
|
|
197
|
+
[
|
|
198
|
+
"participants",
|
|
199
|
+
"groups",
|
|
200
|
+
],
|
|
201
|
+
[
|
|
202
|
+
"companies",
|
|
203
|
+
"disable_participant_check",
|
|
204
|
+
],
|
|
205
|
+
[
|
|
206
|
+
"description",
|
|
207
|
+
"description" if instance.status == Activity.Status.CANCELLED else "result",
|
|
208
|
+
],
|
|
209
|
+
["summary", "summary"],
|
|
210
|
+
],
|
|
211
|
+
grid_auto_columns="1fr",
|
|
212
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
213
|
+
),
|
|
214
|
+
},
|
|
215
|
+
),
|
|
216
|
+
Page(
|
|
217
|
+
title=_("Participant Information"),
|
|
218
|
+
layouts={
|
|
219
|
+
default(): Layout(
|
|
220
|
+
grid_template_areas=[["participants_section"]], sections=(participants_section,)
|
|
221
|
+
)
|
|
222
|
+
},
|
|
223
|
+
),
|
|
224
|
+
Page(
|
|
225
|
+
title=_("Recurrence"),
|
|
226
|
+
layouts={default(): Layout(grid_template_areas=[["propagate_for_all_children"]])},
|
|
227
|
+
),
|
|
228
|
+
Page(
|
|
229
|
+
title=_("Additional Information"),
|
|
230
|
+
layouts={
|
|
231
|
+
default(): Layout(
|
|
232
|
+
grid_template_areas=[
|
|
233
|
+
[
|
|
234
|
+
"assigned_to",
|
|
235
|
+
"assigned_to",
|
|
236
|
+
"reminder_choice",
|
|
237
|
+
"visibility",
|
|
238
|
+
],
|
|
239
|
+
["conference_room", "online_meeting", "location", "importance"],
|
|
240
|
+
[
|
|
241
|
+
"created",
|
|
242
|
+
"edited",
|
|
243
|
+
".",
|
|
244
|
+
".",
|
|
245
|
+
],
|
|
246
|
+
],
|
|
247
|
+
grid_template_columns=[
|
|
248
|
+
"minmax(min-content, 1fr)",
|
|
249
|
+
"minmax(min-content, 1fr)",
|
|
250
|
+
"minmax(min-content, 2fr)",
|
|
251
|
+
"minmax(min-content, 2fr)",
|
|
252
|
+
],
|
|
253
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
254
|
+
)
|
|
255
|
+
},
|
|
256
|
+
),
|
|
257
|
+
]
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
return display
|
|
261
|
+
|
|
262
|
+
@classmethod
|
|
263
|
+
def _get_new_activity_instance_display(cls) -> Display:
|
|
264
|
+
"""Returns the display for creating a new activity
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Display: The display instance
|
|
268
|
+
"""
|
|
269
|
+
|
|
270
|
+
new_recurrence_section = Section(
|
|
271
|
+
key="new_recurrence_section",
|
|
272
|
+
collapsible=False,
|
|
273
|
+
title=_("Repeat Until"),
|
|
274
|
+
display=Display(
|
|
275
|
+
pages=[
|
|
276
|
+
Page(
|
|
277
|
+
title=_("Repeat Until"),
|
|
278
|
+
layouts={
|
|
279
|
+
default(): Layout(
|
|
280
|
+
grid_template_areas=[["recurrence_end", "recurrence_count", "."]],
|
|
281
|
+
grid_template_columns=[
|
|
282
|
+
"minmax(min-content, 1fr)",
|
|
283
|
+
"minmax(min-content, 1fr)",
|
|
284
|
+
"minmax(min-content, 2fr)",
|
|
285
|
+
],
|
|
286
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
287
|
+
)
|
|
288
|
+
},
|
|
289
|
+
),
|
|
290
|
+
]
|
|
291
|
+
),
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
return Display(
|
|
295
|
+
pages=[
|
|
296
|
+
Page(
|
|
297
|
+
title=_("Main Information"),
|
|
298
|
+
layouts={
|
|
299
|
+
default(): Layout(
|
|
300
|
+
grid_template_areas=[
|
|
301
|
+
[
|
|
302
|
+
"title",
|
|
303
|
+
"type",
|
|
304
|
+
],
|
|
305
|
+
[
|
|
306
|
+
"period",
|
|
307
|
+
"all_day",
|
|
308
|
+
],
|
|
309
|
+
[
|
|
310
|
+
"participants",
|
|
311
|
+
"groups",
|
|
312
|
+
],
|
|
313
|
+
[
|
|
314
|
+
"companies",
|
|
315
|
+
"disable_participant_check",
|
|
316
|
+
],
|
|
317
|
+
[
|
|
318
|
+
"description",
|
|
319
|
+
"result",
|
|
320
|
+
],
|
|
321
|
+
],
|
|
322
|
+
grid_auto_columns="1fr",
|
|
323
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
324
|
+
),
|
|
325
|
+
},
|
|
326
|
+
),
|
|
327
|
+
Page(
|
|
328
|
+
title=_("Recurrence"),
|
|
329
|
+
layouts={
|
|
330
|
+
default(): Layout(
|
|
331
|
+
grid_template_areas=[
|
|
332
|
+
["repeat_choice", "."],
|
|
333
|
+
["new_recurrence_section", "new_recurrence_section"],
|
|
334
|
+
],
|
|
335
|
+
grid_template_columns=["minmax(min-content, 1fr)", "minmax(min-content, 3fr)"],
|
|
336
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
337
|
+
sections=(new_recurrence_section,),
|
|
338
|
+
)
|
|
339
|
+
},
|
|
340
|
+
),
|
|
341
|
+
Page(
|
|
342
|
+
title=_("Additional Information"),
|
|
343
|
+
layouts={
|
|
344
|
+
default(): Layout(
|
|
345
|
+
grid_template_areas=[
|
|
346
|
+
[
|
|
347
|
+
"assigned_to",
|
|
348
|
+
"assigned_to",
|
|
349
|
+
"reminder_choice",
|
|
350
|
+
"visibility",
|
|
351
|
+
],
|
|
352
|
+
["conference_room", "online_meeting", "location", "importance"],
|
|
353
|
+
],
|
|
354
|
+
grid_template_columns=[
|
|
355
|
+
"minmax(min-content, 1fr)",
|
|
356
|
+
"minmax(min-content, 1fr)",
|
|
357
|
+
"minmax(min-content, 2fr)",
|
|
358
|
+
"minmax(min-content, 2fr)",
|
|
359
|
+
],
|
|
360
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
361
|
+
)
|
|
362
|
+
},
|
|
363
|
+
),
|
|
364
|
+
]
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
368
|
+
return dp.ListDisplay(
|
|
369
|
+
fields=[
|
|
370
|
+
dp.Field(key="heat", label=_("Sentiment"), width=75),
|
|
371
|
+
dp.Field(key="type", label=_("Type")),
|
|
372
|
+
dp.Field(key="title", label=_("Title")),
|
|
373
|
+
dp.Field(key="summary", label=_("Summary")),
|
|
374
|
+
dp.Field(key="period", label=_("Period")),
|
|
375
|
+
dp.Field(key="participants", label=_("Participants")),
|
|
376
|
+
dp.Field(key="companies", label=_("Companies")),
|
|
377
|
+
dp.Field(key="groups", label=_("Groups")),
|
|
378
|
+
dp.Field(key="edited", label=_("Edited")),
|
|
379
|
+
dp.Field(key="created", label=pgettext("As a table header", "Created")),
|
|
380
|
+
dp.Field(key="description", label=_("Description")),
|
|
381
|
+
dp.Field(key="result", label=pgettext("As a table header", "Review")),
|
|
382
|
+
dp.Field(key="latest_reviewer", label=_("Latest Reviewer")),
|
|
383
|
+
],
|
|
384
|
+
legends=get_activity_legend(),
|
|
385
|
+
formatting=get_activity_list_formatting(),
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
def get_instance_display(self) -> Display:
|
|
389
|
+
return (
|
|
390
|
+
self._get_activity_instance_display(self.view.get_object())
|
|
391
|
+
if "pk" in self.view.kwargs
|
|
392
|
+
else self._get_new_activity_instance_display()
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class ActivityParticipantDisplayConfig(DisplayViewConfig):
|
|
397
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
398
|
+
return dp.ListDisplay(
|
|
399
|
+
fields=[
|
|
400
|
+
dp.Field(key="participant", label=_("Participant")),
|
|
401
|
+
dp.Field(key="participation_status", label=_("Participation Status")),
|
|
402
|
+
dp.Field(key="status_changed", label=_("Status Changed")),
|
|
403
|
+
dp.Field(key="position", label=_("Position")),
|
|
404
|
+
dp.Field(key="primary_email", label=_("Primary Email")),
|
|
405
|
+
dp.Field(key="primary_telephone", label=_("Primary Phone Number")),
|
|
406
|
+
],
|
|
407
|
+
legends=[
|
|
408
|
+
dp.Legend(
|
|
409
|
+
key="is_occupied_filter",
|
|
410
|
+
items=[
|
|
411
|
+
dp.LegendItem(
|
|
412
|
+
icon=WBColor.GREEN_LIGHT.value,
|
|
413
|
+
label=_("Is Available"),
|
|
414
|
+
value=False,
|
|
415
|
+
),
|
|
416
|
+
dp.LegendItem(
|
|
417
|
+
icon=WBColor.RED_LIGHT.value,
|
|
418
|
+
label=_("Is Occupied"),
|
|
419
|
+
value=True,
|
|
420
|
+
),
|
|
421
|
+
],
|
|
422
|
+
)
|
|
423
|
+
],
|
|
424
|
+
formatting=[
|
|
425
|
+
dp.Formatting(
|
|
426
|
+
column="is_occupied",
|
|
427
|
+
formatting_rules=[
|
|
428
|
+
dp.FormattingRule(
|
|
429
|
+
style={"backgroundColor": WBColor.GREEN_LIGHT.value},
|
|
430
|
+
condition=("==", False),
|
|
431
|
+
),
|
|
432
|
+
dp.FormattingRule(
|
|
433
|
+
style={"backgroundColor": WBColor.RED_LIGHT.value},
|
|
434
|
+
condition=("==", True),
|
|
435
|
+
),
|
|
436
|
+
],
|
|
437
|
+
)
|
|
438
|
+
],
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
def get_instance_display(self) -> Display:
|
|
442
|
+
return create_simple_display(
|
|
443
|
+
[["participation_status", "participation_status"], ["participant", "customer_status"]]
|
|
444
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from wbcore.metadata.configs import display as dp
|
|
5
|
+
from wbcore.metadata.configs.display.instance_display import Display
|
|
6
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
7
|
+
create_simple_display,
|
|
8
|
+
)
|
|
9
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GroupModelDisplay(DisplayViewConfig):
|
|
13
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
14
|
+
return dp.ListDisplay(
|
|
15
|
+
fields=(
|
|
16
|
+
dp.Field(key="title", label=_("Name")),
|
|
17
|
+
dp.Field(key="members", label=_("Members")),
|
|
18
|
+
),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def get_instance_display(self) -> Display:
|
|
22
|
+
return create_simple_display([["title"], ["members"]])
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from wbcore.contrib.directory.viewsets.display import CompanyModelDisplay
|
|
5
|
+
from wbcore.dispatch import receiver_all_subclasses
|
|
6
|
+
from wbcore.metadata.configs import display as dp
|
|
7
|
+
from wbcore.metadata.configs.display import add_display_pages
|
|
8
|
+
from wbcore.metadata.configs.display.instance_display import (
|
|
9
|
+
Display,
|
|
10
|
+
Inline,
|
|
11
|
+
Layout,
|
|
12
|
+
Page,
|
|
13
|
+
Section,
|
|
14
|
+
Style,
|
|
15
|
+
)
|
|
16
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
17
|
+
create_simple_display,
|
|
18
|
+
default,
|
|
19
|
+
)
|
|
20
|
+
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ProductDisplay(DisplayViewConfig):
|
|
24
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
25
|
+
return dp.ListDisplay(
|
|
26
|
+
fields=(
|
|
27
|
+
dp.Field(key="title", label=_("Title")),
|
|
28
|
+
dp.Field(key="is_competitor", label=_("Is Competitor")),
|
|
29
|
+
dp.Field(key="prospects", label=_("Prospects")),
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def get_instance_display(self) -> Display:
|
|
34
|
+
return Display(
|
|
35
|
+
pages=[
|
|
36
|
+
Page(
|
|
37
|
+
layouts={
|
|
38
|
+
default(): Layout(
|
|
39
|
+
grid_template_areas=[["title", "is_competitor", "prospects"]],
|
|
40
|
+
grid_template_columns=[
|
|
41
|
+
"minmax(min-content, 0.5fr)",
|
|
42
|
+
"minmax(min-content, 1fr)",
|
|
43
|
+
"minmax(min-content, 1fr)",
|
|
44
|
+
],
|
|
45
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
46
|
+
column_gap=Style.rem(6),
|
|
47
|
+
),
|
|
48
|
+
},
|
|
49
|
+
),
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ProductCompanyRelationshipDisplay(DisplayViewConfig):
|
|
55
|
+
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
56
|
+
return dp.ListDisplay(
|
|
57
|
+
fields=(
|
|
58
|
+
dp.Field(key="product", label=_("Product")),
|
|
59
|
+
dp.Field(key="competitor_product", label=_("Is Competitor")),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def get_instance_display(self) -> Display:
|
|
64
|
+
return create_simple_display([["product"]])
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@receiver_all_subclasses(add_display_pages, sender=CompanyModelDisplay)
|
|
68
|
+
def add_interested_product_page(sender, *args, **kwargs):
|
|
69
|
+
return [
|
|
70
|
+
Page(
|
|
71
|
+
title=_("Interests"),
|
|
72
|
+
layouts={
|
|
73
|
+
default(): Layout(
|
|
74
|
+
grid_template_areas=[["interested_products_section"]],
|
|
75
|
+
grid_auto_columns="minmax(min-content, 1fr)",
|
|
76
|
+
grid_auto_rows=Style.MIN_CONTENT,
|
|
77
|
+
sections=[
|
|
78
|
+
Section(
|
|
79
|
+
key="interested_products_section",
|
|
80
|
+
title=_("Interested Products"),
|
|
81
|
+
collapsible=False,
|
|
82
|
+
display=Display(
|
|
83
|
+
pages=[
|
|
84
|
+
Page(
|
|
85
|
+
title=_("Interested Products"),
|
|
86
|
+
layouts={
|
|
87
|
+
default(): Layout(
|
|
88
|
+
grid_template_areas=[["interested_products_table"]],
|
|
89
|
+
inlines=[
|
|
90
|
+
Inline(
|
|
91
|
+
key="interested_products_table",
|
|
92
|
+
endpoint="interested_products",
|
|
93
|
+
)
|
|
94
|
+
],
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
),
|
|
98
|
+
]
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
],
|
|
102
|
+
),
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .accounts import (
|
|
2
|
+
AccountRoleAccountEndpointConfig,
|
|
3
|
+
ChildAccountAccountEndpointConfig,
|
|
4
|
+
InheritedAccountRoleAccountEndpointConfig,
|
|
5
|
+
)
|
|
6
|
+
from .activities import ActivityEndpointConfig, ActivityParticipantModelEndpointConfig
|
|
7
|
+
from .groups import GroupEndpointConfig
|
|
8
|
+
from .products import ProductCompanyRelationshipEndpointConfig
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ChildAccountAccountEndpointConfig(EndpointViewConfig):
|
|
6
|
+
def get_endpoint(self, **kwargs):
|
|
7
|
+
return reverse(
|
|
8
|
+
"wbcrm:account-childaccount-list",
|
|
9
|
+
args=[self.view.kwargs["account_id"]],
|
|
10
|
+
request=self.request,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AccountRoleAccountEndpointConfig(EndpointViewConfig):
|
|
15
|
+
def get_endpoint(self, **kwargs):
|
|
16
|
+
return reverse(
|
|
17
|
+
"wbcrm:account-accountrole-list",
|
|
18
|
+
args=[self.view.kwargs["account_id"]],
|
|
19
|
+
request=self.request,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class InheritedAccountRoleAccountEndpointConfig(EndpointViewConfig):
|
|
24
|
+
def get_endpoint(self, **kwargs):
|
|
25
|
+
return None
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ActivityEndpointConfig(EndpointViewConfig):
|
|
6
|
+
def get_create_endpoint(self, **kwargs):
|
|
7
|
+
user_id = self.request.user.profile.id
|
|
8
|
+
base_url = "wbcrm:activity-list"
|
|
9
|
+
filter_url = f"?participants={user_id}"
|
|
10
|
+
|
|
11
|
+
if participants := self.request.GET.get("participants", None):
|
|
12
|
+
filter_url += f",{participants}"
|
|
13
|
+
if companies := self.request.GET.get("companies", None):
|
|
14
|
+
filter_url += f"&companies={companies}"
|
|
15
|
+
return f"{reverse(base_url, args=[], request=self.request)}{filter_url}"
|
|
16
|
+
|
|
17
|
+
def get_delete_endpoint(self, **kwargs):
|
|
18
|
+
if "pk" in self.view.kwargs and (self.view.is_private_for_user or self.view.is_confidential_for_user):
|
|
19
|
+
return None
|
|
20
|
+
return super().get_delete_endpoint(**kwargs)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ActivityParticipantModelEndpointConfig(EndpointViewConfig):
|
|
24
|
+
def get_endpoint(self, **kwargs):
|
|
25
|
+
return reverse("wbcrm:activity-participant-list", args=[self.view.kwargs["activity_id"]], request=self.request)
|
|
26
|
+
|
|
27
|
+
def get_create_endpoint(self, **kwargs):
|
|
28
|
+
if "activity_id" in self.view.kwargs:
|
|
29
|
+
return f"{super().get_create_endpoint(**kwargs)}?activity_id={self.view.kwargs['activity_id']}"
|
|
30
|
+
return super().get_create_endpoint(**kwargs)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class GroupEndpointConfig(EndpointViewConfig):
|
|
6
|
+
def get_pre_change_endpoint(self, pk):
|
|
7
|
+
return reverse("wbcrm:group-pre-change", args=[pk], request=self.request)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ProductCompanyRelationshipEndpointConfig(EndpointViewConfig):
|
|
6
|
+
def get_endpoint(self, **kwargs):
|
|
7
|
+
return reverse(
|
|
8
|
+
"wbcrm:company-interestedproduct-list", args=[self.view.kwargs["company_id"]], request=self.request
|
|
9
|
+
)
|