fx-shared-models 0.2.2__tar.gz → 0.2.4__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 (126) hide show
  1. {fx_shared_models-0.2.2/fx_shared_models.egg-info → fx_shared_models-0.2.4}/PKG-INFO +1 -1
  2. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4/fx_shared_models.egg-info}/PKG-INFO +1 -1
  3. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/fx_shared_models.egg-info/SOURCES.txt +2 -0
  4. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/setup.py +1 -1
  5. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/__init__.py +1 -1
  6. fx_shared_models-0.2.4/shared_models/common/__pycache__/mixins.cpython-313.pyc +0 -0
  7. fx_shared_models-0.2.4/shared_models/common/mixins.py +201 -0
  8. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/__pycache__/models.cpython-313.pyc +0 -0
  9. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/models.py +3 -3
  10. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/LICENSE +0 -0
  11. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/MANIFEST.in +0 -0
  12. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/README.md +0 -0
  13. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/fx_shared_models.egg-info/dependency_links.txt +0 -0
  14. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/fx_shared_models.egg-info/requires.txt +0 -0
  15. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/fx_shared_models.egg-info/top_level.txt +0 -0
  16. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/setup.cfg +0 -0
  17. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/__init__.py +0 -0
  18. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/apps.py +0 -0
  19. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0001_initial.py +0 -0
  20. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0002_remove_account_group_type_account_has_bonus_and_more.py +0 -0
  21. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0003_account_is_archived_account_is_trading_enabled.py +0 -0
  22. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0004_alter_account_created_at_alter_account_created_by_and_more.py +0 -0
  23. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0005_account_currency.py +0 -0
  24. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/0006_alter_account_options.py +0 -0
  25. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/migrations/__init__.py +0 -0
  26. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/accounts/models.py +0 -0
  27. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/common/__pycache__/base.cpython-313.pyc +0 -0
  28. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/common/__pycache__/utils.cpython-313.pyc +0 -0
  29. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/common/base.py +0 -0
  30. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/common/utils.py +0 -0
  31. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/company_ba/__init__.py +0 -0
  32. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/company_ba/apps.py +0 -0
  33. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/company_ba/migrations/0001_initial.py +0 -0
  34. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/company_ba/migrations/__init__.py +0 -0
  35. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/company_ba/models.py +0 -0
  36. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/constants.py +0 -0
  37. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/__init__.py +0 -0
  38. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/__pycache__/__init__.cpython-313.pyc +0 -0
  39. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/__pycache__/apps.cpython-313.pyc +0 -0
  40. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/apps.py +0 -0
  41. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0001_initial.py +0 -0
  42. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0002_alter_customer_email_alter_customer_first_name_and_more.py +0 -0
  43. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0004_customerauth_two_factor_backup_codes_and_more.py +0 -0
  44. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0005_customerauth_temp_webauthn_challenge.py +0 -0
  45. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0006_customerauth_webauthn_challenge.py +0 -0
  46. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0007_customerauth_blocked_customerauth_blocked_at_and_more.py +0 -0
  47. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/0008_customer_email_hash.py +0 -0
  48. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__init__.py +0 -0
  49. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
  50. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0002_alter_customer_email_alter_customer_first_name_and_more.cpython-313.pyc +0 -0
  51. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0004_customerauth_two_factor_backup_codes_and_more.cpython-313.pyc +0 -0
  52. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0005_customerauth_temp_webauthn_challenge.cpython-313.pyc +0 -0
  53. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0006_customerauth_webauthn_challenge.cpython-313.pyc +0 -0
  54. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0007_customerauth_blocked_customerauth_blocked_at_and_more.cpython-313.pyc +0 -0
  55. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/0008_customer_email_hash.cpython-313.pyc +0 -0
  56. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/customers/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  57. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/__init__.py +0 -0
  58. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/apps.py +0 -0
  59. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0001_initial.py +0 -0
  60. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0002_alter_clientibmapping_id_and_more.py +0 -0
  61. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0003_commissiondistribution_is_pass_up_and_more.py +0 -0
  62. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0004_rename_ib_commissi_account_76e731_idx_ib_commissi_account_10d556_idx_and_more.py +0 -0
  63. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0005_alter_ibagreementmember_start_date.py +0 -0
  64. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0006_clientibmapping_agreement_and_more.py +0 -0
  65. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0007_alter_clientibmapping_mt5_login.py +0 -0
  66. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0008_commissiondistribution_is_processed_and_more.py +0 -0
  67. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/0009_commissiondistribution_processing_notes_and_more.py +0 -0
  68. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/migrations/__init__.py +0 -0
  69. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/models.py +0 -0
  70. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/services/__init__.py +0 -0
  71. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/ib_commission/services/commission_calculator_service.py +0 -0
  72. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/services/group_resolver.py +0 -0
  73. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/__pycache__/apps.cpython-313.pyc +0 -0
  74. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/__pycache__/serializers.cpython-313.pyc +0 -0
  75. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/apps.py +0 -0
  76. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0001_initial.py +0 -0
  77. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0002_rename_is_enabled_systemsetting_is_active.py +0 -0
  78. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0003_tradingplatformserver.py +0 -0
  79. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0004_tradingplatformserver_connection_timeout_and_more.py +0 -0
  80. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0005_accountsequence_accounttype.py +0 -0
  81. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0006_alter_accounttype_sequence.py +0 -0
  82. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0007_remove_accounttype_default_group_type_and_more.py +0 -0
  83. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0008_paymentgatewayconfig_paymentmethodconfig_and_more.py +0 -0
  84. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0009_alter_accountsequence_created_at_and_more.py +0 -0
  85. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/0010_alter_paymentgatewayconfig_gateway_and_more.py +0 -0
  86. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__init__.py +0 -0
  87. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
  88. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0002_rename_is_enabled_systemsetting_is_active.cpython-313.pyc +0 -0
  89. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0003_tradingplatformserver.cpython-313.pyc +0 -0
  90. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0004_tradingplatformserver_connection_timeout_and_more.cpython-313.pyc +0 -0
  91. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0005_accountsequence_accounttype.cpython-313.pyc +0 -0
  92. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0006_alter_accounttype_sequence.cpython-313.pyc +0 -0
  93. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0007_remove_accounttype_default_group_type_and_more.cpython-313.pyc +0 -0
  94. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0008_paymentgatewayconfig_paymentmethodconfig_and_more.cpython-313.pyc +0 -0
  95. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0009_alter_accountsequence_created_at_and_more.cpython-313.pyc +0 -0
  96. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/0010_alter_paymentgatewayconfig_gateway_and_more.cpython-313.pyc +0 -0
  97. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  98. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__init__.py +0 -0
  99. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/__init__.cpython-313.pyc +0 -0
  100. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/account_sequence.cpython-313.pyc +0 -0
  101. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/account_types.cpython-313.pyc +0 -0
  102. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/accounts.cpython-313.pyc +0 -0
  103. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/base.cpython-313.pyc +0 -0
  104. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/email.cpython-313.pyc +0 -0
  105. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/group_configurations.cpython-313.pyc +0 -0
  106. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/payment_methods.cpython-313.pyc +0 -0
  107. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/trading_platform.cpython-313.pyc +0 -0
  108. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/__pycache__/transaction_configs.cpython-313.pyc +0 -0
  109. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/account_sequence.py +0 -0
  110. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/account_types.py +0 -0
  111. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/base.py +0 -0
  112. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/email.py +0 -0
  113. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/group_configurations.py +0 -0
  114. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/payment_methods.py +0 -0
  115. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/trading_platform.py +0 -0
  116. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/models/transaction_configs.py +0 -0
  117. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/system_settings/serializers.py +0 -0
  118. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/__init__.py +0 -0
  119. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/apps.py +0 -0
  120. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/constants.py +0 -0
  121. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/enums.py +0 -0
  122. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/migrations/0001_initial.py +0 -0
  123. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/migrations/0002_transaction_mt5_ticket.py +0 -0
  124. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/migrations/0003_alter_transaction_options.py +0 -0
  125. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/migrations/__init__.py +0 -0
  126. {fx_shared_models-0.2.2 → fx_shared_models-0.2.4}/shared_models/transactions/models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fx-shared-models
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Shared models for FX Backend
5
5
  Home-page: https://github.com/fxbackend/fx-shared-models
6
6
  Author: FX Backend
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fx-shared-models
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Shared models for FX Backend
5
5
  Home-page: https://github.com/fxbackend/fx-shared-models
6
6
  Author: FX Backend
@@ -20,8 +20,10 @@ shared_models/accounts/migrations/0005_account_currency.py
20
20
  shared_models/accounts/migrations/0006_alter_account_options.py
21
21
  shared_models/accounts/migrations/__init__.py
22
22
  shared_models/common/base.py
23
+ shared_models/common/mixins.py
23
24
  shared_models/common/utils.py
24
25
  shared_models/common/__pycache__/base.cpython-313.pyc
26
+ shared_models/common/__pycache__/mixins.cpython-313.pyc
25
27
  shared_models/common/__pycache__/utils.cpython-313.pyc
26
28
  shared_models/company_ba/__init__.py
27
29
  shared_models/company_ba/apps.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
 
3
3
  setup(
4
4
  name='fx-shared-models',
5
- version='0.2.2',
5
+ version='0.2.4',
6
6
  packages=find_namespace_packages(include=['shared_models*']),
7
7
  install_requires=[
8
8
  'Django>=3.0',
@@ -3,4 +3,4 @@ Shared models package for FX Backend
3
3
  Contains Customer, System Settings, and IB Commission models
4
4
  """
5
5
 
6
- __version__ = '0.2.2'
6
+ __version__ = '0.2.4'
@@ -0,0 +1,201 @@
1
+ import logging
2
+ from django.conf import settings
3
+ from django.db import models
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ class SensitiveFieldsTrackingMixin:
8
+ """
9
+ Mixin to track changes in sensitive fields and log them appropriately.
10
+ """
11
+ sensitive_fields = [] # List of fields to track
12
+ requires_approval_fields = [] # Fields that require approval before change
13
+
14
+ def __init__(self, *args, **kwargs):
15
+ super().__init__(*args, **kwargs)
16
+ self._original_sensitive_values = self._get_sensitive_values()
17
+
18
+ def _get_sensitive_values(self):
19
+ """Get current values of sensitive fields"""
20
+ return {
21
+ field: getattr(self, field)
22
+ for field in self.sensitive_fields
23
+ if hasattr(self, field)
24
+ }
25
+
26
+ def _get_sensitive_field_changes(self):
27
+ """Compare current values with original values"""
28
+ current_values = self._get_sensitive_values()
29
+ changes = {}
30
+
31
+ for field, original_value in self._original_sensitive_values.items():
32
+ current_value = current_values.get(field)
33
+ if current_value != original_value:
34
+ changes[field] = {
35
+ 'from': original_value,
36
+ 'to': current_value
37
+ }
38
+ return changes
39
+
40
+ def _get_actor_info(self, request=None):
41
+ """Get actor information from request"""
42
+ if request and hasattr(request, 'user') and request.user and request.user.is_authenticated:
43
+ # User is authenticated
44
+ service_name = getattr(settings, 'SERVICE_NAME', '').lower()
45
+ actor_details = {
46
+ 'email': getattr(request.user, 'email', None),
47
+ 'username': getattr(request.user, 'username', None),
48
+ 'first_name': getattr(request.user, 'first_name', None),
49
+ 'last_name': getattr(request.user, 'last_name', None)
50
+ }
51
+ logger.debug(f"Found authenticated user: {actor_details['email']}")
52
+
53
+ if service_name == 'cp':
54
+ return {
55
+ 'type': 'CUSTOMER',
56
+ 'id': request.user.id,
57
+ 'details': actor_details
58
+ }
59
+ return {
60
+ 'type': 'USER',
61
+ 'id': request.user.id,
62
+ 'details': actor_details
63
+ }
64
+
65
+ logger.debug("No authenticated user found, using SYSTEM actor")
66
+ return {
67
+ 'type': 'SYSTEM',
68
+ 'id': 0,
69
+ 'details': {'system': 'automated'}
70
+ }
71
+
72
+ def _get_affected_customer_id(self):
73
+ """Get the affected customer ID"""
74
+ # Import locally to avoid circular imports
75
+ try:
76
+ from shared_models.customers.models import Customer
77
+ except ImportError:
78
+ # Fallback if the import fails
79
+ Customer = None
80
+
81
+ # If this model is a Customer
82
+ if Customer and isinstance(self, Customer):
83
+ return self.id
84
+
85
+ # If this model has a customer relation
86
+ if hasattr(self, 'customer_id'):
87
+ return self.customer_id
88
+ if hasattr(self, 'customer'):
89
+ return self.customer.id
90
+
91
+ return None
92
+
93
+ def save(self, *args, **kwargs):
94
+ # Extract request from kwargs if present
95
+ request = kwargs.pop('request', None)
96
+
97
+ is_new = self._state.adding
98
+ if not is_new:
99
+ changes = self._get_sensitive_field_changes()
100
+ if changes:
101
+ self._handle_sensitive_field_changes(changes, request=request)
102
+
103
+ result = super().save(*args, **kwargs)
104
+ if not is_new:
105
+ self._original_sensitive_values = self._get_sensitive_values()
106
+ return result
107
+
108
+ def _handle_sensitive_field_changes(self, changes, request=None):
109
+ """Handle changes in sensitive fields"""
110
+ # Get actor information using passed request if available
111
+ actor_info = self._get_actor_info(request)
112
+ affected_customer_id = self._get_affected_customer_id()
113
+
114
+ logger.debug(f"Handling sensitive changes. Actor: {actor_info}, Customer: {affected_customer_id}")
115
+
116
+ ip_address = None
117
+ user_agent = None
118
+
119
+ if request:
120
+ # Get IP address
121
+ x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
122
+ if x_forwarded_for:
123
+ ip_address = x_forwarded_for.split(',')[0]
124
+ else:
125
+ ip_address = request.META.get('REMOTE_ADDR')
126
+
127
+ # Get user agent
128
+ user_agent = request.META.get('HTTP_USER_AGENT')
129
+
130
+ logger.debug(f"Request context found. IP: {ip_address}, UA: {user_agent}")
131
+ else:
132
+ logger.debug("No request context found")
133
+
134
+ for field, change in changes.items():
135
+ # Try to import AuditLogService, but make it optional
136
+ try:
137
+ from apps.common.modules.audit.services import AuditLogService
138
+ # Create audit log entry with full context
139
+ AuditLogService.log(
140
+ actor_type=actor_info['type'],
141
+ actor_id=actor_info['id'],
142
+ actor_details=actor_info['details'],
143
+ action='SENSITIVE_CHANGE',
144
+ description=f'Sensitive field {field} was changed',
145
+ customer_description=f'Your {field} information was updated',
146
+ target_object=self,
147
+ level='WARNING',
148
+ changes={
149
+ 'field': field,
150
+ 'changes': change,
151
+ 'field_type': 'sensitive'
152
+ },
153
+ metadata={
154
+ 'service': {
155
+ 'name': getattr(settings, 'SERVICE_NAME', 'crm'),
156
+ 'environment': getattr(settings, 'ENVIRONMENT', 'development')
157
+ },
158
+ 'event': {
159
+ 'dataset': 'sensitive_data',
160
+ 'module': 'customer',
161
+ 'field_name': field
162
+ },
163
+ 'request': {
164
+ 'ip_address': ip_address,
165
+ 'user_agent': user_agent
166
+ }
167
+ },
168
+ affected_customer_id=affected_customer_id,
169
+ ip_address=ip_address,
170
+ user_agent=user_agent
171
+ )
172
+ except ImportError:
173
+ # Log that audit service is not available
174
+ logger.warning(f"AuditLogService not available. Sensitive field {field} was changed but not logged.")
175
+
176
+ # If field requires approval, handle it
177
+ if field in self.requires_approval_fields:
178
+ self._handle_approval_required_change(field, change)
179
+
180
+ def _handle_approval_required_change(self, field, change):
181
+ """Handle changes that require approval"""
182
+ try:
183
+ from apps.common.modules.notifications.services import NotificationService
184
+
185
+ # Create a notification for admins
186
+ NotificationService.send_notification(
187
+ type='SENSITIVE_DATA',
188
+ subtype='CHANGE_APPROVAL_REQUIRED',
189
+ title=f'Approval Required: {field} Change',
190
+ message=f'A change to {field} requires approval',
191
+ level='WARNING',
192
+ data={
193
+ 'field': field,
194
+ 'changes': change,
195
+ 'model': self._meta.model_name,
196
+ 'object_id': self.pk
197
+ }
198
+ )
199
+ except ImportError:
200
+ # Log that notification service is not available
201
+ logger.warning(f"NotificationService not available. Approval required for {field} change but notification not sent.")
@@ -5,7 +5,7 @@ from django.contrib.auth.hashers import make_password, check_password
5
5
  from shared_models.common.base import BaseModel
6
6
  from shared_models.common.utils import generate_referral_code
7
7
  from encrypted_model_fields.fields import EncryptedEmailField, EncryptedCharField
8
- from apps.common.utils.mixins import SensitiveFieldsTrackingMixin
8
+ from shared_models.common.mixins import SensitiveFieldsTrackingMixin
9
9
  import hashlib
10
10
 
11
11
  logger = logging.getLogger(__name__)
@@ -435,8 +435,8 @@ class CustomerAuth(SensitiveFieldsTrackingMixin, BaseModel):
435
435
  blocked_reason = models.TextField(blank=True, null=True)
436
436
  blocked_at = models.DateTimeField(null=True, blank=True)
437
437
  unblocked_at = models.DateTimeField(null=True, blank=True)
438
- blocked_by = models.ForeignKey('crm_user.CRMUser', null=True, blank=True, on_delete=models.SET_NULL, related_name='blocked_customers')
439
- unblocked_by = models.ForeignKey('crm_user.CRMUser', null=True, blank=True, on_delete=models.SET_NULL, related_name='unblocked_customers')
438
+ # blocked_by = models.ForeignKey('crm_user.CRMUser', null=True, blank=True, on_delete=models.SET_NULL, related_name='blocked_customers')
439
+ # unblocked_by = models.ForeignKey('crm_user.CRMUser', null=True, blank=True, on_delete=models.SET_NULL, related_name='unblocked_customers')
440
440
 
441
441
  def set_password(self, raw_password):
442
442
  self.password = make_password(raw_password)