#!/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 </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 </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 </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}¤tPage=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 "=========================================="