amsdal_crm 0.2.2__py3-none-any.whl → 0.2.4__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.
amsdal_crm/__about__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.2.2'
1
+ __version__ = '0.2.4'
@@ -65,6 +65,7 @@ class Migration(migrations.Migration):
65
65
  "properties": {
66
66
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
67
67
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
68
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
68
69
  "name": {"type": "string", "title": "Entity Name"},
69
70
  "legal_name": {"type": "string", "title": "Legal Name"},
70
71
  "status": {
@@ -75,10 +76,9 @@ class Migration(migrations.Migration):
75
76
  "enum": ["Active", "Inactive"],
76
77
  },
77
78
  "note": {"type": "string", "title": "Note"},
78
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
79
79
  "assigned_to": {"type": "User", "title": "Assigned To"},
80
80
  },
81
- "custom_code": 'from amsdal.contrib.auth.models.user import User\n\n\n@property\ndef display_name(self) -> str:\n """Return display name for the account."""\n return self.name\n\nasync def apost_update(self) -> None:\n """Async hook called after updating account."""\n from amsdal_crm.services.workflow_service import WorkflowService\n await WorkflowService.aexecute_rules(\'Entity\', \'update\', self)\n\nasync def apre_create(self) -> None:\n """Async hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'Entity\', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n """Async hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'Entity\', self.custom_fields)\n await super().apre_update()\n\ndef has_object_permission(self, user: \'User\', action: str) -> bool:\n """Check if user has permission to perform action on this account.\n\n Args:\n user: The user attempting the action\n action: The action being attempted (read, create, update, delete)\n\n Returns:\n True if user has permission, False otherwise\n """\n if self.assigned_to and self.assigned_to.email == user.email:\n return True\n if user.permissions:\n for permission in user.permissions:\n if permission.model == \'*\' and permission.action in (\'*\', action):\n return True\n if permission.model == \'Entity\' and permission.action in (\'*\', action):\n return True\n return False\n\ndef post_update(self) -> None:\n """Hook called after updating account."""\n from amsdal_crm.services.workflow_service import WorkflowService\n WorkflowService.execute_rules(\'Entity\', \'update\', self)\n\ndef pre_create(self) -> None:\n """Hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'Entity\', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n """Hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'Entity\', self.custom_fields)\n super().pre_update()',
81
+ "custom_code": 'from amsdal.contrib.auth.models.user import User\n\n\n@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return \'JsonTemplate\'\n\n@property\ndef display_name(self) -> str:\n """Return display name for the account."""\n return self.name\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apost_update(self) -> None:\n """Async hook called after updating account."""\n from amsdal_crm.services.workflow_service import WorkflowService\n await WorkflowService.aexecute_rules(\'Entity\', \'update\', self)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef has_object_permission(self, user: \'User\', action: str) -> bool:\n """Check if user has permission to perform action on this account.\n\n Args:\n user: The user attempting the action\n action: The action being attempted (read, create, update, delete)\n\n Returns:\n True if user has permission, False otherwise\n """\n if self.assigned_to and self.assigned_to.email == user.email:\n return True\n if user.permissions:\n for permission in user.permissions:\n if permission.model == \'*\' and permission.action in (\'*\', action):\n return True\n if permission.model == \'Entity\' and permission.action in (\'*\', action):\n return True\n return False\n\ndef post_update(self) -> None:\n """Hook called after updating account."""\n from amsdal_crm.services.workflow_service import WorkflowService\n WorkflowService.execute_rules(\'Entity\', \'update\', self)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n self._validate_custom_fields()\n super().pre_update()',
82
82
  "storage_metadata": {
83
83
  "table_name": "Entity",
84
84
  "db_fields": {"assigned_to": ["assigned_to_partition_key"]},
@@ -100,6 +100,7 @@ class Migration(migrations.Migration):
100
100
  "properties": {
101
101
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
102
102
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
103
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
103
104
  "line1": {"type": "string", "title": "Address Line 1"},
104
105
  "line2": {"type": "string", "title": "Address Line 2"},
105
106
  "city": {"type": "string", "title": "City"},
@@ -107,9 +108,8 @@ class Migration(migrations.Migration):
107
108
  "postal_code": {"type": "string", "title": "Postal Code"},
108
109
  "country": {"type": "string", "title": "Country"},
109
110
  "is_primary": {"type": "boolean", "default": False, "title": "Is Primary"},
110
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
111
111
  },
112
- "custom_code": 'async def apre_create(self) -> None:\n """Async hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityAddress\', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n """Async hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityAddress\', self.custom_fields)\n await super().apre_update()\n\ndef pre_create(self) -> None:\n """Hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityAddress\', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n """Hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityAddress\', self.custom_fields)\n super().pre_update()',
112
+ "custom_code": "@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return 'JsonTemplate'\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n self._validate_custom_fields()\n super().pre_update()",
113
113
  "storage_metadata": {
114
114
  "table_name": "EntityAddress",
115
115
  "db_fields": {},
@@ -373,17 +373,17 @@ class Migration(migrations.Migration):
373
373
  "properties": {
374
374
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
375
375
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
376
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
376
377
  "value": {"type": "string", "title": "Contact Point Value"},
377
378
  "is_primary": {"type": "boolean", "default": False, "title": "Is Primary"},
378
379
  "can_contact": {"type": "boolean", "default": True, "title": "Can Contact"},
379
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
380
380
  "entity": {
381
381
  "type": "Entity",
382
382
  "title": "Entity",
383
383
  "description": "Entity (Person/Organization/Trust) model.\n\nRepresents a company or organization in the CRM system.\nOwned by individual users with permission controls.",
384
384
  },
385
385
  },
386
- "custom_code": 'async def apre_create(self) -> None:\n """Async hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityContactPoint\', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n """Async hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityContactPoint\', self.custom_fields)\n await super().apre_update()\n\ndef pre_create(self) -> None:\n """Hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityContactPoint\', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n """Hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityContactPoint\', self.custom_fields)\n super().pre_update()',
386
+ "custom_code": "@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return 'JsonTemplate'\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n self._validate_custom_fields()\n super().pre_update()",
387
387
  "storage_metadata": {
388
388
  "table_name": "EntityContactPoint",
389
389
  "db_fields": {"entity": ["entity_partition_key"]},
@@ -401,17 +401,17 @@ class Migration(migrations.Migration):
401
401
  "properties": {
402
402
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
403
403
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
404
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
404
405
  "value": {"type": "string", "title": "Identifier Value"},
405
406
  "country": {"type": "string", "title": "Country"},
406
407
  "is_primary": {"type": "boolean", "default": False, "title": "Is Primary"},
407
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
408
408
  "entity": {
409
409
  "type": "Entity",
410
410
  "title": "Entity",
411
411
  "description": "Entity (Person/Organization/Trust) model.\n\nRepresents a company or organization in the CRM system.\nOwned by individual users with permission controls.",
412
412
  },
413
413
  },
414
- "custom_code": 'async def apre_create(self) -> None:\n """Async hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityIdentifier\', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n """Async hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityIdentifier\', self.custom_fields)\n await super().apre_update()\n\ndef pre_create(self) -> None:\n """Hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityIdentifier\', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n """Hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityIdentifier\', self.custom_fields)\n super().pre_update()',
414
+ "custom_code": "@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return 'JsonTemplate'\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n self._validate_custom_fields()\n super().pre_update()",
415
415
  "storage_metadata": {
416
416
  "table_name": "EntityIdentifier",
417
417
  "db_fields": {"entity": ["entity_partition_key"]},
@@ -429,10 +429,10 @@ class Migration(migrations.Migration):
429
429
  "properties": {
430
430
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
431
431
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
432
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
432
433
  "start_date": {"type": "string", "title": "Start Date"},
433
434
  "end_date": {"type": "string", "title": "End Date"},
434
435
  "relationship_group_name": {"type": "string", "title": "Relationship Group Name"},
435
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
436
436
  "from_entity": {
437
437
  "type": "Entity",
438
438
  "title": "From Entity",
@@ -444,7 +444,7 @@ class Migration(migrations.Migration):
444
444
  "description": "Entity (Person/Organization/Trust) model.\n\nRepresents a company or organization in the CRM system.\nOwned by individual users with permission controls.",
445
445
  },
446
446
  },
447
- "custom_code": 'async def apre_create(self) -> None:\n """Async hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityRelationship\', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n """Async hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(\'EntityRelationship\', self.custom_fields)\n await super().apre_update()\n\ndef pre_create(self) -> None:\n """Hook called before creating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityRelationship\', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n """Hook called before updating account."""\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(\'EntityRelationship\', self.custom_fields)\n super().pre_update()',
447
+ "custom_code": "@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return 'JsonTemplate'\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n self._validate_custom_fields()\n super().pre_update()",
448
448
  "storage_metadata": {
449
449
  "table_name": "EntityRelationship",
450
450
  "db_fields": {
@@ -513,6 +513,7 @@ class Migration(migrations.Migration):
513
513
  "properties": {
514
514
  "created_at": {"type": "datetime", "title": "Created At", "format": "date-time"},
515
515
  "updated_at": {"type": "datetime", "title": "Updated At", "format": "date-time"},
516
+ "custom_fields": {"type": "anything", "title": "Custom Fields"},
516
517
  "name": {"type": "string", "title": "Deal Name"},
517
518
  "amount": {"type": "number", "title": "Amount"},
518
519
  "currency": {"type": "string", "default": "USD", "title": "Currency"},
@@ -539,10 +540,9 @@ class Migration(migrations.Migration):
539
540
  "title": "Status",
540
541
  "enum": ["open", "closed_won", "closed_lost"],
541
542
  },
542
- "custom_fields": {"type": "anything", "title": "Custom Fields"},
543
543
  "assigned_to": {"type": "User", "title": "Assigned To"},
544
544
  },
545
- "custom_code": "import datetime as _dt\n\nfrom amsdal.contrib.auth.models.user import User\nfrom amsdal_utils.models.data_models.reference import Reference\n\n\n@property\ndef display_name(self) -> str:\n \"\"\"Return display name for the deal.\"\"\"\n return self.name\n\n@property\ndef stage_name(self) -> str:\n \"\"\"Returns stage name for display.\"\"\"\n if hasattr(self.stage, 'name'):\n return self.stage.name\n return str(self.stage)\n\nasync def apost_update(self) -> None:\n \"\"\"Async hook called after updating deal.\"\"\"\n from amsdal_crm.services.workflow_service import WorkflowService\n await WorkflowService.aexecute_rules('Deal', 'update', self)\n\nasync def apre_create(self) -> None:\n \"\"\"Async hook called before creating deal.\"\"\"\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields('Deal', self.custom_fields)\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n \"\"\"Async hook called before updating deal.\n\n Automatically syncs is_closed and is_won status with stage,\n and sets closed_date when deal is closed.\n \"\"\"\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields('Deal', self.custom_fields)\n stage = await self.stage\n if stage.status == 'open':\n self.status = 'open'\n if stage.status == 'closed_won':\n self.status = 'closed_won'\n if stage.status == 'closed_lost':\n self.status = 'closed_lost'\n if self.status in ('closed_won', 'closed_lost') and (not self.closed_date):\n self.closed_date = _dt.datetime.now(_dt.UTC)\n await super().apre_update()\n\ndef has_object_permission(self, user: 'User', action: str) -> bool:\n \"\"\"Check if user has permission to perform action on this deal.\n\n Args:\n user: The user attempting the action\n action: The action being attempted (read, create, update, delete)\n\n Returns:\n True if user has permission, False otherwise\n \"\"\"\n if self.assigned_to and self.assigned_to.email == user.email:\n return True\n if user.permissions:\n for permission in user.permissions:\n if permission.model == '*' and permission.action in ('*', action):\n return True\n if permission.model == 'Deal' and permission.action in ('*', action):\n return True\n return False\n\ndef post_update(self) -> None:\n \"\"\"Hook called after updating deal.\"\"\"\n from amsdal_crm.services.workflow_service import WorkflowService\n WorkflowService.execute_rules('Deal', 'update', self)\n\ndef pre_create(self) -> None:\n \"\"\"Hook called before creating deal.\"\"\"\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields('Deal', self.custom_fields)\n super().pre_create()\n\ndef pre_update(self) -> None:\n \"\"\"Hook called before updating deal.\n\n Automatically syncs is_closed and is_won status with stage,\n and sets closed_date when deal is closed.\n \"\"\"\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields('Deal', self.custom_fields)\n from amsdal_models.classes.helpers.reference_loader import ReferenceLoader\n stage = ReferenceLoader(self.stage).load_reference() if isinstance(self.stage, Reference) else self.stage\n if stage.status == 'open':\n self.status = 'open'\n if stage.status == 'closed_won':\n self.status = 'closed_won'\n if stage.status == 'closed_lost':\n self.status = 'closed_lost'\n if self.status in ('closed_won', 'closed_lost') and (not self.closed_date):\n self.closed_date = _dt.datetime.now(_dt.UTC)\n super().pre_update()",
545
+ "custom_code": "import datetime as _dt\n\nfrom amsdal.contrib.auth.models.user import User\nfrom amsdal_utils.models.data_models.reference import Reference\n\n\n@classmethod\ndef custom_fields_cell_template(cls) -> str:\n return 'JsonTemplate'\n\n@property\ndef display_name(self) -> str:\n \"\"\"Return display name for the deal.\"\"\"\n return self.name\n\n@property\ndef stage_name(self) -> str:\n \"\"\"Returns stage name for display.\"\"\"\n if hasattr(self.stage, 'name'):\n return self.stage.name\n return str(self.stage)\n\nasync def _avalidate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = await CustomFieldService.avalidate_custom_fields(self.__class__.__name__, self.custom_fields)\n\nasync def apost_update(self) -> None:\n \"\"\"Async hook called after updating deal.\"\"\"\n from amsdal_crm.services.workflow_service import WorkflowService\n await WorkflowService.aexecute_rules('Deal', 'update', self)\n\nasync def apre_create(self) -> None:\n await self._avalidate_custom_fields()\n await super().apre_create()\n\nasync def apre_update(self) -> None:\n \"\"\"Async hook called before updating deal.\n\n Automatically syncs is_closed and is_won status with stage,\n and sets closed_date when deal is closed.\n \"\"\"\n stage = await self.stage\n if stage.status == 'open':\n self.status = 'open'\n if stage.status == 'closed_won':\n self.status = 'closed_won'\n if stage.status == 'closed_lost':\n self.status = 'closed_lost'\n if self.status in ('closed_won', 'closed_lost') and (not self.closed_date):\n self.closed_date = _dt.datetime.now(_dt.UTC)\n await super().apre_update()\n\ndef _validate_custom_fields(self) -> None:\n if self.custom_fields:\n from amsdal_crm.services.custom_field_service import CustomFieldService\n self.custom_fields = CustomFieldService.validate_custom_fields(self.__class__.__name__, self.custom_fields)\n\ndef has_object_permission(self, user: 'User', action: str) -> bool:\n \"\"\"Check if user has permission to perform action on this deal.\n\n Args:\n user: The user attempting the action\n action: The action being attempted (read, create, update, delete)\n\n Returns:\n True if user has permission, False otherwise\n \"\"\"\n if self.assigned_to and self.assigned_to.email == user.email:\n return True\n if user.permissions:\n for permission in user.permissions:\n if permission.model == '*' and permission.action in ('*', action):\n return True\n if permission.model == 'Deal' and permission.action in ('*', action):\n return True\n return False\n\ndef post_update(self) -> None:\n \"\"\"Hook called after updating deal.\"\"\"\n from amsdal_crm.services.workflow_service import WorkflowService\n WorkflowService.execute_rules('Deal', 'update', self)\n\ndef pre_create(self) -> None:\n self._validate_custom_fields()\n super().pre_create()\n\ndef pre_update(self) -> None:\n \"\"\"Hook called before updating deal.\n\n Automatically syncs is_closed and is_won status with stage,\n and sets closed_date when deal is closed.\n \"\"\"\n from amsdal_models.classes.helpers.reference_loader import ReferenceLoader\n stage = ReferenceLoader(self.stage).load_reference() if isinstance(self.stage, Reference) else self.stage\n if stage.status == 'open':\n self.status = 'open'\n if stage.status == 'closed_won':\n self.status = 'closed_won'\n if stage.status == 'closed_lost':\n self.status = 'closed_lost'\n if self.status in ('closed_won', 'closed_lost') and (not self.closed_date):\n self.closed_date = _dt.datetime.now(_dt.UTC)\n super().pre_update()",
546
546
  "storage_metadata": {
547
547
  "table_name": "Deal",
548
548
  "db_fields": {
@@ -0,0 +1,45 @@
1
+ from typing import Any
2
+
3
+ from pydantic.fields import Field
4
+
5
+
6
+ class CustomFieldsMixin:
7
+ custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
8
+
9
+ @classmethod
10
+ def custom_fields_cell_template(cls) -> str:
11
+ return 'JsonTemplate'
12
+
13
+ def pre_create(self) -> None:
14
+ self._validate_custom_fields()
15
+ super().pre_create()
16
+
17
+ async def apre_create(self) -> None:
18
+ await self._avalidate_custom_fields()
19
+ await super().apre_create()
20
+
21
+ def pre_update(self) -> None:
22
+ self._validate_custom_fields()
23
+ super().pre_update()
24
+
25
+ async def apre_update(self) -> None:
26
+ await self._avalidate_custom_fields()
27
+ await super().apre_update()
28
+
29
+ def _validate_custom_fields(self) -> None:
30
+ if self.custom_fields:
31
+ from amsdal_crm.services.custom_field_service import CustomFieldService
32
+
33
+ self.custom_fields = CustomFieldService.validate_custom_fields(
34
+ self.__class__.__name__,
35
+ self.custom_fields,
36
+ )
37
+
38
+ async def _avalidate_custom_fields(self) -> None:
39
+ if self.custom_fields:
40
+ from amsdal_crm.services.custom_field_service import CustomFieldService
41
+
42
+ self.custom_fields = await CustomFieldService.avalidate_custom_fields(
43
+ self.__class__.__name__,
44
+ self.custom_fields,
45
+ )
amsdal_crm/models/deal.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """Deal Model."""
2
2
 
3
3
  import datetime as _dt
4
- from typing import Any
5
4
  from typing import ClassVar
6
5
  from typing import Literal
7
6
 
@@ -14,13 +13,15 @@ from amsdal_utils.models.data_models.reference import Reference
14
13
  from amsdal_utils.models.enums import ModuleType
15
14
  from pydantic.fields import Field
16
15
 
16
+ from amsdal_crm.models.common import CustomFieldsMixin
17
+
17
18
 
18
19
  class DealManager(Manager):
19
20
  def get_queryset(self) -> 'DealManager':
20
21
  return super().get_queryset().select_related('stage')
21
22
 
22
23
 
23
- class Deal(TimestampMixin, Model):
24
+ class Deal(CustomFieldsMixin, TimestampMixin, Model):
24
25
  """Deal (Sales Opportunity) model.
25
26
 
26
27
  Represents a sales opportunity linked to an account and contact,
@@ -50,9 +51,6 @@ class Deal(TimestampMixin, Model):
50
51
  # Status tracking
51
52
  status: Literal['open', 'closed_won', 'closed_lost'] = Field(default='open', title='Status')
52
53
 
53
- # Custom fields (JSON)
54
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
55
-
56
54
  @property
57
55
  def display_name(self) -> str:
58
56
  """Return display name for the deal."""
@@ -90,34 +88,12 @@ class Deal(TimestampMixin, Model):
90
88
 
91
89
  return False
92
90
 
93
- def pre_create(self) -> None:
94
- """Hook called before creating deal."""
95
- if self.custom_fields:
96
- from amsdal_crm.services.custom_field_service import CustomFieldService
97
-
98
- self.custom_fields = CustomFieldService.validate_custom_fields('Deal', self.custom_fields)
99
- super().pre_create()
100
-
101
- async def apre_create(self) -> None:
102
- """Async hook called before creating deal."""
103
- if self.custom_fields:
104
- from amsdal_crm.services.custom_field_service import CustomFieldService
105
-
106
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Deal', self.custom_fields)
107
- await super().apre_create()
108
-
109
91
  def pre_update(self) -> None:
110
92
  """Hook called before updating deal.
111
93
 
112
94
  Automatically syncs is_closed and is_won status with stage,
113
95
  and sets closed_date when deal is closed.
114
96
  """
115
- # Validate custom fields first
116
- if self.custom_fields:
117
- from amsdal_crm.services.custom_field_service import CustomFieldService
118
-
119
- self.custom_fields = CustomFieldService.validate_custom_fields('Deal', self.custom_fields)
120
-
121
97
  # Load stage if it's a reference and sync closed status
122
98
  from amsdal_models.classes.helpers.reference_loader import ReferenceLoader
123
99
 
@@ -142,14 +118,7 @@ class Deal(TimestampMixin, Model):
142
118
 
143
119
  Automatically syncs is_closed and is_won status with stage,
144
120
  and sets closed_date when deal is closed.
145
- """
146
- # Validate custom fields first
147
- if self.custom_fields:
148
- from amsdal_crm.services.custom_field_service import CustomFieldService
149
-
150
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Deal', self.custom_fields)
151
-
152
- # Load stage if it's a reference and sync closed status
121
+ """ # Load stage if it's a reference and sync closed status
153
122
 
154
123
  stage = await self.stage
155
124
  if stage.status == 'open':
@@ -1,6 +1,5 @@
1
1
  """Account Model."""
2
2
 
3
- from typing import Any
4
3
  from typing import ClassVar
5
4
  from typing import Literal
6
5
 
@@ -12,8 +11,10 @@ from amsdal_models.classes.model import Model
12
11
  from amsdal_utils.models.enums import ModuleType
13
12
  from pydantic.fields import Field
14
13
 
14
+ from amsdal_crm.models.common import CustomFieldsMixin
15
15
 
16
- class Entity(TimestampMixin, Model):
16
+
17
+ class Entity(CustomFieldsMixin, TimestampMixin, Model):
17
18
  """Entity (Person/Organization/Trust) model.
18
19
 
19
20
  Represents a company or organization in the CRM system.
@@ -34,9 +35,6 @@ class Entity(TimestampMixin, Model):
34
35
 
35
36
  assigned_to: User | None = Field(default=None, title='Assigned To')
36
37
 
37
- # Custom fields (JSON)
38
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
39
-
40
38
  @property
41
39
  def display_name(self) -> str:
42
40
  """Return display name for the account."""
@@ -65,44 +63,6 @@ class Entity(TimestampMixin, Model):
65
63
 
66
64
  return False
67
65
 
68
- def pre_create(self) -> None:
69
- """Hook called before creating account."""
70
- if self.custom_fields:
71
- from amsdal_crm.services.custom_field_service import CustomFieldService
72
-
73
- self.custom_fields = CustomFieldService.validate_custom_fields('Entity', self.custom_fields)
74
- super().pre_create()
75
-
76
- async def apre_create(self) -> None:
77
- """Async hook called before creating account."""
78
- if self.custom_fields:
79
- from amsdal_crm.services.custom_field_service import CustomFieldService
80
-
81
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('Entity', self.custom_fields)
82
- await super().apre_create()
83
-
84
- def pre_update(self) -> None:
85
- """Hook called before updating account."""
86
- # Validate custom fields first
87
- if self.custom_fields:
88
- from amsdal_crm.services.custom_field_service import CustomFieldService
89
-
90
- self.custom_fields = CustomFieldService.validate_custom_fields('Entity', self.custom_fields)
91
-
92
- # Call parent to handle timestamps
93
- super().pre_update()
94
-
95
- async def apre_update(self) -> None:
96
- """Async 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 = await CustomFieldService.avalidate_custom_fields('Entity', self.custom_fields)
102
-
103
- # Call parent to handle timestamps
104
- await super().apre_update()
105
-
106
66
  def post_update(self) -> None:
107
67
  """Hook called after updating account."""
108
68
  from amsdal_crm.services.workflow_service import WorkflowService
@@ -116,7 +76,7 @@ class Entity(TimestampMixin, Model):
116
76
  await WorkflowService.aexecute_rules('Entity', 'update', self)
117
77
 
118
78
 
119
- class EntityRelationship(TimestampMixin, Model):
79
+ class EntityRelationship(CustomFieldsMixin, TimestampMixin, Model):
120
80
  __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
121
81
 
122
82
  from_entity: Entity = Field(title='From Entity')
@@ -125,53 +85,8 @@ class EntityRelationship(TimestampMixin, Model):
125
85
  end_date: str | None = Field(default=None, title='End Date')
126
86
  relationship_group_name: str | None = Field(default=None, title='Relationship Group Name')
127
87
 
128
- # Custom fields (JSON)
129
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
130
-
131
- def pre_create(self) -> None:
132
- """Hook called before creating account."""
133
- if self.custom_fields:
134
- from amsdal_crm.services.custom_field_service import CustomFieldService
135
-
136
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityRelationship', self.custom_fields)
137
- super().pre_create()
138
88
 
139
- async def apre_create(self) -> None:
140
- """Async hook called before creating account."""
141
- if self.custom_fields:
142
- from amsdal_crm.services.custom_field_service import CustomFieldService
143
-
144
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
145
- 'EntityRelationship', self.custom_fields
146
- )
147
- await super().apre_create()
148
-
149
- def pre_update(self) -> None:
150
- """Hook called before updating account."""
151
- # Validate custom fields first
152
- if self.custom_fields:
153
- from amsdal_crm.services.custom_field_service import CustomFieldService
154
-
155
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityRelationship', self.custom_fields)
156
-
157
- # Call parent to handle timestamps
158
- super().pre_update()
159
-
160
- async def apre_update(self) -> None:
161
- """Async hook called before updating account."""
162
- # Validate custom fields first
163
- if self.custom_fields:
164
- from amsdal_crm.services.custom_field_service import CustomFieldService
165
-
166
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
167
- 'EntityRelationship', self.custom_fields
168
- )
169
-
170
- # Call parent to handle timestamps
171
- await super().apre_update()
172
-
173
-
174
- class EntityIdentifier(TimestampMixin, Model):
89
+ class EntityIdentifier(CustomFieldsMixin, TimestampMixin, Model):
175
90
  __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
176
91
 
177
92
  entity: Entity = Field(title='Entity')
@@ -181,53 +96,8 @@ class EntityIdentifier(TimestampMixin, Model):
181
96
  # TODO: validate one per entity
182
97
  is_primary: bool = Field(default=False, title='Is Primary')
183
98
 
184
- # Custom fields (JSON)
185
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
186
-
187
- def pre_create(self) -> None:
188
- """Hook called before creating account."""
189
- if self.custom_fields:
190
- from amsdal_crm.services.custom_field_service import CustomFieldService
191
-
192
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityIdentifier', self.custom_fields)
193
- super().pre_create()
194
-
195
- async def apre_create(self) -> None:
196
- """Async hook called before creating account."""
197
- if self.custom_fields:
198
- from amsdal_crm.services.custom_field_service import CustomFieldService
199
-
200
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
201
- 'EntityIdentifier', self.custom_fields
202
- )
203
- await super().apre_create()
204
-
205
- def pre_update(self) -> None:
206
- """Hook called before updating account."""
207
- # Validate custom fields first
208
- if self.custom_fields:
209
- from amsdal_crm.services.custom_field_service import CustomFieldService
210
99
 
211
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityIdentifier', self.custom_fields)
212
-
213
- # Call parent to handle timestamps
214
- super().pre_update()
215
-
216
- async def apre_update(self) -> None:
217
- """Async hook called before updating account."""
218
- # Validate custom fields first
219
- if self.custom_fields:
220
- from amsdal_crm.services.custom_field_service import CustomFieldService
221
-
222
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
223
- 'EntityIdentifier', self.custom_fields
224
- )
225
-
226
- # Call parent to handle timestamps
227
- await super().apre_update()
228
-
229
-
230
- class EntityContactPoint(TimestampMixin, Model):
100
+ class EntityContactPoint(CustomFieldsMixin, TimestampMixin, Model):
231
101
  __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
232
102
 
233
103
  entity: Entity = Field(title='Entity')
@@ -237,53 +107,8 @@ class EntityContactPoint(TimestampMixin, Model):
237
107
  is_primary: bool = Field(default=False, title='Is Primary')
238
108
  can_contact: bool = Field(default=True, title='Can Contact')
239
109
 
240
- # Custom fields (JSON)
241
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
242
-
243
- def pre_create(self) -> None:
244
- """Hook called before creating account."""
245
- if self.custom_fields:
246
- from amsdal_crm.services.custom_field_service import CustomFieldService
247
-
248
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityContactPoint', self.custom_fields)
249
- super().pre_create()
250
-
251
- async def apre_create(self) -> None:
252
- """Async hook called before creating account."""
253
- if self.custom_fields:
254
- from amsdal_crm.services.custom_field_service import CustomFieldService
255
-
256
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
257
- 'EntityContactPoint', self.custom_fields
258
- )
259
- await super().apre_create()
260
-
261
- def pre_update(self) -> None:
262
- """Hook called before updating account."""
263
- # Validate custom fields first
264
- if self.custom_fields:
265
- from amsdal_crm.services.custom_field_service import CustomFieldService
266
-
267
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityContactPoint', self.custom_fields)
268
-
269
- # Call parent to handle timestamps
270
- super().pre_update()
271
-
272
- async def apre_update(self) -> None:
273
- """Async hook called before updating account."""
274
- # Validate custom fields first
275
- if self.custom_fields:
276
- from amsdal_crm.services.custom_field_service import CustomFieldService
277
110
 
278
- self.custom_fields = await CustomFieldService.avalidate_custom_fields(
279
- 'EntityContactPoint', self.custom_fields
280
- )
281
-
282
- # Call parent to handle timestamps
283
- await super().apre_update()
284
-
285
-
286
- class EntityAddress(TimestampMixin, Model):
111
+ class EntityAddress(CustomFieldsMixin, TimestampMixin, Model):
287
112
  __module_type__: ClassVar[ModuleType] = ModuleType.CONTRIB
288
113
 
289
114
  line1: str | None = Field(title='Address Line 1')
@@ -295,44 +120,3 @@ class EntityAddress(TimestampMixin, Model):
295
120
 
296
121
  # TODO: validate one per entity
297
122
  is_primary: bool = Field(default=False, title='Is Primary')
298
-
299
- # Custom fields (JSON)
300
- custom_fields: dict[str, Any] | None = Field(default=None, title='Custom Fields')
301
-
302
- def pre_create(self) -> None:
303
- """Hook called before creating account."""
304
- if self.custom_fields:
305
- from amsdal_crm.services.custom_field_service import CustomFieldService
306
-
307
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityAddress', self.custom_fields)
308
- super().pre_create()
309
-
310
- async def apre_create(self) -> None:
311
- """Async hook called before creating account."""
312
- if self.custom_fields:
313
- from amsdal_crm.services.custom_field_service import CustomFieldService
314
-
315
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('EntityAddress', self.custom_fields)
316
- await super().apre_create()
317
-
318
- def pre_update(self) -> None:
319
- """Hook called before updating account."""
320
- # Validate custom fields first
321
- if self.custom_fields:
322
- from amsdal_crm.services.custom_field_service import CustomFieldService
323
-
324
- self.custom_fields = CustomFieldService.validate_custom_fields('EntityAddress', self.custom_fields)
325
-
326
- # Call parent to handle timestamps
327
- super().pre_update()
328
-
329
- async def apre_update(self) -> None:
330
- """Async hook called before updating account."""
331
- # Validate custom fields first
332
- if self.custom_fields:
333
- from amsdal_crm.services.custom_field_service import CustomFieldService
334
-
335
- self.custom_fields = await CustomFieldService.avalidate_custom_fields('EntityAddress', self.custom_fields)
336
-
337
- # Call parent to handle timestamps
338
- await super().apre_update()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amsdal_crm
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: amsdal-crm plugin for AMSDAL Framework
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: aiohttp==3.12.15
@@ -1,5 +1,5 @@
1
1
  amsdal_crm/Third-Party Materials - AMSDAL Dependencies - License Notices.md,sha256=ML7PqsHrTMNNZn8E_rA-LzDCAafMSxMcrmSg8YOi-wo,113896
2
- amsdal_crm/__about__.py,sha256=QQ0yjZQnvXM7JeLLZEZWX6NmVUPu1lSROWOXF49_gug,22
2
+ amsdal_crm/__about__.py,sha256=N5-p8dQB8uwuCMpS1ADLf_E6rvWovtRRp3vY9Cq2gw4,22
3
3
  amsdal_crm/__init__.py,sha256=b4wxJYesA5Ctk1IrAvlw64i_0EU3SiK1Tw6sUYakd18,303
4
4
  amsdal_crm/app.py,sha256=JLvueh_2KURQLDWMQlq4Z6gAFsqBDTRf6pK095ehp14,1373
5
5
  amsdal_crm/constants.py,sha256=5Ga7q9zEKcQZnAoKv_SE_7w8WxvhPFkM9gY9NruOEaA,347
@@ -10,13 +10,14 @@ amsdal_crm/fixtures/permissions.py,sha256=TQEY_zX60GSudSZqmonaYqWCaod6oBsQw1NQPu
10
10
  amsdal_crm/fixtures/pipelines.py,sha256=ZCLmgrA700Sl7Oy7l4IQ8FbIbC1378OkcJTrZe5701o,2064
11
11
  amsdal_crm/lifecycle/__init__.py,sha256=B8nw19lEIr7U15Lnu6jh7yzZwF9LWWh4-p3X63sAicQ,31
12
12
  amsdal_crm/lifecycle/consumer.py,sha256=owS9kXKPs3Lzy7RiN_jI6hHEO6c90Tf-DT6aNqQ3uj4,8893
13
- amsdal_crm/migrations/0000_initial.py,sha256=uo0C4qXYVFkkM5iMAXTmsJCjducalpx9Y9Fyuuz9T1c,63814
13
+ amsdal_crm/migrations/0000_initial.py,sha256=Jf7iw4wOzwM9DIFfNGZoaaB_AsmUnRz8OB8iy7skUqM,62079
14
14
  amsdal_crm/models/__init__.py,sha256=3c-gqBkw2PXg4rp_wH2EN6viRu7Ff926Etn_BkQa5RU,18
15
15
  amsdal_crm/models/activity.py,sha256=Hwy_Z_zhk96yopTcm4vU4-SZbPg152r7N9er96Jkdho,4732
16
16
  amsdal_crm/models/attachment.py,sha256=B-6IuPrF6-VDnsFz_Q4UCh09YcFMs4o4zyT4VpvLe3U,1513
17
+ amsdal_crm/models/common.py,sha256=cKArZNNO7hsXrd9s4GF36nqZbsLkVldHovcCH5cJ-aM,1398
17
18
  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=r5_t8SSf4fneukhtFS59iLJt_yC1DIv0gyQW29Qhons,13280
19
+ amsdal_crm/models/deal.py,sha256=dwO3NFL-l_2tgWXEKtouuUF40VV5f_bqN_NcW7Mhr38,5300
20
+ amsdal_crm/models/entity.py,sha256=Xtwu6IiGU3DRw-55zcGrFtt_k4Eit0KhOkLC9kn-QqE,4642
20
21
  amsdal_crm/models/pipeline.py,sha256=DXJh5MbCCRctEHhDfxef5RxFWSKN0D4v6UK75q5ssL8,925
21
22
  amsdal_crm/models/stage.py,sha256=57rhfA4Oib8DKjDifWQe3EFxh-Auww3_PgOPfj4-L0E,1666
22
23
  amsdal_crm/models/workflow_rule.py,sha256=g-vAdJHKyA1PsiB3vPhd474Uvq94USHz35W1c5XyrAQ,1535
@@ -26,6 +27,6 @@ amsdal_crm/services/custom_field_service.py,sha256=r2dr2gijTbi9r56XV64bSArx0jTGw
26
27
  amsdal_crm/services/deal_service.py,sha256=PTxCQy6YqMyrtL4sRhyCU09V6OemrmZ405sQk-eBUlA,4803
27
28
  amsdal_crm/services/email_service.py,sha256=L9o-WaOET0tjo9g-zzC8GGCtfDZVheziHM_ob10jO2M,3518
28
29
  amsdal_crm/services/workflow_service.py,sha256=7m_vbk9FL_FCy9KS9LM4ueztO9ZsLwbvubdo9NA345g,7020
29
- amsdal_crm-0.2.2.dist-info/METADATA,sha256=XAgx-kT5AOq9ECz512STMaPZN0e_Jx1SOvo1AgBT9Js,1596
30
- amsdal_crm-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
31
- amsdal_crm-0.2.2.dist-info/RECORD,,
30
+ amsdal_crm-0.2.4.dist-info/METADATA,sha256=OR346BRRjyP-Od4wg4T4b8q5-A0luscGgU0u8G2j2bU,1596
31
+ amsdal_crm-0.2.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
32
+ amsdal_crm-0.2.4.dist-info/RECORD,,