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.

Files changed (155) hide show
  1. wbcrm/__init__.py +1 -0
  2. wbcrm/admin/__init__.py +4 -0
  3. wbcrm/admin/accounts.py +59 -0
  4. wbcrm/admin/activities.py +101 -0
  5. wbcrm/admin/groups.py +7 -0
  6. wbcrm/admin/products.py +8 -0
  7. wbcrm/apps.py +5 -0
  8. wbcrm/configurations/__init__.py +1 -0
  9. wbcrm/configurations/base.py +16 -0
  10. wbcrm/dynamic_preferences_registry.py +38 -0
  11. wbcrm/factories/__init__.py +14 -0
  12. wbcrm/factories/accounts.py +56 -0
  13. wbcrm/factories/activities.py +125 -0
  14. wbcrm/factories/groups.py +23 -0
  15. wbcrm/factories/products.py +10 -0
  16. wbcrm/filters/__init__.py +10 -0
  17. wbcrm/filters/accounts.py +67 -0
  18. wbcrm/filters/activities.py +181 -0
  19. wbcrm/filters/groups.py +20 -0
  20. wbcrm/filters/products.py +37 -0
  21. wbcrm/filters/signals.py +94 -0
  22. wbcrm/migrations/0001_initial_squashed_squashed_0032_productcompanyrelationship_alter_product_prospects_and_more.py +3948 -0
  23. wbcrm/migrations/0002_alter_activity_repeat_choice.py +32 -0
  24. wbcrm/migrations/0003_remove_activity_external_id_and_more.py +63 -0
  25. wbcrm/migrations/0004_alter_activity_status.py +28 -0
  26. wbcrm/migrations/0005_account_accountrole_accountroletype_and_more.py +182 -0
  27. wbcrm/migrations/0006_alter_activity_location.py +17 -0
  28. wbcrm/migrations/0007_alter_account_status.py +23 -0
  29. wbcrm/migrations/0008_alter_activity_options.py +16 -0
  30. wbcrm/migrations/0009_alter_account_is_public.py +19 -0
  31. wbcrm/migrations/0010_alter_account_reference_id.py +17 -0
  32. wbcrm/migrations/0011_activity_summary.py +22 -0
  33. wbcrm/migrations/0012_alter_activity_summary.py +17 -0
  34. wbcrm/migrations/0013_account_action_plan_account_relationship_status_and_more.py +34 -0
  35. wbcrm/migrations/0014_alter_account_relationship_status.py +24 -0
  36. wbcrm/migrations/0015_alter_activity_type.py +23 -0
  37. wbcrm/migrations/0016_auto_20241205_1015.py +106 -0
  38. wbcrm/migrations/__init__.py +0 -0
  39. wbcrm/models/__init__.py +4 -0
  40. wbcrm/models/accounts.py +637 -0
  41. wbcrm/models/activities.py +1335 -0
  42. wbcrm/models/groups.py +118 -0
  43. wbcrm/models/products.py +83 -0
  44. wbcrm/models/recurrence.py +279 -0
  45. wbcrm/preferences.py +14 -0
  46. wbcrm/serializers/__init__.py +23 -0
  47. wbcrm/serializers/accounts.py +126 -0
  48. wbcrm/serializers/activities.py +526 -0
  49. wbcrm/serializers/groups.py +30 -0
  50. wbcrm/serializers/products.py +57 -0
  51. wbcrm/serializers/recurrence.py +90 -0
  52. wbcrm/serializers/signals.py +70 -0
  53. wbcrm/synchronization/__init__.py +0 -0
  54. wbcrm/synchronization/activity/__init__.py +0 -0
  55. wbcrm/synchronization/activity/admin.py +72 -0
  56. wbcrm/synchronization/activity/backend.py +207 -0
  57. wbcrm/synchronization/activity/backends/__init__.py +0 -0
  58. wbcrm/synchronization/activity/backends/google/__init__.py +2 -0
  59. wbcrm/synchronization/activity/backends/google/google_calendar_backend.py +399 -0
  60. wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
  61. wbcrm/synchronization/activity/backends/google/tasks.py +21 -0
  62. wbcrm/synchronization/activity/backends/google/tests/__init__.py +0 -0
  63. wbcrm/synchronization/activity/backends/google/tests/conftest.py +1 -0
  64. wbcrm/synchronization/activity/backends/google/tests/test_data.py +81 -0
  65. wbcrm/synchronization/activity/backends/google/tests/test_google_backend.py +319 -0
  66. wbcrm/synchronization/activity/backends/google/tests/test_utils.py +274 -0
  67. wbcrm/synchronization/activity/backends/google/typing_informations.py +139 -0
  68. wbcrm/synchronization/activity/backends/google/utils.py +216 -0
  69. wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
  70. wbcrm/synchronization/activity/backends/outlook/backend.py +576 -0
  71. wbcrm/synchronization/activity/backends/outlook/msgraph.py +438 -0
  72. wbcrm/synchronization/activity/backends/outlook/parser.py +423 -0
  73. wbcrm/synchronization/activity/backends/outlook/tests/__init__.py +0 -0
  74. wbcrm/synchronization/activity/backends/outlook/tests/conftest.py +1 -0
  75. wbcrm/synchronization/activity/backends/outlook/tests/fixtures.py +606 -0
  76. wbcrm/synchronization/activity/backends/outlook/tests/test_admin.py +117 -0
  77. wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +269 -0
  78. wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +237 -0
  79. wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +173 -0
  80. wbcrm/synchronization/activity/controller.py +545 -0
  81. wbcrm/synchronization/activity/dynamic_preferences_registry.py +107 -0
  82. wbcrm/synchronization/activity/preferences.py +21 -0
  83. wbcrm/synchronization/activity/shortcuts.py +9 -0
  84. wbcrm/synchronization/activity/signals.py +28 -0
  85. wbcrm/synchronization/activity/tasks.py +21 -0
  86. wbcrm/synchronization/activity/urls.py +6 -0
  87. wbcrm/synchronization/activity/utils.py +46 -0
  88. wbcrm/synchronization/activity/views.py +37 -0
  89. wbcrm/synchronization/admin.py +1 -0
  90. wbcrm/synchronization/apps.py +15 -0
  91. wbcrm/synchronization/dynamic_preferences_registry.py +1 -0
  92. wbcrm/synchronization/management.py +36 -0
  93. wbcrm/synchronization/tasks.py +1 -0
  94. wbcrm/synchronization/urls.py +5 -0
  95. wbcrm/tasks.py +312 -0
  96. wbcrm/tests/__init__.py +0 -0
  97. wbcrm/tests/accounts/__init__.py +0 -0
  98. wbcrm/tests/accounts/test_models.py +380 -0
  99. wbcrm/tests/accounts/test_viewsets.py +87 -0
  100. wbcrm/tests/conftest.py +76 -0
  101. wbcrm/tests/disable_signals.py +52 -0
  102. wbcrm/tests/e2e/__init__.py +1 -0
  103. wbcrm/tests/e2e/e2e_wbcrm_utility.py +82 -0
  104. wbcrm/tests/e2e/test_e2e.py +369 -0
  105. wbcrm/tests/test_assignee_methods.py +39 -0
  106. wbcrm/tests/test_chartviewsets.py +111 -0
  107. wbcrm/tests/test_dto.py +63 -0
  108. wbcrm/tests/test_filters.py +51 -0
  109. wbcrm/tests/test_models.py +216 -0
  110. wbcrm/tests/test_recurrence.py +291 -0
  111. wbcrm/tests/test_report.py +20 -0
  112. wbcrm/tests/test_serializers.py +170 -0
  113. wbcrm/tests/test_tasks.py +94 -0
  114. wbcrm/tests/test_viewsets.py +967 -0
  115. wbcrm/tests/tests.py +120 -0
  116. wbcrm/typings.py +107 -0
  117. wbcrm/urls.py +67 -0
  118. wbcrm/viewsets/__init__.py +22 -0
  119. wbcrm/viewsets/accounts.py +121 -0
  120. wbcrm/viewsets/activities.py +315 -0
  121. wbcrm/viewsets/buttons/__init__.py +7 -0
  122. wbcrm/viewsets/buttons/accounts.py +27 -0
  123. wbcrm/viewsets/buttons/activities.py +68 -0
  124. wbcrm/viewsets/buttons/signals.py +17 -0
  125. wbcrm/viewsets/display/__init__.py +12 -0
  126. wbcrm/viewsets/display/accounts.py +110 -0
  127. wbcrm/viewsets/display/activities.py +443 -0
  128. wbcrm/viewsets/display/groups.py +22 -0
  129. wbcrm/viewsets/display/products.py +105 -0
  130. wbcrm/viewsets/endpoints/__init__.py +8 -0
  131. wbcrm/viewsets/endpoints/accounts.py +32 -0
  132. wbcrm/viewsets/endpoints/activities.py +30 -0
  133. wbcrm/viewsets/endpoints/groups.py +7 -0
  134. wbcrm/viewsets/endpoints/products.py +9 -0
  135. wbcrm/viewsets/groups.py +37 -0
  136. wbcrm/viewsets/menu/__init__.py +8 -0
  137. wbcrm/viewsets/menu/accounts.py +18 -0
  138. wbcrm/viewsets/menu/activities.py +61 -0
  139. wbcrm/viewsets/menu/groups.py +16 -0
  140. wbcrm/viewsets/menu/products.py +20 -0
  141. wbcrm/viewsets/mixins.py +34 -0
  142. wbcrm/viewsets/previews/__init__.py +1 -0
  143. wbcrm/viewsets/previews/activities.py +10 -0
  144. wbcrm/viewsets/products.py +56 -0
  145. wbcrm/viewsets/recurrence.py +26 -0
  146. wbcrm/viewsets/titles/__init__.py +13 -0
  147. wbcrm/viewsets/titles/accounts.py +22 -0
  148. wbcrm/viewsets/titles/activities.py +61 -0
  149. wbcrm/viewsets/titles/products.py +13 -0
  150. wbcrm/viewsets/titles/utils.py +46 -0
  151. wbcrm/workflows/__init__.py +1 -0
  152. wbcrm/workflows/assignee_methods.py +25 -0
  153. wbcrm-2.2.1.dist-info/METADATA +11 -0
  154. wbcrm-2.2.1.dist-info/RECORD +155 -0
  155. wbcrm-2.2.1.dist-info/WHEEL +5 -0
wbcrm/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -0,0 +1,4 @@
1
+ from .accounts import AccountRoleModelAdmin, AccountModelAdmin
2
+ from .activities import ActivityAdmin, ActivityTypeAdmin
3
+ from .groups import GroupModelAdmin
4
+ from .products import ProductAdmin
@@ -0,0 +1,59 @@
1
+ from django.contrib import admin
2
+ from mptt.admin import MPTTModelAdmin
3
+ from wbcrm.models.accounts import (
4
+ Account,
5
+ AccountRole,
6
+ AccountRoleType,
7
+ AccountRoleValidity,
8
+ )
9
+
10
+
11
+ class AccountRoleValidityTabularInline(admin.TabularInline):
12
+ model = AccountRoleValidity
13
+ fields = ("timespan",)
14
+ extra = 0
15
+
16
+
17
+ class AccountRoleTabularInline(admin.TabularInline):
18
+ model = AccountRole
19
+ fields = ("role_type", "entry", "weighting", "is_hidden")
20
+ autocomplete_fields = ["entry", "account"]
21
+ extra = 0
22
+ show_change_link = True
23
+
24
+
25
+ class AccountTabularInline(admin.TabularInline):
26
+ model = Account
27
+ fields = ("title", "status", "owner", "is_terminal_account", "is_active", "is_public")
28
+ autocomplete_fields = ["owner", "parent"]
29
+ fk_name = "parent"
30
+ show_change_link = True
31
+ extra = 0
32
+
33
+
34
+ @admin.register(AccountRoleType)
35
+ class AccountRoleTypeModelAdmin(admin.ModelAdmin):
36
+ list_display = ("title", "key")
37
+ search_fields = ("title", "key")
38
+
39
+
40
+ @admin.register(AccountRole)
41
+ class AccountRoleModelAdmin(admin.ModelAdmin):
42
+ list_display = ("role_type", "entry", "account", "is_hidden")
43
+ inlines = [AccountRoleValidityTabularInline]
44
+
45
+ def get_queryset(self, request):
46
+ return super().get_queryset(request).select_related("entry", "account")
47
+
48
+
49
+ @admin.register(Account)
50
+ class AccountModelAdmin(MPTTModelAdmin):
51
+ mptt_level_indent = 20
52
+ fsm_field = ["status"]
53
+ search_fields = ["title"]
54
+ list_display = ["computed_str", "status", "is_active", "is_terminal_account", "is_public", "owner"]
55
+ inlines = [AccountRoleTabularInline, AccountTabularInline]
56
+ autocomplete_fields = ["owner", "parent"]
57
+
58
+ def get_queryset(self, request):
59
+ return Account.all_objects.select_related("owner", "parent")
@@ -0,0 +1,101 @@
1
+ from django.contrib import admin
2
+ from django.utils.translation import gettext_lazy as _
3
+ from reversion.admin import VersionAdmin
4
+ from wbcrm.models import Activity, ActivityParticipant, ActivityType
5
+
6
+
7
+ class ParticipantInline(admin.TabularInline):
8
+ model = ActivityParticipant
9
+
10
+
11
+ class CompanyInline(admin.TabularInline):
12
+ model = ActivityParticipant
13
+
14
+
15
+ @admin.register(ActivityType)
16
+ class ActivityTypeAdmin(admin.ModelAdmin):
17
+ search_fields = ("title",)
18
+ list_display = ("id", "title")
19
+
20
+
21
+ class ActivityInline(admin.StackedInline):
22
+ model = Activity
23
+ fk_name = "parent_occurrence"
24
+ extra = 0
25
+ fieldsets = (
26
+ (
27
+ _("Main information"),
28
+ {
29
+ "fields": (
30
+ "title",
31
+ "description",
32
+ )
33
+ },
34
+ ),
35
+ )
36
+
37
+
38
+ @admin.register(Activity)
39
+ class ActivityAdmin(VersionAdmin):
40
+ search_fields = ("title",)
41
+ list_display = ("id", "status", "title", "period", "is_active", "parent_occurrence_id", "metadata")
42
+ fieldsets = (
43
+ (_("Main information"), {"fields": ("title", "description", "result", "creator")}),
44
+ (_("Meta"), {"fields": ("status", "type", "visibility", "is_active", "metadata")}),
45
+ (_("Temporal Information"), {"fields": ("period", "all_day")}),
46
+ (_("Geographical Information"), {"fields": ("location", "location_longitude", "location_latitude")}),
47
+ (_("Linked Entries"), {"fields": ("assigned_to", "groups")}),
48
+ (_("Linked Activities"), {"fields": ("preceded_by",)}),
49
+ (
50
+ _("Recurrence"),
51
+ {
52
+ "fields": (
53
+ "repeat_choice",
54
+ "parent_occurrence",
55
+ ("recurrence_count", "recurrence_end"),
56
+ "propagate_for_all_children",
57
+ )
58
+ },
59
+ ),
60
+ )
61
+
62
+ raw_id_fields = (
63
+ "assigned_to",
64
+ "participants",
65
+ "groups",
66
+ "preceded_by",
67
+ "creator",
68
+ "latest_reviewer",
69
+ "parent_occurrence",
70
+ )
71
+
72
+ inlines = [ActivityInline, ParticipantInline, CompanyInline]
73
+
74
+ def reversion_register(self, model, **options):
75
+ options = {
76
+ "exclude": (
77
+ "created",
78
+ "creator",
79
+ "edited",
80
+ ),
81
+ }
82
+ super().reversion_register(model, **options)
83
+
84
+ def get_queryset(self, request):
85
+ return Activity.all_objects.all()
86
+
87
+
88
+ @admin.register(ActivityParticipant)
89
+ class ActivityParticipantAdmin(VersionAdmin):
90
+ search_fields = ("activity", "participant")
91
+ list_display = ("id", "activity", "participant", "participation_status")
92
+
93
+ def reversion_register(self, model, **options):
94
+ options = {
95
+ "follow": (
96
+ "activity",
97
+ "participant",
98
+ "participation_status",
99
+ )
100
+ }
101
+ super().reversion_register(model, **options)
wbcrm/admin/groups.py ADDED
@@ -0,0 +1,7 @@
1
+ from django.contrib import admin
2
+ from wbcrm.models import Group
3
+
4
+
5
+ @admin.register(Group)
6
+ class GroupModelAdmin(admin.ModelAdmin):
7
+ autocomplete_fields = ("members",)
@@ -0,0 +1,8 @@
1
+ from django.contrib import admin
2
+ from wbcrm.models import Product
3
+
4
+
5
+ @admin.register(Product)
6
+ class ProductAdmin(admin.ModelAdmin):
7
+ search_fields = ("title",)
8
+ list_display = ("title", "id")
wbcrm/apps.py ADDED
@@ -0,0 +1,5 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class WbcrmConfig(AppConfig):
5
+ name = "wbcrm"
@@ -0,0 +1 @@
1
+ from .base import CRMDevBaseConfiguration, CRMProductionBaseConfiguration
@@ -0,0 +1,16 @@
1
+ from configurations import values
2
+ from wbcore.configurations import DevBaseConfiguration, ProductionBaseConfiguration
3
+
4
+
5
+ class CRMDevBaseConfiguration(DevBaseConfiguration):
6
+ SECRET_KEY = values.Value("THIS-IS-NOT-A-SECRET-KEY", environ_prefix=None)
7
+ DEBUG = values.BooleanValue(True, environ_prefix=None)
8
+ DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
9
+ DISABLE_NOTIFICATION = values.BooleanValue(False, environ_prefix=None)
10
+ DEV_USER = values.Value(None, environ_prefix=None)
11
+ ADD_REVERSION_ADMIN = True
12
+ DEFAULT_CREATE_ENDPOINT_BASENAME = values.Value("wbcrm:activity-list", environ_prefix=None)
13
+
14
+
15
+ class CRMProductionBaseConfiguration(ProductionBaseConfiguration):
16
+ pass
@@ -0,0 +1,38 @@
1
+ from django.utils.translation import gettext as _
2
+ from dynamic_preferences.preferences import Section
3
+ from dynamic_preferences.registries import global_preferences_registry
4
+ from dynamic_preferences.types import BooleanPreference, IntegerPreference
5
+
6
+ general = Section("wbcrm")
7
+
8
+
9
+ @global_preferences_registry.register
10
+ class CheckForMandatoryParticipants(BooleanPreference):
11
+ section = general
12
+ name = "mandatory_participants"
13
+ default = True
14
+
15
+ verbose_name = _("Check for mandatory participants")
16
+ help_text = _(
17
+ 'Determines whether or not companies must be entered as participants in the "Companies" field for activities.'
18
+ )
19
+
20
+
21
+ @global_preferences_registry.register
22
+ class RecurrenceActivityEndDate(IntegerPreference):
23
+ section = general
24
+ name = "recurrence_maximum_allowed_days"
25
+ # this short default value, is just for the moment to test the process and until we know how to handle the recurring activities more efficient
26
+ default = 10 * 365
27
+
28
+ verbose_name = _("The default Maximum allowed days")
29
+
30
+
31
+ @global_preferences_registry.register
32
+ class RecurrenceActivityDateListLength(IntegerPreference):
33
+ section = general
34
+ name = "recurrence_maximum_count"
35
+ # this short default value, is just for the moment to test the process and until we know how to handle the recurring activities more efficient
36
+ default = 366
37
+
38
+ # verbose_name = _("For each date in the date list we create a child activity.number at which the date list will be cut.")
@@ -0,0 +1,14 @@
1
+ # from wbcore.contrib.currency.tests import factories
2
+
3
+ from .accounts import AccountFactory, AccountRoleFactory, AccountRoleTypeFactory, AccountWithOwnerFactory
4
+ from .activities import (
5
+ ActivityCompanyFactory,
6
+ ActivityFactory,
7
+ ActivityParticipantFactory,
8
+ ActivityPersonFactory,
9
+ ActivityTypeCALLFactory,
10
+ ActivityTypeFactory,
11
+ RecurringActivityFactory,
12
+ )
13
+ from .groups import GroupFactory
14
+ from .products import ProductFactory
@@ -0,0 +1,56 @@
1
+ import factory
2
+ from slugify import slugify
3
+ from wbcrm.models.accounts import Account, AccountRole, AccountRoleType
4
+
5
+
6
+ class AccountFactory(factory.django.DjangoModelFactory):
7
+ title = factory.Faker("company")
8
+ status = Account.Status.OPEN
9
+ # owner =
10
+ is_public = True
11
+ is_active = True
12
+ is_terminal_account = True
13
+
14
+ class Meta:
15
+ model = Account
16
+
17
+
18
+ class AccountWithOwnerFactory(AccountFactory):
19
+ owner = factory.SubFactory("wbcore.contrib.directory.factories.entries.EntryFactory")
20
+
21
+
22
+ class AccountRoleTypeFactory(factory.django.DjangoModelFactory):
23
+ title = factory.Faker("word")
24
+ key = factory.LazyAttribute(lambda o: slugify(o.title))
25
+
26
+ class Meta:
27
+ model = AccountRoleType
28
+ django_get_or_create = ["key"]
29
+
30
+
31
+ class AccountRoleFactory(factory.django.DjangoModelFactory):
32
+ role_type = factory.SubFactory("wbcrm.factories.AccountRoleTypeFactory")
33
+ entry = factory.SubFactory("wbcore.contrib.directory.factories.entries.EntryFactory")
34
+ account = factory.SubFactory("wbcrm.factories.AccountFactory", parent=None)
35
+ is_hidden = False
36
+
37
+ @factory.post_generation
38
+ def authorized_hidden_users(self, create, extracted, **kwargs):
39
+ if not create:
40
+ return
41
+
42
+ if extracted:
43
+ for user in extracted:
44
+ self.authorized_hidden_users.add(user)
45
+
46
+ @factory.post_generation
47
+ def visibility_daterange(self, create, extracted, **kwargs):
48
+ if not create:
49
+ return
50
+ if extracted:
51
+ v = self.validity_set.first()
52
+ v.timespan = extracted
53
+ v.save()
54
+
55
+ class Meta:
56
+ model = AccountRole
@@ -0,0 +1,125 @@
1
+ import datetime
2
+ import random
3
+
4
+ import factory
5
+ import pytz
6
+ from dynamic_preferences.registries import global_preferences_registry
7
+ from faker import Faker
8
+ from wbcore.contrib.authentication.factories import InternalUserFactory
9
+ from wbcore.contrib.directory.factories import CompanyFactory, PersonFactory
10
+ from wbcrm.models.activities import Activity, ActivityParticipant, ActivityType
11
+
12
+ fake = Faker()
13
+
14
+
15
+ class ActivityTypeFactory(factory.django.DjangoModelFactory):
16
+ title = factory.Faker("text", max_nb_chars=32)
17
+ color = factory.Faker("color")
18
+ score = factory.Iterator([ActivityType.Score.HIGH, ActivityType.Score.MEDIUM, ActivityType.Score.LOW])
19
+
20
+ class Meta:
21
+ model = ActivityType
22
+ django_get_or_create = ("title",)
23
+
24
+
25
+ class ActivityTypeCALLFactory(ActivityTypeFactory):
26
+ title = "Call"
27
+
28
+
29
+ class ActivityFactory(factory.django.DjangoModelFactory):
30
+ class Meta:
31
+ model = Activity
32
+
33
+ title = factory.Faker("text", max_nb_chars=64)
34
+ description = factory.Faker("paragraph", nb_sentences=5)
35
+ start = factory.LazyAttribute(lambda _: fake.date_time(tzinfo=pytz.utc))
36
+ end = factory.LazyAttribute(
37
+ lambda _self: _self.start + datetime.timedelta(days=fake.pyint(0, 100), hours=fake.pyint(1, 23))
38
+ )
39
+ disable_participant_check = True
40
+ location = factory.Faker("local_latlng")
41
+ location_longitude = factory.Faker("longitude")
42
+ location_latitude = factory.Faker("latitude")
43
+ created = factory.Faker("date_time", tzinfo=pytz.utc)
44
+ creator = factory.LazyAttribute(lambda _: InternalUserFactory.create().profile)
45
+ latest_reviewer = factory.SubFactory(PersonFactory)
46
+ reviewed_at = factory.Faker("date_time", tzinfo=pytz.utc)
47
+ edited = factory.Faker("date_time", tzinfo=pytz.utc)
48
+ assigned_to = factory.SubFactory(PersonFactory)
49
+ preceded_by = None
50
+ parent_occurrence = None
51
+ propagate_for_all_children = False
52
+ recurrence_end = None
53
+ recurrence_count = None
54
+ repeat_choice = Activity.ReoccuranceChoice.NEVER
55
+ type = factory.SubFactory(ActivityTypeFactory)
56
+ item_type = "wbcrm.Activity"
57
+
58
+ @factory.post_generation
59
+ def participants(self, create, extracted, **kwargs):
60
+ if not create:
61
+ return
62
+
63
+ if extracted:
64
+ for participant in extracted:
65
+ self.participants.add(participant)
66
+
67
+ @factory.post_generation
68
+ def companies(self, create, extracted, **kwargs):
69
+ if not create:
70
+ return
71
+
72
+ if extracted:
73
+ for company in extracted:
74
+ self.companies.add(company)
75
+
76
+ @factory.post_generation
77
+ def groups(self, create, extracted, **kwargs):
78
+ if not create:
79
+ return
80
+
81
+ if extracted:
82
+ for group in extracted:
83
+ self.groups.add(group)
84
+
85
+ @factory.post_generation
86
+ def entities(self, create, extracted, **kwargs):
87
+ if not create:
88
+ return
89
+
90
+ if extracted:
91
+ for entity in extracted:
92
+ self.entities.add(entity)
93
+
94
+
95
+ class RecurringActivityFactory(ActivityFactory):
96
+ repeat_choice = random.choice(list(filter(lambda x: x != "NEVER", Activity.ReoccuranceChoice.names)))
97
+ recurrence_count = 3
98
+
99
+
100
+ class ActivityCompanyFactory(ActivityFactory):
101
+ @factory.post_generation
102
+ def companies(self, create, extracted, **kwargs):
103
+ # Create company
104
+ company = CompanyFactory()
105
+ # Set global config main_company=company.id
106
+ global_preferences_registry.manager()["directory__main_company"] = company.id
107
+ global_preferences = global_preferences_registry.manager()
108
+ assert global_preferences
109
+ self.companies.add(company)
110
+
111
+
112
+ class ActivityPersonFactory(ActivityFactory):
113
+ @factory.post_generation
114
+ def participants(self, create, extracted, **kwargs):
115
+ # Create person
116
+ person = PersonFactory()
117
+ self.participants.add(person)
118
+
119
+
120
+ class ActivityParticipantFactory(factory.django.DjangoModelFactory):
121
+ class Meta:
122
+ model = ActivityParticipant
123
+
124
+ participant = factory.SubFactory(PersonFactory)
125
+ activity = factory.SubFactory(ActivityFactory)
@@ -0,0 +1,23 @@
1
+ import random
2
+
3
+ import factory
4
+ from wbcore.contrib.directory.factories import EntryFactory
5
+ from wbcrm.models.groups import Group
6
+
7
+
8
+ class GroupFactory(factory.django.DjangoModelFactory):
9
+ class Meta:
10
+ model = Group
11
+
12
+ title = factory.Faker("text", max_nb_chars=64)
13
+
14
+ @factory.post_generation
15
+ def members(self, create, extracted, **kwargs):
16
+ if not create:
17
+ return
18
+ elif extracted:
19
+ for member in extracted:
20
+ self.members.add(member)
21
+ else:
22
+ for i in range(1, random.randrange(2, 10)):
23
+ self.members.add(EntryFactory())
@@ -0,0 +1,10 @@
1
+ import factory
2
+ from wbcrm.models import Product
3
+
4
+
5
+ class ProductFactory(factory.django.DjangoModelFactory):
6
+ title = factory.Faker("text", max_nb_chars=32)
7
+ is_competitor = factory.Faker("pybool")
8
+
9
+ class Meta:
10
+ model = Product
@@ -0,0 +1,10 @@
1
+ from .accounts import AccountFilter, AccountRoleFilterSet
2
+ from .activities import (
3
+ ActivityChartFilter,
4
+ ActivityFilter,
5
+ ActivityParticipantFilter,
6
+ ActivityTypeFilter,
7
+ )
8
+ from .groups import GroupFilter
9
+ from .products import ProductCompanyFilterSet, ProductFilterSet
10
+ from .signals import *
@@ -0,0 +1,67 @@
1
+ from wbcore import filters as wb_filters
2
+ from wbcore.contrib.directory.models import Entry
3
+ from wbcrm.models.accounts import Account, AccountRole
4
+
5
+
6
+ class AccountFilter(wb_filters.FilterSet):
7
+ customer = wb_filters.ModelChoiceFilter(
8
+ label="Customer",
9
+ queryset=Entry.objects.all(),
10
+ endpoint=Entry.get_representation_endpoint(),
11
+ value_key=Entry.get_representation_value_key(),
12
+ label_key=Entry.get_representation_label_key(),
13
+ method="filter_customer",
14
+ )
15
+
16
+ owner = wb_filters.ModelMultipleChoiceFilter(
17
+ label="Owner",
18
+ queryset=Entry.objects.all(),
19
+ endpoint=Entry.get_representation_endpoint(),
20
+ value_key=Entry.get_representation_value_key(),
21
+ label_key=Entry.get_representation_label_key(),
22
+ )
23
+
24
+ not_owner = wb_filters.ModelMultipleChoiceFilter(
25
+ column_field_name="owner",
26
+ lookup_icon="!=",
27
+ lookup_label="Not Equals",
28
+ queryset=Entry.objects.all(),
29
+ endpoint=Entry.get_representation_endpoint(),
30
+ value_key=Entry.get_representation_value_key(),
31
+ label_key=Entry.get_representation_label_key(),
32
+ method="filter_not_owner",
33
+ )
34
+
35
+ def filter_not_owner(self, queryset, name, value):
36
+ if value:
37
+ return queryset.exclude(owner__in=value)
38
+ return queryset
39
+
40
+ def filter_customer(self, queryset, name, value):
41
+ if value:
42
+ return queryset.filter(id__in=Account.get_accounts_for_customer(value))
43
+ return queryset
44
+
45
+ class Meta:
46
+ model = Account
47
+ fields = {
48
+ "reference_id": ["icontains"],
49
+ "status": ["exact"],
50
+ "is_active": ["exact"],
51
+ "parent": ["exact", "isnull"],
52
+ "is_terminal_account": ["exact"],
53
+ "is_public": ["exact"],
54
+ }
55
+
56
+
57
+ class AccountRoleFilterSet(wb_filters.FilterSet):
58
+ is_currently_valid = wb_filters.BooleanFilter(label="Valid", default=True, field_name="is_currently_valid")
59
+
60
+ class Meta:
61
+ model = AccountRole
62
+ fields = {
63
+ "role_type": ["exact"],
64
+ "entry": ["exact"],
65
+ "is_hidden": ["exact"],
66
+ "authorized_hidden_users": ["exact"],
67
+ }