sophhub 0.4.21 → 0.4.22
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.
- package/package.json +1 -1
- package/skills/insurance-customer-policy/skill.json +12 -0
- package/skills/insurance-customer-policy/src/SKILL.md +121 -0
- package/skills/insurance-customer-policy/src/pyproject.toml +9 -0
- package/skills/insurance-customer-policy/src/scripts/cli.py +16 -0
- package/skills/insurance-customer-policy/src/scripts/cloud_insurance_full_test.py +785 -0
- package/skills/insurance-customer-policy/src/scripts/dashboard_all.py +205 -0
- package/skills/insurance-customer-policy/src/scripts/insurance_customer_cli/__init__.py +0 -0
- package/skills/insurance-customer-policy/src/scripts/insurance_customer_cli/__main__.py +4 -0
- package/skills/insurance-customer-policy/src/scripts/insurance_customer_cli/cli.py +816 -0
- package/skills/insurance-customer-policy/src/scripts/insurance_customer_cli/db.py +181 -0
- package/skills/insurance-customer-policy/src/scripts/insurance_customer_cli/insurance_paths.py +184 -0
- package/skills/insurance-customer-policy/src/scripts/run_e2e_smoke.py +164 -0
- package/skills/insurance-customer-policy/src/scripts/test_cloud_zero_config.py +217 -0
- package/skills/insurance-customer-policy/src/scripts/test_dashboard_all.py +113 -0
- package/skills/insurance-customer-policy/src/src/insurance_customer_cli/__init__.py +0 -0
- package/skills/insurance-customer-policy/src/src/insurance_customer_cli/__main__.py +4 -0
- package/skills/insurance-customer-policy/src/src/insurance_customer_cli/cli.py +816 -0
- package/skills/insurance-customer-policy/src/src/insurance_customer_cli/db.py +181 -0
- package/skills/insurance-customer-policy/src/src/insurance_customer_cli/insurance_paths.py +184 -0
- package/skills/insurance-product-analysis/skill.json +12 -0
- package/skills/insurance-product-analysis/src/SKILL.md +99 -0
- package/skills/insurance-product-analysis/src/pyproject.toml +9 -0
- package/skills/insurance-product-analysis/src/scripts/cli.py +16 -0
- package/skills/insurance-product-analysis/src/scripts/insurance_product_cli/__init__.py +0 -0
- package/skills/insurance-product-analysis/src/scripts/insurance_product_cli/__main__.py +4 -0
- package/skills/insurance-product-analysis/src/scripts/insurance_product_cli/cli.py +545 -0
- package/skills/insurance-product-analysis/src/scripts/insurance_product_cli/db.py +180 -0
- package/skills/insurance-product-analysis/src/scripts/insurance_product_cli/orchestrator.py +163 -0
- package/skills/insurance-product-analysis/src/scripts/run_e2e_smoke.py +202 -0
- package/skills/insurance-product-analysis/src/src/insurance_product_cli/__init__.py +0 -0
- package/skills/insurance-product-analysis/src/src/insurance_product_cli/__main__.py +4 -0
- package/skills/insurance-product-analysis/src/src/insurance_product_cli/cli.py +545 -0
- package/skills/insurance-product-analysis/src/src/insurance_product_cli/db.py +180 -0
- package/skills/insurance-product-analysis/src/src/insurance_product_cli/orchestrator.py +163 -0
- package/skills/insurance-sales-pipeline/skill.json +12 -0
- package/skills/insurance-sales-pipeline/src/SKILL.md +102 -0
- package/skills/insurance-sales-pipeline/src/pyproject.toml +9 -0
- package/skills/insurance-sales-pipeline/src/scripts/cli.py +16 -0
- package/skills/insurance-sales-pipeline/src/scripts/insurance_pipeline_cli/__init__.py +0 -0
- package/skills/insurance-sales-pipeline/src/scripts/insurance_pipeline_cli/__main__.py +4 -0
- package/skills/insurance-sales-pipeline/src/scripts/insurance_pipeline_cli/cli.py +496 -0
- package/skills/insurance-sales-pipeline/src/scripts/insurance_pipeline_cli/db.py +180 -0
- package/skills/insurance-sales-pipeline/src/scripts/insurance_pipeline_cli/orchestrator.py +36 -0
- package/skills/insurance-sales-pipeline/src/scripts/run_e2e_smoke.py +208 -0
- package/skills/insurance-sales-pipeline/src/src/insurance_pipeline_cli/__init__.py +0 -0
- package/skills/insurance-sales-pipeline/src/src/insurance_pipeline_cli/__main__.py +4 -0
- package/skills/insurance-sales-pipeline/src/src/insurance_pipeline_cli/cli.py +496 -0
- package/skills/insurance-sales-pipeline/src/src/insurance_pipeline_cli/db.py +180 -0
- package/skills/insurance-sales-pipeline/src/src/insurance_pipeline_cli/orchestrator.py +36 -0
- package/skills/insurance-schedule-renewal/skill.json +12 -0
- package/skills/insurance-schedule-renewal/src/SKILL.md +94 -0
- package/skills/insurance-schedule-renewal/src/pyproject.toml +9 -0
- package/skills/insurance-schedule-renewal/src/scripts/cli.py +16 -0
- package/skills/insurance-schedule-renewal/src/scripts/insurance_schedule_cli/__init__.py +0 -0
- package/skills/insurance-schedule-renewal/src/scripts/insurance_schedule_cli/__main__.py +4 -0
- package/skills/insurance-schedule-renewal/src/scripts/insurance_schedule_cli/cli.py +429 -0
- package/skills/insurance-schedule-renewal/src/scripts/insurance_schedule_cli/db.py +180 -0
- package/skills/insurance-schedule-renewal/src/scripts/insurance_schedule_cli/orchestrator.py +94 -0
- package/skills/insurance-schedule-renewal/src/scripts/run_e2e_smoke.py +218 -0
- package/skills/insurance-schedule-renewal/src/src/insurance_schedule_cli/__init__.py +0 -0
- package/skills/insurance-schedule-renewal/src/src/insurance_schedule_cli/__main__.py +4 -0
- package/skills/insurance-schedule-renewal/src/src/insurance_schedule_cli/cli.py +429 -0
- package/skills/insurance-schedule-renewal/src/src/insurance_schedule_cli/db.py +180 -0
- package/skills/insurance-schedule-renewal/src/src/insurance_schedule_cli/orchestrator.py +94 -0
- package/skills/insurance-shared-data/skill.json +20 -0
- package/skills/insurance-shared-data/src/SKILL.md +33 -0
- package/skills/insurance-shared-data/src/scripts/cloud_insurance_super_test.py +246 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Aggregate insurance overview directly from shared insurance.sqlite3."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
SCRIPTS_DIR = Path(__file__).resolve().parent
|
|
12
|
+
if str(SCRIPTS_DIR) not in sys.path:
|
|
13
|
+
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
14
|
+
|
|
15
|
+
from insurance_customer_cli import db
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def aggregate() -> dict[str, Any]:
|
|
19
|
+
conn = db.connect()
|
|
20
|
+
month = conn.execute("SELECT strftime('%Y-%m','now','localtime') AS m").fetchone()["m"]
|
|
21
|
+
start = f"{month}-01 00:00:00"
|
|
22
|
+
y, m = map(int, month.split("-"))
|
|
23
|
+
end = f"{y + 1:04d}-01-01 00:00:00" if m == 12 else f"{y:04d}-{m + 1:02d}-01 00:00:00"
|
|
24
|
+
|
|
25
|
+
customers_total = int(conn.execute("SELECT COUNT(*) AS n FROM customers WHERE status='active'").fetchone()["n"])
|
|
26
|
+
hi_value = int(
|
|
27
|
+
conn.execute(
|
|
28
|
+
"""
|
|
29
|
+
SELECT COUNT(*) AS n FROM (
|
|
30
|
+
SELECT c.id, COALESCE(SUM(p.premium),0) AS annual
|
|
31
|
+
FROM customers c
|
|
32
|
+
LEFT JOIN policies p ON p.customer_id=c.id AND p.status='active'
|
|
33
|
+
WHERE c.status='active'
|
|
34
|
+
GROUP BY c.id
|
|
35
|
+
HAVING annual > 50000
|
|
36
|
+
)
|
|
37
|
+
"""
|
|
38
|
+
).fetchone()["n"]
|
|
39
|
+
)
|
|
40
|
+
active = int(
|
|
41
|
+
conn.execute(
|
|
42
|
+
"""
|
|
43
|
+
SELECT COUNT(DISTINCT customer_id) AS n
|
|
44
|
+
FROM followups
|
|
45
|
+
WHERE created_at >= datetime('now','-30 days')
|
|
46
|
+
"""
|
|
47
|
+
).fetchone()["n"]
|
|
48
|
+
)
|
|
49
|
+
new = int(
|
|
50
|
+
conn.execute(
|
|
51
|
+
"SELECT COUNT(*) AS n FROM customers WHERE status='active' AND created_at >= datetime('now','-30 days')"
|
|
52
|
+
).fetchone()["n"]
|
|
53
|
+
)
|
|
54
|
+
dormant = int(
|
|
55
|
+
conn.execute(
|
|
56
|
+
"""
|
|
57
|
+
SELECT COUNT(*) AS n
|
|
58
|
+
FROM customers c
|
|
59
|
+
WHERE c.status='active'
|
|
60
|
+
AND c.created_at < datetime('now','-60 days')
|
|
61
|
+
AND COALESCE(
|
|
62
|
+
(SELECT MAX(f.created_at) FROM followups f WHERE f.customer_id=c.id),
|
|
63
|
+
c.created_at
|
|
64
|
+
) < datetime('now','-60 days')
|
|
65
|
+
"""
|
|
66
|
+
).fetchone()["n"]
|
|
67
|
+
)
|
|
68
|
+
policies_total = int(conn.execute("SELECT COUNT(*) AS n FROM policies WHERE status='active'").fetchone()["n"])
|
|
69
|
+
total_premium = float(
|
|
70
|
+
conn.execute("SELECT COALESCE(SUM(premium),0) AS s FROM policies WHERE status='active'").fetchone()["s"]
|
|
71
|
+
)
|
|
72
|
+
products_total = int(conn.execute("SELECT COUNT(*) AS n FROM products WHERE status='active'").fetchone()["n"])
|
|
73
|
+
renewal_30d = int(
|
|
74
|
+
conn.execute(
|
|
75
|
+
"""
|
|
76
|
+
SELECT COUNT(*) AS n FROM policies
|
|
77
|
+
WHERE status='active'
|
|
78
|
+
AND (
|
|
79
|
+
(expire_date IS NOT NULL AND expire_date<>'' AND expire_date<=date('now','+30 days') AND expire_date>=date('now'))
|
|
80
|
+
OR
|
|
81
|
+
(next_pay_date IS NOT NULL AND next_pay_date<>'' AND next_pay_date<=date('now','+30 days') AND next_pay_date>=date('now'))
|
|
82
|
+
)
|
|
83
|
+
"""
|
|
84
|
+
).fetchone()["n"]
|
|
85
|
+
)
|
|
86
|
+
followup_30d_lapsed = int(
|
|
87
|
+
conn.execute(
|
|
88
|
+
"""
|
|
89
|
+
SELECT COUNT(*) AS n
|
|
90
|
+
FROM customers c
|
|
91
|
+
WHERE c.status='active'
|
|
92
|
+
AND COALESCE(
|
|
93
|
+
(SELECT MAX(f.created_at) FROM followups f WHERE f.customer_id=c.id),
|
|
94
|
+
c.created_at
|
|
95
|
+
) < datetime('now','-30 days')
|
|
96
|
+
"""
|
|
97
|
+
).fetchone()["n"]
|
|
98
|
+
)
|
|
99
|
+
dormant_60d = dormant
|
|
100
|
+
active_deals = int(
|
|
101
|
+
conn.execute(
|
|
102
|
+
"SELECT COUNT(*) AS n FROM deals WHERE stage IN ('在谈','方案中','议价')"
|
|
103
|
+
).fetchone()["n"]
|
|
104
|
+
)
|
|
105
|
+
this_month_target = float(
|
|
106
|
+
(conn.execute("SELECT target_premium FROM monthly_targets WHERE month=?", (month,)).fetchone() or {"target_premium": 0})[
|
|
107
|
+
"target_premium"
|
|
108
|
+
]
|
|
109
|
+
)
|
|
110
|
+
this_month_closed = float(
|
|
111
|
+
conn.execute(
|
|
112
|
+
"""
|
|
113
|
+
SELECT COALESCE(SUM(COALESCE(actual_premium, estimated_premium, 0)),0) AS s
|
|
114
|
+
FROM deals
|
|
115
|
+
WHERE stage='已成交' AND closed_at >= ? AND closed_at < ?
|
|
116
|
+
""",
|
|
117
|
+
(start, end),
|
|
118
|
+
).fetchone()["s"]
|
|
119
|
+
)
|
|
120
|
+
this_month_forecast = float(
|
|
121
|
+
conn.execute(
|
|
122
|
+
"""
|
|
123
|
+
SELECT COALESCE(SUM(
|
|
124
|
+
CASE
|
|
125
|
+
WHEN stage='在谈' THEN estimated_premium * 0.20
|
|
126
|
+
WHEN stage='方案中' THEN estimated_premium * 0.50
|
|
127
|
+
WHEN stage='议价' THEN estimated_premium * 0.80
|
|
128
|
+
ELSE 0
|
|
129
|
+
END
|
|
130
|
+
),0) AS s
|
|
131
|
+
FROM deals
|
|
132
|
+
"""
|
|
133
|
+
).fetchone()["s"]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
overview = {
|
|
137
|
+
"customers_total": customers_total,
|
|
138
|
+
"hi_value": hi_value,
|
|
139
|
+
"active": active,
|
|
140
|
+
"dormant": dormant,
|
|
141
|
+
"new": new,
|
|
142
|
+
"policies_total": policies_total,
|
|
143
|
+
"total_premium": total_premium,
|
|
144
|
+
"products_total": products_total,
|
|
145
|
+
"renewal_30d": renewal_30d,
|
|
146
|
+
"followup_30d_lapsed": followup_30d_lapsed,
|
|
147
|
+
"dormant_60d": dormant_60d,
|
|
148
|
+
"this_month": month,
|
|
149
|
+
"active_deals": active_deals,
|
|
150
|
+
"this_month_target": this_month_target,
|
|
151
|
+
"this_month_closed": this_month_closed,
|
|
152
|
+
"this_month_forecast": this_month_forecast,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
md_lines: list[str] = []
|
|
156
|
+
month_label = overview.get("this_month", "")
|
|
157
|
+
md_lines.append(f"🛡️ **经营概览({month_label})**" if month_label else "🛡️ **经营概览**")
|
|
158
|
+
md_lines.append("")
|
|
159
|
+
md_lines.append(
|
|
160
|
+
f"👥 客户:{overview['customers_total']}人(高净值{overview['hi_value']} / "
|
|
161
|
+
f"活跃{overview['active']} / 沉睡{overview['dormant']} / 新客{overview['new']})"
|
|
162
|
+
)
|
|
163
|
+
md_lines.append(
|
|
164
|
+
f"📋 保单:{overview['policies_total']}份(总保费约¥{overview['total_premium']:,.0f})"
|
|
165
|
+
)
|
|
166
|
+
md_lines.append(f"📦 产品库:{overview['products_total']} 款")
|
|
167
|
+
md_lines.append(f"⏰ 本月续保:{overview['renewal_30d']}份 30 天内到期")
|
|
168
|
+
md_lines.append(
|
|
169
|
+
f"🎯 本月目标:保费¥{overview['this_month_target']:,.0f} | "
|
|
170
|
+
f"已完成:¥{overview['this_month_closed']:,.0f} | "
|
|
171
|
+
f"在谈预估:¥{overview['this_month_forecast']:,.0f} | "
|
|
172
|
+
f"在谈商机:{overview['active_deals']}单"
|
|
173
|
+
)
|
|
174
|
+
md_lines.append("")
|
|
175
|
+
md_lines.append("⚠️ 待处理:")
|
|
176
|
+
md_lines.append(f"- {overview['renewal_30d']} 份保单 30 天内到期")
|
|
177
|
+
md_lines.append(f"- {overview['followup_30d_lapsed']} 位客户超 30 天未联系")
|
|
178
|
+
md_lines.append(f"- {overview['dormant_60d']} 位客户超 60 天未联系(沉睡)")
|
|
179
|
+
|
|
180
|
+
conn.close()
|
|
181
|
+
return {"ok": True, "overview": overview, "skills": {"source": "shared-db"}, "markdown": "\n".join(md_lines)}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def main(argv: list[str] | None = None) -> int:
|
|
185
|
+
parser = argparse.ArgumentParser(prog="dashboard_all")
|
|
186
|
+
parser.add_argument("--json", action="store_true",
|
|
187
|
+
help="只输出 JSON(默认就是 JSON;保留参数对齐子命令风格)")
|
|
188
|
+
parser.add_argument("--md", action="store_true",
|
|
189
|
+
help="只打印 markdown 卡片(不打 JSON)")
|
|
190
|
+
args = parser.parse_args(argv)
|
|
191
|
+
try:
|
|
192
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
193
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
194
|
+
except (AttributeError, OSError):
|
|
195
|
+
pass
|
|
196
|
+
data = aggregate()
|
|
197
|
+
if args.md:
|
|
198
|
+
print(data["markdown"])
|
|
199
|
+
else:
|
|
200
|
+
print(json.dumps(data, ensure_ascii=False, indent=2))
|
|
201
|
+
return 0
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
raise SystemExit(main())
|
|
File without changes
|