160 lines
6.8 KiB
Bash
160 lines
6.8 KiB
Bash
#!/bin/bash
|
||
# dealerhub 全业务链端到端冒烟(进货 → 付款 → 销售 → 收款)
|
||
# 需先 smoke.sh 跑过;使用 P999/W999/S999/C999 等已建实体
|
||
set -e
|
||
|
||
BASE=${1:-http://192.168.5.7:18050}
|
||
TENANT="default"
|
||
SUFFIX=$(date +%H%M%S)
|
||
|
||
echo "===== dealerhub 完整业务链冒烟 ====="
|
||
echo "BASE=$BASE SUFFIX=$SUFFIX"
|
||
echo ""
|
||
|
||
TOKEN=$(curl -s -X POST $BASE/api/v1/auth/token/ \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"username":"alice","password":"alice12345"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['access'])")
|
||
echo "[0] TOKEN 长度: ${#TOKEN}"
|
||
echo ""
|
||
|
||
H_AUTH=("-H" "Authorization: Bearer $TOKEN" "-H" "X-Tenant-Id: $TENANT" "-H" "Content-Type: application/json")
|
||
|
||
# 创建基础实体(每次用 SUFFIX 区分)
|
||
echo "[1] 创建测试实体(SUFFIX=$SUFFIX)"
|
||
P=$(curl -s -X POST $BASE/api/v1/catalog/products/ "${H_AUTH[@]}" \
|
||
-d "{\"code\":\"P$SUFFIX\",\"name\":\"测试商品\",\"status\":\"active\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id', 'ERR'))")
|
||
echo " product id=$P"
|
||
|
||
W=$(curl -s -X POST $BASE/api/v1/inventory/warehouses/ "${H_AUTH[@]}" \
|
||
-d "{\"code\":\"W$SUFFIX\",\"name\":\"测试仓\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id', 'ERR'))")
|
||
echo " warehouse id=$W"
|
||
|
||
SUP=$(curl -s -X POST $BASE/api/v1/partner/suppliers/ "${H_AUTH[@]}" \
|
||
-d "{\"code\":\"S$SUFFIX\",\"name\":\"测试供应商\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id', 'ERR'))")
|
||
echo " supplier id=$SUP"
|
||
|
||
CUS=$(curl -s -X POST $BASE/api/v1/partner/customers/ "${H_AUTH[@]}" \
|
||
-d "{\"code\":\"C$SUFFIX\",\"name\":\"测试客户\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id', 'ERR'))")
|
||
echo " customer id=$CUS"
|
||
echo ""
|
||
|
||
# 进货:通过 docker exec 在容器内调用 services(API 没暴露 create_bill)
|
||
echo "[2] 在容器内创建进货单并过账(写库存 + 生成应付)"
|
||
docker exec backend-backend-1 sh -c "
|
||
cd /app && DJANGO_SETTINGS_MODULE=config.settings.prod python manage.py shell -c \"
|
||
from decimal import Decimal
|
||
from apps.purchase import services as ps
|
||
from apps.purchase.models import PurchaseBill
|
||
from apps.partner.models import Supplier
|
||
from apps.inventory.models import Warehouse
|
||
from apps.catalog.models import Product
|
||
from django.contrib.auth import get_user_model
|
||
|
||
U = get_user_model().objects.get(username='alice')
|
||
T = U.tenant if hasattr(U,'tenant') else None
|
||
|
||
# 我们直接通过 services 创建(skip view 层,因为 view 没暴露)
|
||
import django
|
||
django.setup()
|
||
tenant = django.apps.apps.get_model('core','Tenant').objects.get(code='default')
|
||
sup = Supplier.objects.get(tenant=tenant, code='S$SUFFIX')
|
||
wh = Warehouse.objects.get(tenant=tenant, code='W$SUFFIX')
|
||
p = Product.objects.get(tenant=tenant, code='P$SUFFIX')
|
||
|
||
bill = ps.create_purchase_bill(
|
||
tenant=tenant, supplier=sup, warehouse=wh,
|
||
lines=[{'product': p, 'quantity': Decimal('20'), 'unit_price': Decimal('8')}],
|
||
)
|
||
ps.confirm_purchase_bill(bill)
|
||
print(f' purchase_bill: {bill.bill_no} state={bill.state} total={bill.total_amount}')
|
||
\"
|
||
" 2>&1 | tail -5
|
||
echo ""
|
||
|
||
echo "[3] 检查库存 + 应付"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/inventory/stocks/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' stocks count = {d[\"count\"]}')
|
||
for s in d['results'][:5]:
|
||
print(f' {s[\"product_code\"]}/{s[\"warehouse_code\"]} on_hand={s[\"on_hand\"]} avg_cost={s[\"avg_cost\"]}')
|
||
"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/payables/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' payables count = {d[\"count\"]}')
|
||
for p in d['results'][:5]:
|
||
print(f' {p[\"bill_no\"]} {p[\"supplier_code\"]} total={p[\"total_amount\"]} status={p[\"status\"]}')
|
||
"
|
||
echo ""
|
||
|
||
# 销售:同样在容器内调用 services
|
||
echo "[4] 在容器内创建销售单并过账(扣库存 + 生成应收)"
|
||
docker exec backend-backend-1 sh -c "
|
||
cd /app && DJANGO_SETTINGS_MODULE=config.settings.prod python manage.py shell -c \"
|
||
from decimal import Decimal
|
||
from apps.sales import services as ss
|
||
from apps.partner.models import Customer
|
||
from apps.inventory.models import Warehouse
|
||
from apps.catalog.models import Product
|
||
from apps.core.models import Tenant
|
||
|
||
tenant = Tenant.objects.get(code='default')
|
||
cus = Customer.objects.get(tenant=tenant, code='C$SUFFIX')
|
||
wh = Warehouse.objects.get(tenant=tenant, code='W$SUFFIX')
|
||
p = Product.objects.get(tenant=tenant, code='P$SUFFIX')
|
||
|
||
bill = ss.create_sales_bill(
|
||
tenant=tenant, customer=cus, warehouse=wh,
|
||
lines=[{'product': p, 'quantity': Decimal('7'), 'unit_price': Decimal('12')}],
|
||
)
|
||
ss.confirm_sales_bill(bill)
|
||
print(f' sales_bill: {bill.bill_no} state={bill.state} total={bill.total_amount}')
|
||
\"
|
||
" 2>&1 | tail -5
|
||
echo ""
|
||
|
||
echo "[5] 检查应收(应该 7*12=84)"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/receivables/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' receivables count = {d[\"count\"]}')
|
||
for r in d['results'][:5]:
|
||
print(f' {r[\"bill_no\"]} {r[\"customer_code\"]} total={r[\"total_amount\"]} balance={r[\"balance\"]} status={r[\"status\"]}')
|
||
"
|
||
echo ""
|
||
|
||
echo "[6] 检查财务凭证(业财一体化自动生成凭证)"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/vouchers/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' vouchers count = {d[\"count\"]}')
|
||
for v in d['results'][:5]:
|
||
print(f' {v[\"bill_no\"]} source={v[\"source_type\"]} 借/贷={v[\"total_debit\"]}/{v[\"total_credit\"]} [{v[\"status\"]}] {v[\"summary\"]}')
|
||
"
|
||
echo ""
|
||
|
||
echo "[7] 检查科目余额表(试算平衡)"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/reports/trial-balance/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' trial_balance is_balanced = {d.get(\"is_balanced\")} rows = {len(d.get(\"rows\", []))}')
|
||
print(f' 期末借方合计 = {d.get(\"totals\", {}).get(\"ending_debit\")} 期末贷方合计 = {d.get(\"totals\", {}).get(\"ending_credit\")}')
|
||
"
|
||
echo ""
|
||
|
||
echo "[8] 检查资产负债表与利润表"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/reports/balance-sheet/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' balance_sheet balanced = {d.get(\"balanced\")} 资产总计 = {d.get(\"asset_total\")} 负债及权益 = {d.get(\"total_liabilities_and_equity\")}')
|
||
"
|
||
curl -s -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT" $BASE/api/v1/finance/reports/income-statement/ | python3 -c "
|
||
import sys, json
|
||
d = json.load(sys.stdin)
|
||
print(f' income_statement 收入 = {d.get(\"total_revenue\")} 成本 = {d.get(\"cogs\")} 毛利 = {d.get(\"gross_profit\")} 净利润 = {d.get(\"net_profit\")}')
|
||
"
|
||
echo ""
|
||
|
||
echo "===== 全部通过 ====="
|