test_lq_inventory_update.sh 7.9 KB
#!/bin/bash
# 库存更新接口(PUT /api/Extend/LqInventory/Update)测试脚本
# 覆盖:采购入库(stockInType=2) 与 普通入库(stockInType=1) 的价格变更逻辑
# 测试前请确保后端服务已启动(如 http://localhost:2011)

set -e
BASE_URL="${BASE_URL:-http://localhost:2011}"
API_UPDATE="${BASE_URL}/api/Extend/LqInventory/Update"
API_GETLIST="${BASE_URL}/api/Extend/LqInventory/GetList"

echo "=========================================="
echo "库存更新接口测试 (LqInventory/Update)"
echo "BASE_URL=$BASE_URL"
echo "=========================================="

# 获取 Token
echo ""
echo "正在获取 Token..."
LOGIN_RESPONSE=$(curl -s -X POST "${BASE_URL}/api/oauth/Login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e")
TOKEN=$(echo "$LOGIN_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin).get('data',{}).get('token',''))" 2>/dev/null)
if [ -z "$TOKEN" ]; then
  echo "❌ 获取 Token 失败"
  echo "响应: $LOGIN_RESPONSE"
  exit 1
fi
echo "✅ Token 获取成功"

# 获取一条有效库存记录(用于更新测试)
echo ""
echo "正在获取一条库存记录(用于更新)..."
LIST_RESPONSE=$(curl -s -X GET "${API_GETLIST}?currentPage=1&pageSize=1" -H "Authorization: $TOKEN")
CODE=$(echo "$LIST_RESPONSE" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('code', 0))" 2>/dev/null)
if [ "$CODE" != "200" ]; then
  echo "❌ GetList 失败 (code=$CODE)"
  echo "$LIST_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$LIST_RESPONSE"
  exit 1
fi
INVENTORY_ID=$(echo "$LIST_RESPONSE" | python3 -c "
import sys, json
d = json.load(sys.stdin)
lst = d.get('data',{}).get('list') or d.get('data',{}).get('data',[]) or []
if not lst:
    sys.exit(1)
print(lst[0].get('id',''))
" 2>/dev/null)
PRODUCT_ID=$(echo "$LIST_RESPONSE" | python3 -c "
import sys, json
d = json.load(sys.stdin)
lst = d.get('data',{}).get('list') or d.get('data',{}).get('data',[]) or []
if not lst:
    sys.exit(1)
print(lst[0].get('productId',''))
" 2>/dev/null)

if [ -z "$INVENTORY_ID" ] || [ -z "$PRODUCT_ID" ]; then
  echo "⚠️ 未获取到库存记录,将使用占位 ID 仅验证接口可达性与参数校验"
  INVENTORY_ID="${INVENTORY_ID:-test-invalid-id}"
  PRODUCT_ID="${PRODUCT_ID:-test-invalid-product}"
fi

# 测试1:采购入库更新(stockInType=2,带单价与金额)
echo ""
echo "=== 测试1: 采购入库更新 (stockInType=2, purchaseUnitPrice=50, finalAmount=5000) ==="
BODY1=$(cat <<EOF
{
  "id": "$INVENTORY_ID",
  "productId": "$PRODUCT_ID",
  "quantity": 100,
  "stockInType": 2,
  "purchaseUnitPrice": 50.00,
  "finalAmount": 5000.00
}
EOF
)
RESP1=$(curl -s -w "\n%{http_code}" -X PUT "$API_UPDATE" \
  -H "Authorization: $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$BODY1")
HTTP1=$(echo "$RESP1" | tail -n1)
BODY1_RESP=$(echo "$RESP1" | sed '$d')
CODE1=$(echo "$BODY1_RESP" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('code', d.get('statusCode', 0)))" 2>/dev/null || echo "0")
echo "HTTP: $HTTP1, 业务 code: $CODE1"
echo "$BODY1_RESP" | python3 -m json.tool 2>/dev/null || echo "$BODY1_RESP"
if [ "$HTTP1" = "200" ] && [ "$CODE1" = "200" ]; then
  echo "✅ 测试1 通过:采购入库更新成功"
else
  if [ "$INVENTORY_ID" = "test-invalid-id" ]; then
    echo "⚠️ 预期失败(无有效库存ID),接口与参数格式正常"
  else
    echo "❌ 测试1 失败"
    exit 1
  fi
fi

# 测试2:普通入库更新(stockInType=1,带单价与金额)
echo ""
echo "=== 测试2: 普通入库更新 (stockInType=1, purchaseUnitPrice=30, finalAmount=3000) ==="
BODY2=$(cat <<EOF
{
  "id": "$INVENTORY_ID",
  "productId": "$PRODUCT_ID",
  "quantity": 100,
  "stockInType": 1,
  "purchaseUnitPrice": 30.00,
  "finalAmount": 3000.00
}
EOF
)
RESP2=$(curl -s -w "\n%{http_code}" -X PUT "$API_UPDATE" \
  -H "Authorization: $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$BODY2")
HTTP2=$(echo "$RESP2" | tail -n1)
BODY2_RESP=$(echo "$RESP2" | sed '$d')
CODE2=$(echo "$BODY2_RESP" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('code', d.get('statusCode', 0)))" 2>/dev/null || echo "0")
echo "HTTP: $HTTP2, 业务 code: $CODE2"
echo "$BODY2_RESP" | python3 -m json.tool 2>/dev/null || echo "$BODY2_RESP"
if [ "$HTTP2" = "200" ] && [ "$CODE2" = "200" ]; then
  echo "✅ 测试2 通过:普通入库价格变更成功"
else
  if [ "$INVENTORY_ID" = "test-invalid-id" ]; then
    echo "⚠️ 预期失败(无有效库存ID),接口与参数格式正常"
  else
    echo "❌ 测试2 失败"
    exit 1
  fi
fi

# 测试3:参数校验(数量<=0 应报错)
echo ""
echo "=== 测试3: 参数校验(quantity=0 应返回错误) ==="
BODY3=$(cat <<EOF
{
  "id": "$INVENTORY_ID",
  "productId": "$PRODUCT_ID",
  "quantity": 0,
  "stockInType": 1
}
EOF
)
RESP3=$(curl -s -X PUT "$API_UPDATE" \
  -H "Authorization: $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$BODY3")
CODE3=$(echo "$RESP3" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d.get('code', 200))" 2>/dev/null || echo "200")
echo "业务 code: $CODE3 (预期非 200)"
if [ "$CODE3" != "200" ]; then
  echo "✅ 测试3 通过:数量校验生效"
else
  echo "⚠️ 测试3:接口未对 quantity<=0 返回错误(请确认业务是否允许)"
fi

# 测试4:验证更新后加权平均单价计算正确(与 RecalculateProductAveragePriceAsync 一致)
if [ "$INVENTORY_ID" != "test-invalid-id" ] && [ -n "$PRODUCT_ID" ]; then
  echo ""
  echo "=== 测试4: 验证加权平均单价计算 ==="
  API_GETINFO="${BASE_URL}/api/Extend/LqProduct/GetInfo"
  INFO_RESP=$(curl -s -X GET "${API_GETINFO}?id=${PRODUCT_ID}" -H "Authorization: $TOKEN")
  LIST_FULL=$(curl -s -X GET "${API_GETLIST}?productId=${PRODUCT_ID}&currentPage=1&pageSize=100" -H "Authorization: $TOKEN")
  VERIFY=$(echo "$INFO_RESP
$LIST_FULL" | python3 -c "
import sys, json
lines = sys.stdin.read().strip().split('\n')
if len(lines) < 2:
    print('FAIL: no data')
    sys.exit(1)
info = json.loads(lines[0])
lst_data = json.loads(lines[1])
if info.get('code') != 200:
    print('FAIL: GetInfo code', info.get('code'))
    sys.exit(1)
lst = lst_data.get('data',{}).get('list') or lst_data.get('data',{}).get('data',[]) or []
# 产品基础价(无 FinalAmount/PurchaseUnitPrice 时用);产品当前平均单价(接口返回)
product_price = float(info.get('data',{}).get('price') or 0)
product_avg = float(info.get('data',{}).get('averagePrice') or 0)
# 与 RecalculateProductAveragePriceAsync 一致:优先 FinalAmount/Quantity,其次 PurchaseUnitPrice,最后 Product.Price
total_amount = 0
total_qty = 0
for row in lst:
    qty = int(row.get('quantity') or 0)
    if qty <= 0:
        continue
    fa = row.get('finalAmount')
    pu = row.get('purchaseUnitPrice')
    if fa is not None and float(fa or 0) > 0:
        unit = float(fa) / qty
    elif pu is not None and float(pu or 0) > 0:
        unit = float(pu)
    else:
        unit = product_price
    total_amount += unit * qty
    total_qty += qty
expected_avg = (total_amount / total_qty) if total_qty > 0 else product_price
diff = abs(expected_avg - product_avg) if product_avg else abs(expected_avg)
# 允许四舍五入误差
ok = diff < 0.02
print('OK' if ok else 'FAIL')
print('expected_avg=%.4f product_avg=%.4f total_amount=%.2f total_qty=%d' % (expected_avg, product_avg, total_amount, total_qty))
" 2>/dev/null)
  VERIFY_OK=$(echo "$VERIFY" | head -1)
  VERIFY_DETAIL=$(echo "$VERIFY" | tail -1)
  if [ "$VERIFY_OK" = "OK" ]; then
    echo "✅ 测试4 通过:加权平均单价与接口返回一致 ($VERIFY_DETAIL)"
  else
    echo "❌ 测试4 失败:加权平均与产品平均单价不一致"
    echo "    $VERIFY_DETAIL"
    exit 1
  fi
else
  echo ""
  echo "=== 测试4: 跳过(无有效库存/产品ID) ==="
fi

echo ""
echo "=========================================="
echo "库存更新接口测试完成"
echo "=========================================="