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/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
wbcrm/admin/__init__.py
ADDED
wbcrm/admin/accounts.py
ADDED
|
@@ -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
wbcrm/admin/products.py
ADDED
wbcrm/apps.py
ADDED
|
@@ -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
|
+
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
|
+
}
|