perf(small-payment-work-orders): 筛选金额合计改为键集分块查询
- 只取金额所需字段,按 w.Id 键集分块批量读取,避免逐行游标造成的每行一次网络往返 - 抽出 PAYMENT_AMOUNT_FIELDS 常量,与行内金额解析共用,避免口径漂移 - 抽出 centsFromMoney/formatCents,去掉重复的金额累加逻辑
This commit is contained in:
parent
80bb67a14c
commit
9cca643a7e
@ -40,6 +40,9 @@ class SmallPaymentWorkOrderMirrorRepository
|
||||
|
||||
private const COMPLETED_WORK_ORDER_STATUSES = ['CONFIRMED', '已完成', '已确认'];
|
||||
|
||||
/** 打款金额在 businessFieldList 中的候选字段名(按优先级) */
|
||||
private const PAYMENT_AMOUNT_FIELDS = ['打款金额', '付款金额', '小额打款金额', 'amountField'];
|
||||
|
||||
private readonly ConnectionInterface $connection;
|
||||
|
||||
public function __construct(
|
||||
@ -177,18 +180,48 @@ class SmallPaymentWorkOrderMirrorRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计当前筛选条件下全部记录的打款金额合计。
|
||||
*
|
||||
* 只取金额所需字段,按 Id 做键集分块批量读取:不使用逐行游标(本地/远端库时每次取行都是一次网络往返),
|
||||
* 也不复用导出用的分页排序查询(会为大结果集重复执行连接与排序)。
|
||||
*
|
||||
* @param array{from:string,to:string,work_order_no:string,shop_name:string,transaction_no:string,online_order_no:string,status:string,payment_reason:string} $filters
|
||||
*/
|
||||
public function filteredPaymentAmount(array $filters): string
|
||||
public function filteredPaymentAmount(array $filters, int $chunkSize = 1000): string
|
||||
{
|
||||
$this->ensureReady();
|
||||
|
||||
$amounts = [];
|
||||
foreach ($this->exportRows($filters, 100) as $row) {
|
||||
$amounts[] = $row['payment_amount'] ?? null;
|
||||
}
|
||||
$query = $this->baseQuery();
|
||||
$this->applyFilters($query, $filters);
|
||||
|
||||
return $this->sumMoney($amounts);
|
||||
$chunkSize = min(max($chunkSize, 100), 5000);
|
||||
$cents = 0;
|
||||
$lastId = null;
|
||||
|
||||
do {
|
||||
$chunk = (clone $query)
|
||||
->select(['w.Id AS source_id', 'w.businessFieldList'])
|
||||
->when($lastId !== null, static fn (Builder $q): Builder => $q->where('w.Id', '>', $lastId))
|
||||
->orderBy('w.Id')
|
||||
->limit($chunkSize)
|
||||
->get();
|
||||
|
||||
foreach ($chunk as $row) {
|
||||
$cents += $this->centsFromMoney($this->paymentAmountOf($row->businessFieldList ?? null));
|
||||
}
|
||||
|
||||
$lastId = $chunk->isEmpty() ? null : $chunk->last()->source_id;
|
||||
} while ($chunk->count() === $chunkSize);
|
||||
|
||||
return $this->formatCents($cents);
|
||||
}
|
||||
|
||||
private function paymentAmountOf(mixed $businessFieldList): ?string
|
||||
{
|
||||
return $this->money($this->field(
|
||||
$this->businessFields($businessFieldList),
|
||||
self::PAYMENT_AMOUNT_FIELDS,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,9 +423,7 @@ class SmallPaymentWorkOrderMirrorRepository
|
||||
$row['alipay_batch_no'] = $this->field($fields, [
|
||||
'支付宝批次号', '支付宝打款批次号', '打款批次号', '批次号', 'alipayBatchNo', 'batchNo',
|
||||
]);
|
||||
$row['payment_amount'] = $this->money($this->field($fields, [
|
||||
'打款金额', '付款金额', '小额打款金额', 'amountField',
|
||||
]));
|
||||
$row['payment_amount'] = $this->money($this->field($fields, self::PAYMENT_AMOUNT_FIELDS));
|
||||
$row['online_order_no'] = $this->firstFilled(
|
||||
$this->field($fields, ['线上订单号', '线上单号', '订单号', 'orderField']),
|
||||
$row['mapped_online_order_no'] ?? null,
|
||||
@ -535,14 +566,26 @@ class SmallPaymentWorkOrderMirrorRepository
|
||||
{
|
||||
$cents = 0;
|
||||
foreach ($amounts as $amount) {
|
||||
if ($amount === null || ! preg_match('/^(-?)(\d+)\.(\d{2})$/', (string) $amount, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = ((int) $matches[2] * 100) + (int) $matches[3];
|
||||
$cents += $matches[1] === '-' ? -$value : $value;
|
||||
$cents += $this->centsFromMoney($amount);
|
||||
}
|
||||
|
||||
return $this->formatCents($cents);
|
||||
}
|
||||
|
||||
/** 将 '123.45' / '-123.45' 形式的金额字符串转成分(无效值计 0)。 */
|
||||
private function centsFromMoney(mixed $amount): int
|
||||
{
|
||||
if ($amount === null || ! preg_match('/^(-?)(\d+)\.(\d{2})$/', (string) $amount, $matches)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$value = ((int) $matches[2] * 100) + (int) $matches[3];
|
||||
|
||||
return $matches[1] === '-' ? -$value : $value;
|
||||
}
|
||||
|
||||
private function formatCents(int $cents): string
|
||||
{
|
||||
$sign = $cents < 0 ? '-' : '';
|
||||
$absolute = abs($cents);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user