wbcrm 1.43.1__tar.gz
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-1.43.1/.gitignore +181 -0
- wbcrm-1.43.1/PKG-INFO +11 -0
- wbcrm-1.43.1/pyproject.toml +35 -0
- wbcrm-1.43.1/wbcrm/__init__.py +1 -0
- wbcrm-1.43.1/wbcrm/admin/__init__.py +5 -0
- wbcrm-1.43.1/wbcrm/admin/accounts.py +59 -0
- wbcrm-1.43.1/wbcrm/admin/activities.py +102 -0
- wbcrm-1.43.1/wbcrm/admin/events.py +42 -0
- wbcrm-1.43.1/wbcrm/admin/groups.py +7 -0
- wbcrm-1.43.1/wbcrm/admin/products.py +8 -0
- wbcrm-1.43.1/wbcrm/apps.py +5 -0
- wbcrm-1.43.1/wbcrm/configurations/__init__.py +1 -0
- wbcrm-1.43.1/wbcrm/configurations/base.py +16 -0
- wbcrm-1.43.1/wbcrm/dynamic_preferences_registry.py +38 -0
- wbcrm-1.43.1/wbcrm/factories/__init__.py +14 -0
- wbcrm-1.43.1/wbcrm/factories/accounts.py +56 -0
- wbcrm-1.43.1/wbcrm/factories/activities.py +125 -0
- wbcrm-1.43.1/wbcrm/factories/groups.py +23 -0
- wbcrm-1.43.1/wbcrm/factories/products.py +10 -0
- wbcrm-1.43.1/wbcrm/filters/__init__.py +10 -0
- wbcrm-1.43.1/wbcrm/filters/accounts.py +67 -0
- wbcrm-1.43.1/wbcrm/filters/activities.py +199 -0
- wbcrm-1.43.1/wbcrm/filters/groups.py +20 -0
- wbcrm-1.43.1/wbcrm/filters/products.py +37 -0
- wbcrm-1.43.1/wbcrm/filters/signals.py +94 -0
- wbcrm-1.43.1/wbcrm/fixtures/wbcrm.json +1215 -0
- wbcrm-1.43.1/wbcrm/kpi_handlers/activities.py +171 -0
- wbcrm-1.43.1/wbcrm/locale/de/LC_MESSAGES/django.po +1538 -0
- wbcrm-1.43.1/wbcrm/migrations/0001_initial_squashed_squashed_0032_productcompanyrelationship_alter_product_prospects_and_more.py +3948 -0
- wbcrm-1.43.1/wbcrm/migrations/0002_alter_activity_repeat_choice.py +32 -0
- wbcrm-1.43.1/wbcrm/migrations/0003_remove_activity_external_id_and_more.py +63 -0
- wbcrm-1.43.1/wbcrm/migrations/0004_alter_activity_status.py +28 -0
- wbcrm-1.43.1/wbcrm/migrations/0005_account_accountrole_accountroletype_and_more.py +182 -0
- wbcrm-1.43.1/wbcrm/migrations/0006_alter_activity_location.py +17 -0
- wbcrm-1.43.1/wbcrm/migrations/0007_alter_account_status.py +23 -0
- wbcrm-1.43.1/wbcrm/migrations/0008_alter_activity_options.py +16 -0
- wbcrm-1.43.1/wbcrm/migrations/0009_alter_account_is_public.py +19 -0
- wbcrm-1.43.1/wbcrm/migrations/0010_alter_account_reference_id.py +17 -0
- wbcrm-1.43.1/wbcrm/migrations/0011_activity_summary.py +22 -0
- wbcrm-1.43.1/wbcrm/migrations/0012_alter_activity_summary.py +17 -0
- wbcrm-1.43.1/wbcrm/migrations/0013_account_action_plan_account_relationship_status_and_more.py +34 -0
- wbcrm-1.43.1/wbcrm/migrations/0014_alter_account_relationship_status.py +24 -0
- wbcrm-1.43.1/wbcrm/migrations/0015_alter_activity_type.py +23 -0
- wbcrm-1.43.1/wbcrm/migrations/0016_auto_20241205_1015.py +106 -0
- wbcrm-1.43.1/wbcrm/migrations/0017_event.py +40 -0
- wbcrm-1.43.1/wbcrm/migrations/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/models/__init__.py +5 -0
- wbcrm-1.43.1/wbcrm/models/accounts.py +637 -0
- wbcrm-1.43.1/wbcrm/models/activities.py +1341 -0
- wbcrm-1.43.1/wbcrm/models/events.py +12 -0
- wbcrm-1.43.1/wbcrm/models/groups.py +118 -0
- wbcrm-1.43.1/wbcrm/models/llm/activity_summaries.py +33 -0
- wbcrm-1.43.1/wbcrm/models/llm/analyze_relationship.py +54 -0
- wbcrm-1.43.1/wbcrm/models/products.py +83 -0
- wbcrm-1.43.1/wbcrm/models/recurrence.py +279 -0
- wbcrm-1.43.1/wbcrm/preferences.py +14 -0
- wbcrm-1.43.1/wbcrm/report/activity_report.py +110 -0
- wbcrm-1.43.1/wbcrm/serializers/__init__.py +23 -0
- wbcrm-1.43.1/wbcrm/serializers/accounts.py +126 -0
- wbcrm-1.43.1/wbcrm/serializers/activities.py +526 -0
- wbcrm-1.43.1/wbcrm/serializers/groups.py +30 -0
- wbcrm-1.43.1/wbcrm/serializers/products.py +57 -0
- wbcrm-1.43.1/wbcrm/serializers/recurrence.py +90 -0
- wbcrm-1.43.1/wbcrm/serializers/signals.py +70 -0
- wbcrm-1.43.1/wbcrm/static/wbcrm/markdown/documentation/activity.md +86 -0
- wbcrm-1.43.1/wbcrm/static/wbcrm/markdown/documentation/activitytype.md +20 -0
- wbcrm-1.43.1/wbcrm/static/wbcrm/markdown/documentation/group.md +2 -0
- wbcrm-1.43.1/wbcrm/static/wbcrm/markdown/documentation/product.md +11 -0
- wbcrm-1.43.1/wbcrm/synchronization/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/admin.py +72 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backend.py +213 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/__init__.py +2 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/google_calendar_backend.py +399 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/create.py +75 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/delete.py +78 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/update.py +155 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/request_utils/internal_to_external/update.py +180 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tasks.py +21 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tests/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tests/conftest.py +1 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tests/test_data.py +81 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tests/test_google_backend.py +319 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/tests/test_utils.py +274 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/typing_informations.py +139 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/google/utils.py +216 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/backend.py +585 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/msgraph.py +438 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/parser.py +431 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/conftest.py +1 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/fixtures.py +606 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/test_admin.py +117 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +273 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +248 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +173 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/controller.py +624 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/dynamic_preferences_registry.py +119 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/preferences.py +27 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/shortcuts.py +10 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/tasks.py +21 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/urls.py +6 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/utils.py +46 -0
- wbcrm-1.43.1/wbcrm/synchronization/activity/views.py +40 -0
- wbcrm-1.43.1/wbcrm/synchronization/admin.py +1 -0
- wbcrm-1.43.1/wbcrm/synchronization/apps.py +14 -0
- wbcrm-1.43.1/wbcrm/synchronization/dynamic_preferences_registry.py +1 -0
- wbcrm-1.43.1/wbcrm/synchronization/management.py +36 -0
- wbcrm-1.43.1/wbcrm/synchronization/tasks.py +1 -0
- wbcrm-1.43.1/wbcrm/synchronization/urls.py +5 -0
- wbcrm-1.43.1/wbcrm/tasks.py +312 -0
- wbcrm-1.43.1/wbcrm/templates/email/activity.html +98 -0
- wbcrm-1.43.1/wbcrm/templates/email/activity_report.html +6 -0
- wbcrm-1.43.1/wbcrm/templates/email/daily_summary.html +72 -0
- wbcrm-1.43.1/wbcrm/templates/email/global_daily_summary.html +85 -0
- wbcrm-1.43.1/wbcrm/tests/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/tests/accounts/__init__.py +0 -0
- wbcrm-1.43.1/wbcrm/tests/accounts/test_models.py +380 -0
- wbcrm-1.43.1/wbcrm/tests/accounts/test_viewsets.py +87 -0
- wbcrm-1.43.1/wbcrm/tests/conftest.py +76 -0
- wbcrm-1.43.1/wbcrm/tests/disable_signals.py +52 -0
- wbcrm-1.43.1/wbcrm/tests/e2e/__init__.py +1 -0
- wbcrm-1.43.1/wbcrm/tests/e2e/e2e_wbcrm_utility.py +82 -0
- wbcrm-1.43.1/wbcrm/tests/e2e/test_e2e.py +369 -0
- wbcrm-1.43.1/wbcrm/tests/test_assignee_methods.py +39 -0
- wbcrm-1.43.1/wbcrm/tests/test_chartviewsets.py +111 -0
- wbcrm-1.43.1/wbcrm/tests/test_dto.py +63 -0
- wbcrm-1.43.1/wbcrm/tests/test_filters.py +51 -0
- wbcrm-1.43.1/wbcrm/tests/test_models.py +216 -0
- wbcrm-1.43.1/wbcrm/tests/test_recurrence.py +291 -0
- wbcrm-1.43.1/wbcrm/tests/test_report.py +20 -0
- wbcrm-1.43.1/wbcrm/tests/test_serializers.py +170 -0
- wbcrm-1.43.1/wbcrm/tests/test_tasks.py +94 -0
- wbcrm-1.43.1/wbcrm/tests/test_viewsets.py +967 -0
- wbcrm-1.43.1/wbcrm/tests/tests.py +120 -0
- wbcrm-1.43.1/wbcrm/typings.py +109 -0
- wbcrm-1.43.1/wbcrm/urls.py +67 -0
- wbcrm-1.43.1/wbcrm/viewsets/__init__.py +22 -0
- wbcrm-1.43.1/wbcrm/viewsets/accounts.py +121 -0
- wbcrm-1.43.1/wbcrm/viewsets/activities.py +344 -0
- wbcrm-1.43.1/wbcrm/viewsets/buttons/__init__.py +7 -0
- wbcrm-1.43.1/wbcrm/viewsets/buttons/accounts.py +27 -0
- wbcrm-1.43.1/wbcrm/viewsets/buttons/activities.py +88 -0
- wbcrm-1.43.1/wbcrm/viewsets/buttons/signals.py +17 -0
- wbcrm-1.43.1/wbcrm/viewsets/display/__init__.py +12 -0
- wbcrm-1.43.1/wbcrm/viewsets/display/accounts.py +110 -0
- wbcrm-1.43.1/wbcrm/viewsets/display/activities.py +443 -0
- wbcrm-1.43.1/wbcrm/viewsets/display/groups.py +22 -0
- wbcrm-1.43.1/wbcrm/viewsets/display/products.py +105 -0
- wbcrm-1.43.1/wbcrm/viewsets/endpoints/__init__.py +8 -0
- wbcrm-1.43.1/wbcrm/viewsets/endpoints/accounts.py +32 -0
- wbcrm-1.43.1/wbcrm/viewsets/endpoints/activities.py +30 -0
- wbcrm-1.43.1/wbcrm/viewsets/endpoints/groups.py +7 -0
- wbcrm-1.43.1/wbcrm/viewsets/endpoints/products.py +9 -0
- wbcrm-1.43.1/wbcrm/viewsets/groups.py +37 -0
- wbcrm-1.43.1/wbcrm/viewsets/menu/__init__.py +8 -0
- wbcrm-1.43.1/wbcrm/viewsets/menu/accounts.py +18 -0
- wbcrm-1.43.1/wbcrm/viewsets/menu/activities.py +61 -0
- wbcrm-1.43.1/wbcrm/viewsets/menu/groups.py +16 -0
- wbcrm-1.43.1/wbcrm/viewsets/menu/products.py +20 -0
- wbcrm-1.43.1/wbcrm/viewsets/mixins.py +34 -0
- wbcrm-1.43.1/wbcrm/viewsets/previews/__init__.py +1 -0
- wbcrm-1.43.1/wbcrm/viewsets/previews/activities.py +10 -0
- wbcrm-1.43.1/wbcrm/viewsets/products.py +56 -0
- wbcrm-1.43.1/wbcrm/viewsets/recurrence.py +26 -0
- wbcrm-1.43.1/wbcrm/viewsets/titles/__init__.py +13 -0
- wbcrm-1.43.1/wbcrm/viewsets/titles/accounts.py +22 -0
- wbcrm-1.43.1/wbcrm/viewsets/titles/activities.py +61 -0
- wbcrm-1.43.1/wbcrm/viewsets/titles/products.py +13 -0
- wbcrm-1.43.1/wbcrm/viewsets/titles/utils.py +46 -0
- wbcrm-1.43.1/wbcrm/workflows/__init__.py +1 -0
- wbcrm-1.43.1/wbcrm/workflows/assignee_methods.py +25 -0
wbcrm-1.43.1/.gitignore
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
~
|
|
2
|
+
|
|
3
|
+
# Docker volumes
|
|
4
|
+
volumes/
|
|
5
|
+
# Poetry auth file
|
|
6
|
+
auth.toml
|
|
7
|
+
|
|
8
|
+
media/*
|
|
9
|
+
media/
|
|
10
|
+
mediafiles/
|
|
11
|
+
mediafiles/*
|
|
12
|
+
test/*
|
|
13
|
+
staticfiles/*
|
|
14
|
+
staticfiles/
|
|
15
|
+
#
|
|
16
|
+
# Byte-compiled / optimized / DLL files
|
|
17
|
+
__pycache__/
|
|
18
|
+
*.py[cod]
|
|
19
|
+
*$py.class
|
|
20
|
+
|
|
21
|
+
# C extensions
|
|
22
|
+
*.so
|
|
23
|
+
|
|
24
|
+
# Distribution / packaging
|
|
25
|
+
.Python
|
|
26
|
+
build/
|
|
27
|
+
develop-eggs/
|
|
28
|
+
dist/
|
|
29
|
+
info/
|
|
30
|
+
downloads/
|
|
31
|
+
eggs/
|
|
32
|
+
.eggs/
|
|
33
|
+
lib/
|
|
34
|
+
lib64/
|
|
35
|
+
parts/
|
|
36
|
+
sdist/
|
|
37
|
+
var/
|
|
38
|
+
wheels/
|
|
39
|
+
share/python-wheels/
|
|
40
|
+
*.egg-info/
|
|
41
|
+
.installed.cfg
|
|
42
|
+
*.egg
|
|
43
|
+
MANIFEST
|
|
44
|
+
|
|
45
|
+
# PyInstaller
|
|
46
|
+
# Usually these files are written by a python script from a template
|
|
47
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
48
|
+
*.manifest
|
|
49
|
+
*.spec
|
|
50
|
+
|
|
51
|
+
# Installer logs
|
|
52
|
+
pip-log.txt
|
|
53
|
+
pip-delete-this-directory.txt
|
|
54
|
+
|
|
55
|
+
# Unit test / coverage reports
|
|
56
|
+
htmlcov/
|
|
57
|
+
.tox/
|
|
58
|
+
.nox/
|
|
59
|
+
.coverage
|
|
60
|
+
.coverage.*
|
|
61
|
+
.cache
|
|
62
|
+
.dccache
|
|
63
|
+
nosetests.xml
|
|
64
|
+
coverage.xml
|
|
65
|
+
*.cover
|
|
66
|
+
*.py,cover
|
|
67
|
+
.hypothesis/
|
|
68
|
+
.pytest_cache/
|
|
69
|
+
cover/
|
|
70
|
+
report.xml
|
|
71
|
+
*/report.xml
|
|
72
|
+
|
|
73
|
+
# Translations
|
|
74
|
+
*.mo
|
|
75
|
+
*.pot
|
|
76
|
+
|
|
77
|
+
# Django stuff:
|
|
78
|
+
*.log
|
|
79
|
+
local_settings.py
|
|
80
|
+
*.sqlite3
|
|
81
|
+
db.sqlite3-journal
|
|
82
|
+
|
|
83
|
+
# Flask stuff:
|
|
84
|
+
instance/
|
|
85
|
+
.webassets-cache
|
|
86
|
+
|
|
87
|
+
# Scrapy stuff:
|
|
88
|
+
.scrapy
|
|
89
|
+
|
|
90
|
+
# Sphinx documentation
|
|
91
|
+
docs/_build/
|
|
92
|
+
|
|
93
|
+
# PyBuilder
|
|
94
|
+
.pybuilder/
|
|
95
|
+
target/
|
|
96
|
+
|
|
97
|
+
# Jupyter Notebook
|
|
98
|
+
.ipynb_checkpoints
|
|
99
|
+
*.ipynb
|
|
100
|
+
# IPython
|
|
101
|
+
profile_default/
|
|
102
|
+
ipython_config.py
|
|
103
|
+
|
|
104
|
+
# pyenv
|
|
105
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
106
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
107
|
+
# .python-version
|
|
108
|
+
|
|
109
|
+
# pipenv
|
|
110
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
111
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
112
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
113
|
+
# install all needed dependencies.
|
|
114
|
+
#Pipfile.lock
|
|
115
|
+
|
|
116
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
117
|
+
__pypackages__/
|
|
118
|
+
|
|
119
|
+
# Celery stuff
|
|
120
|
+
celerybeat-schedule
|
|
121
|
+
celerybeat.pid
|
|
122
|
+
|
|
123
|
+
# SageMath parsed files
|
|
124
|
+
*.sage.py
|
|
125
|
+
|
|
126
|
+
# Environments
|
|
127
|
+
.env
|
|
128
|
+
.envrc
|
|
129
|
+
.venv
|
|
130
|
+
env/
|
|
131
|
+
venv/
|
|
132
|
+
ENV/
|
|
133
|
+
env.bak/
|
|
134
|
+
venv.bak/
|
|
135
|
+
.vscode/
|
|
136
|
+
.idea/
|
|
137
|
+
.idea.bkp/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
crm/
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# Gitlab Runner
|
|
164
|
+
builds
|
|
165
|
+
builds/
|
|
166
|
+
|
|
167
|
+
# Integrator Office 365 : reverse proxy tunnel for outlook365
|
|
168
|
+
ngrok
|
|
169
|
+
*/ngrok
|
|
170
|
+
/modules/**/system/
|
|
171
|
+
|
|
172
|
+
/modules/wbmailing/files/*
|
|
173
|
+
/modules/wbmailing/mailing/*
|
|
174
|
+
|
|
175
|
+
/projects/*/requirements.txt
|
|
176
|
+
public
|
|
177
|
+
|
|
178
|
+
# Ignore archive localization generated folder
|
|
179
|
+
backend/modules/**/archive/*
|
|
180
|
+
**/**/requirements.txt
|
|
181
|
+
CHANGELOG-*
|
wbcrm-1.43.1/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wbcrm
|
|
3
|
+
Version: 1.43.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.*
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "wbcrm"
|
|
3
|
+
description = "A workbench module that contains all the functionality related to a customer relationship management."
|
|
4
|
+
authors = [{ name = "Christopher Wittlinger", email = "c.wittlinger@stainly.com"}]
|
|
5
|
+
dynamic = ["version"]
|
|
6
|
+
|
|
7
|
+
dependencies = [
|
|
8
|
+
"wbcore",
|
|
9
|
+
"django-eventtools == 1.*",
|
|
10
|
+
"google-api-python-client == 2.62.*",
|
|
11
|
+
"google-auth-httplib2 == 0.1.*",
|
|
12
|
+
"google-auth-oauthlib == 0.5.*",
|
|
13
|
+
"XlsxWriter == 3.*"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[tool.uv.sources]
|
|
17
|
+
wbcore = { workspace = true }
|
|
18
|
+
|
|
19
|
+
[tool.uv]
|
|
20
|
+
package = true
|
|
21
|
+
|
|
22
|
+
[tool.hatch.version]
|
|
23
|
+
path = "../../pyproject.toml"
|
|
24
|
+
|
|
25
|
+
[tool.hatch.build]
|
|
26
|
+
include = ["wbcrm/**/*"]
|
|
27
|
+
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["hatchling"]
|
|
30
|
+
build-backend = "hatchling.build"
|
|
31
|
+
|
|
32
|
+
[tool.pyright]
|
|
33
|
+
venvPath = "../.."
|
|
34
|
+
venv = ".venv"
|
|
35
|
+
reportIncompatibleVariableOverride = false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -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,102 @@
|
|
|
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
|
+
from wbcrm.models.activities import ActivityCompanyThroughModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ParticipantInline(admin.TabularInline):
|
|
9
|
+
model = ActivityParticipant
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CompanyInline(admin.TabularInline):
|
|
13
|
+
model = ActivityCompanyThroughModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@admin.register(ActivityType)
|
|
17
|
+
class ActivityTypeAdmin(admin.ModelAdmin):
|
|
18
|
+
search_fields = ("title",)
|
|
19
|
+
list_display = ("id", "title")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ActivityInline(admin.StackedInline):
|
|
23
|
+
model = Activity
|
|
24
|
+
fk_name = "parent_occurrence"
|
|
25
|
+
extra = 0
|
|
26
|
+
fieldsets = (
|
|
27
|
+
(
|
|
28
|
+
_("Main information"),
|
|
29
|
+
{
|
|
30
|
+
"fields": (
|
|
31
|
+
"title",
|
|
32
|
+
"description",
|
|
33
|
+
)
|
|
34
|
+
},
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@admin.register(Activity)
|
|
40
|
+
class ActivityAdmin(VersionAdmin):
|
|
41
|
+
search_fields = ("title",)
|
|
42
|
+
list_display = ("id", "status", "title", "period", "is_active", "parent_occurrence_id", "metadata")
|
|
43
|
+
fieldsets = (
|
|
44
|
+
(_("Main information"), {"fields": ("title", "description", "result", "creator")}),
|
|
45
|
+
(_("Meta"), {"fields": ("status", "type", "visibility", "is_active", "metadata")}),
|
|
46
|
+
(_("Temporal Information"), {"fields": ("period", "all_day")}),
|
|
47
|
+
(_("Geographical Information"), {"fields": ("location", "location_longitude", "location_latitude")}),
|
|
48
|
+
(_("Linked Entries"), {"fields": ("assigned_to", "groups")}),
|
|
49
|
+
(_("Linked Activities"), {"fields": ("preceded_by",)}),
|
|
50
|
+
(
|
|
51
|
+
_("Recurrence"),
|
|
52
|
+
{
|
|
53
|
+
"fields": (
|
|
54
|
+
"repeat_choice",
|
|
55
|
+
"parent_occurrence",
|
|
56
|
+
("recurrence_count", "recurrence_end"),
|
|
57
|
+
"propagate_for_all_children",
|
|
58
|
+
)
|
|
59
|
+
},
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
raw_id_fields = (
|
|
64
|
+
"assigned_to",
|
|
65
|
+
"participants",
|
|
66
|
+
"groups",
|
|
67
|
+
"preceded_by",
|
|
68
|
+
"creator",
|
|
69
|
+
"latest_reviewer",
|
|
70
|
+
"parent_occurrence",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
inlines = [ActivityInline, ParticipantInline, CompanyInline]
|
|
74
|
+
|
|
75
|
+
def reversion_register(self, model, **options):
|
|
76
|
+
options = {
|
|
77
|
+
"exclude": (
|
|
78
|
+
"created",
|
|
79
|
+
"creator",
|
|
80
|
+
"edited",
|
|
81
|
+
),
|
|
82
|
+
}
|
|
83
|
+
super().reversion_register(model, **options)
|
|
84
|
+
|
|
85
|
+
def get_queryset(self, request):
|
|
86
|
+
return Activity.all_objects.all()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@admin.register(ActivityParticipant)
|
|
90
|
+
class ActivityParticipantAdmin(VersionAdmin):
|
|
91
|
+
search_fields = ("activity", "participant")
|
|
92
|
+
list_display = ("id", "activity", "participant", "participation_status")
|
|
93
|
+
|
|
94
|
+
def reversion_register(self, model, **options):
|
|
95
|
+
options = {
|
|
96
|
+
"follow": (
|
|
97
|
+
"activity",
|
|
98
|
+
"participant",
|
|
99
|
+
"participation_status",
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
super().reversion_register(model, **options)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from wbcrm.models.events import Event
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@admin.register(Event)
|
|
6
|
+
class EventModelAdmin(admin.ModelAdmin):
|
|
7
|
+
list_display = (
|
|
8
|
+
"id",
|
|
9
|
+
"resource",
|
|
10
|
+
"change_type",
|
|
11
|
+
"subject",
|
|
12
|
+
"resource_uuid",
|
|
13
|
+
"action_type",
|
|
14
|
+
"action",
|
|
15
|
+
"created",
|
|
16
|
+
"updated",
|
|
17
|
+
)
|
|
18
|
+
search_fields = ("data", "result")
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def change_type(obj):
|
|
22
|
+
return obj.data.get("change_type", "")
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def resource(obj):
|
|
26
|
+
return obj.data.get("resource", "")
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def subject(obj):
|
|
30
|
+
return obj.data.get("subject", "")
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def resource_uuid(obj):
|
|
34
|
+
return obj.data.get("uid", "")
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def action_type(obj):
|
|
38
|
+
return obj.result.get("action_type", "")
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def action(obj):
|
|
42
|
+
return obj.result.get("action", "")
|
|
@@ -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
|