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.
Files changed (182) hide show
  1. wbcrm/__init__.py +1 -0
  2. wbcrm/admin/__init__.py +5 -0
  3. wbcrm/admin/accounts.py +60 -0
  4. wbcrm/admin/activities.py +104 -0
  5. wbcrm/admin/events.py +43 -0
  6. wbcrm/admin/groups.py +8 -0
  7. wbcrm/admin/products.py +9 -0
  8. wbcrm/apps.py +5 -0
  9. wbcrm/configurations/__init__.py +1 -0
  10. wbcrm/configurations/base.py +16 -0
  11. wbcrm/dynamic_preferences_registry.py +38 -0
  12. wbcrm/factories/__init__.py +14 -0
  13. wbcrm/factories/accounts.py +57 -0
  14. wbcrm/factories/activities.py +124 -0
  15. wbcrm/factories/groups.py +24 -0
  16. wbcrm/factories/products.py +11 -0
  17. wbcrm/filters/__init__.py +10 -0
  18. wbcrm/filters/accounts.py +80 -0
  19. wbcrm/filters/activities.py +204 -0
  20. wbcrm/filters/groups.py +21 -0
  21. wbcrm/filters/products.py +38 -0
  22. wbcrm/filters/signals.py +95 -0
  23. wbcrm/fixtures/wbcrm.json +1215 -0
  24. wbcrm/kpi_handlers/activities.py +171 -0
  25. wbcrm/locale/de/LC_MESSAGES/django.mo +0 -0
  26. wbcrm/locale/de/LC_MESSAGES/django.po +1557 -0
  27. wbcrm/locale/de/LC_MESSAGES/django.po.translated +1630 -0
  28. wbcrm/locale/en/LC_MESSAGES/django.mo +0 -0
  29. wbcrm/locale/en/LC_MESSAGES/django.po +1466 -0
  30. wbcrm/locale/fr/LC_MESSAGES/django.mo +0 -0
  31. wbcrm/locale/fr/LC_MESSAGES/django.po +1467 -0
  32. wbcrm/migrations/0001_initial_squashed_squashed_0032_productcompanyrelationship_alter_product_prospects_and_more.py +3948 -0
  33. wbcrm/migrations/0002_alter_activity_repeat_choice.py +32 -0
  34. wbcrm/migrations/0003_remove_activity_external_id_and_more.py +63 -0
  35. wbcrm/migrations/0004_alter_activity_status.py +28 -0
  36. wbcrm/migrations/0005_account_accountrole_accountroletype_and_more.py +182 -0
  37. wbcrm/migrations/0006_alter_activity_location.py +17 -0
  38. wbcrm/migrations/0007_alter_account_status.py +23 -0
  39. wbcrm/migrations/0008_alter_activity_options.py +16 -0
  40. wbcrm/migrations/0009_alter_account_is_public.py +19 -0
  41. wbcrm/migrations/0010_alter_account_reference_id.py +17 -0
  42. wbcrm/migrations/0011_activity_summary.py +22 -0
  43. wbcrm/migrations/0012_alter_activity_summary.py +17 -0
  44. wbcrm/migrations/0013_account_action_plan_account_relationship_status_and_more.py +34 -0
  45. wbcrm/migrations/0014_alter_account_relationship_status.py +24 -0
  46. wbcrm/migrations/0015_alter_activity_type.py +23 -0
  47. wbcrm/migrations/0016_auto_20241205_1015.py +106 -0
  48. wbcrm/migrations/0017_event.py +40 -0
  49. wbcrm/migrations/0018_activity_search_vector.py +24 -0
  50. wbcrm/migrations/__init__.py +0 -0
  51. wbcrm/models/__init__.py +5 -0
  52. wbcrm/models/accounts.py +648 -0
  53. wbcrm/models/activities.py +1419 -0
  54. wbcrm/models/events.py +15 -0
  55. wbcrm/models/groups.py +119 -0
  56. wbcrm/models/llm/activity_summaries.py +41 -0
  57. wbcrm/models/llm/analyze_relationship.py +50 -0
  58. wbcrm/models/products.py +86 -0
  59. wbcrm/models/recurrence.py +280 -0
  60. wbcrm/preferences.py +13 -0
  61. wbcrm/report/activity_report.py +110 -0
  62. wbcrm/serializers/__init__.py +23 -0
  63. wbcrm/serializers/accounts.py +141 -0
  64. wbcrm/serializers/activities.py +525 -0
  65. wbcrm/serializers/groups.py +30 -0
  66. wbcrm/serializers/products.py +58 -0
  67. wbcrm/serializers/recurrence.py +91 -0
  68. wbcrm/serializers/signals.py +71 -0
  69. wbcrm/static/wbcrm/markdown/documentation/activity.md +86 -0
  70. wbcrm/static/wbcrm/markdown/documentation/activitytype.md +20 -0
  71. wbcrm/static/wbcrm/markdown/documentation/group.md +2 -0
  72. wbcrm/static/wbcrm/markdown/documentation/product.md +11 -0
  73. wbcrm/synchronization/__init__.py +0 -0
  74. wbcrm/synchronization/activity/__init__.py +0 -0
  75. wbcrm/synchronization/activity/admin.py +73 -0
  76. wbcrm/synchronization/activity/backend.py +214 -0
  77. wbcrm/synchronization/activity/backends/__init__.py +0 -0
  78. wbcrm/synchronization/activity/backends/google/__init__.py +2 -0
  79. wbcrm/synchronization/activity/backends/google/google_calendar_backend.py +406 -0
  80. wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
  81. wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/create.py +75 -0
  82. wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/delete.py +78 -0
  83. wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/update.py +155 -0
  84. wbcrm/synchronization/activity/backends/google/request_utils/internal_to_external/update.py +181 -0
  85. wbcrm/synchronization/activity/backends/google/tasks.py +21 -0
  86. wbcrm/synchronization/activity/backends/google/tests/__init__.py +0 -0
  87. wbcrm/synchronization/activity/backends/google/tests/conftest.py +1 -0
  88. wbcrm/synchronization/activity/backends/google/tests/test_data.py +81 -0
  89. wbcrm/synchronization/activity/backends/google/tests/test_google_backend.py +319 -0
  90. wbcrm/synchronization/activity/backends/google/tests/test_utils.py +274 -0
  91. wbcrm/synchronization/activity/backends/google/typing_informations.py +139 -0
  92. wbcrm/synchronization/activity/backends/google/utils.py +217 -0
  93. wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
  94. wbcrm/synchronization/activity/backends/outlook/backend.py +593 -0
  95. wbcrm/synchronization/activity/backends/outlook/msgraph.py +436 -0
  96. wbcrm/synchronization/activity/backends/outlook/parser.py +432 -0
  97. wbcrm/synchronization/activity/backends/outlook/tests/__init__.py +0 -0
  98. wbcrm/synchronization/activity/backends/outlook/tests/conftest.py +1 -0
  99. wbcrm/synchronization/activity/backends/outlook/tests/fixtures.py +606 -0
  100. wbcrm/synchronization/activity/backends/outlook/tests/test_admin.py +118 -0
  101. wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +274 -0
  102. wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +249 -0
  103. wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +174 -0
  104. wbcrm/synchronization/activity/controller.py +627 -0
  105. wbcrm/synchronization/activity/dynamic_preferences_registry.py +119 -0
  106. wbcrm/synchronization/activity/preferences.py +27 -0
  107. wbcrm/synchronization/activity/shortcuts.py +16 -0
  108. wbcrm/synchronization/activity/tasks.py +21 -0
  109. wbcrm/synchronization/activity/urls.py +7 -0
  110. wbcrm/synchronization/activity/utils.py +46 -0
  111. wbcrm/synchronization/activity/views.py +41 -0
  112. wbcrm/synchronization/admin.py +1 -0
  113. wbcrm/synchronization/apps.py +14 -0
  114. wbcrm/synchronization/dynamic_preferences_registry.py +1 -0
  115. wbcrm/synchronization/management.py +36 -0
  116. wbcrm/synchronization/tasks.py +1 -0
  117. wbcrm/synchronization/urls.py +5 -0
  118. wbcrm/tasks.py +264 -0
  119. wbcrm/templates/email/activity.html +98 -0
  120. wbcrm/templates/email/activity_report.html +6 -0
  121. wbcrm/templates/email/daily_summary.html +72 -0
  122. wbcrm/templates/email/global_daily_summary.html +85 -0
  123. wbcrm/tests/__init__.py +0 -0
  124. wbcrm/tests/accounts/__init__.py +0 -0
  125. wbcrm/tests/accounts/test_models.py +393 -0
  126. wbcrm/tests/accounts/test_viewsets.py +88 -0
  127. wbcrm/tests/conftest.py +76 -0
  128. wbcrm/tests/disable_signals.py +62 -0
  129. wbcrm/tests/e2e/__init__.py +1 -0
  130. wbcrm/tests/e2e/e2e_wbcrm_utility.py +83 -0
  131. wbcrm/tests/e2e/test_e2e.py +370 -0
  132. wbcrm/tests/test_assignee_methods.py +40 -0
  133. wbcrm/tests/test_chartviewsets.py +112 -0
  134. wbcrm/tests/test_dto.py +64 -0
  135. wbcrm/tests/test_filters.py +52 -0
  136. wbcrm/tests/test_models.py +217 -0
  137. wbcrm/tests/test_recurrence.py +292 -0
  138. wbcrm/tests/test_report.py +21 -0
  139. wbcrm/tests/test_serializers.py +171 -0
  140. wbcrm/tests/test_tasks.py +95 -0
  141. wbcrm/tests/test_viewsets.py +967 -0
  142. wbcrm/tests/tests.py +121 -0
  143. wbcrm/typings.py +109 -0
  144. wbcrm/urls.py +67 -0
  145. wbcrm/viewsets/__init__.py +22 -0
  146. wbcrm/viewsets/accounts.py +122 -0
  147. wbcrm/viewsets/activities.py +341 -0
  148. wbcrm/viewsets/buttons/__init__.py +7 -0
  149. wbcrm/viewsets/buttons/accounts.py +27 -0
  150. wbcrm/viewsets/buttons/activities.py +89 -0
  151. wbcrm/viewsets/buttons/signals.py +17 -0
  152. wbcrm/viewsets/display/__init__.py +12 -0
  153. wbcrm/viewsets/display/accounts.py +110 -0
  154. wbcrm/viewsets/display/activities.py +444 -0
  155. wbcrm/viewsets/display/groups.py +22 -0
  156. wbcrm/viewsets/display/products.py +105 -0
  157. wbcrm/viewsets/endpoints/__init__.py +8 -0
  158. wbcrm/viewsets/endpoints/accounts.py +25 -0
  159. wbcrm/viewsets/endpoints/activities.py +30 -0
  160. wbcrm/viewsets/endpoints/groups.py +7 -0
  161. wbcrm/viewsets/endpoints/products.py +9 -0
  162. wbcrm/viewsets/groups.py +38 -0
  163. wbcrm/viewsets/menu/__init__.py +8 -0
  164. wbcrm/viewsets/menu/accounts.py +18 -0
  165. wbcrm/viewsets/menu/activities.py +49 -0
  166. wbcrm/viewsets/menu/groups.py +16 -0
  167. wbcrm/viewsets/menu/products.py +20 -0
  168. wbcrm/viewsets/mixins.py +35 -0
  169. wbcrm/viewsets/previews/__init__.py +1 -0
  170. wbcrm/viewsets/previews/activities.py +10 -0
  171. wbcrm/viewsets/products.py +57 -0
  172. wbcrm/viewsets/recurrence.py +27 -0
  173. wbcrm/viewsets/titles/__init__.py +13 -0
  174. wbcrm/viewsets/titles/accounts.py +23 -0
  175. wbcrm/viewsets/titles/activities.py +61 -0
  176. wbcrm/viewsets/titles/products.py +13 -0
  177. wbcrm/viewsets/titles/utils.py +46 -0
  178. wbcrm/workflows/__init__.py +1 -0
  179. wbcrm/workflows/assignee_methods.py +25 -0
  180. wbcrm-1.56.8.dist-info/METADATA +11 -0
  181. wbcrm-1.56.8.dist-info/RECORD +182 -0
  182. wbcrm-1.56.8.dist-info/WHEEL +5 -0
@@ -0,0 +1,38 @@
1
+ from rest_framework.decorators import action
2
+ from wbcore import viewsets
3
+ from wbcore.metadata.configs.display.instance_display.shortcuts import (
4
+ create_simple_display,
5
+ )
6
+ from wbcore.viewsets import RepresentationViewSet
7
+
8
+ from wbcrm.filters import GroupFilter
9
+ from wbcrm.models import Group
10
+ from wbcrm.serializers import GroupModelSerializer, GroupRepresentationSerializer
11
+ from wbcrm.viewsets.display import GroupModelDisplay
12
+ from wbcrm.viewsets.endpoints import GroupEndpointConfig
13
+
14
+
15
+ class GroupRepresentationViewSet(RepresentationViewSet):
16
+ queryset = Group.objects.all()
17
+ search_fields = ("title",)
18
+ serializer_class = GroupRepresentationSerializer
19
+
20
+
21
+ class GroupModelViewSet(viewsets.ModelViewSet):
22
+ LIST_DOCUMENTATION = "wbcrm/markdown/documentation/group.md"
23
+ IDENTIFIER = "wbcrm:group"
24
+ ordering = ("title",)
25
+ ordering_fields = ("title", "members")
26
+ search_fields = ("title",)
27
+ filterset_class = GroupFilter
28
+ queryset = Group.objects.all().prefetch_related("members")
29
+ serializer_class = GroupModelSerializer
30
+ display_config_class = GroupModelDisplay
31
+ endpoint_config_class = GroupEndpointConfig
32
+
33
+ @action(methods=["GET"], detail=True)
34
+ def pre_change(self, request, pk=None):
35
+ return viewsets.PreAction(
36
+ message="Do you really want to change this?",
37
+ instance_display=create_simple_display([["title"]]),
38
+ ).to_response()
@@ -0,0 +1,8 @@
1
+ from .accounts import ACCOUNT_MENUITEM
2
+ from .activities import (
3
+ ACTIVITY_MENUTITEM,
4
+ ACTIVITYCHART_MENUITEM,
5
+ ACTIVITYTYPE_MENUITEM,
6
+ )
7
+ from .groups import GROUPS_MENUITEM
8
+ from .products import PRODUCT_MENUITEM
@@ -0,0 +1,18 @@
1
+ from wbcore.menus import ItemPermission, MenuItem
2
+ from wbcore.permissions.shortcuts import is_internal_user
3
+
4
+ ACCOUNT_MENUITEM = MenuItem(
5
+ label="Accounts",
6
+ endpoint="wbcrm:account-list",
7
+ endpoint_get_parameters={"parent__isnull": True},
8
+ permission=ItemPermission(
9
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_account"]
10
+ ),
11
+ add=MenuItem(
12
+ label="Create Account",
13
+ endpoint="wbcrm:account-list",
14
+ permission=ItemPermission(
15
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.add_account"]
16
+ ),
17
+ ),
18
+ )
@@ -0,0 +1,49 @@
1
+ from django.utils.translation import gettext_lazy as _
2
+ from wbcore.menus import ItemPermission, MenuItem
3
+ from wbcore.permissions.shortcuts import is_internal_user
4
+
5
+
6
+ def default_activity_create_get_params(request) -> dict:
7
+ return {"participants": request.user.profile.id}
8
+
9
+
10
+ ACTIVITYTYPE_MENUITEM = MenuItem(
11
+ label=_("Activity Types"),
12
+ endpoint="wbcrm:activitytype-list",
13
+ permission=ItemPermission(
14
+ method=lambda request: is_internal_user(request.user),
15
+ permissions=["wbcrm.view_activitytype"],
16
+ ),
17
+ add=MenuItem(
18
+ label=_("Create Activity Type"),
19
+ endpoint="wbcrm:activitytype-list",
20
+ permission=ItemPermission(
21
+ method=lambda request: is_internal_user(request.user),
22
+ permissions=["wbcrm.add_activitytype"],
23
+ ),
24
+ ),
25
+ )
26
+
27
+
28
+ ACTIVITY_MENUTITEM = MenuItem(
29
+ label=_("Activities"),
30
+ endpoint="wbcrm:activity-list",
31
+ permission=ItemPermission(
32
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_activity"]
33
+ ),
34
+ add=MenuItem(
35
+ label=_("Create Activity"),
36
+ endpoint="wbcrm:activity-list",
37
+ permission=ItemPermission(
38
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.add_activity"]
39
+ ),
40
+ endpoint_get_parameters=default_activity_create_get_params,
41
+ ),
42
+ )
43
+ ACTIVITYCHART_MENUITEM = MenuItem(
44
+ label=_("Activity Chart"),
45
+ endpoint="wbcrm:activitychart-list",
46
+ permission=ItemPermission(
47
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_activity"]
48
+ ),
49
+ )
@@ -0,0 +1,16 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.menus import ItemPermission, MenuItem
3
+ from wbcore.permissions.shortcuts import is_internal_user
4
+
5
+ GROUPS_MENUITEM = MenuItem(
6
+ label=_("Groups"),
7
+ endpoint="wbcrm:group-list",
8
+ permission=ItemPermission(method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_group"]),
9
+ add=MenuItem(
10
+ label=_("Create Groups"),
11
+ endpoint="wbcrm:group-list",
12
+ permission=ItemPermission(
13
+ method=lambda request: is_internal_user(request.user), permissions=["wbcrm.add_group"]
14
+ ),
15
+ ),
16
+ )
@@ -0,0 +1,20 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.menus import ItemPermission, MenuItem
3
+ from wbcore.permissions.shortcuts import is_internal_user
4
+
5
+ PRODUCT_MENUITEM = MenuItem(
6
+ label=_("Products"),
7
+ endpoint="wbcrm:product-list",
8
+ permission=ItemPermission(
9
+ method=lambda request: is_internal_user(request.user),
10
+ permissions=["wbcrm.view_product"],
11
+ ),
12
+ add=MenuItem(
13
+ label=_("Create Product"),
14
+ endpoint="wbcrm:product-list",
15
+ permission=ItemPermission(
16
+ method=lambda request: is_internal_user(request.user),
17
+ permissions=["wbcrm.add_product"],
18
+ ),
19
+ ),
20
+ )
@@ -0,0 +1,35 @@
1
+ from datetime import date
2
+
3
+ from django.utils.functional import cached_property
4
+
5
+ from wbcrm.models.accounts import Account, AccountRole
6
+
7
+
8
+ class AccountPermissionMixin:
9
+ queryset = Account.objects.all()
10
+
11
+ @cached_property
12
+ def validity_date(self) -> date:
13
+ if validity_date_repr := self.request.GET.get("validity_date"):
14
+ return date.strftime(validity_date_repr, "%Y-%m-%d")
15
+ return date.today()
16
+
17
+ def get_queryset(self, *args, **kwargs):
18
+ return (
19
+ super().get_queryset(*args, **kwargs).filter_for_user(self.request.user, validity_date=self.validity_date)
20
+ )
21
+
22
+
23
+ class AccountRolePermissionMixin:
24
+ queryset = AccountRole.objects.all()
25
+
26
+ @cached_property
27
+ def validity_date(self) -> date:
28
+ if validity_date_repr := self.request.GET.get("validity_date"):
29
+ return date.strftime(validity_date_repr, "%Y-%m-%d")
30
+ return date.today()
31
+
32
+ def get_queryset(self, *args, **kwargs):
33
+ return (
34
+ super().get_queryset(*args, **kwargs).filter_for_user(self.request.user, validity_date=self.validity_date)
35
+ )
@@ -0,0 +1 @@
1
+ from .activities import ActivityPreviewConfig
@@ -0,0 +1,10 @@
1
+ from wbcore.metadata.configs.display.instance_display.shortcuts import (
2
+ Display,
3
+ create_simple_display,
4
+ )
5
+ from wbcore.metadata.configs.preview import PreviewViewConfig
6
+
7
+
8
+ class ActivityPreviewConfig(PreviewViewConfig):
9
+ def get_display(self) -> Display:
10
+ return create_simple_display([["title", "type", "result"]])
@@ -0,0 +1,57 @@
1
+ from django.db.models import F
2
+ from wbcore import viewsets
3
+
4
+ from wbcrm.filters.products import ProductCompanyFilterSet, ProductFilterSet
5
+ from wbcrm.models import Product, ProductCompanyRelationship
6
+ from wbcrm.serializers import (
7
+ ProductCompanyRelationshipModelSerializer,
8
+ ProductModelSerializer,
9
+ ProductRepresentationSerializer,
10
+ )
11
+ from wbcrm.viewsets.display import ProductCompanyRelationshipDisplay, ProductDisplay
12
+ from wbcrm.viewsets.endpoints import ProductCompanyRelationshipEndpointConfig
13
+ from wbcrm.viewsets.titles import ProductTitleConfig
14
+
15
+
16
+ class ProductModelViewSet(viewsets.ModelViewSet):
17
+ IDENTIFIER = "wbcrm:product"
18
+ LIST_DOCUMENTATION = "wbcrm/markdown/documentation/product.md"
19
+ queryset = Product.objects.all()
20
+ serializer_class = ProductModelSerializer
21
+ display_config_class = ProductDisplay
22
+ title_config_class = ProductTitleConfig
23
+ search_fields = ("title",)
24
+
25
+ filterset_class = ProductFilterSet
26
+ ordering_fields = ("title",)
27
+ ordering = ["title", "is_competitor"]
28
+
29
+
30
+ class ProductCompanyRelationshipCompanyModelViewSet(viewsets.ModelViewSet):
31
+ IDENTIFIER = "wbcrm:company-interestedproduct"
32
+ queryset = ProductCompanyRelationship.objects.all()
33
+ serializer_class = ProductCompanyRelationshipModelSerializer
34
+ display_config_class = ProductCompanyRelationshipDisplay
35
+ title_config_class = ProductTitleConfig
36
+ endpoint_config_class = ProductCompanyRelationshipEndpointConfig
37
+ search_fields = ("product__title",)
38
+ ordering_fields = ("product__title",)
39
+ ordering = ("product__title", "company__name")
40
+ filterset_class = ProductCompanyFilterSet
41
+
42
+ def get_queryset(self):
43
+ qs = (
44
+ super()
45
+ .get_queryset()
46
+ .filter(company=self.kwargs["company_id"])
47
+ .annotate(competitor_product=F("product__is_competitor"))
48
+ )
49
+ return qs
50
+
51
+
52
+ class ProductRepresentationViewSet(viewsets.RepresentationViewSet):
53
+ IDENTIFIER = "wbcrm:productrepresentation"
54
+ serializer_class = ProductRepresentationSerializer
55
+ search_fields = ("title",)
56
+ queryset = Product.objects.all()
57
+ ordering = ("title", "is_competitor")
@@ -0,0 +1,27 @@
1
+ from django.contrib.messages import warning
2
+ from django.shortcuts import get_object_or_404
3
+ from django.utils.translation import gettext as _
4
+ from rest_framework import permissions
5
+ from rest_framework.decorators import action
6
+ from rest_framework.response import Response
7
+
8
+ from wbcrm.models.recurrence import Recurrence
9
+
10
+
11
+ class RecurrenceModelViewSetMixin:
12
+ @action(detail=True, methods=["DELETE"], permission_classes=[permissions.IsAuthenticated])
13
+ def delete_next_occurrences(self, request, pk=None):
14
+ instance = get_object_or_404(self.queryset.model, pk=pk)
15
+ instance.forward_deletion()
16
+ return Response({})
17
+
18
+ def add_messages(self, request, instance=None, **kwargs):
19
+ if instance:
20
+ # If true, this activity is recurring.
21
+ if instance.is_recurrent:
22
+ warning(
23
+ request,
24
+ _("This is a recurring occurrence with period {repeat_choice}").format(
25
+ repeat_choice=Recurrence.ReoccuranceChoice(instance.repeat_choice).label
26
+ ),
27
+ )
@@ -0,0 +1,13 @@
1
+ from wbcrm.viewsets.titles.activities import (
2
+ ActivityChartModelTitleConfig,
3
+ ActivityParticipantTitleConfig,
4
+ ActivityTitleConfig,
5
+ ActivityTypeTitleConfig,
6
+ )
7
+
8
+ from .accounts import (
9
+ AccountRoleAccountTitleConfig,
10
+ AccountTitleConfig,
11
+ ChildAccountAccountTitleConfig,
12
+ )
13
+ from .products import ProductTitleConfig
@@ -0,0 +1,23 @@
1
+ from wbcore.metadata.configs.titles import TitleViewConfig
2
+
3
+ from wbcrm.models.accounts import Account
4
+
5
+
6
+ class AccountTitleConfig(TitleViewConfig):
7
+ def get_instance_title(self):
8
+ return "Account: {{title}}"
9
+
10
+ def get_list_title(self):
11
+ return "Accounts"
12
+
13
+
14
+ class ChildAccountAccountTitleConfig(TitleViewConfig):
15
+ def get_list_title(self):
16
+ account = Account.all_objects.get(id=self.view.kwargs["account_id"])
17
+ return f"{account.title}: Sub Accounts"
18
+
19
+
20
+ class AccountRoleAccountTitleConfig(TitleViewConfig):
21
+ def get_list_title(self):
22
+ account = Account.all_objects.get(id=self.view.kwargs["account_id"])
23
+ return f"Roles for Account {str(account)}"
@@ -0,0 +1,61 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.metadata.configs.titles import TitleViewConfig
3
+
4
+
5
+ class ActivityTypeTitleConfig(TitleViewConfig):
6
+ def get_list_title(self):
7
+ return _("Activity Types")
8
+
9
+ def get_create_title(self):
10
+ return _("New Activity Type")
11
+
12
+ def get_instance_title(self):
13
+ return _("Activity Type")
14
+
15
+
16
+ class ActivityTitleConfig(TitleViewConfig):
17
+ def get_instance_title(self):
18
+ if "pk" in self.view.kwargs:
19
+ if self.view.is_private_for_user:
20
+ return _("Private Activity")
21
+
22
+ elif self.view.is_confidential_for_user:
23
+ return _("Confidential Activity")
24
+
25
+ return _("Activity: {{title}}")
26
+
27
+ def get_delete_title(self):
28
+ if "pk" in self.view.kwargs:
29
+ if self.view.is_private_for_user:
30
+ return _("Delete Private Activity")
31
+
32
+ elif self.view.is_confidential_for_user:
33
+ return _("Delete Confidential Activity")
34
+
35
+ return _("Delete Activity: {{title}}")
36
+
37
+ def get_list_title(self):
38
+ if self.view.participants.exists():
39
+ if self.view.participants.count() == 1:
40
+ return _("Activities for {person}").format(person=str(self.view.participants.first()))
41
+ else:
42
+ return _("Activities for Multiple Persons")
43
+
44
+ if self.view.companies.exists():
45
+ return _("Activities for {}").format(", ".join(self.view.companies.values_list("name", flat=True)))
46
+ return _("Activities")
47
+
48
+ def get_create_title(self):
49
+ if self.view.entry:
50
+ return _("New Activity for {entry}").format(entry=self.view.entry.computed_str)
51
+ return _("New Activity")
52
+
53
+
54
+ class ActivityParticipantTitleConfig(TitleViewConfig):
55
+ def get_instance_title(self):
56
+ return _("Participation Status")
57
+
58
+
59
+ class ActivityChartModelTitleConfig(TitleViewConfig):
60
+ def get_list_title(self):
61
+ return _("Activity Chart")
@@ -0,0 +1,13 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.metadata.configs.titles import TitleViewConfig
3
+
4
+
5
+ class ProductTitleConfig(TitleViewConfig):
6
+ def get_list_title(self):
7
+ return _("Products")
8
+
9
+ def get_create_title(self):
10
+ return _("Add Product")
11
+
12
+ def get_instance_title(self):
13
+ return _("Product")
@@ -0,0 +1,46 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.metadata.configs.titles import TitleViewConfig
3
+
4
+
5
+ class CustomerStatusTitleConfig(TitleViewConfig):
6
+ def get_list_title(self):
7
+ return _("Customer Statuses")
8
+
9
+ def get_create_title(self):
10
+ return _("New Customer Status")
11
+
12
+ def get_instance_title(self):
13
+ return _("Customer Status")
14
+
15
+
16
+ class PositionTitleConfig(TitleViewConfig):
17
+ def get_list_title(self):
18
+ return _("Company Positions")
19
+
20
+ def get_create_title(self):
21
+ return _("New Company Position")
22
+
23
+ def get_instance_title(self):
24
+ return _("Company Position")
25
+
26
+
27
+ class CompanyTypeTitleConfig(TitleViewConfig):
28
+ def get_list_title(self):
29
+ return _("Company Types")
30
+
31
+ def get_create_title(self):
32
+ return _("New Company Type")
33
+
34
+ def get_instance_title(self):
35
+ return _("Company Type")
36
+
37
+
38
+ class SpecializationTitleConfig(TitleViewConfig):
39
+ def get_list_title(self):
40
+ return _("Specializations")
41
+
42
+ def get_create_title(self):
43
+ return _("New Specialization")
44
+
45
+ def get_instance_title(self):
46
+ return _("Specialization")
@@ -0,0 +1 @@
1
+ from .assignee_methods import *
@@ -0,0 +1,25 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.contrib.authentication.models import User
3
+ from wbcore.contrib.directory.models import Person
4
+ from wbcore.contrib.workflow.decorators import register_assignee
5
+ from wbcore.contrib.workflow.models import ProcessStep
6
+
7
+ # We need to migrate upon name changes!
8
+
9
+
10
+ # TODO: Generalize this through field filter
11
+ @register_assignee("Activity Assignee")
12
+ def activity_assignee(process_step: ProcessStep, **kwargs) -> User | None:
13
+ if hasattr(process_step.process.instance, "assigned_to"):
14
+ assignee: Person = process_step.process.instance.assigned_to
15
+ if hasattr(assignee, "user_account"):
16
+ return assignee.user_account
17
+ else:
18
+ error_message = _("Assignee has no user account!")
19
+ else:
20
+ error_message = _("No activity attached!")
21
+
22
+ process_step.step.get_casted_step().set_failed(
23
+ process_step, _("Error in assignee method: {}").format(error_message)
24
+ )
25
+ return None
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: wbcrm
3
+ Version: 1.56.8
4
+ Summary: A workbench module that contains all the functionality related to a customer relationship management.
5
+ Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
6
+ Requires-Dist: django-eventtools==1.*
7
+ Requires-Dist: google-api-python-client==2.62.*
8
+ Requires-Dist: google-auth-httplib2==0.1.*
9
+ Requires-Dist: google-auth-oauthlib==0.5.*
10
+ Requires-Dist: wbcore
11
+ Requires-Dist: xlsxwriter==3.*