feat(M08-B): 补保洁结算发放记录
This commit is contained in:
@@ -122,6 +122,26 @@ const app = await buildApp({
|
||||
calls.push(['confirmSettlement', input]);
|
||||
return settlementResponse('CONFIRMED');
|
||||
},
|
||||
async markSettlementPaid(input) {
|
||||
calls.push(['markSettlementPaid', input]);
|
||||
return {
|
||||
...settlementResponse('PAID'),
|
||||
paidBy: input.userId,
|
||||
paidAt: new Date(),
|
||||
payoutChannel: input.payoutChannel,
|
||||
payoutReference: input.payoutReference,
|
||||
payoutError: ''
|
||||
};
|
||||
},
|
||||
async recordSettlementPayoutFailure(input) {
|
||||
calls.push(['recordSettlementPayoutFailure', input]);
|
||||
return {
|
||||
...settlementResponse('CONFIRMED'),
|
||||
payoutChannel: input.payoutChannel || '',
|
||||
payoutReference: input.payoutReference || '',
|
||||
payoutError: input.error
|
||||
};
|
||||
},
|
||||
async reclaimTimeouts(input) {
|
||||
calls.push(['reclaimTimeouts', input]);
|
||||
return { reclaimed: 2, taskIds: ['101', '102'] };
|
||||
@@ -322,6 +342,37 @@ assert.equal(confirmedSettlement.statusCode, 200);
|
||||
assert.equal(calls.at(-1)[0], 'confirmSettlement');
|
||||
assert.equal(calls.at(-1)[1].settlementId, '501');
|
||||
|
||||
const failedPayout = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin-api/cleaning/settlements/501/payout-failure',
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
payload: {
|
||||
payoutChannel: 'WECHAT_TRANSFER',
|
||||
payoutReference: 'wx-failed-001',
|
||||
error: 'insufficient merchant balance',
|
||||
note: 'retry later'
|
||||
}
|
||||
});
|
||||
assert.equal(failedPayout.statusCode, 200);
|
||||
assert.equal(calls.at(-1)[0], 'recordSettlementPayoutFailure');
|
||||
assert.equal(calls.at(-1)[1].settlementId, '501');
|
||||
assert.equal(calls.at(-1)[1].error, 'insufficient merchant balance');
|
||||
|
||||
const paidSettlement = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin-api/cleaning/settlements/501/paid',
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
payload: {
|
||||
payoutChannel: 'WECHAT_TRANSFER',
|
||||
payoutReference: 'wx-paid-001',
|
||||
note: 'paid'
|
||||
}
|
||||
});
|
||||
assert.equal(paidSettlement.statusCode, 200);
|
||||
assert.equal(paidSettlement.json().data.status, 'PAID');
|
||||
assert.equal(paidSettlement.json().data.payoutReference, 'wx-paid-001');
|
||||
assert.equal(calls.at(-1)[0], 'markSettlementPaid');
|
||||
|
||||
const reclaimed = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin-api/cleaning/reclaim-timeouts',
|
||||
@@ -383,8 +434,12 @@ function settlementResponse(status) {
|
||||
totalRewardCents: 1200,
|
||||
periodStart: new Date(),
|
||||
periodEnd: new Date(),
|
||||
paidBy: status === 'PAID' ? '31' : null,
|
||||
confirmedAt: status === 'CONFIRMED' ? new Date() : null,
|
||||
paidAt: null,
|
||||
paidAt: status === 'PAID' ? new Date() : null,
|
||||
payoutChannel: '',
|
||||
payoutReference: '',
|
||||
payoutError: '',
|
||||
note: ''
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ const cleaningSettlementVerifySql = read('database/migrations/2026062626_m08b_cl
|
||||
const cleaningCollaborationUpSql = read('database/migrations/2026062627_m08b_cleaning_collaboration.up.sql');
|
||||
const cleaningCollaborationDownSql = read('database/migrations/2026062627_m08b_cleaning_collaboration.down.sql');
|
||||
const cleaningCollaborationVerifySql = read('database/migrations/2026062627_m08b_cleaning_collaboration.verify.sql');
|
||||
const cleaningPayoutUpSql = read('database/migrations/2026062728_m08b_cleaning_payouts.up.sql');
|
||||
const cleaningPayoutDownSql = read('database/migrations/2026062728_m08b_cleaning_payouts.down.sql');
|
||||
const cleaningPayoutVerifySql = read('database/migrations/2026062728_m08b_cleaning_payouts.verify.sql');
|
||||
|
||||
const coreTables = [
|
||||
'qipai_schema_migrations',
|
||||
@@ -426,4 +429,15 @@ assert.match(cleaningCollaborationDownSql, /ADD UNIQUE KEY uq_qipai_cleaning_set
|
||||
assert.match(cleaningCollaborationVerifySql, /'qipai_cleaning_task_members'/);
|
||||
assert.match(cleaningCollaborationVerifySql, /'cleaner_user_id'/);
|
||||
|
||||
assert.match(cleaningPayoutUpSql, /ADD COLUMN paid_by BIGINT UNSIGNED NULL/);
|
||||
assert.match(cleaningPayoutUpSql, /ADD COLUMN payout_channel VARCHAR\(32\) NOT NULL DEFAULT ''/);
|
||||
assert.match(cleaningPayoutUpSql, /ADD COLUMN payout_reference VARCHAR\(128\) NOT NULL DEFAULT ''/);
|
||||
assert.match(cleaningPayoutUpSql, /ADD COLUMN payout_error VARCHAR\(512\) NOT NULL DEFAULT ''/);
|
||||
assert.match(cleaningPayoutUpSql, /fk_qipai_cleaning_settlements_paid_by/);
|
||||
assert.match(cleaningPayoutUpSql, /idx_qipai_cleaning_settlement_payout/);
|
||||
assert.match(cleaningPayoutDownSql, /DROP FOREIGN KEY fk_qipai_cleaning_settlements_paid_by/);
|
||||
assert.match(cleaningPayoutDownSql, /DROP COLUMN payout_error/);
|
||||
assert.match(cleaningPayoutVerifySql, /'payout_reference'/);
|
||||
assert.match(cleaningPayoutVerifySql, /'2026062728'/);
|
||||
|
||||
console.log('PASS: M01-B through M08-B migration contracts are present.');
|
||||
|
||||
@@ -37,7 +37,8 @@ assert.match(plan.file, /2026062422_m07b_recharge_plans\.up\.sql/);
|
||||
assert.match(plan.file, /2026062524_m08a_recharge_wechat\.up\.sql/);
|
||||
assert.match(plan.file, /2026062525_m08b_cleaner_tasks\.up\.sql/);
|
||||
assert.match(plan.file, /2026062626_m08b_cleaning_settlements\.up\.sql/);
|
||||
assert.match(plan.file, /2026062627_m08b_cleaning_collaboration\.up\.sql$/);
|
||||
assert.match(plan.file, /2026062627_m08b_cleaning_collaboration\.up\.sql/);
|
||||
assert.match(plan.file, /2026062728_m08b_cleaning_payouts\.up\.sql$/);
|
||||
assert.match(plan.checksum, /^[a-f0-9]{64}$/);
|
||||
assert.ok(plan.statements.length >= 11);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user