amsdal_crm 0.1.9__py3-none-any.whl → 0.2.0__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.
@@ -20,7 +20,7 @@ class WorkflowService:
20
20
  Called from lifecycle hooks (post_create, post_update, post_delete).
21
21
 
22
22
  Args:
23
- entity_type: Type of entity (Contact, Account, Deal, Activity)
23
+ entity_type: Type of entity (Entity, Deal, Activity)
24
24
  trigger_event: Event that triggered the rule (create, update, delete)
25
25
  entity: The entity instance
26
26
  """
@@ -48,7 +48,7 @@ class WorkflowService:
48
48
  Called from lifecycle hooks (post_create, post_update, post_delete).
49
49
 
50
50
  Args:
51
- entity_type: Type of entity (Contact, Account, Deal, Activity)
51
+ entity_type: Type of entity (Entity, Deal, Activity)
52
52
  trigger_event: Event that triggered the rule (create, update, delete)
53
53
  entity: The entity instance
54
54
  """
@@ -128,7 +128,7 @@ class WorkflowService:
128
128
  description=rule.action_config.get('description', ''),
129
129
  related_to_type=ActivityRelatedTo[rule.entity_type.upper()],
130
130
  related_to_id=entity._object_id,
131
- owner_email=entity.owner_email if hasattr(entity, 'owner_email') else '',
131
+ assigned_to=entity.assigned_to if hasattr(entity, 'assigned_to') else None,
132
132
  due_date=None,
133
133
  completed_at=None,
134
134
  is_completed=False,
@@ -164,7 +164,7 @@ class WorkflowService:
164
164
  description=rule.action_config.get('description', ''),
165
165
  related_to_type=ActivityRelatedTo[rule.entity_type.upper()],
166
166
  related_to_id=entity._object_id,
167
- owner_email=entity.owner_email if hasattr(entity, 'owner_email') else '',
167
+ assigned_to=entity.assigned_to if hasattr(entity, 'assigned_to') else None,
168
168
  due_date=None,
169
169
  completed_at=None,
170
170
  is_completed=False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amsdal_crm
3
- Version: 0.1.9
3
+ Version: 0.2.0
4
4
  Summary: amsdal-crm plugin for AMSDAL Framework
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: aiohttp==3.12.15
@@ -0,0 +1,31 @@
1
+ amsdal_crm/Third-Party Materials - AMSDAL Dependencies - License Notices.md,sha256=ML7PqsHrTMNNZn8E_rA-LzDCAafMSxMcrmSg8YOi-wo,113896
2
+ amsdal_crm/__about__.py,sha256=FVHPBGkfhbQDi_z3v0PiKJrXXqXOx0vGW_1VaqNJi7U,22
3
+ amsdal_crm/__init__.py,sha256=b4wxJYesA5Ctk1IrAvlw64i_0EU3SiK1Tw6sUYakd18,303
4
+ amsdal_crm/app.py,sha256=JLvueh_2KURQLDWMQlq4Z6gAFsqBDTRf6pK095ehp14,1373
5
+ amsdal_crm/constants.py,sha256=5Ga7q9zEKcQZnAoKv_SE_7w8WxvhPFkM9gY9NruOEaA,347
6
+ amsdal_crm/errors.py,sha256=vLANHcfz5YHO1O_gb4LaCK3KrQI2yi_BJjKg-7HdF68,515
7
+ amsdal_crm/settings.py,sha256=YbwDeiKaahqipGoBGkMRzYKGk8flt7IrkmMTLDyC9OQ,751
8
+ amsdal_crm/fixtures/__init__.py,sha256=1tDNXZhcbZBd4tX3lTKKlom1NUg1TX2aa2IbymWO9f0,20
9
+ amsdal_crm/fixtures/permissions.py,sha256=TQEY_zX60GSudSZqmonaYqWCaod6oBsQw1NQPuXIQto,894
10
+ amsdal_crm/fixtures/pipelines.py,sha256=ZCLmgrA700Sl7Oy7l4IQ8FbIbC1378OkcJTrZe5701o,2064
11
+ amsdal_crm/lifecycle/__init__.py,sha256=B8nw19lEIr7U15Lnu6jh7yzZwF9LWWh4-p3X63sAicQ,31
12
+ amsdal_crm/lifecycle/consumer.py,sha256=owS9kXKPs3Lzy7RiN_jI6hHEO6c90Tf-DT6aNqQ3uj4,8893
13
+ amsdal_crm/migrations/0000_initial.py,sha256=4V7_TeFUwvTRyLMm9QFHyuab-kiMuOlQZCA3hkO_YLg,51543
14
+ amsdal_crm/models/__init__.py,sha256=3c-gqBkw2PXg4rp_wH2EN6viRu7Ff926Etn_BkQa5RU,18
15
+ amsdal_crm/models/activity.py,sha256=Hwy_Z_zhk96yopTcm4vU4-SZbPg152r7N9er96Jkdho,4732
16
+ amsdal_crm/models/attachment.py,sha256=B-6IuPrF6-VDnsFz_Q4UCh09YcFMs4o4zyT4VpvLe3U,1513
17
+ amsdal_crm/models/custom_field_definition.py,sha256=0IIWcetZ0vXT8lPRGahyt7phoNKuCq2MQO6C8wEGk4Q,1749
18
+ amsdal_crm/models/deal.py,sha256=xmJOCE_fvY6asnOp2_eeWLW3clSiS-MoV9Bm-1gtEF0,6583
19
+ amsdal_crm/models/entity.py,sha256=YH7qhoAndTYzo-x7faZkqgYpoHmXzUk0seORRngK3ww,12568
20
+ amsdal_crm/models/pipeline.py,sha256=DXJh5MbCCRctEHhDfxef5RxFWSKN0D4v6UK75q5ssL8,925
21
+ amsdal_crm/models/stage.py,sha256=57rhfA4Oib8DKjDifWQe3EFxh-Auww3_PgOPfj4-L0E,1666
22
+ amsdal_crm/models/workflow_rule.py,sha256=g-vAdJHKyA1PsiB3vPhd474Uvq94USHz35W1c5XyrAQ,1535
23
+ amsdal_crm/services/__init__.py,sha256=ngHA-MUPrsHvga8vFP61b8v7rrAWl-h1VZTjhlJCXkI,465
24
+ amsdal_crm/services/activity_service.py,sha256=3iuEmaSicwm81rouLPum5VaWW0bAMnNWNPRCHkNhewU,1873
25
+ amsdal_crm/services/custom_field_service.py,sha256=r2dr2gijTbi9r56XV64bSArx0jTGwcjTlIdxzWb0ZCM,5170
26
+ amsdal_crm/services/deal_service.py,sha256=PTxCQy6YqMyrtL4sRhyCU09V6OemrmZ405sQk-eBUlA,4803
27
+ amsdal_crm/services/email_service.py,sha256=L9o-WaOET0tjo9g-zzC8GGCtfDZVheziHM_ob10jO2M,3518
28
+ amsdal_crm/services/workflow_service.py,sha256=7m_vbk9FL_FCy9KS9LM4ueztO9ZsLwbvubdo9NA345g,7020
29
+ amsdal_crm-0.2.0.dist-info/METADATA,sha256=tfgcmbT3KQyuqgaSldO2AYeRb8nhFDuISTFtHE0k7kA,1596
30
+ amsdal_crm-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
31
+ amsdal_crm-0.2.0.dist-info/RECORD,,
@@ -1,127 +0,0 @@
1
- """Account Model."""
2
-
3
- from typing import Any
4
- from typing import ClassVar
5
-
6
- from amsdal.contrib.auth.models.user import User
7
- from amsdal.models.mixins import TimestampMixin
8
- from amsdal_models.classes.data_models.constraints import UniqueConstraint
9
- from amsdal_models.classes.data_models.indexes import IndexInfo
10
- from amsdal_models.classes.model import Model
11
- from amsdal_utils.models.enums import ModuleType
12
- from pydantic.fields import Field
13
-
14
-
15
- class Account(TimestampMixin, Model):
16
- """Account (Company/Organization) model.
17
-
18
- Represents a company or organization in the CRM system.
19
- Owned by individual users with permission controls.
20
- """
21
-
22
- __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
23
- __constraints__: ClassVar[list[UniqueConstraint]] = [
24
- UniqueConstraint(name='unq_account_name_owner', fields=['name', 'owner_email'])
25
- ]
26
- __indexes__: ClassVar[list[IndexInfo]] = [
27
- IndexInfo(name='idx_account_owner_email', field='owner_email'),
28
- IndexInfo(name='idx_account_created_at', field='created_at'),
29
- ]
30
-
31
- # Core fields
32
- name: str = Field(title='Account Name')
33
- website: str | None = Field(default=None, title='Website')
34
- phone: str | None = Field(default=None, title='Phone')
35
- industry: str | None = Field(default=None, title='Industry')
36
-
37
- # Address fields
38
- billing_street: str | None = Field(default=None, title='Billing Street')
39
- billing_city: str | None = Field(default=None, title='Billing City')
40
- billing_state: str | None = Field(default=None, title='Billing State')
41
- billing_postal_code: str | None = Field(default=None, title='Billing Postal Code')
42
- billing_country: str | None = Field(default=None, title='Billing Country')
43
-
44
- # Ownership
45
- owner_email: str = Field(title='Owner Email')
46
-
47
- # Custom fields (JSON)
48
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
49
-
50
- @property
51
- def display_name(self) -> str:
52
- """Return display name for the account."""
53
- return self.name
54
-
55
- def has_object_permission(self, user: 'User', action: str) -> bool:
56
- """Check if user has permission to perform action on this account.
57
-
58
- Args:
59
- user: The user attempting the action
60
- action: The action being attempted (read, create, update, delete)
61
-
62
- Returns:
63
- True if user has permission, False otherwise
64
- """
65
- # Owner has all permissions
66
- if self.owner_email == user.email:
67
- return True
68
-
69
- # Check admin permissions
70
- if user.permissions:
71
- for permission in user.permissions:
72
- if permission.model == '*' and permission.action in ('*', action):
73
- return True
74
- if permission.model == 'Account' and permission.action in ('*', action):
75
- return True
76
-
77
- return False
78
-
79
- def pre_create(self) -> None:
80
- """Hook called before creating account."""
81
- if self.custom_fields:
82
- from amsdal_crm.services.custom_field_service import CustomFieldService
83
-
84
- self.custom_fields = CustomFieldService.validate_custom_fields('Account', self.custom_fields)
85
- super().pre_create()
86
-
87
- async def apre_create(self) -> None:
88
- """Async hook called before creating account."""
89
- if self.custom_fields:
90
- from amsdal_crm.services.custom_field_service import CustomFieldService
91
-
92
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Account', self.custom_fields)
93
- await super().apre_create()
94
-
95
- def pre_update(self) -> None:
96
- """Hook called before updating account."""
97
- # Validate custom fields first
98
- if self.custom_fields:
99
- from amsdal_crm.services.custom_field_service import CustomFieldService
100
-
101
- self.custom_fields = CustomFieldService.validate_custom_fields('Account', self.custom_fields)
102
-
103
- # Call parent to handle timestamps
104
- super().pre_update()
105
-
106
- async def apre_update(self) -> None:
107
- """Async hook called before updating account."""
108
- # Validate custom fields first
109
- if self.custom_fields:
110
- from amsdal_crm.services.custom_field_service import CustomFieldService
111
-
112
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Account', self.custom_fields)
113
-
114
- # Call parent to handle timestamps
115
- await super().apre_update()
116
-
117
- def post_update(self) -> None:
118
- """Hook called after updating account."""
119
- from amsdal_crm.services.workflow_service import WorkflowService
120
-
121
- WorkflowService.execute_rules('Account', 'update', self)
122
-
123
- async def apost_update(self) -> None:
124
- """Async hook called after updating account."""
125
- from amsdal_crm.services.workflow_service import WorkflowService
126
-
127
- await WorkflowService.aexecute_rules('Account', 'update', self)
@@ -1,132 +0,0 @@
1
- """Contact Model."""
2
-
3
- from typing import Any
4
- from typing import ClassVar
5
- from typing import Optional
6
-
7
- from amsdal.contrib.auth.models.user import User
8
- from amsdal.models.mixins import TimestampMixin
9
- from amsdal_models.classes.data_models.constraints import UniqueConstraint
10
- from amsdal_models.classes.data_models.indexes import IndexInfo
11
- from amsdal_models.classes.model import Model
12
- from amsdal_utils.models.enums import ModuleType
13
- from pydantic.fields import Field
14
-
15
-
16
- class Contact(TimestampMixin, Model):
17
- """Contact (Person) model.
18
-
19
- Represents a person in the CRM system, optionally linked to an Account.
20
- Owned by individual users with permission controls.
21
- """
22
-
23
- __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
24
- __constraints__: ClassVar[list[UniqueConstraint]] = [UniqueConstraint(name='unq_contact_email', fields=['email'])]
25
- __indexes__: ClassVar[list[IndexInfo]] = [
26
- IndexInfo(name='idx_contact_owner_email', field='owner_email'),
27
- IndexInfo(name='idx_contact_created_at', field='created_at'),
28
- ]
29
-
30
- # Core fields
31
- first_name: str = Field(title='First Name')
32
- last_name: str = Field(title='Last Name')
33
- email: str = Field(title='Email')
34
- phone: str | None = Field(default=None, title='Phone Number')
35
- mobile: str | None = Field(default=None, title='Mobile Number')
36
- title: str | None = Field(default=None, title='Job Title')
37
-
38
- # Relationships
39
- account: Optional['Account'] = Field(default=None, title='Account')
40
- owner_email: str = Field(title='Owner Email')
41
-
42
- # Custom fields (JSON)
43
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
44
-
45
- @property
46
- def display_name(self) -> str:
47
- """Return display name for the contact."""
48
- return f'{self.first_name} {self.last_name}'
49
-
50
- @property
51
- def full_name(self) -> str:
52
- """Return full name of the contact."""
53
- return f'{self.first_name} {self.last_name}'
54
-
55
- def has_object_permission(self, user: 'User', action: str) -> bool:
56
- """Check if user has permission to perform action on this contact.
57
-
58
- Args:
59
- user: The user attempting the action
60
- action: The action being attempted (read, create, update, delete)
61
-
62
- Returns:
63
- True if user has permission, False otherwise
64
- """
65
- # Owner has all permissions
66
- if self.owner_email == user.email:
67
- return True
68
-
69
- # Check admin permissions
70
- if user.permissions:
71
- for permission in user.permissions:
72
- if permission.model == '*' and permission.action in ('*', action):
73
- return True
74
- if permission.model == 'Contact' and permission.action in ('*', action):
75
- return True
76
-
77
- return False
78
-
79
- def pre_create(self) -> None:
80
- """Hook called before creating contact."""
81
- if self.custom_fields:
82
- from amsdal_crm.services.custom_field_service import CustomFieldService
83
-
84
- self.custom_fields = CustomFieldService.validate_custom_fields('Contact', self.custom_fields)
85
- super().pre_create()
86
-
87
- async def apre_create(self) -> None:
88
- """Async hook called before creating contact."""
89
- if self.custom_fields:
90
- from amsdal_crm.services.custom_field_service import CustomFieldService
91
-
92
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Contact', self.custom_fields)
93
- await super().apre_create()
94
-
95
- def pre_update(self) -> None:
96
- """Hook called before updating contact."""
97
- # Validate custom fields first
98
- if self.custom_fields:
99
- from amsdal_crm.services.custom_field_service import CustomFieldService
100
-
101
- self.custom_fields = CustomFieldService.validate_custom_fields('Contact', self.custom_fields)
102
-
103
- # Call parent to handle timestamps
104
- super().pre_update()
105
-
106
- async def apre_update(self) -> None:
107
- """Async hook called before updating contact."""
108
- # Validate custom fields first
109
- if self.custom_fields:
110
- from amsdal_crm.services.custom_field_service import CustomFieldService
111
-
112
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Contact', self.custom_fields)
113
-
114
- # Call parent to handle timestamps
115
- await super().apre_update()
116
-
117
- def post_update(self) -> None:
118
- """Hook called after updating contact."""
119
- from amsdal_crm.services.workflow_service import WorkflowService
120
-
121
- WorkflowService.execute_rules('Contact', 'update', self)
122
-
123
- async def apost_update(self) -> None:
124
- """Async hook called after updating contact."""
125
- from amsdal_crm.services.workflow_service import WorkflowService
126
-
127
- await WorkflowService.aexecute_rules('Contact', 'update', self)
128
-
129
-
130
- from amsdal_crm.models.account import Account
131
-
132
- Contact.model_rebuild()
@@ -1,32 +0,0 @@
1
- amsdal_crm/Third-Party Materials - AMSDAL Dependencies - License Notices.md,sha256=ML7PqsHrTMNNZn8E_rA-LzDCAafMSxMcrmSg8YOi-wo,113896
2
- amsdal_crm/__about__.py,sha256=2uYVJ4eLF8kKOzfX6k2Go3u7xIwcGSuemAueAoXn-5o,22
3
- amsdal_crm/__init__.py,sha256=b4wxJYesA5Ctk1IrAvlw64i_0EU3SiK1Tw6sUYakd18,303
4
- amsdal_crm/app.py,sha256=JLvueh_2KURQLDWMQlq4Z6gAFsqBDTRf6pK095ehp14,1373
5
- amsdal_crm/constants.py,sha256=5Ga7q9zEKcQZnAoKv_SE_7w8WxvhPFkM9gY9NruOEaA,347
6
- amsdal_crm/errors.py,sha256=vLANHcfz5YHO1O_gb4LaCK3KrQI2yi_BJjKg-7HdF68,515
7
- amsdal_crm/settings.py,sha256=YbwDeiKaahqipGoBGkMRzYKGk8flt7IrkmMTLDyC9OQ,751
8
- amsdal_crm/fixtures/__init__.py,sha256=1tDNXZhcbZBd4tX3lTKKlom1NUg1TX2aa2IbymWO9f0,20
9
- amsdal_crm/fixtures/permissions.py,sha256=cYA-gWkKQdoN79GymQVHtT0GyFXMzaskwp13Ietp9wE,1107
10
- amsdal_crm/fixtures/pipelines.py,sha256=ZCLmgrA700Sl7Oy7l4IQ8FbIbC1378OkcJTrZe5701o,2064
11
- amsdal_crm/lifecycle/__init__.py,sha256=B8nw19lEIr7U15Lnu6jh7yzZwF9LWWh4-p3X63sAicQ,31
12
- amsdal_crm/lifecycle/consumer.py,sha256=NhfFsbQeQUfCb9Mz-YBRZjKHL-annAqHt6Gc9b-I9_g,8824
13
- amsdal_crm/migrations/0000_initial.py,sha256=6IWS1zmS44F9wLWXnUPdWC-ga7pLSZ7b2dSOMcM1tcQ,56862
14
- amsdal_crm/models/__init__.py,sha256=DSuGeLKPNL_EUGohWtrH6Eof6Nk--dHyZpfqbGWmYIY,1350
15
- amsdal_crm/models/account.py,sha256=prb8Tl0nYyObTeql1fLX1cVRszauzPRSN7xv-H26hRg,4918
16
- amsdal_crm/models/activity.py,sha256=UtO1--oSPfrQCfQwWfIlEkjdXuaRG9znesPrGe1JqGM,4775
17
- amsdal_crm/models/attachment.py,sha256=CzS8sUMw0_8T_a4Ey6uzrSdEc12Fki5FbrFRXrsTExk,1525
18
- amsdal_crm/models/contact.py,sha256=xOTl8zUIEm2_Tk-CQxGAjzR_iuLA7Q_aKmJZAMXZ1F0,4924
19
- amsdal_crm/models/custom_field_definition.py,sha256=Z0k_QR6rZ1hWkg4Wn-w8Rn9GSIgpOg_moUYRsmRPZQI,1666
20
- amsdal_crm/models/deal.py,sha256=kFh6vrdu5NSXT21jwKkqYdP9SYhbncOJbgJB2udwkGE,6471
21
- amsdal_crm/models/pipeline.py,sha256=DXJh5MbCCRctEHhDfxef5RxFWSKN0D4v6UK75q5ssL8,925
22
- amsdal_crm/models/stage.py,sha256=LWG0Kr58srfqCrxjzRlrJogxpWbKvBOvkiHPbxVElbM,1612
23
- amsdal_crm/models/workflow_rule.py,sha256=cnIEaX-hWcRYvN5gR4uPt7Cirr8sPPdJibZapD8VRpY,1547
24
- amsdal_crm/services/__init__.py,sha256=ngHA-MUPrsHvga8vFP61b8v7rrAWl-h1VZTjhlJCXkI,465
25
- amsdal_crm/services/activity_service.py,sha256=3iuEmaSicwm81rouLPum5VaWW0bAMnNWNPRCHkNhewU,1873
26
- amsdal_crm/services/custom_field_service.py,sha256=r2dr2gijTbi9r56XV64bSArx0jTGwcjTlIdxzWb0ZCM,5170
27
- amsdal_crm/services/deal_service.py,sha256=ZF7cAc6r10xgXZ8D8Oy3hnE-6GgAXq8fuG_Y4QerRGw,4839
28
- amsdal_crm/services/email_service.py,sha256=kung83otZAzm5MjezbWFP_Bp9CJ2NXLlDdjMX9MvNIc,3788
29
- amsdal_crm/services/workflow_service.py,sha256=oKOFJrwnMZxAiHuScs63tZxL801z-6ryrUuPMC7OXlE,7036
30
- amsdal_crm-0.1.9.dist-info/METADATA,sha256=LqJtmAKjQewvDtkQ0KZifTdoYw49kdQozF-G7gYTL7k,1596
31
- amsdal_crm-0.1.9.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
32
- amsdal_crm-0.1.9.dist-info/RECORD,,