fusesell 1.2.1__py3-none-any.whl → 1.2.2__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.

Potentially problematic release.


This version of fusesell might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fusesell
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Local implementation of FuseSell AI sales automation pipeline
5
5
  Author-email: FuseSell Team <team@fusesell.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  fusesell.py,sha256=t5PjkhWEJGINp4k517u0EX0ge7lzuHOUHHro-BE1mGk,596
2
- fusesell-1.2.1.dist-info/licenses/LICENSE,sha256=GDz1ZoC4lB0kwjERpzqc_OdA_awYVso2aBnUH-ErW_w,1070
3
- fusesell_local/__init__.py,sha256=zCkVbO68h1wbnV8owWjLdBqMK3F_gyFgrtRZICeU_KQ,967
2
+ fusesell-1.2.2.dist-info/licenses/LICENSE,sha256=GDz1ZoC4lB0kwjERpzqc_OdA_awYVso2aBnUH-ErW_w,1070
3
+ fusesell_local/__init__.py,sha256=GmgCJXR8YDix18M51v04I2sh6EI9Z6H8tlXqyZzhs_c,966
4
4
  fusesell_local/api.py,sha256=AcPune5YJdgi7nsMeusCUqc49z5UiycsQb6n3yiV_No,10839
5
5
  fusesell_local/cli.py,sha256=l9ZjiRJpYCjFfSLmTvxRs8XhB6TqRPkeqbFZsM2xP5o,64870
6
6
  fusesell_local/pipeline.py,sha256=KO5oAIHZ3L_uAZWOszauJyv0QWlsQMIDNGRuwQSxNmQ,39531
@@ -14,18 +14,22 @@ fusesell_local/stages/data_preparation.py,sha256=XWLg9b1w2NrMxLcrWDqB95mRmLQmVIM
14
14
  fusesell_local/stages/follow_up.py,sha256=2CSen5SHJ5k6KMHXpqoRBb3n3IrcMRdDnuyTsOeuRTA,74625
15
15
  fusesell_local/stages/initial_outreach.py,sha256=jox2caveSwI3xIfjn8FGYprkjTbW8YhDNvCzz9wNcBE,107503
16
16
  fusesell_local/stages/lead_scoring.py,sha256=ir3l849eMGrGLf0OYUcmA1F3FwyYhAplS4niU3R2GRY,60658
17
+ fusesell_local/tests/conftest.py,sha256=TWUtlP6cNPVOYkTPz-j9BzS_KnXdPWy8D-ObPLHvXYs,366
17
18
  fusesell_local/tests/test_api.py,sha256=763rUVb5pAuAQOovug6Ka0T9eGK8-WVOC_J08M7TETo,1827
18
19
  fusesell_local/tests/test_cli.py,sha256=iNgU8nDlVrcQM5MpBUTIJ5q3oh2-jgX77hJeaqBxToM,1007
20
+ fusesell_local/tests/test_data_manager_products.py,sha256=V88N6NEmaa-o84-aReh2lKDGteB76wwTCg_xM6da3kQ,2669
21
+ fusesell_local/tests/test_data_manager_sales_process.py,sha256=NbwxQ9oBKCZfrkRQYxzHHQ08F7epqPUsyeGz_vm3kf8,4447
22
+ fusesell_local/tests/test_data_manager_teams.py,sha256=kjk4V4r9ja4EVREIiQMxkuZd470SSwRHJAvpHln9KO4,4578
19
23
  fusesell_local/utils/__init__.py,sha256=TVemlo0wpckhNUxP3a1Tky3ekswy8JdIHaXBlkKXKBQ,330
20
24
  fusesell_local/utils/birthday_email_manager.py,sha256=NKLoUyzPedyhewZPma21SOoU8p9wPquehloer7TRA9U,20478
21
- fusesell_local/utils/data_manager.py,sha256=wMP0fGeFVCEVOl6QOu2lXvzGqfW3apn_H3Fl7vy11lE,175558
25
+ fusesell_local/utils/data_manager.py,sha256=68ECkZ6fN9Ccc_Me7yh-qGB6tl32TSm4GB058SE0C94,176793
22
26
  fusesell_local/utils/event_scheduler.py,sha256=rjtWwtYQoJP0YwoN1-43t6K9GpLfqRq3c7Fv4papvbI,25725
23
27
  fusesell_local/utils/llm_client.py,sha256=FVc25UlGt6hro7h5Iw7PHSXY3E3_67Xc-SUbHuMSRs0,10437
24
28
  fusesell_local/utils/logger.py,sha256=sWlV8Tjyz_Z8J4zXKOnNalh8_iD6ytfrwPZpD-wcEOs,6259
25
29
  fusesell_local/utils/timezone_detector.py,sha256=0cAE4c8ZXqCA8AvxRKm6PrFKmAmsbq3HOHR6w-mW3KQ,39997
26
30
  fusesell_local/utils/validators.py,sha256=Z1VzeoxFsnuzlIA_ZaMWoy-0Cgyqupd47kIdljlMDbs,15438
27
- fusesell-1.2.1.dist-info/METADATA,sha256=BoUem4q6oYCj8oh_BnH42ihbeJLKRUESwWp-Ct0_Qfw,34976
28
- fusesell-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- fusesell-1.2.1.dist-info/entry_points.txt,sha256=Vqek7tbiX7iF4rQkCRBZvT5WrB0HUduqKTsI2ZjhsXo,53
30
- fusesell-1.2.1.dist-info/top_level.txt,sha256=VP9y1K6DEq6gNq2UgLd7ChujxViF6OzeAVCK7IUBXPA,24
31
- fusesell-1.2.1.dist-info/RECORD,,
31
+ fusesell-1.2.2.dist-info/METADATA,sha256=ASCu2jnknl2Oz7BvqtQMmIGAXpQAOQKH6E8ia9GbSaw,34976
32
+ fusesell-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ fusesell-1.2.2.dist-info/entry_points.txt,sha256=Vqek7tbiX7iF4rQkCRBZvT5WrB0HUduqKTsI2ZjhsXo,53
34
+ fusesell-1.2.2.dist-info/top_level.txt,sha256=VP9y1K6DEq6gNq2UgLd7ChujxViF6OzeAVCK7IUBXPA,24
35
+ fusesell-1.2.2.dist-info/RECORD,,
@@ -32,6 +32,6 @@ __all__ = [
32
32
  "validate_config",
33
33
  ]
34
34
 
35
- __version__ = "1.2.1"
35
+ __version__ = "1.2.2"
36
36
  __author__ = "FuseSell Team"
37
37
  __description__ = "Local implementation of FuseSell AI sales automation pipeline"
@@ -0,0 +1,11 @@
1
+ import pytest
2
+
3
+ from fusesell_local.utils.data_manager import LocalDataManager
4
+
5
+
6
+ @pytest.fixture
7
+ def data_manager(tmp_path):
8
+ """Provide an isolated LocalDataManager instance backed by a temporary directory."""
9
+ LocalDataManager._initialized_databases.clear()
10
+ LocalDataManager._initialization_lock = False
11
+ return LocalDataManager(data_dir=str(tmp_path))
@@ -0,0 +1,74 @@
1
+ import sqlite3
2
+
3
+
4
+ def _sample_product_payload(product_id: str = "prod-001", **overrides):
5
+ payload = {
6
+ "product_id": product_id,
7
+ "org_id": "org-123",
8
+ "org_name": "FuseSell Org",
9
+ "project_code": "proj-001",
10
+ "productName": "FuseSell AI Suite",
11
+ "shortDescription": "AI-powered sales automation",
12
+ "longDescription": "Comprehensive automation platform for revenue teams.",
13
+ "category": "Software",
14
+ "subcategory": "Sales Automation",
15
+ "targetUsers": ["Sales reps"],
16
+ "keyFeatures": ["Automation", "CRM sync"],
17
+ "uniqueSellingPoints": ["Privacy-first"],
18
+ "pricing": {"monthly": 199},
19
+ "pricingRules": {"currency": "USD"},
20
+ "productWebsite": "https://fusesell.test/ai-suite",
21
+ }
22
+ payload.update(overrides)
23
+ return payload
24
+
25
+
26
+ def test_save_and_get_product_roundtrip(data_manager):
27
+ payload = _sample_product_payload()
28
+ product_id = data_manager.save_product(payload)
29
+
30
+ assert product_id == payload["product_id"]
31
+
32
+ stored = data_manager.get_product(product_id)
33
+ assert stored is not None
34
+ assert stored["product_name"] == payload["productName"]
35
+ assert stored["org_id"] == payload["org_id"]
36
+ assert stored["key_features"] == payload["keyFeatures"]
37
+ assert stored["pricing"] == payload["pricing"]
38
+
39
+
40
+ def test_update_product_merges_changes(data_manager):
41
+ payload = _sample_product_payload()
42
+ product_id = data_manager.save_product(payload)
43
+
44
+ updated = {
45
+ "shortDescription": "Updated messaging",
46
+ "pricing": {"monthly": 249, "yearly": 2490},
47
+ "keyFeatures": ["Automation", "Analytics"],
48
+ }
49
+ assert data_manager.update_product(product_id, updated) is True
50
+
51
+ stored = data_manager.get_product(product_id)
52
+ assert stored["short_description"] == updated["shortDescription"]
53
+ assert stored["pricing"]["monthly"] == 249
54
+ assert stored["key_features"] == updated["keyFeatures"]
55
+
56
+
57
+ def test_get_products_by_org_returns_active_products_only(data_manager):
58
+ active = _sample_product_payload("prod-active")
59
+ inactive = _sample_product_payload("prod-inactive")
60
+
61
+ data_manager.save_product(active)
62
+ data_manager.save_product(inactive)
63
+
64
+ # Mark one product inactive directly to exercise status filtering
65
+ with sqlite3.connect(data_manager.db_path) as conn:
66
+ conn.execute(
67
+ "UPDATE products SET status = 'inactive' WHERE product_id = ?",
68
+ (inactive["product_id"],),
69
+ )
70
+ conn.commit()
71
+
72
+ results = data_manager.get_products_by_org(active["org_id"])
73
+ assert len(results) == 1
74
+ assert results[0]["product_id"] == active["product_id"]
@@ -0,0 +1,115 @@
1
+ def _create_task(data_manager, task_id: str, customer: str = "Acme Corp", status: str = "running"):
2
+ request_body = {"customer_info": customer, "org_name": "FuseSell Org"}
3
+ data_manager.create_task(
4
+ task_id=task_id,
5
+ plan_id="plan-456",
6
+ org_id="org-123",
7
+ request_body=request_body,
8
+ status=status,
9
+ )
10
+ return request_body
11
+
12
+
13
+ def test_create_task_and_get_task_by_id(data_manager):
14
+ task_id = "task-001"
15
+ request_body = _create_task(data_manager, task_id)
16
+
17
+ record = data_manager.get_task_by_id(task_id)
18
+ assert record is not None
19
+ assert record["task_id"] == task_id
20
+ assert record["status"] == "running"
21
+ assert record["request_body"]["customer_info"] == request_body["customer_info"]
22
+ assert record["messages"] == []
23
+
24
+
25
+ def test_update_task_status_tracks_runtime(data_manager):
26
+ task_id = "task-002"
27
+ _create_task(data_manager, task_id)
28
+
29
+ data_manager.update_task_status(task_id, "completed", runtime_index=4)
30
+
31
+ record = data_manager.get_task_by_id(task_id)
32
+ assert record["status"] == "completed"
33
+ assert record["current_runtime_index"] == 4
34
+
35
+
36
+ def test_create_operation_and_update_status(data_manager):
37
+ task_id = "task-003"
38
+ _create_task(data_manager, task_id)
39
+
40
+ operation_id = data_manager.create_operation(
41
+ task_id, "gs_161_data_acquisition", runtime_index=0, chain_index=0, input_data={"step": 1}
42
+ )
43
+ operation = data_manager.get_operation(operation_id)
44
+ assert operation is not None
45
+ assert operation["execution_status"] == "running"
46
+ assert operation["input_data"]["step"] == 1
47
+
48
+ data_manager.update_operation_status(operation_id, "done", {"result": "ok"})
49
+ updated = data_manager.get_operation(operation_id)
50
+ assert updated["execution_status"] == "done"
51
+ assert updated["output_data"]["result"] == "ok"
52
+
53
+
54
+ def test_get_task_with_operations_returns_summary(data_manager):
55
+ task_id = "task-ops"
56
+ _create_task(data_manager, task_id)
57
+
58
+ op_a = data_manager.create_operation(
59
+ task_id, "gs_161_data_acquisition", runtime_index=0, chain_index=0, input_data={"stage": "acquire"}
60
+ )
61
+ op_b = data_manager.create_operation(
62
+ task_id, "gs_161_data_preparation", runtime_index=0, chain_index=1, input_data={"stage": "prepare"}
63
+ )
64
+ data_manager.update_operation_status(op_a, "done", {"status": "ok"})
65
+ data_manager.update_operation_status(op_b, "running")
66
+
67
+ record = data_manager.get_task_with_operations(task_id)
68
+ assert record is not None
69
+ assert record["task_id"] == task_id
70
+ assert len(record["operations"]) == 2
71
+ assert record["summary"]["completed_operations"] == 1
72
+ assert record["summary"]["running_operations"] == 1
73
+
74
+
75
+ def test_find_sales_processes_by_customer(data_manager):
76
+ task_acme = "task-acme"
77
+ task_beta = "task-beta"
78
+ _create_task(data_manager, task_acme, customer="Acme Corp")
79
+ _create_task(data_manager, task_beta, customer="Beta LLC")
80
+
81
+ results = data_manager.find_sales_processes_by_customer("Acme")
82
+ assert len(results) == 1
83
+ assert results[0]["task_id"] == task_acme
84
+ assert results[0]["request_body"]["customer_info"] == "Acme Corp"
85
+
86
+
87
+ def test_list_tasks_filters_by_status(data_manager):
88
+ running_id = "task-running"
89
+ completed_id = "task-completed"
90
+ _create_task(data_manager, running_id, status="running")
91
+ _create_task(data_manager, completed_id, status="running")
92
+ data_manager.update_task_status(completed_id, "completed")
93
+
94
+ running_tasks = data_manager.list_tasks(status="running")
95
+ completed_tasks = data_manager.list_tasks(status="completed")
96
+
97
+ assert {task["task_id"] for task in running_tasks} == {running_id}
98
+ assert {task["task_id"] for task in completed_tasks} == {completed_id}
99
+
100
+
101
+ def test_get_execution_timeline_orders_by_indices(data_manager):
102
+ task_id = "task-timeline"
103
+ _create_task(data_manager, task_id)
104
+
105
+ op_first = data_manager.create_operation(
106
+ task_id, "gs_161_data_acquisition", runtime_index=0, chain_index=0, input_data={"order": 1}
107
+ )
108
+ op_second = data_manager.create_operation(
109
+ task_id, "gs_161_data_preparation", runtime_index=0, chain_index=1, input_data={"order": 2}
110
+ )
111
+ data_manager.update_operation_status(op_first, "done")
112
+ data_manager.update_operation_status(op_second, "done")
113
+
114
+ timeline = data_manager.get_execution_timeline(task_id)
115
+ assert [entry["input_data"]["order"] for entry in timeline] == [1, 2]
@@ -0,0 +1,133 @@
1
+ def _team_payload(team_id: str = "team-001", **overrides):
2
+ payload = {
3
+ "team_id": team_id,
4
+ "org_id": "org-123",
5
+ "org_name": "FuseSell Org",
6
+ "plan_id": "plan-456",
7
+ "plan_name": "FuseSell AI",
8
+ "project_code": "proj-001",
9
+ "name": "Outbound Squad",
10
+ "description": "Primary outreach team",
11
+ "avatar": "https://fusesell.test/avatar.png",
12
+ }
13
+ payload.update(overrides)
14
+ return payload
15
+
16
+
17
+ def test_save_and_get_team_roundtrip(data_manager):
18
+ payload = _team_payload()
19
+ data_manager.save_team(**payload)
20
+
21
+ stored = data_manager.get_team(payload["team_id"])
22
+ assert stored is not None
23
+ assert stored["team_id"] == payload["team_id"]
24
+ assert stored["name"] == payload["name"]
25
+ assert stored["plan_id"] == payload["plan_id"]
26
+
27
+
28
+ def test_update_team_modifies_selected_fields(data_manager):
29
+ payload = _team_payload()
30
+ data_manager.save_team(**payload)
31
+
32
+ updated_name = "Expansion Squad"
33
+ updated_plan = "FuseSell AI Enterprise"
34
+ assert data_manager.update_team(
35
+ payload["team_id"], name=updated_name, plan_name=updated_plan
36
+ )
37
+
38
+ stored = data_manager.get_team(payload["team_id"])
39
+ assert stored["name"] == updated_name
40
+ assert stored["plan_name"] == updated_plan
41
+
42
+
43
+ def test_list_teams_returns_all_for_org(data_manager):
44
+ first = _team_payload("team-001")
45
+ second = _team_payload("team-002", name="Inbound Squad")
46
+ data_manager.save_team(**first)
47
+ data_manager.save_team(**second)
48
+
49
+ teams = data_manager.list_teams(first["org_id"])
50
+ identifiers = {team["team_id"] for team in teams}
51
+ assert identifiers == {first["team_id"], second["team_id"]}
52
+
53
+
54
+ def test_save_and_get_team_settings_roundtrip(data_manager):
55
+ payload = _team_payload()
56
+ data_manager.save_team(**payload)
57
+
58
+ data_manager.save_team_settings(
59
+ team_id=payload["team_id"],
60
+ org_id=payload["org_id"],
61
+ plan_id=payload["plan_id"],
62
+ team_name=payload["name"],
63
+ gs_team_organization={"sales_regions": ["NA", "EU"]},
64
+ gs_team_rep=[{"name": "Alex"}],
65
+ gs_team_product=[{"product_id": "prod-001"}],
66
+ gs_team_schedule_time={"timezone": "UTC"},
67
+ gs_team_initial_outreach={"enabled": True},
68
+ gs_team_follow_up={"sequence": 2},
69
+ gs_team_auto_interaction={"mode": "assist"},
70
+ gs_team_followup_schedule_time={"window": "business_hours"},
71
+ gs_team_birthday_email={"enabled": False},
72
+ )
73
+
74
+ settings = data_manager.get_team_settings(payload["team_id"])
75
+ assert settings is not None
76
+ assert settings["org_id"] == payload["org_id"]
77
+ assert settings["gs_team_organization"]["sales_regions"] == ["NA", "EU"]
78
+ assert settings["gs_team_rep"][0]["name"] == "Alex"
79
+ assert settings["gs_team_product"][0]["product_id"] == "prod-001"
80
+
81
+
82
+ def test_save_team_settings_updates_existing_record(data_manager):
83
+ payload = _team_payload()
84
+ data_manager.save_team(**payload)
85
+
86
+ data_manager.save_team_settings(
87
+ team_id=payload["team_id"],
88
+ org_id=payload["org_id"],
89
+ plan_id=payload["plan_id"],
90
+ team_name=payload["name"],
91
+ gs_team_schedule_time={"timezone": "UTC"},
92
+ )
93
+
94
+ data_manager.save_team_settings(
95
+ team_id=payload["team_id"],
96
+ org_id=payload["org_id"],
97
+ plan_id=payload["plan_id"],
98
+ team_name=payload["name"],
99
+ gs_team_schedule_time={"timezone": "America/New_York"},
100
+ )
101
+
102
+ settings = data_manager.get_team_settings(payload["team_id"])
103
+ assert settings["gs_team_schedule_time"]["timezone"] == "America/New_York"
104
+
105
+
106
+ def test_get_products_by_team_uses_team_settings(data_manager):
107
+ team = _team_payload()
108
+ data_manager.save_team(**team)
109
+
110
+ product_payload = {
111
+ "product_id": "prod-001",
112
+ "org_id": team["org_id"],
113
+ "org_name": team["org_name"],
114
+ "project_code": team["project_code"],
115
+ "productName": "FuseSell Starter",
116
+ "shortDescription": "Entry-level automation",
117
+ "longDescription": "Starter bundle.",
118
+ "category": "Software",
119
+ "targetUsers": ["SMB"],
120
+ }
121
+ data_manager.save_product(product_payload)
122
+
123
+ data_manager.save_team_settings(
124
+ team_id=team["team_id"],
125
+ org_id=team["org_id"],
126
+ plan_id=team["plan_id"],
127
+ team_name=team["name"],
128
+ gs_team_product=[{"product_id": product_payload["product_id"]}],
129
+ )
130
+
131
+ products = data_manager.get_products_by_team(team["team_id"])
132
+ assert len(products) == 1
133
+ assert products[0]["product_id"] == product_payload["product_id"]
@@ -2135,73 +2135,101 @@ class LocalDataManager:
2135
2135
  "SELECT COUNT(*) FROM team_settings WHERE org_id = 'rta'")
2136
2136
  team_count = cursor.fetchone()[0]
2137
2137
 
2138
- if team_count == 0:
2139
- default_team_settings = {
2140
- 'id': 'team_rta_default_settings',
2141
- 'team_id': 'team_rta_default',
2142
- 'org_id': 'rta',
2143
- 'plan_id': '569cdcbd-cf6d-4e33-b0b2-d2f6f15a0832',
2144
- 'plan_name': 'FuseSell AI (v1.025)',
2145
- 'project_code': 'FUSESELL',
2146
- 'team_name': 'RTA Default Team',
2147
- 'organization_settings': json.dumps({
2148
- 'name': 'RTA',
2149
- 'industry': 'Technology',
2150
- 'website': 'https://rta.vn'
2151
- }),
2152
- 'sales_rep_settings': json.dumps([{
2153
- 'name': 'Sales Team',
2154
- 'email': 'sales@rta.vn',
2155
- 'position': 'Sales Representative',
2156
- 'is_primary': True
2157
- }]),
2158
- 'product_settings': json.dumps([
2159
- {'product_id': 'prod-12345678-1234-1234-1234-123456789012',
2160
- 'enabled': True, 'priority': 1},
2161
- {'product_id': 'prod-87654321-4321-4321-4321-210987654321',
2162
- 'enabled': True, 'priority': 2}
2163
- ]),
2164
- 'schedule_time_settings': json.dumps({
2165
- 'business_hours_start': '08:00',
2166
- 'business_hours_end': '20:00',
2167
- 'default_delay_hours': 2,
2168
- 'respect_weekends': True
2169
- }),
2170
- 'initial_outreach_settings': json.dumps({
2171
- 'default_tone': 'professional',
2172
- 'approaches': ['professional_direct', 'consultative', 'industry_expert', 'relationship_building'],
2173
- 'subject_line_variations': 4
2174
- }),
2175
- 'follow_up_settings': json.dumps({
2176
- 'max_follow_ups': 5,
2177
- 'default_interval_days': 3,
2178
- 'strategies': ['gentle_reminder', 'value_add', 'alternative_approach', 'final_attempt', 'graceful_farewell']
2179
- })
2180
- }
2181
-
2182
- cursor.execute("""
2183
- INSERT INTO team_settings
2184
- (id, team_id, org_id, plan_id, plan_name, project_code, team_name,
2185
- organization_settings, sales_rep_settings, product_settings,
2186
- schedule_time_settings, initial_outreach_settings, follow_up_settings)
2187
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2188
- """, (
2189
- default_team_settings['id'],
2190
- default_team_settings['team_id'],
2191
- default_team_settings['org_id'],
2192
- default_team_settings['plan_id'],
2193
- default_team_settings['plan_name'],
2194
- default_team_settings['project_code'],
2195
- default_team_settings['team_name'],
2196
- default_team_settings['organization_settings'],
2197
- default_team_settings['sales_rep_settings'],
2198
- default_team_settings['product_settings'],
2199
- default_team_settings['schedule_time_settings'],
2200
- default_team_settings['initial_outreach_settings'],
2201
- default_team_settings['follow_up_settings']
2202
- ))
2203
-
2204
- self.logger.debug("Initialized default team settings")
2138
+ if team_count == 0:
2139
+ default_team_settings = {
2140
+ 'id': 'team_rta_default_settings',
2141
+ 'team_id': 'team_rta_default',
2142
+ 'org_id': 'rta',
2143
+ 'plan_id': '569cdcbd-cf6d-4e33-b0b2-d2f6f15a0832',
2144
+ 'plan_name': 'FuseSell AI (v1.025)',
2145
+ 'project_code': 'FUSESELL',
2146
+ 'team_name': 'RTA Default Team',
2147
+ 'gs_team_organization': json.dumps({
2148
+ 'name': 'RTA',
2149
+ 'industry': 'Technology',
2150
+ 'website': 'https://rta.vn'
2151
+ }),
2152
+ 'gs_team_rep': json.dumps([{
2153
+ 'name': 'Sales Team',
2154
+ 'email': 'sales@rta.vn',
2155
+ 'position': 'Sales Representative',
2156
+ 'is_primary': True
2157
+ }]),
2158
+ 'gs_team_product': json.dumps([
2159
+ {'product_id': 'prod-12345678-1234-1234-1234-123456789012',
2160
+ 'enabled': True, 'priority': 1},
2161
+ {'product_id': 'prod-87654321-4321-4321-4321-210987654321',
2162
+ 'enabled': True, 'priority': 2}
2163
+ ]),
2164
+ 'gs_team_schedule_time': json.dumps({
2165
+ 'business_hours_start': '08:00',
2166
+ 'business_hours_end': '20:00',
2167
+ 'default_delay_hours': 2,
2168
+ 'respect_weekends': True
2169
+ }),
2170
+ 'gs_team_initial_outreach': json.dumps({
2171
+ 'default_tone': 'professional',
2172
+ 'approaches': [
2173
+ 'professional_direct',
2174
+ 'consultative',
2175
+ 'industry_expert',
2176
+ 'relationship_building'
2177
+ ],
2178
+ 'subject_line_variations': 4
2179
+ }),
2180
+ 'gs_team_follow_up': json.dumps({
2181
+ 'max_follow_ups': 5,
2182
+ 'default_interval_days': 3,
2183
+ 'strategies': [
2184
+ 'gentle_reminder',
2185
+ 'value_add',
2186
+ 'alternative_approach',
2187
+ 'final_attempt',
2188
+ 'graceful_farewell'
2189
+ ]
2190
+ }),
2191
+ 'gs_team_auto_interaction': json.dumps({
2192
+ 'enabled': True,
2193
+ 'handoff_threshold': 0.8,
2194
+ 'monitoring': 'standard'
2195
+ }),
2196
+ 'gs_team_followup_schedule_time': json.dumps({
2197
+ 'timezone': 'Asia/Ho_Chi_Minh',
2198
+ 'window': 'business_hours'
2199
+ }),
2200
+ 'gs_team_birthday_email': json.dumps({
2201
+ 'enabled': True,
2202
+ 'template': 'birthday_2025'
2203
+ })
2204
+ }
2205
+
2206
+ cursor.execute("""
2207
+ INSERT INTO team_settings
2208
+ (id, team_id, org_id, plan_id, plan_name, project_code, team_name,
2209
+ gs_team_organization, gs_team_rep, gs_team_product,
2210
+ gs_team_schedule_time, gs_team_initial_outreach, gs_team_follow_up,
2211
+ gs_team_auto_interaction, gs_team_followup_schedule_time, gs_team_birthday_email)
2212
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2213
+ """, (
2214
+ default_team_settings['id'],
2215
+ default_team_settings['team_id'],
2216
+ default_team_settings['org_id'],
2217
+ default_team_settings['plan_id'],
2218
+ default_team_settings['plan_name'],
2219
+ default_team_settings['project_code'],
2220
+ default_team_settings['team_name'],
2221
+ default_team_settings['gs_team_organization'],
2222
+ default_team_settings['gs_team_rep'],
2223
+ default_team_settings['gs_team_product'],
2224
+ default_team_settings['gs_team_schedule_time'],
2225
+ default_team_settings['gs_team_initial_outreach'],
2226
+ default_team_settings['gs_team_follow_up'],
2227
+ default_team_settings['gs_team_auto_interaction'],
2228
+ default_team_settings['gs_team_followup_schedule_time'],
2229
+ default_team_settings['gs_team_birthday_email']
2230
+ ))
2231
+
2232
+ self.logger.debug("Initialized default team settings")
2205
2233
 
2206
2234
  conn.commit()
2207
2235