From c27cfabd2292e7f387a17ce3a7594698fe20e2c7 Mon Sep 17 00:00:00 2001 From: adonis Date: Sun, 30 Aug 2026 20:47:26 +0330 Subject: [PATCH] added some feature for accounting --- .../Controllers/Admin/TahesabController.php | 49 ++++++++++++ app/Services/TahesabInboundWalletService.php | 78 +++++++++++++++++++ routes/admin.php | 1 + 3 files changed, 128 insertions(+) diff --git a/app/Http/Controllers/Admin/TahesabController.php b/app/Http/Controllers/Admin/TahesabController.php index 2a960f1..9ab03a6 100644 --- a/app/Http/Controllers/Admin/TahesabController.php +++ b/app/Http/Controllers/Admin/TahesabController.php @@ -874,6 +874,55 @@ class TahesabController extends Controller ]); } + /** + * لیست مشتریان لینک‌شده با مقایسهٔ کیف و ماندهٔ ته‌حساب. + */ + public function walletLinkedList(Request $request): \Illuminate\Http\JsonResponse + { + if (! app(ConfigService::class)->isTahesabAccounting()) { + return response()->json([ + 'ok' => false, + 'message' => 'حسابداری ته‌حساب فعال نیست', + ], 422); + } + + $search = trim((string) $request->input('search', '')); + $page = max(1, (int) $request->input('page', 1)); + $perPage = max(1, min(50, (int) $request->input('per_page', 20))); + + $base = Customer::query() + ->whereNull('deleted_at') + ->whereNotNull('moshtari_code') + ->where('moshtari_code', '!=', '') + ->where('moshtari_code', '!=', '0'); + + if ($search !== '') { + $base->where(function ($q) use ($search) { + $q->where('name', 'like', '%'.$search.'%') + ->orWhere('mobile', 'like', '%'.$search.'%') + ->orWhere('moshtari_code', 'like', '%'.$search.'%'); + }); + } + + $total = (clone $base)->count(); + $customers = (clone $base) + ->orderBy('id') + ->offset(($page - 1) * $perPage) + ->limit($perPage) + ->get(['id', 'name', 'mobile', 'moshtari_code', 'type']); + + $rows = app(TahesabInboundWalletService::class)->compareCustomers($customers); + + return response()->json([ + 'ok' => true, + 'total' => $total, + 'page' => $page, + 'per_page' => $perPage, + 'last_page' => max(1, (int) ceil($total / max(1, $perPage))), + 'rows' => $rows, + ]); + } + private function tahesabApiUrl(): string { $host = trim((string) $this->Config('tahesab_host')); diff --git a/app/Services/TahesabInboundWalletService.php b/app/Services/TahesabInboundWalletService.php index a9511d2..878bb86 100644 --- a/app/Services/TahesabInboundWalletService.php +++ b/app/Services/TahesabInboundWalletService.php @@ -234,6 +234,84 @@ class TahesabInboundWalletService return $this->parseMandeRow($row); } + /** + * مقایسهٔ کیف اپ با ماندهٔ ته‌حساب برای لیست ادمین — بدون نوشتن. + * + * @param iterable $customers + * @return list> + */ + public function compareCustomers(iterable $customers): array + { + $list = []; + foreach ($customers as $customer) { + if ($customer instanceof Customer) { + $list[] = $customer; + } + } + if ($list === []) { + return []; + } + + $codes = []; + foreach ($list as $customer) { + $code = (int) ($customer->moshtari_code ?? 0); + if ($code > 0) { + $codes[] = $code; + } + } + $mandes = $this->fetchMandeByCodes($codes); + + $rows = []; + foreach ($list as $customer) { + $code = (int) ($customer->moshtari_code ?? 0); + $mande = $code > 0 ? ($mandes[(string) $code] ?? null) : null; + $base = [ + 'id' => (int) $customer->id, + 'name' => (string) ($customer->name ?? ''), + 'mobile' => (string) ($customer->mobile ?? ''), + 'moshtari_code' => $code > 0 ? $code : null, + ]; + if ($mande === null) { + $ownerType = (int) ($customer->type ?? 2); + $wallet = (new WalletInterface((int) $customer->id, $ownerType))->wallet; + $appGold = $this->walletBalance + ->accountingVisibleMainWalletGold((int) $customer->id, $ownerType); + $appCash = (float) ($wallet->cash ?? 0); + $rows[] = array_merge($base, [ + 'app_gold' => $appGold, + 'app_cash' => $appCash, + 'tahesab_gold' => null, + 'tahesab_cash' => null, + 'gold_delta' => null, + 'rial_delta' => null, + 'status' => 'missing', + 'message' => 'مانده از ته‌حساب دریافت نشد', + ]); + continue; + } + + $compared = $this->compareWithWallet($customer, $mande); + $same = $compared['gold_same'] && $compared['rial_same']; + $status = 'conflict'; + if ($same) { + $status = 'same'; + } elseif (! $compared['app_has_balance']) { + $status = 'ready'; + } + + $rows[] = array_merge($base, $compared['comparison'], [ + 'status' => $status, + 'message' => $same + ? 'مانده با ته‌حساب یکسان است' + : ($status === 'ready' + ? 'کیف خالی است؛ همگام‌سازی مانده ته‌حساب را می‌نشاند' + : 'موجودی اپ با ته‌حساب فرق دارد'), + ]); + } + + return $rows; + } + /** * @param array{gold?: float, cash?: float} $mande * @return array{ diff --git a/routes/admin.php b/routes/admin.php index f51c882..0f00a0e 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -254,6 +254,7 @@ Route::middleware('auth:user')->group(function (){ Route::post('tahesab/customer-sync/rollback-import', [TahesabController::class, 'rollbackImport']); Route::post('tahesab/mande-by-codes', [TahesabController::class, 'mandeByCodes']); Route::post('tahesab/wallet-sync/all', [TahesabController::class, 'syncAllWallets']); + Route::get('tahesab/wallet-sync/list', [TahesabController::class, 'walletLinkedList']); Route::get('tahesab/{id}', [TahesabController::class, 'show']); Route::post('tahesab/{id}/retry', [TahesabController::class, 'retrySanad']); Route::post('customer/{id}/tahesab/register', [TahesabController::class, 'registerCustomer']);