feat(settlement): 门店未出账手动提现与总部审核(OPT-010)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 15:32:01 +08:00
parent 666bcb8633
commit f3353bbce5
29 changed files with 1733 additions and 15 deletions
+79 -10
View File
@@ -135,38 +135,107 @@ async function main() {
'/shop/auth/login/sms',
'/shop/auth/sms/send',
);
const shopMe = await req('SHOP_H5', '/shop/auth/me', { token: shopLogin.accessToken });
let shopToken = shopLogin.accessToken;
let shopMe = await req('SHOP_H5', '/shop/auth/me', { token: shopToken });
if (!shopMe?.phone) throw new Error('Shop /shop/auth/me failed');
const refreshed = await req('SHOP_H5', '/shop/auth/token/refresh', {
method: 'POST',
body: JSON.stringify({ refreshToken: shopLogin.refreshToken }),
});
if (!refreshed?.accessToken) throw new Error('Shop token refresh failed');
shopToken = refreshed.accessToken;
shopMe = await req('SHOP_H5', '/shop/auth/me', { token: shopToken });
if (!shopMe.storeId && shopMe.stores?.[0]?.storeId) {
const selected = await req('SHOP_H5', '/shop/auth/select-store', {
method: 'POST',
token: shopToken,
body: JSON.stringify({ storeId: shopMe.stores[0].storeId }),
});
shopToken = selected.accessToken || shopToken;
shopMe = await req('SHOP_H5', '/shop/auth/me', { token: shopToken });
}
if (!shopMe.storeId) throw new Error('Shop storeId missing after select-store');
const preview = await req('SHOP_H5', '/shop/redeem/preview', {
method: 'POST',
token: shopLogin.accessToken,
token: shopToken,
body: JSON.stringify({ token: directToken.token }),
});
if (!preview.amount) throw new Error('Redeem preview failed');
await req('SHOP_H5', '/shop/redeem/confirm', {
method: 'POST',
token: shopLogin.accessToken,
token: shopToken,
body: JSON.stringify({ token: directToken.token }),
});
console.log('9. Admin login + store payout');
console.log('9. Store withdraw (OPT-010)');
const admin = await adminLogin();
const payouts = await req('HQ_WEB', '/admin/store-payouts?status=PENDING', {
token: admin.accessToken,
const shopStoreId = shopMe.storeId || shopMe.stores?.[0]?.storeId;
if (!shopStoreId) throw new Error('Shop storeId missing after login');
const noWhitelistMsg = await expectFail('SHOP_H5', '/shop/withdraw', {
method: 'POST',
token: shopToken,
body: JSON.stringify({}),
});
if (!payouts.items?.length) throw new Error('Expected pending store payout');
const payoutId = payouts.items[0].id;
await req('HQ_WEB', `/admin/store-payouts/${payoutId}/confirm`, {
if (!String(noWhitelistMsg).includes('白名单')) {
throw new Error(`Expected FIN-001 whitelist reject, got: ${noWhitelistMsg}`);
}
await req('HQ_WEB', `/admin/stores/${shopStoreId}`, {
method: 'PUT',
token: admin.accessToken,
body: JSON.stringify({ withdrawWhitelistEnabled: true }),
});
const withdrawSummary = await req('SHOP_H5', '/shop/withdraw/summary', {
token: shopToken,
});
if (!(withdrawSummary.availableAmount > 0)) {
throw new Error('Expected available withdraw amount after redeem');
}
if (!withdrawSummary.whitelistEnabled) {
throw new Error('Expected withdraw whitelist enabled');
}
const applied = await req('SHOP_H5', '/shop/withdraw', {
method: 'POST',
token: shopToken,
body: JSON.stringify({}),
});
if (applied.status !== 'PENDING_REVIEW') {
throw new Error(`Expected PENDING_REVIEW withdraw, got ${applied.status}`);
}
const pendingDup = await expectFail('SHOP_H5', '/shop/withdraw', {
method: 'POST',
token: shopToken,
body: JSON.stringify({}),
});
if (!String(pendingDup).includes('待审核')) {
throw new Error(`Expected pending-request reject, got: ${pendingDup}`);
}
await req('HQ_WEB', `/admin/store-withdrawals/${applied.id}/approve`, {
method: 'POST',
token: admin.accessToken,
body: JSON.stringify({ remark: 'smoke confirm' }),
body: JSON.stringify({ paymentRef: 'smoke-withdraw' }),
});
const withdrawList = await req('SHOP_H5', '/shop/withdraw/requests?status=PAID', {
token: shopToken,
});
const settled = withdrawList.items?.find((w) => w.id === applied.id);
if (!settled || settled.status !== 'PAID') {
throw new Error('Expected settled withdraw request on shop side');
}
const overdue = await req('HQ_WEB', '/admin/store-withdrawals/overdue-summary', {
token: admin.accessToken,
});
if (typeof overdue.pendingCount !== 'number') {
throw new Error('overdue-summary missing pendingCount');
}
console.log('10. Refund ticket flow');
const order2 = await req('USER_H5', '/trade/orders', {
method: 'POST',