fix: 部分收付累计释额并扩展结算 E2E 与 CI
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
lotterLaravel E2E / e2e-api (push) Has been cancelled

账期收付改为按累计已付同步 credit_ledger,修复多笔 partial_paid 与坏账核销重复释额;新增 API E2E(占成、权限、部分收付/坏账)与 GitHub Actions e2e-api job。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-22 09:48:01 +08:00
parent 6ec9634704
commit 3f29229499
23 changed files with 1251 additions and 111 deletions

View File

@@ -359,62 +359,89 @@ final class PlayerCreditService
]);
}
public function releaseFromSettlement(Player $player, int $amountMinor, int $billId): void
/**
* @param int $cumulativePaidMinor 账单累计已登记收付minor支持部分收付多笔递增。
*/
public function releaseFromSettlement(Player $player, int $cumulativePaidMinor, int $billId): void
{
if ($amountMinor <= 0 || ! PlayerFundingMode::usesCredit($player)) {
if ($cumulativePaidMinor <= 0 || ! PlayerFundingMode::usesCredit($player)) {
return;
}
// 幂等闸门credit_ledger (settlement_bill, settlement_confirm) 唯一;重复调用直接返回。
try {
DB::table('credit_ledger')->insert([
'owner_type' => 'player',
'owner_id' => $player->id,
'amount' => $amountMinor,
'reason' => 'settlement_confirm',
'ref_type' => 'settlement_bill',
'ref_id' => $billId,
'created_at' => now(),
'updated_at' => now(),
]);
} catch (QueryException $e) {
if ($this->isUniqueViolation($e)) {
return;
}
throw $e;
$delta = $this->syncSettlementBillLedger(
$player,
$billId,
'settlement_confirm',
$cumulativePaidMinor,
);
if ($delta > 0) {
$this->decreaseUsedCredit($player, $delta);
}
$this->decreaseUsedCredit($player, $amountMinor);
}
public function applySettlementPayout(Player $player, int $amountMinor, int $billId): void
/**
* @param int $cumulativePaidMinor 账单累计已登记收付minor支持部分收付多笔递增。
*/
public function applySettlementPayout(Player $player, int $cumulativePaidMinor, int $billId): void
{
if ($amountMinor <= 0) {
if ($cumulativePaidMinor <= 0 || ! PlayerFundingMode::usesCredit($player)) {
return;
}
if (! PlayerFundingMode::usesCredit($player)) {
return;
$this->syncSettlementBillLedger(
$player,
$billId,
'settlement_payout',
$cumulativePaidMinor,
);
}
/**
* 同步账期收付台账:每账单每种 reason 仅一行amount 为累计已付;返回本次应追加的 minor 增量。
*/
private function syncSettlementBillLedger(
Player $player,
int $billId,
string $reason,
int $cumulativeMinor,
): int {
$existing = DB::table('credit_ledger')
->where('owner_type', 'player')
->where('owner_id', $player->id)
->where('reason', $reason)
->where('ref_type', 'settlement_bill')
->where('ref_id', $billId)
->lockForUpdate()
->first();
$recorded = $existing !== null ? (int) $existing->amount : 0;
$delta = $cumulativeMinor - $recorded;
if ($delta <= 0) {
return 0;
}
// 幂等闸门credit_ledger (settlement_bill, settlement_payout) 唯一;重复入账直接返回。
try {
$now = now();
if ($existing === null) {
DB::table('credit_ledger')->insert([
'owner_type' => 'player',
'owner_id' => $player->id,
'amount' => $amountMinor,
'reason' => 'settlement_payout',
'amount' => $cumulativeMinor,
'reason' => $reason,
'ref_type' => 'settlement_bill',
'ref_id' => $billId,
'created_at' => now(),
'updated_at' => now(),
'created_at' => $now,
'updated_at' => $now,
]);
} catch (QueryException $e) {
if ($this->isUniqueViolation($e)) {
return;
}
throw $e;
} else {
DB::table('credit_ledger')
->where('id', (int) $existing->id)
->update([
'amount' => $cumulativeMinor,
'updated_at' => $now,
]);
}
return $delta;
}
private function decreaseUsedCredit(Player $player, int $amountMinor): void