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
wbcrm/viewsets/groups.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
from wbcrm.filters import GroupFilter
|
|
8
|
+
from wbcrm.models import Group
|
|
9
|
+
from wbcrm.serializers import GroupModelSerializer, GroupRepresentationSerializer
|
|
10
|
+
from wbcrm.viewsets.display import GroupModelDisplay
|
|
11
|
+
from wbcrm.viewsets.endpoints import GroupEndpointConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GroupRepresentationViewSet(RepresentationViewSet):
|
|
15
|
+
queryset = Group.objects.all()
|
|
16
|
+
search_fields = ("title",)
|
|
17
|
+
serializer_class = GroupRepresentationSerializer
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GroupModelViewSet(viewsets.ModelViewSet):
|
|
21
|
+
LIST_DOCUMENTATION = "wbcrm/markdown/documentation/group.md"
|
|
22
|
+
IDENTIFIER = "wbcrm:group"
|
|
23
|
+
ordering = ("title",)
|
|
24
|
+
ordering_fields = ("title", "members")
|
|
25
|
+
search_fields = ("title",)
|
|
26
|
+
filterset_class = GroupFilter
|
|
27
|
+
queryset = Group.objects.all().prefetch_related("members")
|
|
28
|
+
serializer_class = GroupModelSerializer
|
|
29
|
+
display_config_class = GroupModelDisplay
|
|
30
|
+
endpoint_config_class = GroupEndpointConfig
|
|
31
|
+
|
|
32
|
+
@action(methods=["GET"], detail=True)
|
|
33
|
+
def pre_change(self, request, pk=None):
|
|
34
|
+
return viewsets.PreAction(
|
|
35
|
+
message="Do you really want to change this?",
|
|
36
|
+
instance_display=create_simple_display([["title"]]),
|
|
37
|
+
).to_response()
|
|
@@ -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,61 @@
|
|
|
1
|
+
from datetime import timedelta
|
|
2
|
+
|
|
3
|
+
from django.utils import timezone
|
|
4
|
+
from django.utils.translation import gettext as _
|
|
5
|
+
from wbcore.menus import ItemPermission, MenuItem
|
|
6
|
+
from wbcore.permissions.shortcuts import is_internal_user
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def default_activity_create_get_params(request) -> dict:
|
|
10
|
+
return {"participants": request.user.profile.id}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def default_activitychart_get_params(request) -> dict:
|
|
14
|
+
current_last_week_date_start = timezone.now().date() - timedelta(days=7)
|
|
15
|
+
current_next_week_date_end = timezone.now().date() + timedelta(days=7)
|
|
16
|
+
|
|
17
|
+
return {"period": f"{current_last_week_date_start:%Y-%m-%d},{current_next_week_date_end:%Y-%m-%d}"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
ACTIVITYTYPE_MENUITEM = MenuItem(
|
|
21
|
+
label=_("Activity Types"),
|
|
22
|
+
endpoint="wbcrm:activitytype-list",
|
|
23
|
+
permission=ItemPermission(
|
|
24
|
+
method=lambda request: is_internal_user(request.user),
|
|
25
|
+
permissions=["wbcrm.view_activitytype"],
|
|
26
|
+
),
|
|
27
|
+
add=MenuItem(
|
|
28
|
+
label=_("Create Activity Type"),
|
|
29
|
+
endpoint="wbcrm:activitytype-list",
|
|
30
|
+
permission=ItemPermission(
|
|
31
|
+
method=lambda request: is_internal_user(request.user),
|
|
32
|
+
permissions=["wbcrm.add_activitytype"],
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
ACTIVITY_MENUTITEM = MenuItem(
|
|
39
|
+
label=_("Activities"),
|
|
40
|
+
endpoint="wbcrm:activity-list",
|
|
41
|
+
permission=ItemPermission(
|
|
42
|
+
method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_activity"]
|
|
43
|
+
),
|
|
44
|
+
# endpoint_get_parameters={"only_recent": True}, # TODO confirm that this can actually be commented out
|
|
45
|
+
add=MenuItem(
|
|
46
|
+
label=_("Create Activity"),
|
|
47
|
+
endpoint="wbcrm:activity-list",
|
|
48
|
+
permission=ItemPermission(
|
|
49
|
+
method=lambda request: is_internal_user(request.user), permissions=["wbcrm.add_activity"]
|
|
50
|
+
),
|
|
51
|
+
endpoint_get_parameters=default_activity_create_get_params,
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
ACTIVITYCHART_MENUITEM = MenuItem(
|
|
55
|
+
label=_("Activity Chart"),
|
|
56
|
+
endpoint="wbcrm:activitychart-list",
|
|
57
|
+
permission=ItemPermission(
|
|
58
|
+
method=lambda request: is_internal_user(request.user), permissions=["wbcrm.view_activity"]
|
|
59
|
+
),
|
|
60
|
+
endpoint_get_parameters=default_activitychart_get_params,
|
|
61
|
+
)
|
|
@@ -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
|
+
)
|
wbcrm/viewsets/mixins.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
|
|
3
|
+
from django.utils.functional import cached_property
|
|
4
|
+
from wbcrm.models.accounts import Account, AccountRole
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AccountPermissionMixin:
|
|
8
|
+
queryset = Account.objects.all()
|
|
9
|
+
|
|
10
|
+
@cached_property
|
|
11
|
+
def validity_date(self) -> date:
|
|
12
|
+
if validity_date_repr := self.request.GET.get("validity_date"):
|
|
13
|
+
return date.strftime(validity_date_repr, "%Y-%m-%d")
|
|
14
|
+
return date.today()
|
|
15
|
+
|
|
16
|
+
def get_queryset(self, *args, **kwargs):
|
|
17
|
+
return (
|
|
18
|
+
super().get_queryset(*args, **kwargs).filter_for_user(self.request.user, validity_date=self.validity_date)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AccountRolePermissionMixin:
|
|
23
|
+
queryset = AccountRole.objects.all()
|
|
24
|
+
|
|
25
|
+
@cached_property
|
|
26
|
+
def validity_date(self) -> date:
|
|
27
|
+
if validity_date_repr := self.request.GET.get("validity_date"):
|
|
28
|
+
return date.strftime(validity_date_repr, "%Y-%m-%d")
|
|
29
|
+
return date.today()
|
|
30
|
+
|
|
31
|
+
def get_queryset(self, *args, **kwargs):
|
|
32
|
+
return (
|
|
33
|
+
super().get_queryset(*args, **kwargs).filter_for_user(self.request.user, validity_date=self.validity_date)
|
|
34
|
+
)
|
|
@@ -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,56 @@
|
|
|
1
|
+
from django.db.models import F
|
|
2
|
+
from wbcore import viewsets
|
|
3
|
+
from wbcrm.filters.products import ProductCompanyFilterSet, ProductFilterSet
|
|
4
|
+
from wbcrm.models import Product, ProductCompanyRelationship
|
|
5
|
+
from wbcrm.serializers import (
|
|
6
|
+
ProductCompanyRelationshipModelSerializer,
|
|
7
|
+
ProductModelSerializer,
|
|
8
|
+
ProductRepresentationSerializer,
|
|
9
|
+
)
|
|
10
|
+
from wbcrm.viewsets.display import ProductCompanyRelationshipDisplay, ProductDisplay
|
|
11
|
+
from wbcrm.viewsets.endpoints import ProductCompanyRelationshipEndpointConfig
|
|
12
|
+
from wbcrm.viewsets.titles import ProductTitleConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ProductModelViewSet(viewsets.ModelViewSet):
|
|
16
|
+
IDENTIFIER = "wbcrm:product"
|
|
17
|
+
LIST_DOCUMENTATION = "wbcrm/markdown/documentation/product.md"
|
|
18
|
+
queryset = Product.objects.all()
|
|
19
|
+
serializer_class = ProductModelSerializer
|
|
20
|
+
display_config_class = ProductDisplay
|
|
21
|
+
title_config_class = ProductTitleConfig
|
|
22
|
+
search_fields = ("title",)
|
|
23
|
+
|
|
24
|
+
filterset_class = ProductFilterSet
|
|
25
|
+
ordering_fields = ("title",)
|
|
26
|
+
ordering = ["title", "is_competitor"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ProductCompanyRelationshipCompanyModelViewSet(viewsets.ModelViewSet):
|
|
30
|
+
IDENTIFIER = "wbcrm:company-interestedproduct"
|
|
31
|
+
queryset = ProductCompanyRelationship.objects.all()
|
|
32
|
+
serializer_class = ProductCompanyRelationshipModelSerializer
|
|
33
|
+
display_config_class = ProductCompanyRelationshipDisplay
|
|
34
|
+
title_config_class = ProductTitleConfig
|
|
35
|
+
endpoint_config_class = ProductCompanyRelationshipEndpointConfig
|
|
36
|
+
search_fields = ("product__title",)
|
|
37
|
+
ordering_fields = ("product__title",)
|
|
38
|
+
ordering = ("product__title", "company__name")
|
|
39
|
+
filterset_class = ProductCompanyFilterSet
|
|
40
|
+
|
|
41
|
+
def get_queryset(self):
|
|
42
|
+
qs = (
|
|
43
|
+
super()
|
|
44
|
+
.get_queryset()
|
|
45
|
+
.filter(company=self.kwargs["company_id"])
|
|
46
|
+
.annotate(competitor_product=F("product__is_competitor"))
|
|
47
|
+
)
|
|
48
|
+
return qs
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ProductRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
52
|
+
IDENTIFIER = "wbcrm:productrepresentation"
|
|
53
|
+
serializer_class = ProductRepresentationSerializer
|
|
54
|
+
search_fields = ("title",)
|
|
55
|
+
queryset = Product.objects.all()
|
|
56
|
+
ordering = ("title", "is_competitor")
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
from wbcrm.models.recurrence import Recurrence
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RecurrenceModelViewSetMixin:
|
|
11
|
+
@action(detail=True, methods=["DELETE"], permission_classes=[permissions.IsAuthenticated])
|
|
12
|
+
def delete_next_occurrences(self, request, pk=None):
|
|
13
|
+
instance = get_object_or_404(self.queryset.model, pk=pk)
|
|
14
|
+
instance.forward_deletion()
|
|
15
|
+
return Response({})
|
|
16
|
+
|
|
17
|
+
def add_messages(self, request, instance=None, **kwargs):
|
|
18
|
+
if instance:
|
|
19
|
+
# If true, this activity is recurring.
|
|
20
|
+
if instance.is_recurrent:
|
|
21
|
+
warning(
|
|
22
|
+
request,
|
|
23
|
+
_("This is a recurring occurrence with period {repeat_choice}").format(
|
|
24
|
+
repeat_choice=Recurrence.ReoccuranceChoice(instance.repeat_choice).label
|
|
25
|
+
),
|
|
26
|
+
)
|
|
@@ -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,22 @@
|
|
|
1
|
+
from wbcore.metadata.configs.titles import TitleViewConfig
|
|
2
|
+
from wbcrm.models.accounts import Account
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AccountTitleConfig(TitleViewConfig):
|
|
6
|
+
def get_instance_title(self):
|
|
7
|
+
return "Account: {{title}}"
|
|
8
|
+
|
|
9
|
+
def get_list_title(self):
|
|
10
|
+
return "Accounts"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ChildAccountAccountTitleConfig(TitleViewConfig):
|
|
14
|
+
def get_list_title(self):
|
|
15
|
+
account = Account.objects.get(id=self.view.kwargs["account_id"])
|
|
16
|
+
return f"{account.title}: Sub Accounts"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AccountRoleAccountTitleConfig(TitleViewConfig):
|
|
20
|
+
def get_list_title(self):
|
|
21
|
+
account = Account.objects.get(id=self.view.kwargs["account_id"])
|
|
22
|
+
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 = getattr(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.3
|
|
2
|
+
Name: wbcrm
|
|
3
|
+
Version: 2.2.1
|
|
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.*
|