feat(tahesab): pump pending documents slowly from admin, not schedule
Send leftover orders and charges one-by-one with a gap so Tahesab is not rate-limited, skip already-synced rows, and expose start/stop plus progress on existing status APIs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -233,9 +233,75 @@ class TahesabSyncService
|
||||
'missing_withdraws' => $missingWithdraws,
|
||||
'missing_orders' => $missingOrders,
|
||||
'total' => $failedRows + $missingWithdraws + $missingOrders,
|
||||
'doc_sync' => app(TahesabDocSyncService::class)->snapshot(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* تعداد واقعی جاافتادهها بدون سقف ۲۰۰ — برای جاب ارسال همه.
|
||||
*
|
||||
* @return array{failed_rows:int,missing_withdraws:int,missing_orders:int,total:int}
|
||||
*/
|
||||
public function pendingTotals(?int $customerId = null): array
|
||||
{
|
||||
$failedRows = (int) $this->unsyncedRowsQuery()
|
||||
->when($customerId, fn ($q) => $q->where('customer_id', $customerId))
|
||||
->count();
|
||||
$missingWithdraws = $this->countMissingWithdraws($customerId);
|
||||
$missingOrders = $this->countMissingOrders($customerId);
|
||||
|
||||
return [
|
||||
'failed_rows' => $failedRows,
|
||||
'missing_withdraws' => $missingWithdraws,
|
||||
'missing_orders' => $missingOrders,
|
||||
'total' => $failedRows + $missingWithdraws + $missingOrders,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{row?:list<int>,withdraw?:list<int>,order?:list<int>} $skip
|
||||
* @return array{type:string,id:int,label:string}|null
|
||||
*/
|
||||
public function peekNextPending(array $skip = []): ?array
|
||||
{
|
||||
$skipRow = array_values(array_filter($skip['row'] ?? []));
|
||||
$row = $this->unsyncedRowsQuery()
|
||||
->when($skipRow !== [], fn ($q) => $q->whereNotIn('id', $skipRow))
|
||||
->orderBy('id')
|
||||
->first();
|
||||
if ($row) {
|
||||
return [
|
||||
'type' => 'row',
|
||||
'id' => (int) $row->id,
|
||||
'label' => 'سند محلی #'.$row->id,
|
||||
];
|
||||
}
|
||||
|
||||
$wIds = $this->missingWithdrawIds(1, null, array_values(array_filter($skip['withdraw'] ?? [])));
|
||||
if ($wIds !== []) {
|
||||
$id = (int) $wIds[0];
|
||||
|
||||
return [
|
||||
'type' => 'withdraw',
|
||||
'id' => $id,
|
||||
'label' => 'شارژ/برداشت #'.$id,
|
||||
];
|
||||
}
|
||||
|
||||
$oIds = $this->missingOrderIds(1, null, array_values(array_filter($skip['order'] ?? [])));
|
||||
if ($oIds !== []) {
|
||||
$id = (int) $oIds[0];
|
||||
|
||||
return [
|
||||
'type' => 'order',
|
||||
'id' => $id,
|
||||
'label' => 'سفارش #'.$id,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* لیست یکپارچهٔ خطا خورده + جاافتاده برای تب ادمین.
|
||||
*
|
||||
@@ -466,17 +532,33 @@ class TahesabSyncService
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
private function missingWithdrawIds(int $limit, ?int $customerId = null): array
|
||||
private function missingWithdrawIds(int $limit, ?int $customerId = null, array $exclude = []): array
|
||||
{
|
||||
if ($limit <= 0 || ! Schema::hasTable('withdraws')) {
|
||||
$query = $this->missingWithdrawQuery($customerId, $exclude);
|
||||
if ($query === null || $limit <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$linked = Tahesab::query()
|
||||
->whereNotNull('withdraw_id')
|
||||
->when($customerId, fn ($q) => $q->where('customer_id', $customerId))
|
||||
->pluck('withdraw_id')
|
||||
return $query
|
||||
->orderBy('id')
|
||||
->limit($limit)
|
||||
->pluck('id')
|
||||
->map(fn ($id) => (int) $id)
|
||||
->all();
|
||||
}
|
||||
|
||||
public function countMissingWithdraws(?int $customerId = null): int
|
||||
{
|
||||
$query = $this->missingWithdrawQuery($customerId);
|
||||
|
||||
return $query ? (int) $query->count() : 0;
|
||||
}
|
||||
|
||||
private function missingWithdrawQuery(?int $customerId = null, array $exclude = [])
|
||||
{
|
||||
if (! Schema::hasTable('withdraws')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \App\Models\Withdraw::query()
|
||||
->where('sts', 4)
|
||||
@@ -488,7 +570,21 @@ class TahesabSyncService
|
||||
->orWhere('note', 'not like', 'fix:intval-gold-loss%');
|
||||
})
|
||||
->when($customerId, fn ($q) => $q->where('customer_id', $customerId))
|
||||
->when($linked !== [], fn ($q) => $q->whereNotIn('id', $linked))
|
||||
->when($exclude !== [], fn ($q) => $q->whereNotIn('id', $exclude))
|
||||
->whereNotExists(function ($sub) {
|
||||
$sub->from('tahesab')->selectRaw('1')->whereColumn('tahesab.withdraw_id', 'withdraws.id');
|
||||
});
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
private function missingOrderIds(int $limit, ?int $customerId = null, array $exclude = []): array
|
||||
{
|
||||
$query = $this->missingOrderQuery($customerId, $exclude);
|
||||
if ($query === null || $limit <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $query
|
||||
->orderBy('id')
|
||||
->limit($limit)
|
||||
->pluck('id')
|
||||
@@ -496,30 +592,28 @@ class TahesabSyncService
|
||||
->all();
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
private function missingOrderIds(int $limit, ?int $customerId = null): array
|
||||
public function countMissingOrders(?int $customerId = null): int
|
||||
{
|
||||
if ($limit <= 0 || ! Schema::hasTable('orders')) {
|
||||
return [];
|
||||
}
|
||||
$query = $this->missingOrderQuery($customerId);
|
||||
|
||||
$linked = Tahesab::query()
|
||||
->whereNotNull('order_id')
|
||||
->when($customerId, fn ($q) => $q->where('customer_id', $customerId))
|
||||
->pluck('order_id')
|
||||
->all();
|
||||
return $query ? (int) $query->count() : 0;
|
||||
}
|
||||
|
||||
private function missingOrderQuery(?int $customerId = null, array $exclude = [])
|
||||
{
|
||||
if (! Schema::hasTable('orders')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \App\Models\Order::query()
|
||||
->where('sts', 2)
|
||||
->where('payment_sts', 4)
|
||||
->whereIn('direction', [1, 2])
|
||||
->when($customerId, fn ($q) => $q->where('customer_id', $customerId))
|
||||
->when($linked !== [], fn ($q) => $q->whereNotIn('id', $linked))
|
||||
->orderBy('id')
|
||||
->limit($limit)
|
||||
->pluck('id')
|
||||
->map(fn ($id) => (int) $id)
|
||||
->all();
|
||||
->when($exclude !== [], fn ($q) => $q->whereNotIn('id', $exclude))
|
||||
->whereNotExists(function ($sub) {
|
||||
$sub->from('tahesab')->selectRaw('1')->whereColumn('tahesab.order_id', 'orders.id');
|
||||
});
|
||||
}
|
||||
|
||||
private function backfillWithdraw(TahesabController $controller, int $withdrawId): bool
|
||||
|
||||
Reference in New Issue
Block a user