django-spire 0.23.7__py3-none-any.whl → 0.23.8__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.
- django_spire/ai/admin.py +11 -11
- django_spire/ai/chat/apps.py +1 -0
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +1 -1
- django_spire/ai/chat/tests/factories.py +15 -0
- django_spire/ai/chat/tests/test_controller.py +45 -0
- django_spire/ai/chat/tests/test_models.py +301 -0
- django_spire/ai/chat/tests/test_prompts.py +48 -0
- django_spire/ai/chat/tests/test_responses.py +208 -0
- django_spire/ai/chat/tests/test_router/test_base_chat_router.py +66 -6
- django_spire/ai/chat/tests/test_router/test_chat_workflow.py +73 -3
- django_spire/ai/chat/tests/test_router/test_integration.py +86 -6
- django_spire/ai/chat/tests/test_router/test_intent_decoder.py +93 -1
- django_spire/ai/chat/tests/test_router/test_message_intel.py +60 -1
- django_spire/ai/chat/tests/test_router/test_spire_chat_router.py +110 -0
- django_spire/ai/chat/tests/test_urls/test_json_urls.py +202 -1
- django_spire/ai/context/tests/__init__.py +0 -0
- django_spire/ai/context/tests/test_context.py +188 -0
- django_spire/ai/decorators.py +7 -6
- django_spire/ai/prompt/tests/test_bots.py +100 -10
- django_spire/ai/prompt/tests/test_prompt_intel.py +83 -0
- django_spire/ai/prompt/tests/test_prompt_tuning.py +126 -0
- django_spire/ai/sms/decorators.py +8 -2
- django_spire/ai/sms/tests/test_sms.py +240 -16
- django_spire/ai/sms/tests/test_sms_intel.py +42 -0
- django_spire/ai/sms/tests/test_webhook.py +155 -7
- django_spire/ai/sms/views.py +23 -24
- django_spire/ai/tests/test_ai.py +131 -7
- django_spire/auth/apps.py +4 -2
- django_spire/auth/controller/controller.py +36 -23
- django_spire/auth/controller/exceptions.py +9 -0
- django_spire/auth/group/admin.py +1 -0
- django_spire/auth/group/apps.py +2 -0
- django_spire/auth/group/factories.py +17 -8
- django_spire/auth/group/forms.py +7 -0
- django_spire/auth/group/tests/test_factories.py +146 -0
- django_spire/auth/group/tests/test_forms.py +282 -0
- django_spire/auth/group/tests/test_models.py +192 -0
- django_spire/auth/group/tests/test_querysets.py +98 -0
- django_spire/auth/group/tests/test_utils.py +341 -0
- django_spire/auth/group/tests/test_views.py +377 -0
- django_spire/auth/group/urls/__init__.py +3 -1
- django_spire/auth/group/urls/form_urls.py +2 -0
- django_spire/auth/group/urls/json_urls.py +3 -0
- django_spire/auth/group/urls/page_urls.py +2 -0
- django_spire/auth/group/utils.py +6 -2
- django_spire/auth/group/views/form_views.py +6 -3
- django_spire/auth/group/views/json_views.py +6 -2
- django_spire/auth/mfa/admin.py +2 -0
- django_spire/auth/mfa/apps.py +2 -0
- django_spire/auth/mfa/forms.py +1 -0
- django_spire/auth/mfa/querysets.py +9 -2
- django_spire/auth/mfa/tests/test_models.py +233 -0
- django_spire/auth/mfa/tests/test_utils.py +106 -0
- django_spire/auth/mfa/urls/__init__.py +2 -0
- django_spire/auth/mfa/urls/page_urls.py +2 -0
- django_spire/auth/mfa/urls/redirect_urls.py +2 -0
- django_spire/auth/mfa/views/page_views.py +2 -1
- django_spire/auth/permissions/consts.py +2 -2
- django_spire/auth/permissions/decorators.py +8 -8
- django_spire/auth/permissions/permissions.py +28 -35
- django_spire/auth/permissions/tests/test_decorators.py +333 -0
- django_spire/auth/permissions/tests/test_permissions.py +337 -0
- django_spire/auth/permissions/tests/test_tools.py +305 -0
- django_spire/auth/permissions/tools.py +21 -15
- django_spire/auth/seeding/seed.py +3 -0
- django_spire/auth/seeding/seeder.py +2 -0
- django_spire/auth/tests/test_controller.py +323 -0
- django_spire/auth/tests/test_url_endpoints.py +9 -9
- django_spire/auth/tests/test_views.py +406 -0
- django_spire/auth/urls/admin_urls.py +2 -0
- django_spire/auth/urls/redirect_urls.py +2 -0
- django_spire/auth/user/apps.py +2 -0
- django_spire/auth/user/forms.py +9 -0
- django_spire/auth/user/models.py +1 -1
- django_spire/auth/user/services/services.py +1 -0
- django_spire/auth/user/tests/factories.py +14 -13
- django_spire/auth/user/tests/test_factories.py +166 -2
- django_spire/auth/user/tests/test_forms.py +573 -0
- django_spire/auth/user/tests/test_models.py +257 -0
- django_spire/auth/user/tests/test_services.py +200 -0
- django_spire/auth/user/tests/test_tools.py +153 -0
- django_spire/auth/user/tests/test_user_factories.py +139 -0
- django_spire/auth/user/tests/test_views.py +363 -0
- django_spire/auth/user/tools.py +7 -1
- django_spire/auth/user/urls/form_urls.py +3 -0
- django_spire/auth/user/urls/page_urls.py +3 -0
- django_spire/auth/user/views/form_views.py +19 -10
- django_spire/auth/user/views/page_views.py +8 -2
- django_spire/auth/views/redirect_views.py +14 -9
- django_spire/comment/admin.py +2 -0
- django_spire/comment/apps.py +2 -0
- django_spire/comment/templatetags/comment_tags.py +1 -0
- django_spire/comment/tests/test_forms.py +27 -0
- django_spire/comment/tests/test_models.py +215 -0
- django_spire/comment/tests/test_querysets.py +101 -0
- django_spire/comment/tests/test_utils.py +90 -0
- django_spire/comment/urls.py +2 -0
- django_spire/comment/utils.py +22 -13
- django_spire/comment/views.py +1 -1
- django_spire/conf.py +8 -6
- django_spire/consts.py +1 -1
- django_spire/contrib/breadcrumb/apps.py +2 -0
- django_spire/contrib/breadcrumb/breadcrumbs.py +18 -18
- django_spire/contrib/breadcrumb/tests/test_breadcrumbs.py +198 -0
- django_spire/contrib/constructor/__init__.py +3 -3
- django_spire/contrib/constructor/constructor.py +15 -15
- django_spire/contrib/constructor/django_model_constructor.py +5 -4
- django_spire/contrib/constructor/exceptions.py +5 -3
- django_spire/contrib/constructor/tests/__init__.py +0 -0
- django_spire/contrib/constructor/tests/test_constructor.py +193 -0
- django_spire/contrib/form/tests/__init__.py +0 -0
- django_spire/contrib/form/tests/test_forms.py +203 -0
- django_spire/contrib/generic_views/modal_views.py +2 -1
- django_spire/contrib/generic_views/portal_views.py +20 -19
- django_spire/contrib/generic_views/tests/__init__.py +0 -0
- django_spire/contrib/generic_views/tests/test_views.py +459 -0
- django_spire/contrib/help/apps.py +2 -0
- django_spire/contrib/help/templatetags/help.py +1 -0
- django_spire/contrib/help/tests/__init__.py +0 -0
- django_spire/contrib/help/tests/test_templatetags.py +100 -0
- django_spire/contrib/options/mixins.py +6 -5
- django_spire/contrib/options/tests/factories.py +5 -1
- django_spire/contrib/options/tests/test_options.py +234 -0
- django_spire/contrib/ordering/exceptions.py +7 -3
- django_spire/contrib/ordering/mixins.py +2 -0
- django_spire/contrib/ordering/querysets.py +3 -1
- django_spire/contrib/ordering/services/processor_service.py +8 -4
- django_spire/contrib/ordering/services/service.py +1 -2
- django_spire/contrib/ordering/tests/__init__.py +0 -0
- django_spire/contrib/ordering/tests/test_ordering.py +165 -0
- django_spire/contrib/ordering/validators.py +6 -6
- django_spire/contrib/pagination/templatetags/pagination_tags.py +12 -5
- django_spire/contrib/pagination/tests/__init__.py +0 -0
- django_spire/contrib/pagination/tests/test_pagination.py +179 -0
- django_spire/contrib/performance/decorators.py +16 -6
- django_spire/contrib/performance/tests/__init__.py +0 -0
- django_spire/contrib/performance/tests/test_performance.py +107 -0
- django_spire/contrib/queryset/enums.py +3 -1
- django_spire/contrib/queryset/filter_tools.py +10 -5
- django_spire/contrib/queryset/mixins.py +16 -16
- django_spire/contrib/queryset/tests/__init__.py +0 -0
- django_spire/contrib/queryset/tests/test_queryset.py +137 -0
- django_spire/contrib/seeding/field/base.py +13 -7
- django_spire/contrib/seeding/field/callable.py +8 -1
- django_spire/contrib/seeding/field/cleaners.py +5 -5
- django_spire/contrib/seeding/field/custom.py +20 -10
- django_spire/contrib/seeding/field/django/seeder.py +8 -6
- django_spire/contrib/seeding/field/enums.py +7 -5
- django_spire/contrib/seeding/field/override.py +16 -6
- django_spire/contrib/seeding/field/static.py +9 -2
- django_spire/contrib/seeding/field/tests/test_base.py +18 -14
- django_spire/contrib/seeding/field/tests/test_callable.py +13 -9
- django_spire/contrib/seeding/field/tests/test_cleaners.py +51 -38
- django_spire/contrib/seeding/field/tests/test_static.py +13 -9
- django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +2 -0
- django_spire/contrib/seeding/intelligence/intel.py +5 -1
- django_spire/contrib/seeding/intelligence/prompts/factory.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +7 -1
- django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +6 -2
- django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +8 -2
- django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +6 -1
- django_spire/contrib/seeding/management/commands/seeding.py +9 -3
- django_spire/contrib/seeding/management/example.py +2 -0
- django_spire/contrib/seeding/model/base.py +16 -7
- django_spire/contrib/seeding/model/config.py +31 -15
- django_spire/contrib/seeding/model/django/config.py +13 -13
- django_spire/contrib/seeding/model/django/seeder.py +4 -4
- django_spire/contrib/seeding/model/django/tests/test_seeder.py +34 -23
- django_spire/contrib/seeding/model/enums.py +2 -0
- django_spire/contrib/seeding/tests/test_config.py +71 -0
- django_spire/contrib/seeding/tests/test_custom.py +35 -0
- django_spire/contrib/seeding/tests/test_enums.py +40 -0
- django_spire/contrib/seeding/tests/test_intel.py +32 -0
- django_spire/contrib/seeding/tests/test_override.py +63 -0
- django_spire/contrib/service/__init__.py +2 -2
- django_spire/contrib/service/django_model_service.py +16 -15
- django_spire/contrib/service/exceptions.py +5 -3
- django_spire/contrib/service/tests/__init__.py +0 -0
- django_spire/contrib/service/tests/test_service.py +153 -0
- django_spire/contrib/session/apps.py +2 -0
- django_spire/contrib/session/controller.py +48 -42
- django_spire/contrib/session/templatetags/session_tags.py +11 -2
- django_spire/contrib/session/tests/test_session_controller.py +117 -53
- django_spire/contrib/tests/__init__.py +0 -0
- django_spire/contrib/tests/test_utils.py +37 -0
- django_spire/contrib/utils.py +4 -1
- django_spire/core/apps.py +2 -0
- django_spire/core/converters/tests/test_to_data.py +353 -0
- django_spire/core/converters/tests/test_to_enums.py +61 -41
- django_spire/core/converters/tests/test_to_pydantic.py +138 -109
- django_spire/core/converters/to_data.py +29 -10
- django_spire/core/converters/to_enums.py +4 -2
- django_spire/core/converters/to_pydantic.py +22 -22
- django_spire/core/decorators.py +19 -6
- django_spire/core/forms/widgets.py +4 -0
- django_spire/core/maps.py +3 -1
- django_spire/core/middleware/maintenance.py +3 -3
- django_spire/core/middleware.py +8 -6
- django_spire/core/redirect/__init__.py +5 -0
- django_spire/core/redirect/generic_redirect.py +1 -2
- django_spire/core/redirect/tests/__init__.py +0 -0
- django_spire/core/redirect/tests/test_generic_redirect.py +34 -0
- django_spire/core/{tests/tests_redirect.py → redirect/tests/test_safe_redirect.py} +55 -81
- django_spire/core/shortcuts.py +3 -3
- django_spire/core/static/django_spire/css/app-layout.css +1 -1
- django_spire/core/static/django_spire/css/app-navigation.css +3 -3
- django_spire/core/static/django_spire/css/bootstrap-override.css +4 -0
- django_spire/core/tag/admin.py +12 -0
- django_spire/core/tag/intelligence/tag_set_bot.py +2 -0
- django_spire/core/tag/mixins.py +2 -0
- django_spire/core/tag/models.py +2 -0
- django_spire/core/tag/querysets.py +2 -0
- django_spire/core/tag/service/tag_service.py +6 -3
- django_spire/core/tag/tests/test_intelligence.py +9 -9
- django_spire/core/tag/tests/test_tags.py +44 -54
- django_spire/core/tag/tests/test_tools.py +191 -0
- django_spire/core/tag/tools.py +3 -0
- django_spire/core/templates/django_spire/card/card.html +5 -2
- django_spire/core/templates/django_spire/card/title_card.html +9 -4
- django_spire/core/templates/django_spire/infinite_scroll/base.html +1 -0
- django_spire/core/templates/django_spire/navigation/side_navigation.html +19 -24
- django_spire/core/templates/django_spire/page/full_page.html +46 -16
- django_spire/core/templates/django_spire/table/base.html +4 -2
- django_spire/core/templatetags/json.py +6 -2
- django_spire/core/templatetags/message.py +13 -8
- django_spire/core/templatetags/string_formating.py +8 -5
- django_spire/core/templatetags/tests/__init__.py +0 -0
- django_spire/core/templatetags/tests/test_templatetags.py +427 -0
- django_spire/core/templatetags/variable_types.py +17 -9
- django_spire/core/tests/test_cases.py +1 -1
- django_spire/core/tests/test_conf.py +43 -0
- django_spire/core/tests/test_consts.py +28 -0
- django_spire/core/tests/test_context_processors.py +93 -0
- django_spire/core/tests/test_decorators.py +95 -0
- django_spire/core/tests/test_django_spire_utils.py +56 -0
- django_spire/core/tests/test_exceptions.py +37 -0
- django_spire/core/tests/test_models.py +54 -0
- django_spire/core/tests/test_settings.py +45 -0
- django_spire/core/tests/test_shortcuts.py +74 -0
- django_spire/core/tests/test_urls.py +16 -0
- django_spire/core/tests/test_utils.py +58 -0
- django_spire/core/urls.py +4 -1
- django_spire/core/utils.py +12 -8
- django_spire/exceptions.py +16 -1
- django_spire/file/admin.py +4 -2
- django_spire/file/apps.py +8 -10
- django_spire/file/fields.py +7 -7
- django_spire/file/forms.py +1 -1
- django_spire/file/interfaces.py +15 -15
- django_spire/file/mixins.py +1 -4
- django_spire/file/models.py +3 -5
- django_spire/file/tests/factories.py +59 -0
- django_spire/file/tests/test_admin.py +69 -0
- django_spire/file/tests/test_apps.py +24 -0
- django_spire/file/tests/test_fields.py +114 -0
- django_spire/file/tests/test_forms.py +20 -0
- django_spire/file/tests/test_interfaces.py +183 -0
- django_spire/file/tests/test_models.py +82 -0
- django_spire/file/tests/test_querysets.py +102 -0
- django_spire/file/tests/test_utils.py +32 -0
- django_spire/file/tests/test_views.py +145 -0
- django_spire/file/tests/test_widgets.py +82 -0
- django_spire/file/tools.py +8 -2
- django_spire/file/views.py +7 -3
- django_spire/file/widgets.py +12 -12
- django_spire/help_desk/admin.py +15 -0
- django_spire/help_desk/apps.py +2 -0
- django_spire/help_desk/auth/controller.py +2 -0
- django_spire/help_desk/choices.py +2 -0
- django_spire/help_desk/enums.py +2 -0
- django_spire/help_desk/exceptions.py +31 -3
- django_spire/help_desk/forms.py +2 -0
- django_spire/help_desk/models.py +2 -0
- django_spire/help_desk/querysets.py +4 -1
- django_spire/help_desk/services/notification_service.py +26 -27
- django_spire/help_desk/services/service.py +2 -3
- django_spire/help_desk/tests/factories.py +8 -3
- django_spire/help_desk/tests/test_admin.py +41 -0
- django_spire/help_desk/tests/test_apps.py +41 -0
- django_spire/help_desk/tests/test_choices.py +50 -0
- django_spire/help_desk/tests/test_controller.py +87 -0
- django_spire/help_desk/tests/test_enums.py +18 -0
- django_spire/help_desk/tests/test_exceptions.py +37 -0
- django_spire/help_desk/tests/test_forms.py +89 -0
- django_spire/help_desk/tests/test_models.py +59 -0
- django_spire/help_desk/tests/test_querysets.py +38 -0
- django_spire/help_desk/tests/test_services/test_notification_service.py +15 -8
- django_spire/help_desk/tests/test_services/test_service.py +92 -0
- django_spire/help_desk/tests/test_urls/test_form_urls.py +6 -6
- django_spire/help_desk/tests/test_urls/test_page_urls.py +8 -9
- django_spire/help_desk/tests/test_views/test_form_views.py +46 -19
- django_spire/help_desk/tests/test_views/test_page_views.py +32 -9
- django_spire/help_desk/urls/__init__.py +4 -1
- django_spire/help_desk/urls/form_urls.py +3 -0
- django_spire/help_desk/urls/page_urls.py +3 -0
- django_spire/help_desk/views/form_views.py +13 -5
- django_spire/help_desk/views/page_views.py +11 -3
- django_spire/history/activity/admin.py +2 -0
- django_spire/history/activity/apps.py +3 -1
- django_spire/history/activity/mixins.py +13 -7
- django_spire/history/activity/models.py +6 -5
- django_spire/history/activity/querysets.py +2 -0
- django_spire/history/activity/tests/__init__.py +0 -0
- django_spire/history/activity/tests/test_activity.py +176 -0
- django_spire/history/admin.py +9 -2
- django_spire/history/choices.py +3 -0
- django_spire/history/models.py +5 -5
- django_spire/history/tests/test_admin.py +93 -0
- django_spire/history/tests/test_history.py +101 -0
- django_spire/history/tests/test_mixins.py +84 -0
- django_spire/history/viewed/admin.py +3 -1
- django_spire/history/viewed/apps.py +3 -1
- django_spire/history/viewed/models.py +2 -0
- django_spire/history/viewed/tests/__init__.py +0 -0
- django_spire/history/viewed/tests/test_viewed.py +46 -0
- django_spire/knowledge/auth/tests/__init__.py +0 -0
- django_spire/knowledge/auth/tests/test_controller.py +116 -0
- django_spire/knowledge/collection/admin.py +5 -1
- django_spire/knowledge/collection/models.py +3 -1
- django_spire/knowledge/collection/seeding/seed.py +1 -0
- django_spire/knowledge/collection/services/factory_service.py +10 -11
- django_spire/knowledge/collection/services/ordering_service.py +1 -2
- django_spire/knowledge/collection/services/service.py +5 -10
- django_spire/knowledge/collection/services/tag_service.py +5 -2
- django_spire/knowledge/collection/tests/factories.py +28 -1
- django_spire/knowledge/collection/tests/test_models.py +48 -0
- django_spire/knowledge/collection/tests/test_querysets.py +93 -0
- django_spire/knowledge/collection/tests/test_services/test_factory_service.py +100 -0
- django_spire/knowledge/collection/tests/test_services/test_services.py +160 -0
- django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +21 -3
- django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +39 -1
- django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +12 -4
- django_spire/knowledge/collection/urls/__init__.py +3 -0
- django_spire/knowledge/collection/urls/form_urls.py +2 -0
- django_spire/knowledge/collection/urls/json_urls.py +2 -0
- django_spire/knowledge/collection/urls/page_urls.py +2 -0
- django_spire/knowledge/collection/views/form_views.py +4 -4
- django_spire/knowledge/collection/views/json_views.py +5 -1
- django_spire/knowledge/collection/views/page_views.py +5 -2
- django_spire/knowledge/entry/admin.py +7 -1
- django_spire/knowledge/entry/forms.py +2 -0
- django_spire/knowledge/entry/models.py +2 -0
- django_spire/knowledge/entry/seeding/seed.py +3 -0
- django_spire/knowledge/entry/services/automation_service.py +5 -4
- django_spire/knowledge/entry/services/factory_service.py +7 -5
- django_spire/knowledge/entry/services/service.py +4 -7
- django_spire/knowledge/entry/services/tag_service.py +0 -1
- django_spire/knowledge/entry/services/tool_service.py +1 -0
- django_spire/knowledge/entry/services/transformation_services.py +1 -5
- django_spire/knowledge/entry/tests/factories.py +1 -2
- django_spire/knowledge/entry/tests/test_factory_service.py +20 -0
- django_spire/knowledge/entry/tests/test_models.py +41 -0
- django_spire/knowledge/entry/tests/test_querysets.py +71 -0
- django_spire/knowledge/entry/tests/test_services.py +94 -0
- django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +9 -14
- django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +48 -5
- django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +6 -8
- django_spire/knowledge/entry/tests/test_urls/test_template_urls.py +40 -0
- django_spire/knowledge/entry/urls/form_urls.py +2 -0
- django_spire/knowledge/entry/urls/json_urls.py +2 -0
- django_spire/knowledge/entry/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/urls/template_urls.py +2 -0
- django_spire/knowledge/entry/version/block/choices.py +2 -0
- django_spire/knowledge/entry/version/block/data/data.py +1 -0
- django_spire/knowledge/entry/version/block/data/list/data.py +8 -13
- django_spire/knowledge/entry/version/block/data/list/maps.py +3 -0
- django_spire/knowledge/entry/version/block/data/list/meta.py +1 -2
- django_spire/knowledge/entry/version/block/data/list/tests/__init__.py +0 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_maps.py +32 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_meta.py +58 -0
- django_spire/knowledge/entry/version/block/data/maps.py +3 -6
- django_spire/knowledge/entry/version/block/models.py +7 -5
- django_spire/knowledge/entry/version/block/seeding/constants.py +5 -4
- django_spire/knowledge/entry/version/block/services/service.py +2 -3
- django_spire/knowledge/entry/version/block/tests/factories.py +4 -10
- django_spire/knowledge/entry/version/block/tests/test_choices.py +56 -0
- django_spire/knowledge/entry/version/block/tests/test_data.py +90 -0
- django_spire/knowledge/entry/version/block/tests/test_maps.py +37 -0
- django_spire/knowledge/entry/version/block/tests/test_models.py +55 -0
- django_spire/knowledge/entry/version/block/tests/test_querysets.py +35 -0
- django_spire/knowledge/entry/version/block/tests/test_services.py +65 -0
- django_spire/knowledge/entry/version/choices.py +2 -0
- django_spire/knowledge/entry/version/converters/converter.py +1 -1
- django_spire/knowledge/entry/version/converters/docx_converter.py +4 -7
- django_spire/knowledge/entry/version/converters/markdown_converter.py +20 -20
- django_spire/knowledge/entry/version/maps.py +4 -5
- django_spire/knowledge/entry/version/querysets.py +1 -1
- django_spire/knowledge/entry/version/seeding/seeder.py +1 -2
- django_spire/knowledge/entry/version/services/processor_service.py +5 -4
- django_spire/knowledge/entry/version/services/service.py +1 -2
- django_spire/knowledge/entry/version/tests/factories.py +2 -2
- django_spire/knowledge/entry/version/tests/test_choices.py +18 -0
- django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +56 -8
- django_spire/knowledge/entry/version/tests/test_converters/test_markdown_converter.py +78 -0
- django_spire/knowledge/entry/version/tests/test_maps.py +58 -0
- django_spire/knowledge/entry/version/tests/test_models.py +23 -0
- django_spire/knowledge/entry/version/tests/test_querysets.py +26 -0
- django_spire/knowledge/entry/version/tests/test_services.py +62 -0
- django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +27 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +15 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_redirect_urls.py +38 -0
- django_spire/knowledge/entry/version/urls/__init__.py +3 -0
- django_spire/knowledge/entry/version/urls/json_urls.py +2 -1
- django_spire/knowledge/entry/version/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/version/urls/redirect_urls.py +2 -0
- django_spire/knowledge/entry/version/views/json_views.py +5 -1
- django_spire/knowledge/entry/version/views/page_views.py +10 -3
- django_spire/knowledge/entry/version/views/redirect_views.py +5 -1
- django_spire/knowledge/entry/views/form_views.py +16 -8
- django_spire/knowledge/entry/views/json_views.py +3 -1
- django_spire/knowledge/entry/views/page_views.py +8 -2
- django_spire/knowledge/entry/views/template_views.py +7 -1
- django_spire/knowledge/exceptions.py +2 -1
- django_spire/knowledge/intelligence/intel/answer_intel.py +2 -1
- django_spire/knowledge/intelligence/intel/entry_intel.py +0 -1
- django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +4 -5
- django_spire/knowledge/models.py +1 -2
- django_spire/knowledge/tests/__init__.py +0 -0
- django_spire/knowledge/tests/test_templatetags.py +40 -0
- django_spire/knowledge/tests/test_urls/__init__.py +0 -0
- django_spire/knowledge/tests/test_urls/test_page_urls.py +24 -0
- django_spire/knowledge/urls/__init__.py +2 -0
- django_spire/knowledge/urls/page_urls.py +2 -0
- django_spire/knowledge/views/page_views.py +8 -3
- django_spire/notification/admin.py +3 -1
- django_spire/notification/app/admin.py +2 -0
- django_spire/notification/app/apps.py +3 -1
- django_spire/notification/app/exceptions.py +9 -2
- django_spire/notification/app/models.py +8 -4
- django_spire/notification/app/processor.py +22 -26
- django_spire/notification/app/querysets.py +2 -0
- django_spire/notification/app/tests/__init__.py +0 -0
- django_spire/notification/app/tests/factories.py +34 -0
- django_spire/notification/app/tests/test_apps.py +24 -0
- django_spire/notification/app/tests/test_models.py +72 -0
- django_spire/notification/app/tests/test_processor.py +111 -0
- django_spire/notification/app/tests/test_querysets.py +90 -0
- django_spire/notification/app/tests/test_views/__init__.py +0 -0
- django_spire/notification/app/tests/test_views/test_json_views.py +48 -0
- django_spire/notification/app/tests/test_views/test_page_views.py +19 -0
- django_spire/notification/app/urls/__init__.py +3 -1
- django_spire/notification/app/urls/json_urls.py +6 -4
- django_spire/notification/app/urls/page_urls.py +4 -3
- django_spire/notification/app/urls/template_urls.py +4 -2
- django_spire/notification/apps.py +4 -1
- django_spire/notification/email/admin.py +5 -1
- django_spire/notification/email/apps.py +3 -1
- django_spire/notification/email/exceptions.py +4 -2
- django_spire/notification/email/helper.py +5 -3
- django_spire/notification/email/models.py +4 -0
- django_spire/notification/email/processor.py +19 -15
- django_spire/notification/email/querysets.py +3 -0
- django_spire/notification/email/tests/__init__.py +0 -0
- django_spire/notification/email/tests/factories.py +35 -0
- django_spire/notification/email/tests/test_apps.py +24 -0
- django_spire/notification/email/tests/test_models.py +52 -0
- django_spire/notification/email/tests/test_processor.py +92 -0
- django_spire/notification/email/tests/test_querysets.py +43 -0
- django_spire/notification/exceptions.py +17 -2
- django_spire/notification/managers.py +7 -1
- django_spire/notification/maps.py +4 -1
- django_spire/notification/mixins.py +2 -0
- django_spire/notification/models.py +3 -1
- django_spire/notification/processors/notification.py +12 -5
- django_spire/notification/processors/processor.py +2 -0
- django_spire/notification/processors/tests/__init__.py +0 -0
- django_spire/notification/processors/tests/test_notification.py +106 -0
- django_spire/notification/push/admin.py +10 -1
- django_spire/notification/push/apps.py +3 -1
- django_spire/notification/push/models.py +2 -3
- django_spire/notification/push/tests/__init__.py +0 -0
- django_spire/notification/push/tests/test_apps.py +24 -0
- django_spire/notification/push/tests/test_models.py +28 -0
- django_spire/notification/querysets.py +7 -1
- django_spire/notification/sms/admin.py +2 -0
- django_spire/notification/sms/apps.py +4 -1
- django_spire/notification/sms/automations.py +2 -0
- django_spire/notification/sms/choices.py +2 -0
- django_spire/notification/sms/exceptions.py +19 -5
- django_spire/notification/sms/helper.py +33 -23
- django_spire/notification/sms/models.py +5 -1
- django_spire/notification/sms/processor.py +20 -20
- django_spire/notification/sms/querysets.py +2 -0
- django_spire/notification/sms/tests/factories.py +33 -0
- django_spire/notification/sms/tests/test_apps.py +24 -0
- django_spire/notification/sms/tests/test_automation.py +38 -0
- django_spire/notification/sms/tests/test_choices.py +15 -0
- django_spire/notification/sms/tests/test_consts.py +17 -0
- django_spire/notification/sms/tests/test_exceptions.py +27 -0
- django_spire/notification/sms/tests/test_helper.py +50 -0
- django_spire/notification/sms/tests/test_models.py +81 -0
- django_spire/notification/sms/tests/test_processor.py +107 -0
- django_spire/notification/sms/tests/test_tools.py +25 -11
- django_spire/notification/sms/tools.py +16 -5
- django_spire/notification/sms/urls/__init__.py +3 -1
- django_spire/notification/sms/urls/media_urls.py +2 -0
- django_spire/notification/sms/views/media_views.py +14 -4
- django_spire/notification/tests/__init__.py +0 -0
- django_spire/notification/tests/factories.py +26 -0
- django_spire/notification/tests/test_admin.py +55 -0
- django_spire/notification/tests/test_apps.py +30 -0
- django_spire/notification/tests/test_automation.py +18 -0
- django_spire/notification/tests/test_choices.py +59 -0
- django_spire/notification/tests/test_exceptions.py +58 -0
- django_spire/notification/tests/test_managers.py +100 -0
- django_spire/notification/tests/test_maps.py +31 -0
- django_spire/notification/tests/test_models.py +76 -0
- django_spire/notification/tests/test_querysets.py +184 -0
- django_spire/notification/tests/test_utils.py +23 -0
- django_spire/notification/urls.py +3 -1
- django_spire/notification/utils.py +3 -1
- django_spire/settings.py +3 -0
- django_spire/theme/tests/test_context_processor.py +15 -13
- django_spire/theme/tests/test_enums.py +2 -2
- django_spire/theme/tests/test_filesystem.py +2 -5
- django_spire/theme/tests/test_integration.py +12 -12
- django_spire/theme/tests/test_model.py +40 -38
- django_spire/theme/tests/test_views/test_json_views.py +33 -33
- django_spire/theme/urls/json_urls.py +3 -0
- django_spire/theme/urls/page_urls.py +3 -0
- django_spire/urls.py +19 -15
- django_spire/utils.py +13 -4
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/METADATA +1 -1
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/RECORD +530 -358
- django_spire/contrib/options/tests/test_unit.py +0 -148
- django_spire/contrib/seeding/tests/test_seeding.py +0 -25
- django_spire/core/tests/test_templatetags.py +0 -117
- django_spire/core/tests/tests_shortcuts.py +0 -73
- django_spire/history/activity/tests.py +0 -3
- django_spire/history/activity/views.py +0 -3
- django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +0 -71
- django_spire/notification/app/tests.py +0 -3
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/WHEEL +0 -0
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/licenses/LICENSE.md +0 -0
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock, patch
|
|
4
|
+
|
|
5
|
+
from django_spire.core.tests.test_cases import BaseTestCase
|
|
6
|
+
from django_spire.help_desk.choices import (
|
|
7
|
+
HelpDeskTicketPriorityChoices,
|
|
8
|
+
HelpDeskTicketPurposeChoices,
|
|
9
|
+
HelpDeskTicketStatusChoices,
|
|
10
|
+
)
|
|
11
|
+
from django_spire.help_desk.models import HelpDeskTicket
|
|
12
|
+
from django_spire.help_desk.tests.factories import create_test_helpdesk_ticket
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class HelpDeskTicketServiceTests(BaseTestCase):
|
|
16
|
+
def setUp(self):
|
|
17
|
+
super().setUp()
|
|
18
|
+
self.ticket = create_test_helpdesk_ticket()
|
|
19
|
+
|
|
20
|
+
def test_save_model_obj_updates_existing(self):
|
|
21
|
+
self.ticket.services.obj = self.ticket
|
|
22
|
+
updated_ticket, created = self.ticket.services.save_model_obj(
|
|
23
|
+
description='Updated description'
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
assert created is False
|
|
27
|
+
assert updated_ticket.description == 'Updated description'
|
|
28
|
+
|
|
29
|
+
def test_save_model_obj_updates_priority(self):
|
|
30
|
+
self.ticket.services.obj = self.ticket
|
|
31
|
+
updated_ticket, _ = self.ticket.services.save_model_obj(
|
|
32
|
+
priority=HelpDeskTicketPriorityChoices.URGENT
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
assert updated_ticket.priority == HelpDeskTicketPriorityChoices.URGENT
|
|
36
|
+
|
|
37
|
+
def test_save_model_obj_updates_status(self):
|
|
38
|
+
self.ticket.services.obj = self.ticket
|
|
39
|
+
updated_ticket, _ = self.ticket.services.save_model_obj(
|
|
40
|
+
status=HelpDeskTicketStatusChoices.DONE
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
assert updated_ticket.status == HelpDeskTicketStatusChoices.DONE
|
|
44
|
+
|
|
45
|
+
@patch(
|
|
46
|
+
'django_spire.help_desk.services.notification_service.'
|
|
47
|
+
'HelpDeskTicketNotificationService.create_new_ticket_notifications'
|
|
48
|
+
)
|
|
49
|
+
def test_create_sets_created_by(self, _mock_notifications: MagicMock):
|
|
50
|
+
ticket = HelpDeskTicket()
|
|
51
|
+
|
|
52
|
+
created_ticket = ticket.services.create(
|
|
53
|
+
created_by=self.super_user,
|
|
54
|
+
purpose=HelpDeskTicketPurposeChoices.APP,
|
|
55
|
+
priority=HelpDeskTicketPriorityChoices.LOW,
|
|
56
|
+
description='Test ticket',
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
assert created_ticket.created_by == self.super_user
|
|
60
|
+
|
|
61
|
+
@patch(
|
|
62
|
+
'django_spire.help_desk.services.notification_service.'
|
|
63
|
+
'HelpDeskTicketNotificationService.create_new_ticket_notifications'
|
|
64
|
+
)
|
|
65
|
+
def test_create_calls_notification_service(self, mock_notifications: MagicMock):
|
|
66
|
+
ticket = HelpDeskTicket()
|
|
67
|
+
|
|
68
|
+
ticket.services.create(
|
|
69
|
+
created_by=self.super_user,
|
|
70
|
+
purpose=HelpDeskTicketPurposeChoices.APP,
|
|
71
|
+
priority=HelpDeskTicketPriorityChoices.LOW,
|
|
72
|
+
description='Test ticket',
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
mock_notifications.assert_called_once()
|
|
76
|
+
|
|
77
|
+
@patch(
|
|
78
|
+
'django_spire.help_desk.services.notification_service.'
|
|
79
|
+
'HelpDeskTicketNotificationService.create_new_ticket_notifications'
|
|
80
|
+
)
|
|
81
|
+
def test_create_returns_ticket(self, _mock_notifications: MagicMock):
|
|
82
|
+
ticket = HelpDeskTicket()
|
|
83
|
+
|
|
84
|
+
created_ticket = ticket.services.create(
|
|
85
|
+
created_by=self.super_user,
|
|
86
|
+
purpose=HelpDeskTicketPurposeChoices.APP,
|
|
87
|
+
priority=HelpDeskTicketPriorityChoices.LOW,
|
|
88
|
+
description='Test ticket',
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
assert created_ticket.pk is not None
|
|
92
|
+
assert created_ticket.purpose == HelpDeskTicketPurposeChoices.APP
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.urls import reverse
|
|
2
4
|
|
|
3
5
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
@@ -5,17 +7,15 @@ from django_spire.help_desk.tests.factories import create_test_helpdesk_ticket
|
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class HelpDeskFormUrlsTestCase(BaseTestCase):
|
|
8
|
-
def test_helpdesk_ticket_form_create_url_path(self)
|
|
10
|
+
def test_helpdesk_ticket_form_create_url_path(self):
|
|
9
11
|
response = self.client.get(path=reverse('django_spire:help_desk:form:create'))
|
|
12
|
+
assert response.status_code == 200
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_helpdesk_ticket_form_update_url_path(self) -> None:
|
|
14
|
+
def test_helpdesk_ticket_form_update_url_path(self):
|
|
14
15
|
response = self.client.get(
|
|
15
16
|
path=reverse(
|
|
16
17
|
'django_spire:help_desk:form:update',
|
|
17
18
|
kwargs={'pk': create_test_helpdesk_ticket().pk}
|
|
18
19
|
),
|
|
19
20
|
)
|
|
20
|
-
|
|
21
|
-
self.assertEqual(response.status_code, 200)
|
|
21
|
+
assert response.status_code == 200
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.urls import reverse
|
|
2
4
|
|
|
3
5
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
@@ -10,27 +12,24 @@ class HelpDeskPageUrlsTestCase(BaseTestCase):
|
|
|
10
12
|
|
|
11
13
|
self.test_ticket = create_test_helpdesk_ticket()
|
|
12
14
|
|
|
13
|
-
def test_ticket_delete_view_url_path(self)
|
|
15
|
+
def test_ticket_delete_view_url_path(self):
|
|
14
16
|
response = self.client.get(
|
|
15
17
|
path=reverse(
|
|
16
18
|
'django_spire:help_desk:page:delete',
|
|
17
19
|
kwargs={'pk': self.test_ticket.pk}
|
|
18
20
|
),
|
|
19
21
|
)
|
|
22
|
+
assert response.status_code == 200
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_ticket_detail_view_url_path(self) -> None:
|
|
24
|
+
def test_ticket_detail_view_url_path(self):
|
|
24
25
|
response = self.client.get(
|
|
25
26
|
path=reverse(
|
|
26
27
|
'django_spire:help_desk:page:detail',
|
|
27
28
|
kwargs={'pk': self.test_ticket.pk}
|
|
28
29
|
),
|
|
29
30
|
)
|
|
31
|
+
assert response.status_code == 200
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def test_ticket_list_view_url_path(self) -> None:
|
|
33
|
+
def test_ticket_list_view_url_path(self):
|
|
34
34
|
response = self.client.get(path=reverse('django_spire:help_desk:page:list'))
|
|
35
|
-
|
|
36
|
-
self.assertEqual(response.status_code, 200)
|
|
35
|
+
assert response.status_code == 200
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.urls import reverse
|
|
2
4
|
|
|
3
5
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
4
6
|
from django_spire.help_desk.models import HelpDeskTicket
|
|
5
|
-
from django_spire.help_desk.tests.factories import
|
|
6
|
-
|
|
7
|
+
from django_spire.help_desk.tests.factories import (
|
|
8
|
+
create_test_helpdesk_ticket,
|
|
9
|
+
create_test_helpdesk_ticket_data,
|
|
10
|
+
)
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
class HelpDeskFormViewsTestCase(BaseTestCase):
|
|
10
|
-
def
|
|
11
|
-
super().setUp()
|
|
12
|
-
|
|
13
|
-
def test_helpdesk_ticket_form_create_view(self) -> None:
|
|
14
|
+
def test_helpdesk_ticket_form_create_view(self):
|
|
14
15
|
ticket_data = create_test_helpdesk_ticket_data()
|
|
15
16
|
|
|
16
17
|
response = self.client.post(
|
|
@@ -20,15 +21,15 @@ class HelpDeskFormViewsTestCase(BaseTestCase):
|
|
|
20
21
|
|
|
21
22
|
ticket = HelpDeskTicket.objects.first()
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
assert response.status_code == 302
|
|
25
|
+
assert response.url == reverse('django_spire:help_desk:page:list')
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
assert ticket.priority == ticket_data['priority']
|
|
28
|
+
assert ticket.purpose == ticket_data['purpose']
|
|
29
|
+
assert ticket.status == ticket_data['status']
|
|
30
|
+
assert ticket.description == ticket_data['description']
|
|
30
31
|
|
|
31
|
-
def test_helpdesk_ticket_form_update_view(self)
|
|
32
|
+
def test_helpdesk_ticket_form_update_view(self):
|
|
32
33
|
test_ticket = create_test_helpdesk_ticket()
|
|
33
34
|
|
|
34
35
|
updated_ticket_data = create_test_helpdesk_ticket_data(
|
|
@@ -46,11 +47,37 @@ class HelpDeskFormViewsTestCase(BaseTestCase):
|
|
|
46
47
|
),
|
|
47
48
|
)
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
assert response.status_code == 302
|
|
51
|
+
assert response.url == reverse('django_spire:help_desk:page:list')
|
|
51
52
|
|
|
52
53
|
test_ticket.refresh_from_db()
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
assert test_ticket.priority == updated_ticket_data['priority']
|
|
55
|
+
assert test_ticket.purpose == updated_ticket_data['purpose']
|
|
56
|
+
assert test_ticket.status == updated_ticket_data['status']
|
|
57
|
+
assert test_ticket.description == updated_ticket_data['description']
|
|
58
|
+
|
|
59
|
+
def test_helpdesk_ticket_form_create_view_invalid_data(self):
|
|
60
|
+
invalid_data = {
|
|
61
|
+
'priority': '',
|
|
62
|
+
'purpose': '',
|
|
63
|
+
'description': '',
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
response = self.client.post(
|
|
67
|
+
reverse('django_spire:help_desk:form:create'),
|
|
68
|
+
data=invalid_data,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
assert response.status_code == 200
|
|
72
|
+
assert HelpDeskTicket.objects.count() == 0
|
|
73
|
+
|
|
74
|
+
def test_helpdesk_ticket_form_create_view_sets_created_by(self):
|
|
75
|
+
ticket_data = create_test_helpdesk_ticket_data()
|
|
76
|
+
|
|
77
|
+
self.client.post(
|
|
78
|
+
reverse('django_spire:help_desk:form:create'),
|
|
79
|
+
data=ticket_data,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
ticket = HelpDeskTicket.objects.first()
|
|
83
|
+
assert ticket.created_by == self.super_user
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.urls import reverse
|
|
2
4
|
|
|
3
5
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
@@ -10,7 +12,7 @@ class HelpDeskPageViewsTestCase(BaseTestCase):
|
|
|
10
12
|
|
|
11
13
|
self.test_ticket = create_test_helpdesk_ticket()
|
|
12
14
|
|
|
13
|
-
def test_ticket_delete_view(self)
|
|
15
|
+
def test_ticket_delete_view(self):
|
|
14
16
|
response = self.client.post(
|
|
15
17
|
reverse(
|
|
16
18
|
'django_spire:help_desk:page:delete',
|
|
@@ -19,11 +21,11 @@ class HelpDeskPageViewsTestCase(BaseTestCase):
|
|
|
19
21
|
data={'should_delete': 'on'},
|
|
20
22
|
)
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
assert response.status_code == 302
|
|
23
25
|
self.test_ticket.refresh_from_db()
|
|
24
|
-
self.
|
|
26
|
+
assert self.test_ticket.is_deleted is True
|
|
25
27
|
|
|
26
|
-
def test_ticket_detail_view(self)
|
|
28
|
+
def test_ticket_detail_view(self):
|
|
27
29
|
response = self.client.get(
|
|
28
30
|
reverse(
|
|
29
31
|
'django_spire:help_desk:page:detail',
|
|
@@ -31,16 +33,37 @@ class HelpDeskPageViewsTestCase(BaseTestCase):
|
|
|
31
33
|
),
|
|
32
34
|
)
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
assert response.status_code == 200
|
|
37
|
+
assert response.context_data['ticket'] == self.test_ticket
|
|
36
38
|
|
|
37
|
-
def test_ticket_list_view(self)
|
|
39
|
+
def test_ticket_list_view(self):
|
|
38
40
|
tickets = [create_test_helpdesk_ticket() for _ in range(5)]
|
|
39
41
|
|
|
40
42
|
response = self.client.get(
|
|
41
43
|
reverse('django_spire:help_desk:page:list'),
|
|
42
44
|
)
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
assert response.status_code == 200
|
|
45
47
|
for ticket in tickets:
|
|
46
|
-
|
|
48
|
+
assert ticket in response.context_data['tickets']
|
|
49
|
+
|
|
50
|
+
def test_ticket_list_view_excludes_deleted(self):
|
|
51
|
+
deleted_ticket = create_test_helpdesk_ticket()
|
|
52
|
+
deleted_ticket.is_deleted = True
|
|
53
|
+
deleted_ticket.save()
|
|
54
|
+
|
|
55
|
+
response = self.client.get(
|
|
56
|
+
reverse('django_spire:help_desk:page:list'),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
assert deleted_ticket not in response.context_data['tickets']
|
|
60
|
+
|
|
61
|
+
def test_ticket_list_view_ordered_by_created_datetime_desc(self):
|
|
62
|
+
response = self.client.get(
|
|
63
|
+
reverse('django_spire:help_desk:page:list'),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
tickets = list(response.context_data['tickets'])
|
|
67
|
+
if len(tickets) > 1:
|
|
68
|
+
for i in range(len(tickets) - 1):
|
|
69
|
+
assert tickets[i].created_datetime >= tickets[i + 1].created_datetime
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.urls import include, path
|
|
2
4
|
|
|
5
|
+
|
|
3
6
|
app_name = 'help_desk'
|
|
4
7
|
|
|
5
8
|
urlpatterns = [
|
|
6
9
|
path('page/', include('django_spire.help_desk.urls.page_urls', namespace='page')),
|
|
7
10
|
path('form/', include('django_spire.help_desk.urls.form_urls', namespace='form')),
|
|
8
|
-
]
|
|
11
|
+
]
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import django_glue as dg
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
2
7
|
from django.shortcuts import redirect, get_object_or_404
|
|
3
8
|
from django.urls import reverse
|
|
4
9
|
|
|
@@ -8,9 +13,13 @@ from django_spire.contrib.generic_views import portal_views
|
|
|
8
13
|
from django_spire.help_desk import forms
|
|
9
14
|
from django_spire.help_desk.models import HelpDeskTicket
|
|
10
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
18
|
+
from django.template.response import TemplateResponse
|
|
19
|
+
|
|
11
20
|
|
|
12
21
|
@AppAuthController('help_desk').permission_required('can_add')
|
|
13
|
-
def ticket_create_form_view(request):
|
|
22
|
+
def ticket_create_form_view(request: WSGIRequest) -> TemplateResponse:
|
|
14
23
|
ticket = HelpDeskTicket()
|
|
15
24
|
|
|
16
25
|
dg.glue_model_object(request, 'ticket', ticket)
|
|
@@ -34,7 +43,7 @@ def ticket_create_form_view(request):
|
|
|
34
43
|
request,
|
|
35
44
|
form=form,
|
|
36
45
|
template='django_spire/help_desk/page/ticket_form_page.html',
|
|
37
|
-
verb=
|
|
46
|
+
verb='Create',
|
|
38
47
|
obj=ticket,
|
|
39
48
|
context_data={
|
|
40
49
|
'form_action_url': reverse('django_spire:help_desk:form:create'),
|
|
@@ -43,7 +52,7 @@ def ticket_create_form_view(request):
|
|
|
43
52
|
|
|
44
53
|
|
|
45
54
|
@AppAuthController('help_desk').permission_required('can_change')
|
|
46
|
-
def ticket_update_form_view(request, pk: int):
|
|
55
|
+
def ticket_update_form_view(request: WSGIRequest, pk: int) -> TemplateResponse:
|
|
47
56
|
ticket = get_object_or_404(HelpDeskTicket, pk=pk)
|
|
48
57
|
|
|
49
58
|
dg.glue_model_object(request, 'ticket', ticket)
|
|
@@ -52,8 +61,7 @@ def ticket_update_form_view(request, pk: int):
|
|
|
52
61
|
form = forms.HelpDeskTicketUpdateForm(request.POST, instance=ticket)
|
|
53
62
|
|
|
54
63
|
if form.is_valid():
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
ticket.services.save_model_obj(**form.cleaned_data)
|
|
57
65
|
return redirect(reverse('django_spire:help_desk:page:list'))
|
|
58
66
|
|
|
59
67
|
show_form_errors(request, form)
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
1
5
|
from django.shortcuts import get_object_or_404
|
|
2
6
|
from django.urls import reverse
|
|
3
7
|
|
|
@@ -5,9 +9,13 @@ from django_spire.auth.controller.controller import AppAuthController
|
|
|
5
9
|
from django_spire.contrib.generic_views import portal_views
|
|
6
10
|
from django_spire.help_desk.models import HelpDeskTicket
|
|
7
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
14
|
+
from django.template.response import TemplateResponse
|
|
15
|
+
|
|
8
16
|
|
|
9
17
|
@AppAuthController('help_desk').permission_required('can_delete')
|
|
10
|
-
def ticket_delete_view(request, pk):
|
|
18
|
+
def ticket_delete_view(request: WSGIRequest, pk: int):
|
|
11
19
|
ticket = get_object_or_404(HelpDeskTicket, pk=pk)
|
|
12
20
|
|
|
13
21
|
return portal_views.delete_form_view(
|
|
@@ -21,7 +29,7 @@ def ticket_delete_view(request, pk):
|
|
|
21
29
|
|
|
22
30
|
|
|
23
31
|
@AppAuthController('help_desk').permission_required('can_view')
|
|
24
|
-
def ticket_detail_view(request, pk):
|
|
32
|
+
def ticket_detail_view(request: WSGIRequest, pk: int):
|
|
25
33
|
ticket = get_object_or_404(HelpDeskTicket, pk=pk)
|
|
26
34
|
|
|
27
35
|
return portal_views.detail_view(
|
|
@@ -35,7 +43,7 @@ def ticket_detail_view(request, pk):
|
|
|
35
43
|
|
|
36
44
|
|
|
37
45
|
@AppAuthController('help_desk').permission_required('can_view')
|
|
38
|
-
def ticket_list_view(request):
|
|
46
|
+
def ticket_list_view(request: WSGIRequest) -> TemplateResponse:
|
|
39
47
|
tickets = HelpDeskTicket.objects.order_by('-created_datetime').active()
|
|
40
48
|
|
|
41
49
|
return portal_views.list_view(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.apps import AppConfig
|
|
2
4
|
|
|
3
5
|
from django_spire.utils import check_required_apps
|
|
@@ -11,4 +13,4 @@ class HistoryActivityConfig(AppConfig):
|
|
|
11
13
|
REQUIRED_APPS = ('django_spire_core', 'django_spire_history')
|
|
12
14
|
|
|
13
15
|
def ready(self) -> None:
|
|
14
|
-
check_required_apps(self.label)
|
|
16
|
+
check_required_apps(self.label)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
2
5
|
from django.contrib.contenttypes.fields import GenericRelation
|
|
3
6
|
from django.db import models
|
|
4
7
|
|
|
5
8
|
from django_spire.history.activity.models import Activity, ActivitySubscriber
|
|
6
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from django.contrib.auth.models import User
|
|
12
|
+
|
|
7
13
|
|
|
8
14
|
class ActivityMixin(models.Model):
|
|
9
15
|
activities = GenericRelation(
|
|
@@ -13,12 +19,12 @@ class ActivityMixin(models.Model):
|
|
|
13
19
|
)
|
|
14
20
|
|
|
15
21
|
def add_activity(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
self,
|
|
23
|
+
user: User,
|
|
24
|
+
verb: str,
|
|
25
|
+
information: str,
|
|
26
|
+
recipient: User = None,
|
|
27
|
+
subscribers: list[User] | None = None
|
|
22
28
|
) -> Activity:
|
|
23
29
|
|
|
24
30
|
activity = self.activities.create(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django.contrib.auth.models import User
|
|
2
4
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
3
5
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -12,9 +14,10 @@ class Activity(models.Model):
|
|
|
12
14
|
ContentType,
|
|
13
15
|
related_name='activities',
|
|
14
16
|
related_query_name='activity',
|
|
15
|
-
on_delete=models.CASCADE,
|
|
17
|
+
on_delete=models.CASCADE,
|
|
16
18
|
editable=False
|
|
17
19
|
)
|
|
20
|
+
|
|
18
21
|
object_id = models.PositiveIntegerField(editable=False)
|
|
19
22
|
content_object = GenericForeignKey('content_type', 'object_id')
|
|
20
23
|
|
|
@@ -47,9 +50,7 @@ class Activity(models.Model):
|
|
|
47
50
|
return f'{self.user} - {self.verb}'
|
|
48
51
|
|
|
49
52
|
def add_subscriber(self, subscriber: User) -> None:
|
|
50
|
-
self.subscribers.create(
|
|
51
|
-
user=subscriber
|
|
52
|
-
)
|
|
53
|
+
self.subscribers.create(subscriber=subscriber)
|
|
53
54
|
|
|
54
55
|
class Meta:
|
|
55
56
|
db_table = 'django_spire_history_activity'
|
|
@@ -78,7 +79,7 @@ class ActivitySubscriber(models.Model):
|
|
|
78
79
|
|
|
79
80
|
def __str__(self):
|
|
80
81
|
return f'{self.activity} - {self.subscriber}'
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
class Meta:
|
|
83
84
|
db_table = 'django_spire_history_activity_subscriber'
|
|
84
85
|
verbose_name = 'Activity Subscriber'
|
|
File without changes
|