Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

原材料管理模块自动化测试。测试批次入库、预留、消耗、FIFO分配、库存预警。使用此Skill验证原材料管理系统的完整性。

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name test-material-batch
description 原材料管理模块自动化测试。测试批次入库、预留、消耗、FIFO分配、库存预警。使用此Skill验证原材料管理系统的完整性。
allowed-tools Bash, Read, Grep

原材料管理测试 Skill

测试 Cretas 食品溯源系统的原材料批次管理模块。

测试环境

  • 服务地址: localhost:10010
  • 测试工厂: F001

执行测试

运行以下命令执行完整的原材料管理测试:

echo "========================================"
echo "原材料管理模块 - 自动化测试报告"
echo "环境: localhost:10010"
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"
echo ""

# 初始化计数器
PASS=0
FAIL=0

# 获取Token
echo "[前置] 获取测试Token..."
LOGIN_RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/auth/unified-login" \
  -H "Content-Type: application/json" \
  -d '{"username":"factory_admin1","password":"123456"}')
TOKEN=$(echo "$LOGIN_RESULT" | grep -o '"accessToken":"[^"]*"' | cut -d'"' -f4)

if [ -z "$TOKEN" ]; then
  echo "❌ 获取Token失败,测试终止"
  exit 1
fi
echo "✓ Token获取成功"
echo ""

# ========== 测试1: 获取原材料批次列表 ==========
echo "[测试1] 获取原材料批次列表"
echo "  请求: GET /api/mobile/F001/material-batches"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/material-batches" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回批次列表"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试2: 创建原材料批次 ==========
echo "[测试2] 创建原材料批次(入库)"
echo "  请求: POST /api/mobile/F001/material-batches"

BATCH_ID="MB-TEST-$(date +%s)"
RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"batchNumber\": \"$BATCH_ID\",
    \"materialTypeId\": \"MT001\",
    \"quantity\": 500,
    \"unit\": \"kg\",
    \"supplierId\": \"SUP001\",
    \"receivedDate\": \"$(date +%Y-%m-%d)\",
    \"expirationDate\": \"$(date -v+30d +%Y-%m-%d 2>/dev/null || date -d '+30 days' +%Y-%m-%d)\",
    \"storageLocation\": \"仓库A-01\"
  }")

if echo "$RESULT" | grep -q "id\|batchNumber\|success"; then
  MATERIAL_ID=$(echo "$RESULT" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
  if [ -z "$MATERIAL_ID" ]; then
    MATERIAL_ID=$(echo "$RESULT" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
  fi
  echo "  期望: 入库成功,状态AVAILABLE"
  echo "  实际: 创建成功,批次=$BATCH_ID ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 创建成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
  MATERIAL_ID=""
fi
echo ""

# ========== 测试3: 获取批次详情 ==========
echo "[测试3] 获取批次详情"
echo "  请求: GET /api/mobile/F001/material-batches/$BATCH_ID"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回批次详情"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试4: 按状态筛选批次 ==========
echo "[测试4] 按状态筛选批次"
echo "  请求: GET /api/mobile/F001/material-batches?status=AVAILABLE"

RESULT=$(curl -s "http://localhost:10010/api/mobile/F001/material-batches?status=AVAILABLE" \
  -H "Authorization: Bearer $TOKEN")

if echo "$RESULT" | grep -q "content\|data\|\[\]"; then
  echo "  期望: 返回AVAILABLE状态批次"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 返回列表"
  echo "  实际: $(echo $RESULT | head -c 100)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试5: 预留原材料 ==========
echo "[测试5] 预留原材料"
echo "  请求: POST /api/mobile/F001/material-batches/$BATCH_ID/reserve"

# 注意: 后端期望字段是 planId (生产计划ID), 不是 productionBatchId
RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID/reserve" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"quantity": 100, "planId": "PLAN-TEST-001", "notes": "测试预留"}')

if echo "$RESULT" | grep -q "reserved\|success\|RESERVED\|code\":200"; then
  echo "  期望: 预留100kg成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 预留成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试6: 消耗原材料 ==========
echo "[测试6] 消耗原材料"
echo "  请求: POST /api/mobile/F001/material-batches/$BATCH_ID/consume"

# 注意: 后端期望字段是 processId (生产批次ID, Long类型), 不是 productionBatchId (String)
# 还需要 consumedBy 字段 (操作人ID)
RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID/consume" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"quantity": 50, "processId": 1, "consumedBy": 22}')

if echo "$RESULT" | grep -q "consumed\|success\|IN_USE\|code\":200"; then
  echo "  期望: 消耗50kg成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 消耗成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试7: 释放预留 ==========
echo "[测试7] 释放预留"
echo "  请求: POST /api/mobile/F001/material-batches/$BATCH_ID/release"

# 注意: 后端期望字段是 productionPlanId, 不是 productionBatchId
RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID/release" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"quantity": 50, "productionPlanId": "PLAN-TEST-001", "notes": "测试释放"}')

if echo "$RESULT" | grep -q "released\|success\|AVAILABLE\|code\":200"; then
  echo "  期望: 释放50kg预留成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 释放成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试8: 转冻品 ==========
echo "[测试8] 转冻品"
echo "  请求: POST /api/mobile/F001/material-batches/$BATCH_ID/freeze"

RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID/freeze" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason": "测试转冻"}')

if echo "$RESULT" | grep -q "FROZEN\|success\|frozen"; then
  echo "  期望: 转冻品成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 转冻成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试9: 撤销转冻(10分钟内) ==========
echo "[测试9] 撤销转冻(10分钟内可撤销)"
echo "  请求: POST /api/mobile/F001/material-batches/$BATCH_ID/unfreeze"

RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/material-batches/$BATCH_ID/unfreeze" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason": "撤销转冻测试"}')

if echo "$RESULT" | grep -q "AVAILABLE\|success\|unfrozen"; then
  echo "  期望: 撤销成功,恢复AVAILABLE"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 撤销成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试10: 获取材料类型列表 ==========
echo "[测试10] 获取材料类型列表"
echo "  请求: GET /api/mobile/F001/material-types"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/material-types" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回材料类型"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试11: 库存预警查询 ==========
echo "[测试11] 库存预警查询"
echo "  请求: GET /api/mobile/F001/material-batches/alerts"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/material-batches/alerts" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回预警列表"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试12: 即将过期批次查询 ==========
echo "[测试12] 即将过期批次查询"
echo "  请求: GET /api/mobile/F001/material-batches/expiring?days=7"

RESULT=$(curl -s "http://localhost:10010/api/mobile/F001/material-batches/expiring?days=7" \
  -H "Authorization: Bearer $TOKEN")

if echo "$RESULT" | grep -q "content\|data\|\[\]"; then
  echo "  期望: 返回7天内过期批次"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 返回列表"
  echo "  实际: $(echo $RESULT | head -c 100)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试汇总 ==========
echo "========================================"
echo "测试汇总"
echo "========================================"
TOTAL=$((PASS+FAIL))
if [ $TOTAL -gt 0 ]; then
  RATE=$((PASS*100/TOTAL))
else
  RATE=0
fi
echo "总计: $TOTAL | 通过: $PASS | 失败: $FAIL | 通过率: ${RATE}%"
echo "========================================"

if [ $FAIL -eq 0 ]; then
  echo "✅ 所有测试通过!"
else
  echo "⚠️  有 $FAIL 个测试失败,请检查"
fi

批次状态说明

AVAILABLE (可用)
    │
    ├── reserve → RESERVED (已预留)
    │                 │
    │                 ├── consume → IN_USE (使用中)
    │                 │                 │
    │                 │                 └── 全部消耗 → DEPLETED
    │                 │
    │                 └── release → AVAILABLE
    │
    └── freeze → FROZEN (冻品)
                    │
                    └── unfreeze (10分钟内) → AVAILABLE

FIFO原则

系统自动按入库日期排序,优先使用最早入库的批次。

库存预警类型

类型 触发条件
低库存 当前库存 < 最低库存线
即将过期 距离过期 ≤ 7天
已过期 当前日期 > 过期日期