P2-2部署尝试+compose通配符修复 / D2收尾(唯一单号+前后断言+H5回归17过) / P2-1 StorefrontAdmin真分页 / 后端511+PG4
This commit is contained in:
@@ -228,18 +228,30 @@ async def my_orders(request):
|
||||
|
||||
@api_view(["GET"])
|
||||
async def admin_orders(request):
|
||||
"""内部:商城订单列表(默认只看待确认)。"""
|
||||
"""内部:商城订单列表(默认只看待确认,支持 page/page_size 分页)。"""
|
||||
tenant = await _tenant(request)
|
||||
status_filter = request.query_params.get("status", "submitted")
|
||||
try:
|
||||
page = max(int(request.query_params.get("page", 1)), 1)
|
||||
except (TypeError, ValueError):
|
||||
page = 1
|
||||
try:
|
||||
page_size = int(request.query_params.get("page_size", 20))
|
||||
except (TypeError, ValueError):
|
||||
page_size = 20
|
||||
page_size = min(max(page_size, 1), 200)
|
||||
|
||||
def _list():
|
||||
qs = StorefrontOrder.objects.filter(tenant=tenant).select_related("customer")
|
||||
if status_filter and status_filter != "all":
|
||||
qs = qs.filter(status=status_filter)
|
||||
return list(qs.prefetch_related("lines__product").order_by("-created_at")[:100])
|
||||
total = qs.count()
|
||||
rows = list(qs.prefetch_related("lines__product")
|
||||
.order_by("-created_at")[(page - 1) * page_size:page * page_size])
|
||||
return total, rows
|
||||
|
||||
orders = await sync_to_async(_list)()
|
||||
return Response({"results": [
|
||||
total, orders = await sync_to_async(_list)()
|
||||
return Response({"count": total, "results": [
|
||||
{
|
||||
"id": o.id, "order_no": o.order_no, "status": o.status,
|
||||
"status_name": o.get_status_display(),
|
||||
|
||||
@@ -8,7 +8,8 @@ services:
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: config.settings.prod
|
||||
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:?required}
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
# 生产禁通配符:显式域名由部署者传入,与 prod.py 的空值/通配符双门禁一致
|
||||
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:?required}
|
||||
DATABASE_URL: postgres://dealerhub:${POSTGRES_PASSWORD}@pg-main:5432/dealerhub
|
||||
REDIS_URL: redis://dsp-redis:6379/2
|
||||
GRANIAN_WORKERS: "4"
|
||||
@@ -32,7 +33,7 @@ services:
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: config.settings.prod
|
||||
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:?required}
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:?required}
|
||||
DATABASE_URL: postgres://dealerhub:${POSTGRES_PASSWORD}@pg-main:5432/dealerhub
|
||||
REDIS_URL: redis://dsp-redis:6379/2
|
||||
TASK_BROKER: redis
|
||||
|
||||
@@ -13,6 +13,12 @@ import urllib.request
|
||||
BASE = "http://127.0.0.1:18099"
|
||||
PAGE = "http://127.0.0.1:15173/static/#/salesman"
|
||||
|
||||
# D2收尾:残留隔离 —— 每次运行用时间戳唯一收款单号 + 前后计数断言,
|
||||
# 不再依赖固定 SMH50002(重复跑会撞唯一约束),且不删单(过账有副作用)。
|
||||
import time as _time
|
||||
RUN_TAG = _time.strftime("%m%d%H%M%S")
|
||||
RECEIPT_NO = f"SMH{ RUN_TAG }"
|
||||
|
||||
|
||||
def api(method, path, token=None, tenant="default", body=None):
|
||||
req = urllib.request.Request(
|
||||
@@ -47,6 +53,15 @@ async def main():
|
||||
s, custs = api("GET", "/api/v1/partner/customers/?page_size=200",
|
||||
token=token)
|
||||
assert s == 200 and custs["count"] >= 1, f"customers: {s}"
|
||||
# 前后计数基线:验证前后差值断言(残留隔离,不删单)
|
||||
s, _b0 = api("GET", "/api/v1/sales/bills/?page_size=1", token=token)
|
||||
assert s == 200, f"bills baseline: {s}"
|
||||
bills_before = _b0["count"]
|
||||
s, _r0 = api("GET", "/api/v1/finance/receipts/?page_size=1", token=token)
|
||||
assert s == 200, f"receipts baseline: {s}"
|
||||
receipts_before = _r0["count"]
|
||||
print(f"[pre] baseline bills={bills_before} receipts={receipts_before} "
|
||||
f"run_tag={RUN_TAG} receipt_no={RECEIPT_NO}")
|
||||
s, whs = api("GET", "/api/v1/inventory/warehouses/?page_size=200",
|
||||
token=token)
|
||||
assert s == 200 and whs["count"] >= 1, f"warehouses: {s}"
|
||||
@@ -162,7 +177,7 @@ async def main():
|
||||
# 关掉可能残留的下拉浮层后再填单号(Esc 关闭 popper)
|
||||
await page.keyboard.press("Escape")
|
||||
await page.wait_for_timeout(400)
|
||||
bill_no = "SMH50002"
|
||||
bill_no = RECEIPT_NO
|
||||
await page.locator("#pane-receipt input[placeholder]").nth(0).scroll_into_view_if_needed()
|
||||
await page.locator("#pane-receipt input[placeholder]").nth(0).fill(bill_no)
|
||||
amt_input = page.locator("#pane-receipt .el-input-number input")
|
||||
@@ -187,12 +202,21 @@ async def main():
|
||||
assert latest and latest["state"] == "confirmed", \
|
||||
f"expected confirmed bill, got {latest}"
|
||||
|
||||
s, found = api("GET", "/api/v1/finance/receipts/?page_size=50&search=SMH50002",
|
||||
s, found = api("GET", f"/api/v1/finance/receipts/?page_size=50&search={RECEIPT_NO}",
|
||||
token=token)
|
||||
assert s == 200, f"receipts: {s}"
|
||||
hit = [r for r in found["results"] if r["bill_no"] == "SMH50002"]
|
||||
assert hit, f"receipt SMH50002 not found: {[r['bill_no'] for r in found['results'][:5]]}"
|
||||
print(f"[9] receipt SMH50002 ok amount={hit[0]['amount']}")
|
||||
hit = [r for r in found["results"] if r["bill_no"] == RECEIPT_NO]
|
||||
assert hit, f"receipt {RECEIPT_NO} not found: {[r['bill_no'] for r in found['results'][:5]]}"
|
||||
print(f"[9] receipt {RECEIPT_NO} ok amount={hit[0]['amount']}")
|
||||
# 残留隔离断言:本次恰好新增 1 单 + 1 收款(可重复跑,不删单)
|
||||
s, _b1 = api("GET", "/api/v1/sales/bills/?page_size=1", token=token)
|
||||
assert s == 200 and _b1["count"] == bills_before + 1, \
|
||||
f"bills delta: before={bills_before} after={_b1['count']}"
|
||||
s, _r1 = api("GET", "/api/v1/finance/receipts/?page_size=1", token=token)
|
||||
assert s == 200 and _r1["count"] == receipts_before + 1, \
|
||||
f"receipts delta: before={receipts_before} after={_r1['count']}"
|
||||
print(f"[9b] delta ok: bills {bills_before}->{_b1['count']}, "
|
||||
f"receipts {receipts_before}->{_r1['count']}")
|
||||
|
||||
s, debts = api("GET", "/api/v1/finance/receivables/?page_size=50",
|
||||
token=token)
|
||||
|
||||
@@ -389,6 +389,37 @@ def test_admin_orders_list_default_submitted(db, auth_client, pro_plan, tenant,
|
||||
assert orders[0]["id"] == o1.id
|
||||
|
||||
|
||||
def test_admin_orders_pagination(db, auth_client, pro_plan, tenant, account,
|
||||
products, granted, warehouse):
|
||||
"""P2-1:admin_orders 支持 page/page_size 翻页,count 为过滤后总数。"""
|
||||
ids = []
|
||||
for _ in range(3):
|
||||
o = sf_services.submit_order(
|
||||
account.customer,
|
||||
lines=[{"product_id": products["P001"].id, "quantity": 1}],
|
||||
)
|
||||
ids.append(o.id)
|
||||
p1 = auth_client.get(
|
||||
"/api/v1/storefront/admin/orders/",
|
||||
{"status": "submitted", "page": 1, "page_size": 2},
|
||||
)
|
||||
assert p1.status_code == 200, p1.content
|
||||
b1 = p1.json()
|
||||
assert b1["count"] == 3
|
||||
assert len(b1["results"]) == 2
|
||||
p2 = auth_client.get(
|
||||
"/api/v1/storefront/admin/orders/",
|
||||
{"status": "submitted", "page": 2, "page_size": 2},
|
||||
)
|
||||
assert p2.status_code == 200, p2.content
|
||||
b2 = p2.json()
|
||||
assert b2["count"] == 3
|
||||
assert len(b2["results"]) == 1
|
||||
# 两页无重叠
|
||||
got = {r["id"] for r in b1["results"]} | {r["id"] for r in b2["results"]}
|
||||
assert got == set(ids)
|
||||
|
||||
|
||||
def test_admin_confirm_twice_rejected(db, auth_client, pro_plan, tenant, account,
|
||||
products, granted, warehouse):
|
||||
order = sf_services.submit_order(
|
||||
|
||||
Reference in New Issue
Block a user