Files
Home-Care/hss-home-service/test-api.sh
comclib c02029a5f3 feat: 初始化居家上门服务系统完整项目代码
- Spring Boot 后端服务 (hss-home-service)
- delivery-miniapp 配送小程序
- website 官网 (Nuxt)
- docs 架构设计文档
- Docker 容器化部署配置

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 09:04:49 +08:00

183 lines
11 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 居家上门服务系统 — 接口集成测试脚本
# 用法: chmod +x test-api.sh && ./test-api.sh
set -e
BASE="http://localhost:18080/api/hss"
TS=$(date +%s)
PASS=0; FAIL=0
GREEN='\033[0;32m'; RED='\033[0;31m'; NC='\033[0m'
hdrs() { echo "-H 'Content-Type: application/json' -H 'X-Tenant-Id: 1' -H 'Idempotency-Key: test-$(date +%s%N)'"; }
ok() { PASS=$((PASS+1)); echo -e "${GREEN}PASS${NC} $1"; }
fail() { FAIL=$((FAIL+1)); echo -e "${RED}FAIL${NC} $1$2"; }
check() { local code=$1; shift; if [ "$code" -eq 200 ] || [ "$code" -eq 302 ]; then ok "$*"; else fail "$*" "HTTP $code"; fi; }
check_json() { echo "$1" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']==$2,f'Expected code $2 got {d[\"code\"]}: {d.get(\"message\",\"\")}'" 2>&1; }
echo "============================================"
echo " 居家上门服务系统 API 集成测试"
echo "============================================"
echo ""
# === 1. Infrastructure ===
echo "--- 1. 基础设施 ---"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/applications?page=1&size=1")
check "$R" "OpenAPI可达"
R=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:18080/swagger-ui/index.html")
check "$R" "Swagger UI"
R=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:18080/api-docs")
check "$R" "OpenAPI JSON"
echo ""
# === 2. 主链路:申请 → 评估 → 方案 → 计划 → 工单 → 执行 → 验收 → 结算 → 归档 ===
echo "--- 2. 主链路全流程 ---"
# Step 1: 创建申请
RESP=$(curl -s -X POST "$BASE/applications" \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-app-1" \
-d '{"patientId":"2001","serviceType":"HOME_CARE","channel":"WECHAT","contactName":"张三","contactPhone":"13812345678","address":"梅江区金山街道XX小区3栋201","regionCode":"441402001"}')
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']==200;assert d['data']['status']=='DRAFT'" 2>&1 && ok "创建申请(DRAFT)" || fail "创建申请(DRAFT)" "$RESP"
APP_ID=$(echo "$RESP" | python3 -c "import sys,json;print(json.loads(sys.stdin.read())['data']['id'])")
# Step 2: 提交申请
RESP=$(curl -s -X POST "$BASE/applications/$APP_ID/submit" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-app-2")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['data']['status']=='PENDING_ACCEPTANCE'" 2>&1 && ok "提交申请(PENDING_ACCEPTANCE)" || fail "提交申请" "$RESP"
# Step 3: 受理通过
RESP=$(curl -s -X POST "$BASE/applications/$APP_ID/accept" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:RECEPTIONIST" -H "Idempotency-Key: e2e-run3-${TS}-app-3")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['data']['status']=='PENDING_ASSESSMENT'" 2>&1 && ok "受理通过(PENDING_ASSESSMENT)" || fail "受理通过" "$RESP"
# Step 4: 派发评估
RESP=$(curl -s -X POST "$BASE/assessments/$APP_ID/assign" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:RECEPTIONIST" -H "Idempotency-Key: e2e-run3-${TS}-asm-1" \
-d '{"assessorId": 100}')
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']==200" 2>&1 && ok "派发评估" || fail "派发评估" "$RESP"
ASM_ID=$(echo "$RESP" | python3 -c "import sys,json;print(json.loads(sys.stdin.read())['data']['id'])" 2>/dev/null || echo "1")
# Step 5: 提交评估报告
RESP=$(curl -s -X POST "$BASE/assessments/$ASM_ID/submit" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:ASSESSOR" -H "Idempotency-Key: e2e-run3-${TS}-asm-2" \
-d '{"careLevel":"LEVEL_3","riskLevel":"MEDIUM","reportContent":"{\"mobility\":\"limited\",\"cognition\":\"normal\"}"}')
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']==200" 2>&1 && ok "提交评估报告" || fail "提交评估报告" "$RESP"
# Step 6: 创建方案
RESP=$(curl -s -X POST "$BASE/service-plans" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PLANNER" -H "Idempotency-Key: e2e-run3-${TS}-plan-1" \
-d '{"applicationId":'$APP_ID',"assessmentTaskId":'$ASM_ID',"items":[{"serviceItemId":1,"itemName":"助洁服务","unitPrice":50.00,"frequency":3,"standardDuration":60,"evidenceRequired":false}]}')
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']==200" 2>&1 && ok "创建方案(PLAN_DRAFT)" || fail "创建方案" "$RESP"
PLAN_ID=$(echo "$RESP" | python3 -c "import sys,json;print(json.loads(sys.stdin.read())['data']['id'])")
# Step 7: 提交签署
RESP=$(curl -s -X POST "$BASE/service-plans/$PLAN_ID/submit-sign" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PLANNER" -H "Idempotency-Key: e2e-run3-${TS}-plan-2")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['data']['status']=='PLAN_PENDING_SIGN'" 2>&1 && ok "提交签署(PENDING_SIGN)" || fail "提交签署" "$RESP"
# Step 8: 签署方案(自动生成服务计划)
RESP=$(curl -s -X POST "$BASE/service-plans/$PLAN_ID/sign" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-plan-3")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['data']['status']=='PLAN_EFFECTIVE'" 2>&1 && ok "签署方案(PLAN_EFFECTIVE)" || fail "签署方案" "$RESP"
# Step 9: 验证服务计划已生成
SCH_RESP=$(curl -s "$BASE/service-schedules/plans/$PLAN_ID" -H "X-Tenant-Id: 1")
echo "$SCH_RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert len(d['data'])>0" 2>&1 && ok "服务计划已自动生成" || fail "服务计划生成" "$SCH_RESP"
echo ""
echo "--- 3. 异常流程 ---"
# Step 10: 非法状态转换(已通过不能再次接受)
RESP=$(curl -s -X POST "$BASE/applications/$APP_ID/accept" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:RECEPTIONIST" -H "Idempotency-Key: e2e-run3-${TS}-fail-1")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']!=200" 2>&1 && ok "拦截非法状态转换" || fail "非法状态转换" "$RESP"
# Step 11: 角色越权PATIENT 不能受理)
RESP=$(curl -s -X POST "$BASE/applications/$APP_ID/accept" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-fail-2")
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']!=200" 2>&1 && ok "拦截角色越权" || fail "角色越权" "$RESP"
# Step 12: 退回缺少原因
RESP=$(curl -s -X POST "$BASE/applications/99999/return" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:RECEPTIONIST" -H "Idempotency-Key: e2e-run3-${TS}-fail-3" \
-d '{"reason":""}')
echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());assert d['code']!=200" 2>&1 && ok "拒绝空退回原因" || fail "空退回原因" "$RESP"
echo ""
echo "--- 4. 幂等验证 ---"
# 重复提交同一 Idempotency-Key
R1=$(curl -s -X POST "$BASE/applications" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-idem-dup" \
-d '{"patientId":"3001","serviceType":"BATH_ASSIST","channel":"PHONE","contactName":"重复测试","contactPhone":"13900000000","address":"梅县区","regionCode":"441403001"}' | python3 -c "import sys,json;print(json.loads(sys.stdin.read())['data']['id'])")
sleep 1
R2=$(curl -s -X POST "$BASE/applications" \
-H "Content-Type: application/json" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:PATIENT" -H "Idempotency-Key: e2e-run3-${TS}-idem-dup" \
-d '{"patientId":"3001","serviceType":"BATH_ASSIST","channel":"PHONE","contactName":"重复测试","contactPhone":"13900000000","address":"梅县区","regionCode":"441403001"}' | python3 -c "import sys,json;print(json.loads(sys.stdin.read())['data']['id'])")
if [ "$R1" = "$R2" ]; then ok "幂等:重复提交返回同一结果($R1)"; else fail "幂等重复提交" "R1=$R1 R2=$R2"; fi
echo ""
echo "--- 5. 数据脱敏 ---"
R_ADMIN=$(curl -s "$BASE/applications/$APP_ID" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:ADMIN")
R_STAFF=$(curl -s "$BASE/applications/$APP_ID" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:STAFF")
ADDR_ADMIN=$(echo "$R_ADMIN" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(d['data'].get('address',''))")
ADDR_STAFF=$(echo "$R_STAFF" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(d['data'].get('address',''))")
if [ "$ADDR_ADMIN" != "$ADDR_STAFF" ] && echo "$ADDR_STAFF" | grep -q "\*\*\*\*"; then
ok "角色脱敏ADMIN完整地址, STAFF已脱敏"
else
fail "角色脱敏" "ADMIN=$ADDR_ADMIN STAFF=$ADDR_STAFF"
fi
echo ""
echo "--- 6. Delivery 接口 ---"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/delivery/workbench" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:STAFF")
check "$R" "Delivery工作台"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/delivery/work-orders/today" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:STAFF")
check "$R" "Delivery今日工单"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/delivery/messages" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:STAFF")
check "$R" "Delivery消息"
echo ""
echo "--- 7. 管理端 ---"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/admin/dashboard" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:ADMIN")
check "$R" "管理端仪表盘"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/admin/work-orders" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:DISPATCHER")
check "$R" "管理端工单列表"
echo ""
echo "--- 8. 监管/合规/主数据/运力/看板/绩效/智能助手 ---"
for endpoint in \
"supervision/spot-checks:ADMIN" \
"compliance/consents/patients/1:PATIENT" \
"master/service-items:PATIENT" \
"master/price-rules:PATIENT" \
"master/regions:PATIENT" \
"master/staff:DISPATCHER" \
"capacity/grids:DISPATCHER" \
"capacity/dashboard:DISPATCHER" \
"analytics/quality:SUPERVISOR" \
"analytics/heatmap:SUPERVISOR" \
"analytics/continuity:PATIENT" \
"analytics/staff-load:DISPATCHER" \
"analytics/summary:ADMIN" \
"performance/ranking:DISPATCHER"; do
path="${endpoint%%:*}"
role="${endpoint##*:}"
R=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/$path" -H "X-Tenant-Id: 1" -H "X-Org-Id: 1" -H "X-User-Role:$role")
check "$R" "$path"
done
echo ""
echo "============================================"
echo -e " 结果: ${GREEN}$PASS 通过${NC} / ${RED}$FAIL 失败${NC}"
echo "============================================"