letschatty 0.4.343__py3-none-any.whl → 0.4.344__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.
@@ -1,4 +1,9 @@
1
1
  from .assets import *
2
2
  from .empresa import EmpresaModel
3
3
  from .form_field import FormField, FormFieldPreview, CollectedData, SystemFormFields
4
- from .CRM.funnel import Funnel, FunnelPreview, ChatFunnel, StageTransition, FunnelStatus
4
+ from .CRM.funnel import Funnel, FunnelPreview, ChatFunnel, StageTransition, FunnelStatus
5
+ from .integrations.product_sync_status import ProductSyncStatus
6
+ from .integrations.sync_status_enum import SyncStatusEnum
7
+ from .integrations.shopify.shopify_webhook_topics import ShopifyWebhookTopic
8
+ from .integrations.shopify.company_shopify_integration import ShopifyIntegration
9
+ from .integrations.shopify.shopify_product_sync_status import ShopifyProductSyncStatus, ShopifyProductSyncStatusEnum
@@ -1,3 +1,4 @@
1
+ from letschatty.models.company.integrations.shopify.company_shopify_integration import ShopifyIntegration
1
2
  from pydantic import Field, ConfigDict, field_validator, SecretStr, model_validator
2
3
  from typing import Optional, List, Dict
3
4
 
@@ -34,7 +35,7 @@ class EmpresaModel(ChattyAssetModel):
34
35
  continuous_conversation_template_name: Optional[str] = Field(default = None, description="The name of the continuous conversation template")
35
36
  default_follow_up_strategy_id: Optional[StrObjectId] = Field(default = None, description="The id of the default follow up strategy")
36
37
  messaging_settings: MessagingSettings = Field(default = MessagingSettings(), description="The messaging settings for the company")
37
-
38
+ shopify_integration: ShopifyIntegration = Field(default = ShopifyIntegration(), description="The Shopify integration for the company")
38
39
 
39
40
  model_config = ConfigDict(
40
41
  validate_by_name=True,
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+ from typing import ClassVar, Optional
5
+
6
+ from pydantic import Field
7
+
8
+ from letschatty.models.company.integrations.sync_status_enum import SyncStatusEnum
9
+ from letschatty.models.base_models import CompanyAssetModel
10
+
11
+
12
+ class ProductSyncStatus(CompanyAssetModel):
13
+ """Generic product sync status for any e-commerce integration."""
14
+
15
+ COLLECTION: ClassVar[str] = "product_sync_statuses"
16
+
17
+ integration_type: str = Field(
18
+ description="Integration type (shopify, tiendanube, etc.)"
19
+ )
20
+ status: SyncStatusEnum = Field(description="Current sync status")
21
+
22
+ products_created: int = Field(default=0)
23
+ products_updated: int = Field(default=0)
24
+
25
+ name: str = Field(default="")
26
+
27
+ finished_at: Optional[datetime] = Field(default=None)
28
+
@@ -0,0 +1,62 @@
1
+ from typing import List, Optional
2
+ from datetime import datetime
3
+ from zoneinfo import ZoneInfo
4
+ from pydantic import BaseModel, Field
5
+
6
+ class ShopifyWebhookSubscription(BaseModel):
7
+ """Represents a single webhook subscription"""
8
+ topic: str = Field(description="Webhook topic (e.g., 'products/create')")
9
+ webhook_id: Optional[str] = Field(default=None, description="Shopify webhook ID")
10
+ subscribed_at: datetime = Field(default_factory=lambda: datetime.now(tz=ZoneInfo("UTC")))
11
+ is_active: bool = Field(default=True, description="Whether subscription is active")
12
+
13
+ class ShopifyIntegration(BaseModel):
14
+ """Shopify integration for the company"""
15
+ shopify_store_url: str = Field(default="")
16
+ oauth_state: str = Field(default="")
17
+ oauth_state_at: datetime = Field(default_factory=lambda: datetime.now(tz=ZoneInfo("UTC")))
18
+ access_token: Optional[str] = Field(default=None)
19
+ connected_at: Optional[datetime] = Field(default=None)
20
+ scope: Optional[str] = Field(default=None)
21
+
22
+ # Webhook subscriptions
23
+ webhook_subscriptions: List[ShopifyWebhookSubscription] = Field(
24
+ default_factory=list,
25
+ description="List of active webhook subscriptions"
26
+ )
27
+
28
+ # Scheduled sync settings
29
+ product_sync_enabled: bool = Field(
30
+ default=False,
31
+ description="Whether scheduled product sync is enabled"
32
+ )
33
+ product_sync_interval_hours: int = Field(
34
+ default=24,
35
+ description="Interval in hours for scheduled product sync"
36
+ )
37
+ last_product_sync_at: Optional[datetime] = Field(
38
+ default=None,
39
+ description="Timestamp of last product sync"
40
+ )
41
+
42
+ @property
43
+ def is_connected(self) -> bool:
44
+ """Check if the integration is fully connected"""
45
+ return bool(self.access_token and self.shopify_store_url)
46
+
47
+ def get_subscribed_topics(self) -> List[str]:
48
+ """Get list of currently subscribed webhook topics"""
49
+ return [sub.topic for sub in self.webhook_subscriptions if sub.is_active]
50
+
51
+ def reset(self) -> None:
52
+ """Reset integration to disconnected state"""
53
+ self.shopify_store_url = ""
54
+ self.oauth_state = ""
55
+ self.oauth_state_at = datetime.now(tz=ZoneInfo("UTC"))
56
+ self.access_token = None
57
+ self.connected_at = None
58
+ self.scope = None
59
+ self.webhook_subscriptions = []
60
+ self.product_sync_enabled = False
61
+ self.product_sync_interval_hours = 24
62
+ self.last_product_sync_at = None
@@ -0,0 +1,18 @@
1
+ from pydantic import Field
2
+
3
+ from letschatty.models.company.integrations.product_sync_status import ProductSyncStatus
4
+ from letschatty.models.company.integrations.sync_status_enum import SyncStatusEnum
5
+
6
+
7
+ # Backwards-compatible alias (Shopify-specific name, generic enum)
8
+ ShopifyProductSyncStatusEnum = SyncStatusEnum
9
+
10
+
11
+ class ShopifyProductSyncStatus(ProductSyncStatus):
12
+ """Shopify-flavored wrapper for the generic ProductSyncStatus."""
13
+
14
+ integration_type: str = Field(
15
+ default="shopify",
16
+ frozen=True,
17
+ description="Integration type for this sync status"
18
+ )
@@ -0,0 +1,40 @@
1
+ from enum import Enum
2
+
3
+ class ShopifyWebhookTopic(str, Enum):
4
+ """Shopify webhook topics for products and orders"""
5
+
6
+ # Product webhooks
7
+ PRODUCTS_CREATE = "products/create"
8
+ PRODUCTS_UPDATE = "products/update"
9
+ PRODUCTS_DELETE = "products/delete"
10
+
11
+ # Order webhooks
12
+ ORDERS_CREATE = "orders/create"
13
+ ORDERS_UPDATE = "orders/updated"
14
+ ORDERS_DELETE = "orders/delete"
15
+ ORDERS_FULFILLED = "orders/fulfilled"
16
+ ORDERS_PARTIALLY_FULFILLED = "orders/partially_fulfilled"
17
+ ORDERS_PAID = "orders/paid"
18
+ ORDERS_CANCELLED = "orders/cancelled"
19
+
20
+ @classmethod
21
+ def get_product_topics(cls) -> list[str]:
22
+ """Get all product-related webhook topics"""
23
+ return [
24
+ cls.PRODUCTS_CREATE.value,
25
+ cls.PRODUCTS_UPDATE.value,
26
+ cls.PRODUCTS_DELETE.value,
27
+ ]
28
+
29
+ @classmethod
30
+ def get_order_topics(cls) -> list[str]:
31
+ """Get all order-related webhook topics"""
32
+ return [
33
+ cls.ORDERS_CREATE.value,
34
+ cls.ORDERS_UPDATE.value,
35
+ cls.ORDERS_DELETE.value,
36
+ cls.ORDERS_FULFILLED.value,
37
+ cls.ORDERS_PARTIALLY_FULFILLED.value,
38
+ cls.ORDERS_PAID.value,
39
+ cls.ORDERS_CANCELLED.value,
40
+ ]
@@ -0,0 +1,9 @@
1
+ from enum import Enum
2
+
3
+
4
+ class SyncStatusEnum(str, Enum):
5
+ STARTED = "STARTED"
6
+ RUNNING = "RUNNING"
7
+ FINISHED = "FINISHED"
8
+ FAILED = "FAILED"
9
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: letschatty
3
- Version: 0.4.343
3
+ Version: 0.4.344
4
4
  Summary: Models and custom classes to work across the Chattyverse
5
5
  License: MIT
6
6
  Author: Axel
@@ -78,7 +78,7 @@ letschatty/models/chat/temporary_chat.py,sha256=MR68vYrNvoyf40cLs2p5NnI8BNeN1VGT
78
78
  letschatty/models/chat/time_left.py,sha256=2uA9dS_0QAVnWn7Q2wIwGe4tMrlYBP9qySC7M8I0jb8,3307
79
79
  letschatty/models/company/CRM/business_area.py,sha256=U0F_7Rbq-e5tMSj_MugPqMHm2-IHxbAKbN0PWZ_93-o,296
80
80
  letschatty/models/company/CRM/funnel.py,sha256=gBGZhud060sK5QFI5y9NgmFuhLCOAtzK81TKBhK2gxE,15820
81
- letschatty/models/company/__init__.py,sha256=N_I-kRMHrtnp00c_bbFSiYYM47HJRS-d5slgtbexsl4,229
81
+ letschatty/models/company/__init__.py,sha256=s6maWpREH-RAPoTm8svdivJ5foNEBkb5K6ncyZ0oEjo,626
82
82
  letschatty/models/company/assets/__init__.py,sha256=z0xN_lt1D76bXt8DXVdbH3GkofUPQPZU9NioRSLt_lI,244
83
83
  letschatty/models/company/assets/ai_agents_v2/ai_agent_message_draft.py,sha256=xbshA34RSjHm2g8J7hW2FkWo-Qm8MH2HTbcRcoYmyvc,2076
84
84
  letschatty/models/company/assets/ai_agents_v2/ai_agents_decision_output.py,sha256=aEKZCOsGiFFPSx23fkS5Khfsxo-r8JGk3O0sxiGs8T0,5876
@@ -125,9 +125,14 @@ letschatty/models/company/assets/workflow_execution.py,sha256=CKlT9JTryKC8kNniRX
125
125
  letschatty/models/company/company_chats_snapshot.py,sha256=Mg9Wmu3pfE-t5Sf57FCj-psvc5TkDkFfma-hdh6nE0Q,668
126
126
  letschatty/models/company/company_messaging_settgins.py,sha256=7isXt7gmqw-FKSUSZwdctdXDFMfPi2OyPuWqB7WpC6c,957
127
127
  letschatty/models/company/conversation_topic.py,sha256=__IinJ3YcUsiApF4Em5uAgd01ydRUrlCVxaat-pCCRg,1704
128
- letschatty/models/company/empresa.py,sha256=2INPC8YSZJcT10Gny_zXV_PujeqUGccsZHV31ZSywyw,5961
128
+ letschatty/models/company/empresa.py,sha256=o3IgQqMjQmyDjmR9je3bSF4EiIlJk7BnafiCO5c3pVE,6205
129
129
  letschatty/models/company/form_field.py,sha256=LGyMLybwvfEPG3hMmwsoP_4wnMaPJbVFpG6c1HdVC8E,9802
130
130
  letschatty/models/company/insight.py,sha256=B7BL07E4Z1b9aJHi3PXC1atln4-7fSo9JeqgQoeB_ao,7459
131
+ letschatty/models/company/integrations/product_sync_status.py,sha256=115zOvkaeXpHIUQftXe6dJsOUki3ru8hG3c75e2v4ag,814
132
+ letschatty/models/company/integrations/shopify/company_shopify_integration.py,sha256=PbxgIOG0Qp9Bz0WDrQffuSWrbEiV93JjX7PtHeYsqa0,2496
133
+ letschatty/models/company/integrations/shopify/shopify_product_sync_status.py,sha256=FhsmtFIf82pO9a1_OwV3MyKiJ6CGzlw-SCANZoV2M2g,588
134
+ letschatty/models/company/integrations/shopify/shopify_webhook_topics.py,sha256=HlSm0JHH6G3NPug8tbx9PQaC9yO3cwXJPTuU3qkWdDk,1263
135
+ letschatty/models/company/integrations/sync_status_enum.py,sha256=gh5kkKgLRqhygFFUPhITksp0Z-ImFEpGpzVABr7JiFM,154
131
136
  letschatty/models/company/notifications/notification.py,sha256=wE7rIi21nZno6jjIxajMz4e7OJbzrDHjH1KdkNzJiF8,1907
132
137
  letschatty/models/copilot/links.py,sha256=mcddNR6WdWOoOr3NgDl_FElxF15SiZZXw9wmIV08HRw,185
133
138
  letschatty/models/data_base/__init__.py,sha256=cUTj-TBUYJn1iAofztCr3VUJFF9qg1vmaQlOuoKb1MM,45
@@ -275,7 +280,7 @@ letschatty/services/template_campaigns/template_campaign_service.py,sha256=jORgD
275
280
  letschatty/services/users/agent_service.py,sha256=hIkUUJ1SpkKbh5_uo4i2CeqGtuMTjU7tSV8k5J7WPG4,279
276
281
  letschatty/services/users/user_factory.py,sha256=FCB9uiAfjMeYfh4kMdx5h8VDHJ8MCsD-uaxW3X3KaWM,6681
277
282
  letschatty/services/validators/analytics_validator.py,sha256=6ejecLcif2i1C5trUo1qQgp8vKr9WchdljFZ5GzB2i4,7239
278
- letschatty-0.4.343.dist-info/LICENSE,sha256=EClLu_bO2HBLDcThowIwfaIg5EOwIYhpRsBJjVEk92A,1197
279
- letschatty-0.4.343.dist-info/METADATA,sha256=Ul2_TJ2f4qOuipT6V_xt1OK6Vymb5sh1S4pRXyfJIwo,3283
280
- letschatty-0.4.343.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
281
- letschatty-0.4.343.dist-info/RECORD,,
283
+ letschatty-0.4.344.dist-info/LICENSE,sha256=EClLu_bO2HBLDcThowIwfaIg5EOwIYhpRsBJjVEk92A,1197
284
+ letschatty-0.4.344.dist-info/METADATA,sha256=0T1C22R5z3sxTuB3BCpuH5RAJBM81I4Ih0UWjKct3LY,3283
285
+ letschatty-0.4.344.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
286
+ letschatty-0.4.344.dist-info/RECORD,,