django-forms-workflows 0.42.2__tar.gz → 0.44.0__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.
Files changed (180) hide show
  1. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/CHANGELOG.md +31 -0
  2. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/PKG-INFO +1 -1
  3. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/admin.py +49 -47
  4. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/diff_views.py +6 -2
  5. django_forms_workflows-0.44.0/django_forms_workflows/migrations/0074_add_notification_rule.py +136 -0
  6. django_forms_workflows-0.44.0/django_forms_workflows/migrations/0075_migrate_to_notification_rules.py +98 -0
  7. django_forms_workflows-0.44.0/django_forms_workflows/migrations/0076_update_notification_event_choices.py +55 -0
  8. django_forms_workflows-0.44.0/django_forms_workflows/migrations/0077_drop_legacy_notification_models.py +27 -0
  9. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/models.py +113 -173
  10. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/css/forms.css +1 -1
  11. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/sync_api.py +30 -13
  12. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/tasks.py +227 -339
  13. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/workflow_engine.py +48 -163
  14. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/pyproject.toml +1 -1
  15. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/LICENSE +0 -0
  16. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/README.md +0 -0
  17. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/__init__.py +0 -0
  18. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/api_urls.py +0 -0
  19. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/api_views.py +0 -0
  20. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/apps.py +0 -0
  21. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/conditions.py +0 -0
  22. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/context_processors.py +0 -0
  23. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/data_sources/__init__.py +0 -0
  24. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/data_sources/base.py +0 -0
  25. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/data_sources/database_source.py +0 -0
  26. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/data_sources/ldap_source.py +0 -0
  27. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/data_sources/user_source.py +0 -0
  28. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/email_backends/__init__.py +0 -0
  29. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/email_backends/gmail_api.py +0 -0
  30. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/form_builder_urls.py +0 -0
  31. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/form_builder_views.py +0 -0
  32. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/forms.py +0 -0
  33. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/__init__.py +0 -0
  34. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/api_handler.py +0 -0
  35. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/base.py +0 -0
  36. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/database_handler.py +0 -0
  37. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/email_handler.py +0 -0
  38. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/executor.py +0 -0
  39. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/file_handler.py +0 -0
  40. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/handlers/ldap_handler.py +0 -0
  41. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/history.py +0 -0
  42. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/ldap_backend.py +0 -0
  43. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
  44. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/pull_forms.py +0 -0
  45. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/push_forms.py +0 -0
  46. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
  47. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
  48. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
  49. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
  50. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
  51. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
  52. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0001_initial.py +0 -0
  53. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0002_prefillsource_alter_formfield_prefill_source_and_more.py +0 -0
  54. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
  55. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
  56. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
  57. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0006_workflowdefinition_visual_workflow_data_and_more.py +0 -0
  58. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
  59. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
  60. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
  61. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
  62. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0011_postsubmissionaction_email_body_template_and_more.py +0 -0
  63. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
  64. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
  65. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
  66. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
  67. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
  68. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
  69. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
  70. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
  71. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
  72. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0021_alter_pendingnotification_scheduled_for_and_more.py +0 -0
  73. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
  74. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
  75. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
  76. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
  77. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
  78. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
  79. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
  80. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0029_formfield_workflow_stage_fk_drop_groupconfig.py +0 -0
  81. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
  82. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
  83. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0032_approved_pending_detached_sub_workflow.py +0 -0
  84. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0033_add_reject_parent_to_subworkflowdefinition.py +0 -0
  85. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
  86. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
  87. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
  88. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0037_migrate_flat_workflows_to_staged.py +0 -0
  89. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0038_remove_legacy_prefill_source_and_approval_step.py +0 -0
  90. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
  91. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
  92. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
  93. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0042_add_sub_workflow_section_label.py +0 -0
  94. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0043_fix_form_data_decimal_encoding.py +0 -0
  95. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
  96. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
  97. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0046_workflow_definition_one_to_many.py +0 -0
  98. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
  99. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0048_workflowdefinition_trigger_conditions_and_more.py +0 -0
  100. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
  101. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
  102. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
  103. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0052_dynamic_assignee_and_form_field_notifications.py +0 -0
  104. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
  105. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0054_rename_approved_pending_to_pending_approval.py +0 -0
  106. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
  107. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
  108. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
  109. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0058_rename_assignee_email_field_add_lookup_type.py +0 -0
  110. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0059_add_multiselect_list_field_type.py +0 -0
  111. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0060_alter_workflowstage_assignee_lookup_type_helptext.py +0 -0
  112. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0061_add_country_us_state_field_types.py +0 -0
  113. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0062_add_batch_import_to_formdefinition.py +0 -0
  114. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
  115. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0064_add_reviewer_groups.py +0 -0
  116. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0065_workflownotification.py +0 -0
  117. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0066_add_notify_submitter_to_workflownotification.py +0 -0
  118. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0067_migrate_legacy_notify_flags.py +0 -0
  119. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0068_drop_legacy_notify_fields.py +0 -0
  120. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0069_add_signature_field_type.py +0 -0
  121. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0070_workflowstage_allow_edit_form_data.py +0 -0
  122. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0071_alter_pendingnotification_notification_type.py +0 -0
  123. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0072_add_change_history.py +0 -0
  124. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/0073_add_stage_notify_assignee_on_final_decision.py +0 -0
  125. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/migrations/__init__.py +0 -0
  126. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/signals.py +0 -0
  127. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/sso_backends.py +0 -0
  128. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/sso_urls.py +0 -0
  129. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/sso_views.py +0 -0
  130. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui-bundle.js +0 -0
  131. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui.css +0 -0
  132. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +0 -0
  133. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/js/form-enhancements.js +0 -0
  134. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/js/signature-pad.js +0 -0
  135. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/static/django_forms_workflows/js/workflow-builder.js +0 -0
  136. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/sync_views.py +0 -0
  137. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/_sync_diff.html +0 -0
  138. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/diff_forms.html +0 -0
  139. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/form_builder.html +0 -0
  140. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/formdef_change_form.html +0 -0
  141. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/formdefinition/change_list.html +0 -0
  142. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/sync_import.html +0 -0
  143. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/sync_pull.html +0 -0
  144. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/sync_push.html +0 -0
  145. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/admin/django_forms_workflows/workflow_builder.html +0 -0
  146. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
  147. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
  148. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
  149. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
  150. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
  151. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/batch_import_result.html +0 -0
  152. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
  153. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/discard_draft_confirm.html +0 -0
  154. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
  155. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
  156. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
  157. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
  158. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
  159. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
  160. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
  161. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/sub_workflow_detail.html +0 -0
  162. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/submission_bulk_pdf.html +0 -0
  163. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
  164. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
  165. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
  166. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
  167. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
  168. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/approval_request.html +0 -0
  169. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/email_styles.html +0 -0
  170. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
  171. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
  172. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
  173. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
  174. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templates/registration/login.html +0 -0
  175. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templatetags/__init__.py +0 -0
  176. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
  177. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/urls.py +0 -0
  178. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/utils.py +0 -0
  179. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/views.py +0 -0
  180. {django_forms_workflows-0.42.2 → django_forms_workflows-0.44.0}/django_forms_workflows/workflow_builder_views.py +0 -0
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.44.0] - 2026-03-31
11
+
12
+ ### Added
13
+ - **Standalone `NotificationRuleAdmin`** — Full admin interface for NotificationRule with list display, filters, search, and fieldsets. Supports browsing notification rules across all workflows.
14
+
15
+ ### Changed
16
+ - **Unified batching in `send_notification_rules`** — Cadence-aware dispatch now lives inside the unified task. Removed legacy `_queue_workflow_level_notifications` and `_queue_approval_request_notifications` functions. All batching (immediate, daily, weekly, monthly, form_field_date) flows through a single code path.
17
+ - **Simplified `_notify_task_request`** — No longer has its own batching logic; delegates entirely to `_dispatch_notification_rules` + built-in `send_approval_request`.
18
+
19
+ ### Removed
20
+ - **Legacy notification models** — Dropped `WorkflowNotification`, `StageFormFieldNotification`, and `WorkflowStage.notify_assignee_on_final_decision`. All configuration now uses `NotificationRule` exclusively. Legacy task stubs retained for in-flight Celery message compatibility.
21
+ - **Legacy notification functions** — Removed `send_workflow_definition_notifications`, `send_stage_form_field_notifications`, `send_submission_form_field_notifications` implementations (stubs remain as no-ops for Celery compat).
22
+
23
+ ### Fixed
24
+ - **Signature field border visibility** — Changed signature pad canvas border from `#dee2e6` (nearly invisible light gray) to `#adb5bd` (clearly visible medium gray) so users can see the signature area boundary.
25
+
26
+ ## [0.43.0] - 2026-03-31
27
+
28
+ ### Added
29
+ - **Unified `NotificationRule` model** — Replaces `WorkflowNotification`, `StageFormFieldNotification`, and `WorkflowStage.notify_assignee_on_final_decision` with a single, generic model. All six recipient sources (submitter, email field, static emails, stage assignees, stage groups, arbitrary groups) are available on every event type, letting admins configure any combination they need.
30
+ - **New event types** — `stage_decision` (fires when an individual stage completes), `workflow_approved`, `workflow_denied`, `form_withdrawn` replace the legacy `approval_notification`, `rejection_notification`, `withdrawal_notification` names.
31
+ - **Group notifications** — `notify_stage_groups` includes all users in a stage's approval groups; `notify_groups` M2M allows notifying arbitrary Django groups independent of stage assignment.
32
+ - **Stage-scoped vs. workflow-scoped rules** — Setting the optional `stage` FK scopes `notify_stage_assignees` and `notify_stage_groups` to a specific stage. Leaving it null includes all stages.
33
+ - **Unified `send_notification_rules` Celery task** — Single dispatch entry point for all `NotificationRule` records, with full conditions evaluation, recipient resolution, and template rendering.
34
+ - **Data migration `0075`** — Automatically migrates all existing `WorkflowNotification`, `StageFormFieldNotification`, and `notify_assignee_on_final_decision` records into `NotificationRule`.
35
+ - **Comprehensive notification documentation** — `docs/NOTIFICATIONS.md` with architecture overview, model reference, 10 configuration scenarios, troubleshooting guide, and migration notes.
36
+
37
+ ### Changed
38
+ - **Legacy models retained** — `WorkflowNotification` and `StageFormFieldNotification` remain for backward compatibility. The workflow engine dispatches both legacy and unified paths in parallel. Legacy models will be removed in a future release.
39
+ - **Updated `PendingNotification` and `NotificationLog` event types** — Both models now include the new event names alongside legacy names for historical records.
40
+
10
41
  ## [0.42.2] - 2026-03-31
11
42
 
12
43
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-forms-workflows
3
- Version: 0.42.2
3
+ Version: 0.44.0
4
4
  Summary: Enterprise-grade, database-driven form builder with approval workflows and external data integration
5
5
  License: LGPL-3.0-only
6
6
  License-File: LICENSE
@@ -34,15 +34,14 @@ from .models import (
34
34
  LDAPGroupProfile,
35
35
  ManagedFile,
36
36
  NotificationLog,
37
+ NotificationRule,
37
38
  PostSubmissionAction,
38
39
  PrefillSource,
39
40
  StageApprovalGroup,
40
- StageFormFieldNotification,
41
41
  SubWorkflowDefinition,
42
42
  SubWorkflowInstance,
43
43
  UserProfile,
44
44
  WorkflowDefinition,
45
- WorkflowNotification,
46
45
  WorkflowStage,
47
46
  )
48
47
 
@@ -443,59 +442,49 @@ class StageApprovalGroupInline(nested_admin.NestedTabularInline):
443
442
  autocomplete_fields = ("group",)
444
443
 
445
444
 
446
- class StageFormFieldNotificationInline(nested_admin.NestedTabularInline):
447
- """Inline for configuring stage-level notifications (static and/or form-field driven)."""
448
-
449
- model = StageFormFieldNotification
450
- extra = 0
451
- fields = (
452
- "notification_type",
453
- "email_field",
454
- "static_emails",
455
- "subject_template",
456
- "conditions",
457
- )
458
-
459
-
460
445
  class WorkflowStageInline(nested_admin.NestedStackedInline):
461
446
  """Inline for defining ordered stages on a WorkflowDefinition."""
462
447
 
463
448
  model = WorkflowStage
464
449
  extra = 0
465
450
  ordering = ("order",)
466
- inlines = [StageApprovalGroupInline, StageFormFieldNotificationInline]
451
+ inlines = [StageApprovalGroupInline]
467
452
  fields = (
468
453
  ("order", "name"),
469
454
  "approval_logic",
470
455
  "approve_label",
471
456
  "requires_manager_approval",
472
457
  ("assignee_form_field", "assignee_lookup_type"),
473
- ("validate_assignee_group", "notify_assignee_on_final_decision"),
458
+ "validate_assignee_group",
474
459
  ("allow_reassign", "allow_send_back"),
475
460
  "allow_edit_form_data",
476
461
  "trigger_conditions",
477
462
  )
478
463
 
479
464
 
480
- class WorkflowNotificationInline(nested_admin.NestedStackedInline):
481
- """Inline for configuring granular workflow-level notification rules.
465
+ class NotificationRuleInline(nested_admin.NestedStackedInline):
466
+ """Unified notification rule inline.
482
467
 
483
- Each rule fires at a workflow-conclusion event (submission received, final
484
- approval, final rejection, or withdrawal) and can target dynamic recipients
485
- (from a form field) and/or static addresses, with optional conditions.
486
-
487
- Use one row per distinct recipient group / event combination.
468
+ Replaces WorkflowNotificationInline and StageFormFieldNotificationInline
469
+ with a single, generic inline that supports all event types and all
470
+ recipient sources.
488
471
  """
489
472
 
490
- model = WorkflowNotification
473
+ model = NotificationRule
491
474
  extra = 0
492
475
  fieldsets = (
493
476
  (
494
477
  None,
495
478
  {
496
479
  "fields": (
497
- ("notification_type", "notify_submitter"),
480
+ ("event", "stage"),
481
+ (
482
+ "notify_submitter",
483
+ "notify_stage_assignees",
484
+ "notify_stage_groups",
485
+ ),
498
486
  ("email_field", "static_emails"),
487
+ "notify_groups",
499
488
  "subject_template",
500
489
  )
501
490
  },
@@ -521,7 +510,7 @@ class WorkflowDefinitionInline(nested_admin.NestedStackedInline):
521
510
 
522
511
  model = WorkflowDefinition
523
512
  extra = 0
524
- inlines = [WorkflowStageInline, WorkflowNotificationInline]
513
+ inlines = [WorkflowStageInline, NotificationRuleInline]
525
514
  fields = [
526
515
  "name_label",
527
516
  "requires_approval",
@@ -1398,7 +1387,6 @@ class WorkflowStageAdmin(nested_admin.NestedModelAdmin):
1398
1387
  ordering = ("workflow", "order")
1399
1388
  inlines = [
1400
1389
  StageApprovalGroupInline,
1401
- StageFormFieldNotificationInline,
1402
1390
  ChangeHistoryInline,
1403
1391
  ]
1404
1392
  fieldsets = (
@@ -1429,7 +1417,6 @@ class WorkflowStageAdmin(nested_admin.NestedModelAdmin):
1429
1417
  "assignee_form_field",
1430
1418
  "assignee_lookup_type",
1431
1419
  "validate_assignee_group",
1432
- "notify_assignee_on_final_decision",
1433
1420
  "allow_reassign",
1434
1421
  "allow_send_back",
1435
1422
  ),
@@ -1466,7 +1453,11 @@ class WorkflowStageAdmin(nested_admin.NestedModelAdmin):
1466
1453
 
1467
1454
  @admin.register(WorkflowDefinition)
1468
1455
  class WorkflowDefinitionAdmin(nested_admin.NestedModelAdmin):
1469
- inlines = [WorkflowStageInline, WorkflowNotificationInline, ChangeHistoryInline]
1456
+ inlines = [
1457
+ WorkflowStageInline,
1458
+ NotificationRuleInline,
1459
+ ChangeHistoryInline,
1460
+ ]
1470
1461
  list_display = (
1471
1462
  "form_definition",
1472
1463
  "requires_approval",
@@ -1549,23 +1540,32 @@ class WorkflowDefinitionAdmin(nested_admin.NestedModelAdmin):
1549
1540
  )
1550
1541
 
1551
1542
 
1552
- @admin.register(WorkflowNotification)
1553
- class WorkflowNotificationAdmin(admin.ModelAdmin):
1554
- """Standalone admin for WorkflowNotification — searchable across all workflows."""
1543
+ @admin.register(NotificationRule)
1544
+ class NotificationRuleAdmin(admin.ModelAdmin):
1545
+ """Standalone admin for NotificationRule — searchable across all workflows."""
1555
1546
 
1556
1547
  list_display = (
1557
1548
  "workflow_form",
1558
- "notification_type",
1549
+ "event",
1550
+ "stage_name",
1559
1551
  "notify_submitter",
1552
+ "notify_stage_assignees",
1553
+ "notify_stage_groups",
1560
1554
  "email_field",
1561
1555
  "static_emails_truncated",
1562
1556
  "has_conditions",
1563
- "subject_template_truncated",
1564
1557
  )
1565
- list_filter = ("notification_type", "notify_submitter", "workflow__form_definition")
1566
- list_select_related = ("workflow__form_definition",)
1558
+ list_filter = (
1559
+ "event",
1560
+ "notify_submitter",
1561
+ "notify_stage_assignees",
1562
+ "notify_stage_groups",
1563
+ "workflow__form_definition",
1564
+ )
1565
+ list_select_related = ("workflow__form_definition", "stage")
1567
1566
  search_fields = (
1568
1567
  "workflow__form_definition__name",
1568
+ "stage__name",
1569
1569
  "email_field",
1570
1570
  "static_emails",
1571
1571
  )
@@ -1576,8 +1576,14 @@ class WorkflowNotificationAdmin(admin.ModelAdmin):
1576
1576
  {
1577
1577
  "fields": (
1578
1578
  "workflow",
1579
- ("notification_type", "notify_submitter"),
1579
+ ("event", "stage"),
1580
+ (
1581
+ "notify_submitter",
1582
+ "notify_stage_assignees",
1583
+ "notify_stage_groups",
1584
+ ),
1580
1585
  ("email_field", "static_emails"),
1586
+ "notify_groups",
1581
1587
  "subject_template",
1582
1588
  )
1583
1589
  },
@@ -1601,6 +1607,10 @@ class WorkflowNotificationAdmin(admin.ModelAdmin):
1601
1607
  def workflow_form(self, obj):
1602
1608
  return obj.workflow.form_definition.name if obj.workflow_id else "—"
1603
1609
 
1610
+ @admin.display(description="Stage", ordering="stage__name")
1611
+ def stage_name(self, obj):
1612
+ return obj.stage.name if obj.stage_id else "— (all stages)"
1613
+
1604
1614
  @admin.display(description="Static emails")
1605
1615
  def static_emails_truncated(self, obj):
1606
1616
  if not obj.static_emails:
@@ -1611,14 +1621,6 @@ class WorkflowNotificationAdmin(admin.ModelAdmin):
1611
1621
  def has_conditions(self, obj):
1612
1622
  return bool(obj.conditions)
1613
1623
 
1614
- @admin.display(description="Subject template")
1615
- def subject_template_truncated(self, obj):
1616
- if not obj.subject_template:
1617
- return "—"
1618
- return obj.subject_template[:50] + (
1619
- "…" if len(obj.subject_template) > 50 else ""
1620
- )
1621
-
1622
1624
 
1623
1625
  @admin.register(PostSubmissionAction)
1624
1626
  class PostSubmissionActionAdmin(admin.ModelAdmin):
@@ -92,8 +92,12 @@ def _build_summary(forms_data):
92
92
  diffs.append(
93
93
  f"Stage '{key[1]}' {sk}: {bs.get(sk)!r} → {os_.get(sk)!r}"
94
94
  )
95
- b_notifs = bs.get("form_field_notifications", [])
96
- o_notifs = os_.get("form_field_notifications", [])
95
+ b_notifs = bs.get(
96
+ "notification_rules", bs.get("form_field_notifications", [])
97
+ )
98
+ o_notifs = os_.get(
99
+ "notification_rules", os_.get("form_field_notifications", [])
100
+ )
97
101
  if len(b_notifs) != len(o_notifs):
98
102
  diffs.append(
99
103
  f"Stage '{key[1]}' notifications: {len(b_notifs)} → {len(o_notifs)}"
@@ -0,0 +1,136 @@
1
+ # Generated by Django 6.0.3 on 2026-03-31 16:14
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("auth", "0012_alter_user_first_name_max_length"),
11
+ ("django_forms_workflows", "0073_add_stage_notify_assignee_on_final_decision"),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name="NotificationRule",
17
+ fields=[
18
+ (
19
+ "id",
20
+ models.BigAutoField(
21
+ auto_created=True,
22
+ primary_key=True,
23
+ serialize=False,
24
+ verbose_name="ID",
25
+ ),
26
+ ),
27
+ (
28
+ "event",
29
+ models.CharField(
30
+ choices=[
31
+ ("submission_received", "Submission Received"),
32
+ ("approval_request", "Approval Request (stage activated)"),
33
+ (
34
+ "stage_decision",
35
+ "Stage Decision (individual stage completed)",
36
+ ),
37
+ ("workflow_approved", "Workflow Approved (final decision)"),
38
+ ("workflow_denied", "Workflow Denied (final decision)"),
39
+ ("form_withdrawn", "Form Withdrawn"),
40
+ ],
41
+ help_text="The workflow event that triggers this notification.",
42
+ max_length=30,
43
+ ),
44
+ ),
45
+ (
46
+ "conditions",
47
+ models.JSONField(
48
+ blank=True,
49
+ help_text="Optional conditions evaluated against form_data. Uses the same format as stage trigger_conditions. When set, the notification only fires if conditions are met.",
50
+ null=True,
51
+ ),
52
+ ),
53
+ (
54
+ "subject_template",
55
+ models.CharField(
56
+ blank=True,
57
+ default="",
58
+ help_text="Custom email subject line. Supports {form_name} and {submission_id} placeholders. Leave blank for the default.",
59
+ max_length=500,
60
+ ),
61
+ ),
62
+ (
63
+ "notify_submitter",
64
+ models.BooleanField(
65
+ default=False,
66
+ help_text="Include the person who submitted the form.",
67
+ ),
68
+ ),
69
+ (
70
+ "email_field",
71
+ models.CharField(
72
+ blank=True,
73
+ default="",
74
+ help_text="Form field slug whose submitted value is an email address. Resolved from form_data at send time (varies per submission).",
75
+ max_length=200,
76
+ ),
77
+ ),
78
+ (
79
+ "static_emails",
80
+ models.CharField(
81
+ blank=True,
82
+ default="",
83
+ help_text="Comma-separated fixed email addresses.",
84
+ max_length=1000,
85
+ ),
86
+ ),
87
+ (
88
+ "notify_stage_assignees",
89
+ models.BooleanField(
90
+ default=False,
91
+ help_text="Include dynamically-assigned approvers. When a stage is specified, only that stage's assignee is included. When no stage is specified, assignees from all stages are included.",
92
+ ),
93
+ ),
94
+ (
95
+ "notify_stage_groups",
96
+ models.BooleanField(
97
+ default=False,
98
+ help_text="Include all users in the stage's approval groups. When a stage is specified, only that stage's groups are included. When no stage is specified, groups from all stages are included.",
99
+ ),
100
+ ),
101
+ (
102
+ "notify_groups",
103
+ models.ManyToManyField(
104
+ blank=True,
105
+ help_text="Additional groups to notify, independent of stage assignment. All users in these groups with a non-empty email will receive the notification.",
106
+ related_name="notification_rules",
107
+ to="auth.group",
108
+ ),
109
+ ),
110
+ (
111
+ "stage",
112
+ models.ForeignKey(
113
+ blank=True,
114
+ help_text="Optional. When set, scopes this rule to a specific stage. Recipient sources like 'Notify stage assignees' and 'Notify stage groups' will reference only this stage. When blank, they reference all stages in the workflow.",
115
+ null=True,
116
+ on_delete=django.db.models.deletion.CASCADE,
117
+ related_name="notification_rules",
118
+ to="django_forms_workflows.workflowstage",
119
+ ),
120
+ ),
121
+ (
122
+ "workflow",
123
+ models.ForeignKey(
124
+ on_delete=django.db.models.deletion.CASCADE,
125
+ related_name="notification_rules",
126
+ to="django_forms_workflows.workflowdefinition",
127
+ ),
128
+ ),
129
+ ],
130
+ options={
131
+ "verbose_name": "Notification Rule",
132
+ "verbose_name_plural": "Notification Rules",
133
+ "ordering": ["workflow", "event", "stage"],
134
+ },
135
+ ),
136
+ ]
@@ -0,0 +1,98 @@
1
+ """
2
+ Data migration: populate NotificationRule from the three legacy sources.
3
+
4
+ 1. WorkflowNotification → NotificationRule (stage=null)
5
+ 2. StageFormFieldNotification → NotificationRule (stage=notif.stage)
6
+ 3. WorkflowStage.notify_assignee_on_final_decision=True
7
+ → two NotificationRule records (workflow_approved + workflow_denied)
8
+ with notify_stage_assignees=True, scoped to that stage.
9
+
10
+ Event name mapping (old → new):
11
+ approval_notification → workflow_approved
12
+ rejection_notification → workflow_denied
13
+ withdrawal_notification → form_withdrawn
14
+ submission_received → submission_received (unchanged)
15
+ approval_request → approval_request (unchanged)
16
+ """
17
+
18
+ from django.db import migrations
19
+
20
+
21
+ EVENT_MAP = {
22
+ "approval_notification": "workflow_approved",
23
+ "rejection_notification": "workflow_denied",
24
+ "withdrawal_notification": "form_withdrawn",
25
+ "submission_received": "submission_received",
26
+ "approval_request": "approval_request",
27
+ }
28
+
29
+
30
+ def forwards(apps, schema_editor):
31
+ NotificationRule = apps.get_model("django_forms_workflows", "NotificationRule")
32
+ WorkflowNotification = apps.get_model(
33
+ "django_forms_workflows", "WorkflowNotification"
34
+ )
35
+ StageFormFieldNotification = apps.get_model(
36
+ "django_forms_workflows", "StageFormFieldNotification"
37
+ )
38
+ WorkflowStage = apps.get_model("django_forms_workflows", "WorkflowStage")
39
+
40
+ # 1. WorkflowNotification → NotificationRule (workflow-scoped)
41
+ for wn in WorkflowNotification.objects.all():
42
+ NotificationRule.objects.create(
43
+ workflow_id=wn.workflow_id,
44
+ stage=None,
45
+ event=EVENT_MAP.get(wn.notification_type, wn.notification_type),
46
+ conditions=wn.conditions,
47
+ subject_template=wn.subject_template or "",
48
+ notify_submitter=wn.notify_submitter,
49
+ email_field=wn.email_field or "",
50
+ static_emails=wn.static_emails or "",
51
+ notify_stage_assignees=False,
52
+ notify_stage_groups=False,
53
+ )
54
+
55
+ # 2. StageFormFieldNotification → NotificationRule (stage-scoped)
56
+ for sfn in StageFormFieldNotification.objects.select_related("stage").all():
57
+ NotificationRule.objects.create(
58
+ workflow_id=sfn.stage.workflow_id,
59
+ stage_id=sfn.stage_id,
60
+ event=EVENT_MAP.get(sfn.notification_type, sfn.notification_type),
61
+ conditions=sfn.conditions,
62
+ subject_template=sfn.subject_template or "",
63
+ notify_submitter=False,
64
+ email_field=sfn.email_field or "",
65
+ static_emails=sfn.static_emails or "",
66
+ notify_stage_assignees=False,
67
+ notify_stage_groups=False,
68
+ )
69
+
70
+ # 3. WorkflowStage.notify_assignee_on_final_decision → two rules
71
+ for stage in WorkflowStage.objects.filter(
72
+ notify_assignee_on_final_decision=True
73
+ ):
74
+ for event in ("workflow_approved", "workflow_denied"):
75
+ NotificationRule.objects.create(
76
+ workflow_id=stage.workflow_id,
77
+ stage_id=stage.id,
78
+ event=event,
79
+ conditions=None,
80
+ subject_template="",
81
+ notify_submitter=False,
82
+ email_field="",
83
+ static_emails="",
84
+ notify_stage_assignees=True,
85
+ notify_stage_groups=False,
86
+ )
87
+
88
+
89
+ class Migration(migrations.Migration):
90
+
91
+ dependencies = [
92
+ ("django_forms_workflows", "0074_add_notification_rule"),
93
+ ]
94
+
95
+ operations = [
96
+ migrations.RunPython(forwards, migrations.RunPython.noop),
97
+ ]
98
+
@@ -0,0 +1,55 @@
1
+ # Generated by Django 6.0.3 on 2026-03-31 16:29
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("django_forms_workflows", "0075_migrate_to_notification_rules"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="notificationlog",
15
+ name="notification_type",
16
+ field=models.CharField(
17
+ choices=[
18
+ ("submission_received", "Submission Received"),
19
+ ("approval_request", "Approval Request"),
20
+ ("stage_decision", "Stage Decision"),
21
+ ("workflow_approved", "Workflow Approved"),
22
+ ("workflow_denied", "Workflow Denied"),
23
+ ("form_withdrawn", "Form Withdrawn"),
24
+ ("approval_reminder", "Approval Reminder"),
25
+ ("escalation", "Escalation"),
26
+ ("batched", "Batched Digest"),
27
+ ("submission_created", "Submission Received (legacy)"),
28
+ ("approval_notification", "Approved (legacy)"),
29
+ ("rejection_notification", "Rejected (legacy)"),
30
+ ("other", "Other"),
31
+ ],
32
+ db_index=True,
33
+ default="other",
34
+ max_length=50,
35
+ ),
36
+ ),
37
+ migrations.AlterField(
38
+ model_name="pendingnotification",
39
+ name="notification_type",
40
+ field=models.CharField(
41
+ choices=[
42
+ ("submission_received", "Submission Received"),
43
+ ("approval_request", "Approval Request"),
44
+ ("stage_decision", "Stage Decision"),
45
+ ("workflow_approved", "Workflow Approved"),
46
+ ("workflow_denied", "Workflow Denied"),
47
+ ("form_withdrawn", "Form Withdrawn"),
48
+ ("approval_notification", "Approval Notification (legacy)"),
49
+ ("rejection_notification", "Rejection Notification (legacy)"),
50
+ ("withdrawal_notification", "Withdrawal Notification (legacy)"),
51
+ ],
52
+ max_length=30,
53
+ ),
54
+ ),
55
+ ]
@@ -0,0 +1,27 @@
1
+ # Generated by Django 6.0.3 on 2026-03-31 16:50
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("django_forms_workflows", "0076_update_notification_event_choices"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name="workflownotification",
15
+ name="workflow",
16
+ ),
17
+ migrations.RemoveField(
18
+ model_name="workflowstage",
19
+ name="notify_assignee_on_final_decision",
20
+ ),
21
+ migrations.DeleteModel(
22
+ name="StageFormFieldNotification",
23
+ ),
24
+ migrations.DeleteModel(
25
+ name="WorkflowNotification",
26
+ ),
27
+ ]