From 7ac7bbdb9057c7d78bd5491237383c6c600b1f40 Mon Sep 17 00:00:00 2001 From: adonis Date: Sun, 5 Jul 2026 16:43:34 +0330 Subject: [PATCH] added pargar --- README.md | 10 +- .../Controllers/Admin/PargarController.php | 241 +++++++++++ .../Controllers/Admin/WalletController.php | 8 +- .../Controllers/Customer/CartController.php | 49 +++ .../Controllers/Customer/WalletController.php | 3 +- .../Pargar/PargarInboundController.php | 384 ++++++++++++++++++ .../Single/SingleOrderController.php | 10 +- app/Http/Kernel.php | 2 +- app/Http/Middleware/LogRequests.php | 66 --- app/Http/Middleware/PargarAuth.php | 59 +++ app/Models/Customer.php | 1 + app/Models/Pargar.php | 28 -- app/Models/PargarSyncLog.php | 36 ++ app/Observers/CustomerObserver.php | 3 + app/Providers/RouteServiceProvider.php | 11 +- app/Services/ConfigService.php | 32 ++ app/Services/PargarSyncService.php | 269 ++++++++++++ app/Services/ReferralGiftService.php | 4 +- app/Services/TahesabSyncService.php | 15 +- ...11_000001_add_store_tables_and_columns.php | 16 - ...drop_legacy_finance_request_logs_table.php | 16 + ...07_05_000002_create_pargar_integration.php | 59 +++ ...000003_add_accounting_provider_setting.php | 46 +++ database/sql/deploy_settings_const.sql | 55 ++- ...ngs_const_preserve_value_sync_can_edit.sql | 51 ++- routes/admin.php | 10 + routes/pargar.php | 350 +--------------- 27 files changed, 1341 insertions(+), 493 deletions(-) create mode 100644 app/Http/Controllers/Admin/PargarController.php create mode 100644 app/Http/Controllers/Pargar/PargarInboundController.php delete mode 100644 app/Http/Middleware/LogRequests.php create mode 100644 app/Http/Middleware/PargarAuth.php delete mode 100644 app/Models/Pargar.php create mode 100644 app/Models/PargarSyncLog.php create mode 100644 app/Services/PargarSyncService.php create mode 100644 database/migrations/2026_07_05_000001_drop_legacy_finance_request_logs_table.php create mode 100644 database/migrations/2026_07_05_000002_create_pargar_integration.php create mode 100644 database/migrations/2026_07_05_000003_add_accounting_provider_setting.php diff --git a/README.md b/README.md index 310ce59..bd53e66 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,6 @@ server/ │ ├── auth.php │ ├── admin.php │ ├── customer.php -│ ├── pargar.php # فقط is_store │ └── web.php ├── config/ │ ├── auth.php, jwt.php @@ -112,7 +111,6 @@ server/ | `/auth` | api + validation | `auth.php` | ورود | | `/admin` | api | `admin.php` | پنل مدیریت | | `/customer` | api | `customer.php` | اپ مشتری | -| `/pargar` | LogRequests | `pargar.php` | حسابداری (فقط `is_store`) | | `/` | web | `web.php` | views, cron | Rate limit: **60 req/min** روی `api`. @@ -177,10 +175,6 @@ Rate limit: **60 req/min** روی `api`. | Gift Card | `POST /customer/giftcard/use` | | Store | `POST /customer/havale`, `POST /customer/cart/checkout` | -### `/pargar` — حسابداری پرگار (فقط `is_store=true`) - -- webhookهای حسابداری، مشتری، سفارش، مانده - --- ## مدل‌ها و دامنه‌های کسب‌وکار @@ -195,7 +189,7 @@ Rate limit: **60 req/min** روی `api`. | کیف پول | `Wallet`, `Transaction` (Rooyesh) | | فروشگاه | `Cart`, `CartItem` | | کارت هدیه | `GiftCard`, `GiftCardCodes`, `OfferCode` | -| حسابداری | `Tahesab`, `Pargar`, `TransactionsAdmin` | +| حسابداری | `Tahesab`, `TransactionsAdmin` | | سیستم | `Setting`, `Cnt`, `Message`, `Log`, `File`, `City` | | Sync | `PriceSyncLog`, `PriceSyncLogItem` | @@ -232,7 +226,6 @@ Rate limit: **60 req/min** روی `api`. - `auth:user` / `auth:customer` — JWT - `validation` — rules از `config/validation.php` + تبدیل اعداد فارسی - `throttle:api` — 60 req/min -- `LogRequests` — لاگ Pargar --- @@ -273,7 +266,6 @@ packages/rooyesh/wallet/ | سرویس | کاربرد | |--------|--------| | **ته‌حساب** | حسابداری، مانده، اسناد | -| **پرگار** | sync مشتری/سفارش (store mode) | | **PayPing** | درگاه پرداخت | | **Montzar / Zaarbox** | منبع قیمت | | **Jibit** | احراز هویت ثبت‌نام | diff --git a/app/Http/Controllers/Admin/PargarController.php b/app/Http/Controllers/Admin/PargarController.php new file mode 100644 index 0000000..e80d5b8 --- /dev/null +++ b/app/Http/Controllers/Admin/PargarController.php @@ -0,0 +1,241 @@ +orderByDesc('id'); + \App\DB\Te\TableEngine::create($query, $request) + ->initSearch(['desc', 'type']) + ->select(['*']) + ->export($query); + + return response()->json($query); + } + + public function show($id) + { + return response()->json(PargarSyncLog::with('customer')->findOrFail($id)); + } + + public function customerSyncStatus(Request $request) + { + $panelTotal = Customer::whereNull('deleted_at')->count(); + $panelRegistered = Customer::whereNull('deleted_at')->whereNotNull('pargar_account_id')->count(); + $panelOnly = $panelTotal - $panelRegistered; + + $panelOnlyQuery = Customer::whereNull('deleted_at') + ->whereNull('pargar_account_id') + ->select('id', 'name', 'mobile', 'created_at'); + + if ($search = $request->input('search')) { + $panelOnlyQuery->where(function ($q) use ($search) { + $q->where('name', 'like', "%{$search}%") + ->orWhere('mobile', 'like', "%{$search}%"); + }); + } + + $panelOnlyList = $panelOnlyQuery->orderBy('id')->paginate(20); + + $inboundOnlyQuery = PargarSyncLog::query() + ->where('type', 'customer') + ->where('sync_status', PargarSyncService::STATUS_SUCCESS) + ->whereNotNull('pargar_ref') + ->latest('id'); + + $inboundOnlyCount = (clone $inboundOnlyQuery)->count(); + $inboundSample = $inboundOnlyQuery->limit(100)->get(['id', 'customer_id', 'pargar_ref', 'created_at']); + + return response()->json([ + 'panel_total' => $panelTotal, + 'panel_registered' => $panelRegistered, + 'panel_only' => $panelOnly, + 'pargar_total' => $panelRegistered + $inboundOnlyCount, + 'pargar_only_count' => max(0, $inboundOnlyCount), + 'panel_only_list' => $panelOnlyList, + 'pargar_only_list' => [ + 'data' => $inboundSample->map(fn ($row) => [ + 'code' => $row->pargar_ref, + 'name' => $row->customer?->name ?? '', + 'tel' => $row->customer?->mobile ?? '', + 'gid' => null, + 'group' => '', + ])->values(), + 'total' => $inboundOnlyCount, + 'current_page' => 1, + 'last_page' => 1, + ], + ]); + } + + public function syncPanelToPargar() + { + $customers = Customer::whereNull('deleted_at') + ->whereNull('pargar_account_id') + ->get(['id', 'name', 'mobile']); + + $success = 0; + $failed = 0; + $errors = []; + + foreach ($customers as $customer) { + $result = $this->sync()->registerCustomer($customer); + if ($result['ok'] ?? false) { + $success++; + } else { + $failed++; + $errors[] = [ + 'name' => $customer->name, + 'mobile' => $customer->mobile, + 'error' => $result['message'] ?? '', + ]; + } + } + + return response()->json([ + 'ok' => true, + 'success' => $success, + 'failed' => $failed, + 'errors' => $errors, + ]); + } + + public function importFromPargar(Request $request) + { + $validated = $request->validate([ + 'customers' => 'required|array', + 'customers.*.code' => 'required', + 'customers.*.name' => 'required|string', + 'customers.*.tel' => 'nullable|string', + ]); + + $success = 0; + $failed = 0; + $errors = []; + + foreach ($validated['customers'] as $item) { + $tel = trim((string) ($item['tel'] ?? '')); + $mobile = $tel !== '' ? '0' . ltrim($tel, '0') : ''; + $fullName = trim($item['name']); + $accountId = (string) $item['code']; + + $existing = Customer::whereNull('deleted_at') + ->where('pargar_account_id', $accountId) + ->first(); + + if ($existing) { + $success++; + continue; + } + + if ($mobile !== '') { + $byMobile = Customer::whereNull('deleted_at')->where('mobile', $mobile)->first(); + if ($byMobile) { + $byMobile->pargar_account_id = $accountId; + if ($fullName !== '') { + $byMobile->fname = $fullName; + $byMobile->name = $fullName; + } + $byMobile->save(); + $success++; + continue; + } + } + + try { + $customer = new Customer(); + $customer->fname = $fullName; + $customer->lname = ''; + $customer->name = $fullName; + $customer->mobile = $mobile; + $customer->active = true; + $customer->pargar_account_id = $accountId; + $customer->referral_id = $this->uniqueReferralId(); + $customer->type = 2; + if ($mobile !== '') { + $customer->password = $mobile; + } + $customer->save(); + $success++; + } catch (\Throwable $e) { + $failed++; + $errors[] = ['name' => $item['name'], 'code' => $item['code'], 'error' => $e->getMessage()]; + } + } + + return response()->json([ + 'ok' => true, + 'success' => $success, + 'failed' => $failed, + 'errors' => $errors, + ]); + } + + public function rollbackImport(Request $request) + { + $baseQuery = fn () => Customer::whereNotNull('pargar_account_id') + ->where(function ($q) { + $q->whereNull('name')->orWhere('name', ''); + }); + + $count = $baseQuery()->count(); + $sample = $baseQuery() + ->select('id', 'fname', 'name', 'mobile', 'pargar_account_id', 'created_at') + ->orderByDesc('id') + ->limit(20) + ->get(); + + if ($request->boolean('dry_run')) { + return response()->json([ + 'dry_run' => true, + 'count' => $count, + 'sample' => $sample, + ]); + } + + $deleted = $baseQuery()->forceDelete(); + + return response()->json([ + 'ok' => true, + 'deleted' => $deleted, + ]); + } + + public function retrySanad($id) + { + $log = PargarSyncLog::with('customer')->findOrFail($id); + $result = $this->sync()->retry($log); + + return response()->json($result, ($result['ok'] ?? false) ? 200 : 422); + } + + public function registerCustomer($customerId) + { + $customer = Customer::findOrFail($customerId); + $result = $this->sync()->registerCustomer($customer); + + return response()->json($result, ($result['ok'] ?? false) ? 200 : 422); + } + + private function uniqueReferralId(): string + { + do { + $referral = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 4); + } while (Customer::where('referral_id', $referral)->exists()); + + return $referral; + } +} diff --git a/app/Http/Controllers/Admin/WalletController.php b/app/Http/Controllers/Admin/WalletController.php index a7ebaab..6399f80 100644 --- a/app/Http/Controllers/Admin/WalletController.php +++ b/app/Http/Controllers/Admin/WalletController.php @@ -128,7 +128,7 @@ class WalletController extends Controller $this->recordAccountingTransaction($customer, $Withdraw, (int) $user->id, (float) $data['value'], 0, $data['note'] ?? null); - if($this->Config('send_to_tahesab') == "true"){ + if (app(ConfigService::class)->isTahesabAccounting()) { try { $data['direction'] = $deposit ? 0 : 1; $data['withdraw_id'] = $Withdraw->id; @@ -201,7 +201,7 @@ class WalletController extends Controller $this->recordAccountingTransaction($customer, $Withdraw, (int) $user->id, 0, (float) $data['value'], $data['note'] ?? null); //send to tahesab - if($this->Config('send_to_tahesab') == "true"){ + if (app(ConfigService::class)->isTahesabAccounting()) { try { $data['direction'] = $deposit ? 1 : 0; $data['withdraw_id'] = $Withdraw->id; @@ -344,7 +344,7 @@ class WalletController extends Controller ($data['note'] ?? null) ?: ('شارژ ' . $product->title) ); - if ($this->Config('send_to_tahesab') == 'true') { + if (app(ConfigService::class)->isTahesabAccounting()) { try { $data['direction'] = $deposit ? 1 : 0; $data['withdraw_id'] = $Withdraw->id; @@ -548,7 +548,7 @@ class WalletController extends Controller '*', Withdraw::$SELECT_STS_STR, Withdraw::$SELECT_DAJ ])->export($records); - if ($this->Config('send_to_tahesab') === 'true' && isset($records['rows']) && is_array($records['rows'])) { + if (app(ConfigService::class)->isTahesabAccounting() && isset($records['rows']) && is_array($records['rows'])) { $withdrawIds = collect($records['rows'])->pluck('id')->filter()->values()->all(); if ($withdrawIds !== []) { $failedByWithdraw = \App\Models\Tahesab::query() diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 866cce3..2b4e430 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -17,7 +17,10 @@ use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; use App\Models\Price; use App\Http\Controllers\Admin\ProductController; use App\Http\Controllers\Admin\GiftCardController; +use App\Http\Controllers\Admin\TahesabController; +use App\Services\AccountingLedgerService; use App\Services\ConfigService; +use App\Services\PargarSyncService; use App\Services\ProductPriceService; @@ -342,11 +345,55 @@ class CartController extends Controller // $product->decrement('inventory', $item->quantity); } + $this->syncCartOrderAccounting($order, $cart); + return response()->json([ 'message' => 'true', ]); } + /** + * ثبت سبد در دفترکل داخلی + حسابداری بیرونی (مستقل از is_store؛ فقط accounting_provider). + */ + private function syncCartOrderAccounting(Order $order, Cart $cart): void + { + $config = app(ConfigService::class); + + try { + app(AccountingLedgerService::class)->recordTrade($order); + } catch (\Throwable $e) { + report($e); + } + + $primaryProduct = Product::find($cart->items->first()?->product_id); + $metalId = max(1, (int) ($primaryProduct->metal_id ?? 1)); + + if ($config->isTahesabAccounting()) { + try { + app(TahesabController::class)->storeTrade([ + 'customer_id' => $order->customer_id, + 'amount' => $order->amount, + 'direction' => (int) ($order->direction ?? 1), + 'price' => $order->price, + 'total_price' => $order->total_price, + 'pay_at' => $order->pay_at ?? $order->created_at, + 'product' => ['metal_id' => $metalId], + 'order' => ['id' => $order->id], + ]); + } catch (\Throwable $e) { + report($e); + } + } + + if ($config->isPargarAccounting()) { + try { + app(PargarSyncService::class)->recordTrade($order, true); + } catch (\Throwable $e) { + report($e); + } + } + } + /** * تسویه سبد فروشگاهی — قیمت نقدی هر محصول، بدون فرمول آبشده/گرم. */ @@ -476,6 +523,8 @@ class CartController extends Controller Product::where('id', $item->product_id)->decrement('inventory', $item->quantity); } + $this->syncCartOrderAccounting($order, $cart); + return response()->json([ 'message' => 'true', ]); diff --git a/app/Http/Controllers/Customer/WalletController.php b/app/Http/Controllers/Customer/WalletController.php index 36128c4..b949f36 100644 --- a/app/Http/Controllers/Customer/WalletController.php +++ b/app/Http/Controllers/Customer/WalletController.php @@ -14,6 +14,7 @@ use App\Models\BankAccount; use App\Models\Price; use App\Models\Setting; use App\Http\Controllers\Admin\TahesabController; +use App\Services\ConfigService; use App\Services\AssetSummaryService; use App\Services\WalletBalanceService; use App\Services\ZaarboxPriceService; @@ -272,7 +273,7 @@ class WalletController extends Controller $userMobile = $customer->mobile; // User's mobile number $userName = $customer->name; // User's name $withdrawAmount = $data['value']; // amount - if($this->Config('send_to_tahesab') == "true") { + if (app(ConfigService::class)->isTahesabAccounting()) { try { $result = app(TahesabController::class)->wallet([ "customer_id" => auth('customer')->id(), diff --git a/app/Http/Controllers/Pargar/PargarInboundController.php b/app/Http/Controllers/Pargar/PargarInboundController.php new file mode 100644 index 0000000..1806693 --- /dev/null +++ b/app/Http/Controllers/Pargar/PargarInboundController.php @@ -0,0 +1,384 @@ +isPargarAccounting()) { + return response()->json([ + 'success' => false, + 'data' => null, + 'message' => 'Pargar integration is disabled', + ], 503); + } + + $username = (string) $request->input('username', ''); + $password = (string) $request->input('password', ''); + + $expectedUser = trim((string) $this->Config('pargar_username')); + $expectedPass = trim((string) $this->Config('pargar_password')); + + if ($username !== $expectedUser || $password !== $expectedPass || $expectedUser === '') { + return response()->json([ + 'success' => false, + 'data' => null, + 'message' => 'Invalid credentials!', + ]); + } + + $token = PargarAuth::issueToken($username); + + return response()->json([ + 'success' => true, + 'data' => ['token' => $token], + 'message' => 'You are logged in successfully.', + ]); + } + + public function upsertCustomers(Request $request) + { + $customers = $request->input('Customers', []); + if (! is_array($customers) || $customers === []) { + return response()->json([ + 'success' => false, + 'message' => 'Customers list is required', + 'data' => null, + ], 422); + } + + $messages = []; + + foreach ($customers as $row) { + if (! is_array($row)) { + continue; + } + + $accountId = trim((string) ($row['AccountId'] ?? '')); + $fullName = trim((string) ($row['FullName'] ?? '')); + $mobile = $this->normalizeMobile((string) ($row['CellPhone'] ?? '')); + + if ($accountId === '' || $mobile === '') { + $messages[] = 'ردیف نامعتبر: AccountId یا CellPhone خالی است'; + continue; + } + + $customer = Customer::whereNull('deleted_at') + ->where('mobile', $mobile) + ->first(); + + if ($customer) { + if ((string) ($customer->pargar_account_id ?? '') === $accountId) { + $messages[] = 'کد حساب مشتری وجود دارد'; + continue; + } + + $customer->pargar_account_id = $accountId; + if ($fullName !== '') { + $customer->fname = $fullName; + $customer->name = $fullName; + } + $customer->save(); + $messages[] = "کد حسابداری مشتری {$fullName} ویرایش شد"; + continue; + } + + $customer = new Customer(); + $customer->fname = $fullName !== '' ? $fullName : 'مشتری'; + $customer->name = $customer->fname; + $customer->mobile = $mobile; + $customer->pargar_account_id = $accountId; + $customer->active = true; + $customer->type = 2; + $customer->password = $mobile; + $customer->referral_id = $this->uniqueReferralId(); + $customer->save(); + + $messages[] = "مشتری با کد حسابداری {$accountId} ایجاد شد"; + } + + return response()->json([ + 'success' => true, + 'message' => implode(' | ', $messages), + 'data' => null, + ]); + } + + public function listOrders(Request $request) + { + $orders = Order::query() + ->where('sts', 2) + ->whereNull('pargar_confirmed_at') + ->limit(100) + ->get(); + + $documents = $orders->map(function (Order $order) { + $customer = Customer::find((int) ($order->customer_id ?? 0)); + + return [ + 'OrderId' => (string) $order->id, + 'OrderType' => (int) ($order->direction ?? 1) === 1 ? 1 : -1, + 'PriceType' => 1, + 'CustomerAccountId' => (int) ($customer->pargar_account_id ?? 0), + 'ItemId' => 11, + 'ItemName' => $this->pargarItemName($order), + 'OrderDate' => $order->pay_at + ? Jalalian::fromDateTime($order->pay_at)->format('Y/m/d-H:i:s') + : Jalalian::fromDateTime($order->created_at)->format('Y/m/d-H:i:s'), + 'Fee' => (float) ($order->price ?? 0), + 'Count' => 1, + 'Weight' => (float) ($order->amount ?? 0), + 'Price' => (float) ($order->total_price ?? 0), + 'Carat' => 750, + 'Description' => (string) ($order->description ?? ''), + ]; + })->values(); + + return response()->json([ + 'state' => 'true', + 'msg' => '', + 'data' => [ + 'documents' => $documents, + 'duplicated' => 'false', + 'result' => 'OK', + ], + ]); + } + + public function confirmOrders(Request $request) + { + $orderIds = $request->input('OrderIds', []); + if (! is_array($orderIds)) { + return response()->json([ + 'success' => false, + 'message' => 'OrderIds must be an array', + 'data' => null, + ], 422); + } + + $this->sync()->confirmOrders($orderIds); + + return response()->json([ + 'success' => true, + 'message' => 'تاییدیه اسناد با موفقیت دریافت شد', + 'data' => null, + ]); + } + + public function storeDocuments(Request $request) + { + $data = $request->all(); + $accountId = trim((string) ($data['accountId'] ?? '')); + $transactions = $data['transactions'] ?? []; + + $customer = $accountId !== '' + ? Customer::where('pargar_account_id', $accountId)->first() + : null; + + PargarSyncLog::create([ + 'customer_id' => $customer?->id, + 'desc' => 'دریافت اسناد از پرگار', + 'type' => 'document', + 'sync_status' => PargarSyncService::STATUS_SUCCESS, + 'pargar_ref' => $accountId, + 'data' => json_encode($data, JSON_UNESCAPED_UNICODE), + ]); + + return response()->json([ + 'success' => true, + 'message' => 'اسناد مشتری با موفقیت دریافت شد', + 'data' => null, + ]); + } + + public function storeMande(Request $request) + { + $data = $request->all(); + $accountId = trim((string) ($data['AccountId'] ?? '')); + + $customer = Customer::where('pargar_account_id', $accountId)->first(); + if (! $customer) { + return response()->json([ + 'success' => false, + 'message' => 'مشتری یافت نشد', + 'data' => null, + ], 422); + } + + $goldInv = isset($data['GoldInv']) ? (float) str_replace('/', '.', (string) $data['GoldInv']) : 0; + $rialInv = isset($data['RialInv']) ? (float) str_replace('/', '.', (string) $data['RialInv']) : 0; + + $wallet = $customer->wallet->where('fund_id', null)->first(); + if ($wallet) { + $goldDiff = $goldInv - (float) $wallet->gold; + $rialDiff = $rialInv - (float) $wallet->cash; + } else { + $goldDiff = $goldInv; + $rialDiff = $rialInv; + } + + if (abs($goldDiff) >= 0.01 || abs($rialDiff) >= 1) { + $walletInterface = new WalletInterface($customer->id, 2); + new TransactionInterface($walletInterface, [ + 'cash' => $rialDiff, + 'gold' => $goldDiff, + 'expire_at' => now(), + 'active' => true, + 'start_at' => now(), + ], 22, $goldDiff > 0, $rialDiff > 0); + } + + PargarSyncLog::create([ + 'customer_id' => $customer->id, + 'desc' => 'دریافت مانده از پرگار', + 'type' => 'mande', + 'amount' => $goldInv, + 'sync_status' => PargarSyncService::STATUS_SUCCESS, + 'pargar_ref' => $accountId, + 'data' => json_encode($data, JSON_UNESCAPED_UNICODE), + ]); + + return response()->json([ + 'success' => true, + 'message' => 'مانده مشتری با موفقیت دریافت شد', + 'data' => null, + ]); + } + + public function listNewCustomers(Request $request) + { + $customers = Customer::query() + ->whereNull('deleted_at') + ->whereNull('pargar_account_id') + ->limit(100) + ->get(['id', 'fname', 'lname', 'mobile']); + + if ($customers->isEmpty()) { + return response()->json([ + 'success' => true, + 'message' => 'مشتری جدید وجود ندارد', + 'data' => null, + ]); + } + + $rows = $customers->map(function (Customer $customer) { + $nameParts = preg_split('/\s+/', trim((string) $customer->name), 2) ?: ['', '']; + + return [ + 'id' => (string) $customer->id, + 'name' => $nameParts[0] ?? '', + 'family' => $nameParts[1] ?? '', + 'mobile' => (string) $customer->mobile, + ]; + }); + + return response()->json([ + 'state' => 'true', + 'msg' => '', + 'customer' => $rows, + ]); + } + + public function confirmCustomers(Request $request) + { + $rows = $request->input('customers', []); + if (! is_array($rows)) { + return response()->json([ + 'success' => false, + 'message' => 'customers must be an array', + 'data' => null, + ], 422); + } + + foreach ($rows as $row) { + if (! is_array($row)) { + continue; + } + + $customerId = $row['customer_id'] ?? $row['id_customer'] ?? null; + $accountId = $row['accounting_id'] ?? null; + if ($customerId === null || $accountId === null) { + continue; + } + + $customer = Customer::find($customerId); + if ($customer) { + $customer->pargar_account_id = (string) $accountId; + $customer->save(); + + $log = PargarSyncLog::query() + ->where('customer_id', $customer->id) + ->where('type', 'customer') + ->where('sync_status', PargarSyncService::STATUS_PENDING) + ->latest('id') + ->first(); + + if ($log) { + $this->sync()->markSuccess($log, (string) $accountId); + } + } + } + + return response()->json([ + 'success' => true, + 'message' => 'تاییدیه ثبت مشتری با موفقیت دریافت شد', + 'data' => null, + ]); + } + + private function normalizeMobile(string $mobile): string + { + $mobile = trim($mobile); + if ($mobile === '') { + return ''; + } + + return '0' . ltrim($mobile, '0'); + } + + private function uniqueReferralId(): string + { + do { + $referral = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 4); + } while (Customer::where('referral_id', $referral)->exists()); + + return $referral; + } + + private function pargarItemName(Order $order): string + { + return $this->isCartOrder($order) ? 'سبد خرید' : 'آبشده'; + } + + private function isCartOrder(Order $order): bool + { + if (Schema::hasTable('cart') && Schema::hasColumn('cart', 'order_id')) { + return Cart::where('order_id', $order->id)->exists(); + } + + return PargarSyncLog::where('order_id', $order->id) + ->where('desc', 'سبد خرید') + ->exists(); + } +} diff --git a/app/Http/Controllers/Single/SingleOrderController.php b/app/Http/Controllers/Single/SingleOrderController.php index c85e697..78101e8 100644 --- a/app/Http/Controllers/Single/SingleOrderController.php +++ b/app/Http/Controllers/Single/SingleOrderController.php @@ -198,13 +198,21 @@ class SingleOrderController extends Controller } } - if ($config->getString('send_to_tahesab', 'false') === 'true') { + if ($config->isTahesabAccounting()) { try { $data['tahesab'] = app(TahesabController::class)->storeTrade($data); } catch (\Exception $e) { report($e); } } + + if ($config->isPargarAccounting()) { + try { + app(\App\Services\PargarSyncService::class)->recordTrade($data['order'] ?? null); + } catch (\Throwable $e) { + report($e); + } + } // $response['reward'] = $this->give_order_reward($data, $wallet, $wallet_interface); if ((int) $data['direction'] === 1 && $customer) { $referrer = Customer::where('referral_id', $customer->referral_to_id)->first(); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 779f1c1..5d12408 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -66,7 +66,7 @@ class Kernel extends HttpKernel 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'validation'=>ValidationMiddleware::class, 'request.validation' => \App\Http\Middleware\ValidateRequests::class, - 'LogRequests' => \App\Http\Middleware\LogRequests::class, + 'pargar.auth' => \App\Http\Middleware\PargarAuth::class, 'sms.panel.super' => \App\Http\Middleware\EnsureSmsPanelSuperAdmin::class, ]; } diff --git a/app/Http/Middleware/LogRequests.php b/app/Http/Middleware/LogRequests.php deleted file mode 100644 index 50820b8..0000000 --- a/app/Http/Middleware/LogRequests.php +++ /dev/null @@ -1,66 +0,0 @@ -ip = $request->ip(); - $Pargar->m = $request->route()?->getName() ?? 'not_found'; -//get action name from controller - if ($route = $request->route()) { - // تلاش برای گرفتن نام اکشن (کنترلر و متد) - $Pargar->function_name = $route->getActionName(); - } else { - $Pargar->function_name = 'not_found'; - } - - - $Pargar->finance_data = json_encode($request->all(), JSON_UNESCAPED_UNICODE); - $Pargar->finance_head = json_encode($request->headers->all(), JSON_UNESCAPED_UNICODE); - $Pargar->url = $request->fullUrl(); - $Pargar->method = $request->method(); - $Pargar->save(); - } catch (\Throwable $e) { - $Pargar = null; // برای اطمینان از عدم خطا در ادامه - } - - // اجرای درخواست اصلی - $response = $next($request); - - try { - - if ($Pargar) { -// if ($route = $request->route()) { -// try { -// $Pargar->m = $route -// ? $route->getActionName() . ' (' . (new \ReflectionClass($route->getController()))->getFileName() . ')' -// : 'unknown'; -// } catch (\Throwable $e) { -// $Pargar->m = 'unknown'; -// } -// -// } - $Pargar->response = $response->getContent(); - $Pargar->ms = round((microtime(true) - $start) * 1000, 2); // زمان در میلی‌ثانیه - $Pargar->save(); - } - } catch (\Throwable $e) {} - - return $response; - } -} diff --git a/app/Http/Middleware/PargarAuth.php b/app/Http/Middleware/PargarAuth.php new file mode 100644 index 0000000..a11ea14 --- /dev/null +++ b/app/Http/Middleware/PargarAuth.php @@ -0,0 +1,59 @@ +isPargarAccounting()) { + return response()->json([ + 'success' => false, + 'message' => 'Pargar integration is disabled', + 'data' => null, + ], 503); + } + + $auth = $request->header('Authorization') ?? $request->header('pargar'); + $token = is_string($auth) ? trim(str_replace('Bearer ', '', $auth)) : ''; + + if ($token === '' || ! $this->tokenValid($token)) { + return response()->json([ + 'success' => false, + 'message' => 'Invalid credentials!', + 'data' => null, + ], 401); + } + + return $next($request); + } + + public static function issueToken(string $username): string + { + $token = bin2hex(random_bytes(32)); + Cache::put(self::cacheKey($token), $username, now()->addDay()); + + return $token; + } + + public static function tokenValid(string $token): bool + { + $config = app(ConfigService::class); + $static = trim($config->getString('pargar_api_token', '')); + if ($static !== '' && hash_equals($static, $token)) { + return true; + } + + return Cache::has(self::cacheKey($token)); + } + + private static function cacheKey(string $token): string + { + return 'pargar_api_token:' . $token; + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php index b0331d5..03ad641 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -47,6 +47,7 @@ class Customer extends Authenticatable implements JWTSubject 'total_referrals', 'credential_id', 'moshtari_code', + 'pargar_account_id', ]; /** diff --git a/app/Models/Pargar.php b/app/Models/Pargar.php deleted file mode 100644 index 103a0a3..0000000 --- a/app/Models/Pargar.php +++ /dev/null @@ -1,28 +0,0 @@ - 'json', - 'finance_head' => 'json', - 'finance_data' => 'json', - 'response' => 'json', - ]; -} diff --git a/app/Models/PargarSyncLog.php b/app/Models/PargarSyncLog.php new file mode 100644 index 0000000..e298163 --- /dev/null +++ b/app/Models/PargarSyncLog.php @@ -0,0 +1,36 @@ +belongsTo(Customer::class); + } + + public function order(): BelongsTo + { + return $this->belongsTo(Order::class); + } +} diff --git a/app/Observers/CustomerObserver.php b/app/Observers/CustomerObserver.php index b069533..140f11b 100644 --- a/app/Observers/CustomerObserver.php +++ b/app/Observers/CustomerObserver.php @@ -3,6 +3,8 @@ namespace App\Observers; use App\Models\Customer; +use App\Services\ConfigService; +use App\Services\PargarSyncService; use App\Services\TahesabSyncService; class CustomerObserver @@ -10,5 +12,6 @@ class CustomerObserver public function created(Customer $customer): void { app(TahesabSyncService::class)->registerOnCreate($customer); + app(PargarSyncService::class)->registerOnCreate($customer); } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 433897a..de6593e 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -7,7 +7,6 @@ use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvi use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; -use App\Services\ConfigService; class RouteServiceProvider extends ServiceProvider { @@ -56,12 +55,10 @@ class RouteServiceProvider extends ServiceProvider ->namespace($this->namespace) ->group(base_path('routes/customer.php')); - if (app(ConfigService::class)->isStore()) { - Route::prefix('pargar') - ->middleware('LogRequests') - ->namespace($this->namespace) - ->group(base_path('routes/pargar.php')); - } + Route::prefix('pargar') + ->middleware('api') + ->namespace($this->namespace) + ->group(base_path('routes/pargar.php')); Route::middleware('web') ->namespace($this->namespace) diff --git a/app/Services/ConfigService.php b/app/Services/ConfigService.php index 626a4e7..6c58724 100644 --- a/app/Services/ConfigService.php +++ b/app/Services/ConfigService.php @@ -685,4 +685,36 @@ class ConfigService throw new UnprocessableEntityHttpException($this->productTradingClosedMessage($product)); } } + + public const ACCOUNTING_NONE = 'none'; + public const ACCOUNTING_TAHESAB = 'tahesab'; + public const ACCOUNTING_PARGAR = 'pargar'; + + /** none | tahesab | pargar — از setting accounting_provider */ + public function accountingProvider(): string + { + $provider = strtolower(trim($this->getString('accounting_provider', ''))); + if (in_array($provider, [self::ACCOUNTING_NONE, self::ACCOUNTING_TAHESAB, self::ACCOUNTING_PARGAR], true)) { + return $provider; + } + + if ($this->getString('send_to_pargar', 'false') === 'true') { + return self::ACCOUNTING_PARGAR; + } + if ($this->getString('send_to_tahesab', 'false') === 'true') { + return self::ACCOUNTING_TAHESAB; + } + + return self::ACCOUNTING_NONE; + } + + public function isTahesabAccounting(): bool + { + return $this->accountingProvider() === self::ACCOUNTING_TAHESAB; + } + + public function isPargarAccounting(): bool + { + return $this->accountingProvider() === self::ACCOUNTING_PARGAR; + } } diff --git a/app/Services/PargarSyncService.php b/app/Services/PargarSyncService.php new file mode 100644 index 0000000..60dffa5 --- /dev/null +++ b/app/Services/PargarSyncService.php @@ -0,0 +1,269 @@ + $ref, + 'res' => is_array($response) + ? json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) + : (is_string($response) ? $response : null), + 'sync_status' => self::STATUS_SUCCESS, + 'sync_log' => null, + ]; + + if ($payload !== null) { + $update['data'] = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } + + PargarSyncLog::where('id', $log->id)->update($update); + } + + public function markFailed(PargarSyncLog $log, mixed $response = null, ?string $extra = null): void + { + PargarSyncLog::where('id', $log->id)->update([ + 'res' => is_array($response) + ? json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) + : (is_string($response) ? $response : null), + 'sync_status' => self::STATUS_FAILED, + 'sync_log' => $this->buildLog($response, $extra), + ]); + } + + public function isFailed(PargarSyncLog $log): bool + { + return ($log->sync_status ?? null) === self::STATUS_FAILED + || (empty($log->pargar_ref) && ($log->sync_status ?? null) !== self::STATUS_SUCCESS); + } + + public function registerOnCreate(Customer $customer): void + { + if (! empty($customer->pargar_account_id) || ! $this->isSyncEnabled()) { + return; + } + + $customerId = (int) $customer->id; + + dispatch(function () use ($customerId) { + $service = app(self::class); + if (! $service->isSyncEnabled()) { + return; + } + + $customer = Customer::find($customerId); + if ($customer === null || ! empty($customer->pargar_account_id)) { + return; + } + + try { + $service->queueCustomerExport($customer); + } catch (\Throwable $e) { + Log::warning('Pargar auto-queue on customer create failed', [ + 'customer_id' => $customerId, + 'error' => $e->getMessage(), + ]); + } + })->afterResponse(); + } + + public function queueCustomerExport(Customer $customer): PargarSyncLog + { + $existing = PargarSyncLog::query() + ->where('customer_id', $customer->id) + ->where('type', 'customer') + ->where('sync_status', self::STATUS_PENDING) + ->latest('id') + ->first(); + + if ($existing) { + return $existing; + } + + return PargarSyncLog::create([ + 'customer_id' => $customer->id, + 'desc' => 'در انتظار دریافت توسط پرگار', + 'type' => 'customer', + 'sync_status' => self::STATUS_PENDING, + 'data' => json_encode(['handler' => 'exportCustomer'], JSON_UNESCAPED_UNICODE), + ]); + } + + public function registerCustomer(Customer $customer): array + { + $customer->refresh(); + + if (! empty($customer->pargar_account_id)) { + return [ + 'ok' => true, + 'message' => 'مشتری قبلاً در پرگار ثبت شده است', + 'pargar_account_id' => $customer->pargar_account_id, + ]; + } + + $this->queueCustomerExport($customer); + + return [ + 'ok' => true, + 'message' => 'مشتری در صف دریافت پرگار قرار گرفت', + 'pargar_account_id' => null, + ]; + } + + public function recordTrade(?Order $order, bool $fromCart = false): ?PargarSyncLog + { + if (! $order || ! $order->id || ! $this->isSyncEnabled()) { + return null; + } + + $existing = PargarSyncLog::where('order_id', $order->id)->first(); + if ($existing) { + return $existing; + } + + $direction = (int) ($order->direction ?? 0); + $desc = $fromCart + ? 'سبد خرید' + : ($direction === 1 ? 'خرید آبشده' : 'فروش آبشده'); + + return PargarSyncLog::create([ + 'customer_id' => $order->customer_id, + 'amount' => $order->amount, + 'desc' => $desc, + 'order_id' => $order->id, + 'date' => $order->pay_at ?? $order->created_at, + 'type' => 'order', + 'sync_status' => self::STATUS_PENDING, + 'data' => json_encode([ + 'handler' => 'exportOrder', + 'direction' => $direction, + 'price' => $order->price, + 'total_price' => $order->total_price, + ], JSON_UNESCAPED_UNICODE), + ]); + } + + public function confirmOrders(array $orderIds): array + { + $confirmed = 0; + + foreach ($orderIds as $orderId) { + $order = Order::find($orderId); + if (! $order) { + continue; + } + + $order->pargar_confirmed_at = now(); + $order->save(); + + $log = PargarSyncLog::where('order_id', $order->id)->latest('id')->first(); + if ($log) { + $this->markSuccess($log, (string) $order->id, ['OrderId' => (string) $order->id]); + } + + $confirmed++; + } + + return ['confirmed' => $confirmed]; + } + + public function retry(PargarSyncLog $log): array + { + if (! $this->isFailed($log) && ! empty($log->pargar_ref)) { + return ['ok' => false, 'message' => 'این سند قبلاً در پرگار ثبت شده است']; + } + + $payload = json_decode((string) $log->data, true) ?: []; + $handler = $payload['handler'] ?? $this->inferHandler($log); + + if ($handler === 'exportOrder' && $log->order_id) { + Order::where('id', $log->order_id)->update(['pargar_confirmed_at' => null]); + PargarSyncLog::where('id', $log->id)->update([ + 'sync_status' => self::STATUS_PENDING, + 'sync_log' => null, + 'pargar_ref' => null, + ]); + $log->refresh(); + + return [ + 'ok' => true, + 'message' => 'سفارش دوباره در صف ارسال به پرگار قرار گرفت', + 'pargar' => $log, + ]; + } + + if ($handler === 'exportCustomer' && $log->customer_id) { + PargarSyncLog::where('id', $log->id)->update([ + 'sync_status' => self::STATUS_PENDING, + 'sync_log' => null, + 'pargar_ref' => null, + ]); + $log->refresh(); + + return [ + 'ok' => true, + 'message' => 'مشتری دوباره در صف دریافت پرگار قرار گرفت', + 'pargar' => $log, + ]; + } + + return [ + 'ok' => false, + 'message' => $log->sync_log ?: 'ارسال مجدد به پرگار ناموفق بود', + 'pargar' => $log, + ]; + } + + private function inferHandler(PargarSyncLog $log): string + { + if ($log->order_id) { + return 'exportOrder'; + } + + if ($log->type === 'customer') { + return 'exportCustomer'; + } + + if ($log->type === 'mande') { + return 'importMande'; + } + + return 'importDocument'; + } + + public function isSyncEnabled(): bool + { + $config = app(ConfigService::class); + + return $config->isPargarAccounting() + && trim($config->getString('pargar_username', '')) !== '' + && trim($config->getString('pargar_password', '')) !== ''; + } + + public function hasSyncTable(): bool + { + return Schema::hasTable('pargar_sync_logs'); + } +} diff --git a/app/Services/ReferralGiftService.php b/app/Services/ReferralGiftService.php index e41aaad..5dad8dc 100644 --- a/app/Services/ReferralGiftService.php +++ b/app/Services/ReferralGiftService.php @@ -168,7 +168,7 @@ class ReferralGiftService 'withdraw_id' => $withdraw->id, ]); - if ($config->getString('send_to_tahesab', 'false') === 'true') { + if ($config->isTahesabAccounting()) { try { app(TahesabController::class)->referrerGoldReward( $customer, @@ -226,7 +226,7 @@ class ReferralGiftService 'withdraw_id' => $withdraw->id, ]); - if ($config->getString('send_to_tahesab', 'false') === 'true') { + if ($config->isTahesabAccounting()) { try { app(TahesabController::class)->goldReward([ 'customer_id' => $customer->id, diff --git a/app/Services/TahesabSyncService.php b/app/Services/TahesabSyncService.php index fcd6f9a..8c5a82e 100644 --- a/app/Services/TahesabSyncService.php +++ b/app/Services/TahesabSyncService.php @@ -198,16 +198,11 @@ class TahesabSyncService { $config = app(ConfigService::class); - if ($config->getString('send_to_tahesab', 'false') !== 'true') { - return false; - } - - $host = trim($config->getString('tahesab_host', '')); - $port = trim($config->getString('tahesab_port', '')); - $token = trim($config->getString('tahesab_token', '')); - $db = trim($config->getString('tahesab_db', '')); - - return $host !== '' && $port !== '' && $token !== '' && $db !== ''; + return $config->isTahesabAccounting() + && trim($config->getString('tahesab_host', '')) !== '' + && trim($config->getString('tahesab_port', '')) !== '' + && trim($config->getString('tahesab_token', '')) !== '' + && trim($config->getString('tahesab_db', '')) !== ''; } private function hasSyncColumns(): bool diff --git a/database/migrations/2026_06_11_000001_add_store_tables_and_columns.php b/database/migrations/2026_06_11_000001_add_store_tables_and_columns.php index 46fb68e..722e3e9 100644 --- a/database/migrations/2026_06_11_000001_add_store_tables_and_columns.php +++ b/database/migrations/2026_06_11_000001_add_store_tables_and_columns.php @@ -41,21 +41,6 @@ return new class extends Migration }); } - if (! Schema::hasTable('pargar_reqasts')) { - Schema::create('pargar_reqasts', function (Blueprint $table) { - $table->id(); - $table->string('m')->nullable(); - $table->string('route')->nullable(); - $table->string('ip')->nullable(); - $table->json('data')->nullable(); - $table->json('finance_head')->nullable(); - $table->json('finance_data')->nullable(); - $table->json('response')->nullable(); - $table->string('function_name')->nullable(); - $table->timestamps(); - }); - } - if (Schema::hasTable('giftcards') && ! Schema::hasColumn('giftcards', 'use_once')) { Schema::table('giftcards', function (Blueprint $table) { $table->unsignedTinyInteger('use_once')->default(0)->after('customer_id'); @@ -80,7 +65,6 @@ return new class extends Migration Schema::dropIfExists('cart_items'); Schema::dropIfExists('cart'); Schema::dropIfExists('categories'); - Schema::dropIfExists('pargar_reqasts'); if (Schema::hasTable('giftcards') && Schema::hasColumn('giftcards', 'use_once')) { Schema::table('giftcards', function (Blueprint $table) { diff --git a/database/migrations/2026_07_05_000001_drop_legacy_finance_request_logs_table.php b/database/migrations/2026_07_05_000001_drop_legacy_finance_request_logs_table.php new file mode 100644 index 0000000..0b9a1b5 --- /dev/null +++ b/database/migrations/2026_07_05_000001_drop_legacy_finance_request_logs_table.php @@ -0,0 +1,16 @@ +id(); + $table->unsignedBigInteger('customer_id')->nullable()->index(); + $table->float('amount')->nullable(); + $table->string('desc')->nullable(); + $table->unsignedBigInteger('order_id')->nullable()->index(); + $table->unsignedBigInteger('withdraw_id')->nullable()->index(); + $table->timestamp('date')->nullable(); + $table->string('type')->nullable(); + $table->string('sync_status', 20)->default('pending'); + $table->text('sync_log')->nullable(); + $table->string('pargar_ref')->nullable(); + $table->text('res')->nullable(); + $table->text('data')->nullable(); + $table->timestamps(); + }); + } + + if (Schema::hasTable('customers') && ! Schema::hasColumn('customers', 'pargar_account_id')) { + Schema::table('customers', function (Blueprint $table) { + $table->string('pargar_account_id', 64)->nullable()->after('moshtari_code'); + }); + } + + if (Schema::hasTable('orders') && ! Schema::hasColumn('orders', 'pargar_confirmed_at')) { + Schema::table('orders', function (Blueprint $table) { + $table->timestamp('pargar_confirmed_at')->nullable()->after('pay_at'); + }); + } + } + + public function down(): void + { + Schema::dropIfExists('pargar_sync_logs'); + + if (Schema::hasTable('customers') && Schema::hasColumn('customers', 'pargar_account_id')) { + Schema::table('customers', function (Blueprint $table) { + $table->dropColumn('pargar_account_id'); + }); + } + + if (Schema::hasTable('orders') && Schema::hasColumn('orders', 'pargar_confirmed_at')) { + Schema::table('orders', function (Blueprint $table) { + $table->dropColumn('pargar_confirmed_at'); + }); + } + } +}; diff --git a/database/migrations/2026_07_05_000003_add_accounting_provider_setting.php b/database/migrations/2026_07_05_000003_add_accounting_provider_setting.php new file mode 100644 index 0000000..449e350 --- /dev/null +++ b/database/migrations/2026_07_05_000003_add_accounting_provider_setting.php @@ -0,0 +1,46 @@ +where('key', self::KEY)->exists()) { + DB::table('settings')->insert([ + 'key' => self::KEY, + 'value' => 'none', + 'title_fa' => 'سیستم حسابداری', + 'can_edit' => 0, + 'is_active' => 1, + 'description' => 'none,pargar,tahesab', + 'type' => 'select', + ]); + } + + $current = trim((string) DB::table('settings')->where('key', self::KEY)->value('value')); + if ($current !== '' && $current !== 'none') { + return; + } + + $pargarOn = DB::table('settings')->where('key', 'send_to_pargar')->value('value'); + if (in_array(strtolower(trim((string) $pargarOn)), ['true', '1', 'yes'], true)) { + DB::table('settings')->where('key', self::KEY)->update(['value' => 'pargar']); + + return; + } + + $tahesabOn = DB::table('settings')->where('key', 'send_to_tahesab')->value('value'); + if (in_array(strtolower(trim((string) $tahesabOn)), ['true', '1', 'yes'], true)) { + DB::table('settings')->where('key', self::KEY)->update(['value' => 'tahesab']); + } + } + + public function down(): void + { + // تنظیمات حسابداری حذف نمی‌شوند — rollback فقط مقدار را برنمی‌گرداند + } +}; diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index d0581d6..a5e334a 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -220,7 +220,7 @@ SELECT 'montify_name', '', 'نام فروشگاه در درگاه', 0, 1, NULL, WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montify_name' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'is_store', 'false', 'حالت فروشگاهی', 0, 1, 'فعال = سبد خرید، دسته‌بندی، حواله، پرگار، تخفیف', 'switch' +SELECT 'is_store', 'false', 'حالت فروشگاهی', 0, 1, 'فعال = سبد خرید، دسته‌بندی، حواله، تخفیف', 'switch' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'is_store' LIMIT 1); -- Jibit @@ -292,7 +292,7 @@ SELECT 'sms_panel', 'true', 'پنل پیامک (کیف پول)', 0, 1, 'روشن WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'sms_panel' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_host', '', 'آدرس IP سرور ته‌حساب', 1, 1, NULL +SELECT 'tahesab_host', '', 'آدرس IP سرور ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_host' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) @@ -300,21 +300,41 @@ SELECT 'tahesab_port', '', 'پورت سرور ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_port' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_token', '', 'توکن ته‌حساب', 1, 1, NULL +SELECT 'tahesab_token', '', 'توکن ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_token' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_db', '', 'دیتابیس ته‌حساب', 1, 1, NULL +SELECT 'tahesab_db', '', 'دیتابیس ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_db' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_bank_account', '', 'حساب بانکی ته‌حساب', 1, 1, NULL +SELECT 'tahesab_bank_account', '', 'حساب بانکی ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_bank_account' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'send_to_tahesab', 'false', 'ارسال به ته‌حساب', 1, 1, NULL +SELECT 'send_to_tahesab', 'false', 'ارسال به ته‌حساب (قدیمی)', 0, 0, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'send_to_tahesab' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'accounting_provider', 'none', 'سیستم حسابداری', 0, 1, 'none,pargar,tahesab' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'accounting_provider' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'send_to_pargar', 'false', 'ارسال به پرگار (قدیمی)', 0, 0, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'send_to_pargar' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_username', '', 'نام کاربری API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_username' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_password', '', 'رمز عبور API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_password' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_api_token', '', 'توکن ثابت API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_api_token' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) SELECT 'telegram_bot_token', '', 'توکن بات تلگرام', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'telegram_bot_token' LIMIT 1); @@ -600,6 +620,7 @@ UPDATE `settings` SET `type` = 'longtext' WHERE `key` IN ( ); -- select (+ گزینه‌ها در description) +UPDATE `settings` SET `type` = 'select', `description` = 'none,pargar,tahesab' WHERE `key` = 'accounting_provider'; UPDATE `settings` SET `type` = 'select', `description` = 'منبع فعال قیمت|montzar,zaarbox,main_product' WHERE `key` = 'price_provider'; UPDATE `settings` SET `type` = 'switch', `title_fa` = 'کد معرف اجباری', `description` = 'روشن = اجباری در ثبت‌نام | خاموش = اختیاری' WHERE `key` = 'referral_id'; UPDATE `settings` SET `type` = 'select', `description` = 'sepal,' WHERE `key` = 'payping_gateway_name'; @@ -611,7 +632,7 @@ UPDATE `settings` SET `type` = 'switch' WHERE `key` IN ( 'jibit_verification', 'register_jibit_verify', 'open_register', 'auto_active_customer', 'close_price', 'show_last_price', 'fee_deduct_from_gold', - 'send_to_tahesab', 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw', + 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw', 'has_page_earn_money', 'charge_notif', 'group_sms', 'sms_panel', 'montzar_closed', 'montzar_open_buy', 'montzar_open_sell', 'payping_fin_sync_enabled', 'external_order_api_enabled', 'is_store', 'wss_enabled', @@ -645,6 +666,7 @@ UPDATE `settings` SET `type` = 'text' WHERE `key` IN ( 'montzar_truly_buy_mazaneh', 'montzar_truly_sell_mazaneh', 'startDay', 'endDay', 'payping_start_url', 'payping_verify_url', 'payping_gateway_items', 'payping_fin_url', 'payping_fin_token', 'tahesab_host', 'tahesab_token', 'tahesab_db', + 'pargar_username', 'pargar_password', 'pargar_api_token', 'node_client_id', 'node_shared_secret', 'sse_path', 'tahesab_bank_account', 'telegram_bot_token', 'bale_bot_token', 'support_messenger_id', @@ -1222,6 +1244,25 @@ UPDATE `settings` SET `description` = 'روشن: مشتری دقیقاً همان مبلغ یا وزنی را که وارد کرده دریافت می‌کند. در فروش، مثلاً ۱۰۰ میلیون ریال درخواست → همان ۱۰۰ میلیون واریز و کارمزد از طلای کیف کسر می‌شود. در خرید، مثلاً ۱۰ گرم درخواست → همان ۱۰ گرم واریز و کارمزد به ریال قابل پرداخت اضافه می‌شود. خاموش (پیش‌فرض): در فروش کارمزد از مبلغ ریالی واریزی کم می‌شود (مشتری مبلغ کمتری می‌گیرد). در خرید کارمزد از وزن طلای واریزی کم می‌شود (مشتری طلای کمتری می‌گیرد).' WHERE `key` = 'fee_deduct_from_gold'; +-- حسابداری: یک select مرکزی + can_edit=0 +UPDATE `settings` SET `can_edit` = 0, `is_active` = 0 WHERE `key` IN ('send_to_tahesab', 'send_to_pargar'); +UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( + 'accounting_provider', + 'tahesab_host', 'tahesab_port', 'tahesab_token', 'tahesab_db', 'tahesab_bank_account', + 'pargar_username', 'pargar_password', 'pargar_api_token' +); +UPDATE `settings` SET `title_fa` = 'سیستم حسابداری', `type` = 'select', `description` = 'none,pargar,tahesab' +WHERE `key` = 'accounting_provider'; +UPDATE `settings` SET `description` = 'سیستم حسابداری: none=هیچکدام، pargar=API پرگار، tahesab=ارسال خودکار ته‌حساب.' WHERE `key` = 'accounting_provider'; +UPDATE `settings` SET `value` = 'pargar' +WHERE `key` = 'accounting_provider' + AND TRIM(COALESCE(`value`, '')) IN ('', 'none') + AND EXISTS (SELECT 1 FROM (SELECT `value` FROM `settings` WHERE `key` = 'send_to_pargar') AS s WHERE s.`value` IN ('true', '1', 'yes')); +UPDATE `settings` SET `value` = 'tahesab' +WHERE `key` = 'accounting_provider' + AND TRIM(COALESCE(`value`, '')) IN ('', 'none') + AND EXISTS (SELECT 1 FROM (SELECT `value` FROM `settings` WHERE `key` = 'send_to_tahesab') AS s WHERE s.`value` IN ('true', '1', 'yes')); + COMMIT; SELECT 'deploy_settings_const.sql finished' AS status; diff --git a/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql index cb5df43..7e0ac06 100644 --- a/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql +++ b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql @@ -216,7 +216,7 @@ SELECT 'montify_name', '', 'نام فروشگاه در درگاه', 1, 1, NULL, WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montify_name' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'is_store', 'false', 'حالت فروشگاهی', 0, 1, 'فعال = سبد خرید، دسته‌بندی، حواله، پرگار، تخفیف', 'switch' +SELECT 'is_store', 'false', 'حالت فروشگاهی', 0, 1, 'فعال = سبد خرید، دسته‌بندی، حواله، تخفیف', 'switch' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'is_store' LIMIT 1); -- Jibit @@ -288,7 +288,7 @@ SELECT 'sms_panel', 'true', 'پنل پیامک (کیف پول)', 0, 1, 'روشن WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'sms_panel' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_host', '', 'آدرس IP سرور ته‌حساب', 1, 1, NULL +SELECT 'tahesab_host', '', 'آدرس IP سرور ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_host' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) @@ -296,21 +296,41 @@ SELECT 'tahesab_port', '', 'پورت سرور ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_port' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_token', '', 'توکن ته‌حساب', 1, 1, NULL +SELECT 'tahesab_token', '', 'توکن ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_token' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_db', '', 'دیتابیس ته‌حساب', 1, 1, NULL +SELECT 'tahesab_db', '', 'دیتابیس ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_db' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'tahesab_bank_account', '', 'حساب بانکی ته‌حساب', 1, 1, NULL +SELECT 'tahesab_bank_account', '', 'حساب بانکی ته‌حساب', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_bank_account' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -SELECT 'send_to_tahesab', 'false', 'ارسال به ته‌حساب', 1, 1, NULL +SELECT 'send_to_tahesab', 'false', 'ارسال به ته‌حساب (قدیمی)', 0, 0, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'send_to_tahesab' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'accounting_provider', 'none', 'سیستم حسابداری', 0, 1, 'none,pargar,tahesab' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'accounting_provider' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'send_to_pargar', 'false', 'ارسال به پرگار (قدیمی)', 0, 0, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'send_to_pargar' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_username', '', 'نام کاربری API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_username' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_password', '', 'رمز عبور API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_password' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'pargar_api_token', '', 'توکن ثابت API پرگار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'pargar_api_token' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) SELECT 'telegram_bot_token', '', 'توکن بات تلگرام', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'telegram_bot_token' LIMIT 1); @@ -1119,6 +1139,25 @@ UPDATE `settings` SET `type` = 'number' WHERE `key` IN ( 'deposit_sms_support_number' ); +-- حسابداری: یک select مرکزی + can_edit=0 +UPDATE `settings` SET `can_edit` = 0, `is_active` = 0 WHERE `key` IN ('send_to_tahesab', 'send_to_pargar'); +UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( + 'accounting_provider', + 'tahesab_host', 'tahesab_port', 'tahesab_token', 'tahesab_db', 'tahesab_bank_account', + 'pargar_username', 'pargar_password', 'pargar_api_token' +); +UPDATE `settings` SET `title_fa` = 'سیستم حسابداری', `type` = 'select', `description` = 'none,pargar,tahesab' +WHERE `key` = 'accounting_provider'; +UPDATE `settings` SET `description` = 'سیستم حسابداری: none=هیچکدام، pargar=API پرگار، tahesab=ارسال خودکار ته‌حساب.' WHERE `key` = 'accounting_provider'; +UPDATE `settings` SET `value` = 'pargar' +WHERE `key` = 'accounting_provider' + AND TRIM(COALESCE(`value`, '')) IN ('', 'none') + AND EXISTS (SELECT 1 FROM (SELECT `value` FROM `settings` WHERE `key` = 'send_to_pargar') AS s WHERE s.`value` IN ('true', '1', 'yes')); +UPDATE `settings` SET `value` = 'tahesab' +WHERE `key` = 'accounting_provider' + AND TRIM(COALESCE(`value`, '')) IN ('', 'none') + AND EXISTS (SELECT 1 FROM (SELECT `value` FROM `settings` WHERE `key` = 'send_to_tahesab') AS s WHERE s.`value` IN ('true', '1', 'yes')); + COMMIT; SELECT 'deploy_settings_const.sql finished' AS status; diff --git a/routes/admin.php b/routes/admin.php index eb80132..35c100a 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -15,6 +15,7 @@ use App\Http\Controllers\Customer\PriceTriggerController; use App\Http\Controllers\Finance\FinanceController; use App\Http\Controllers\Admin\ProductController; use App\Http\Controllers\Admin\TahesabController; +use App\Http\Controllers\Admin\PargarController; use App\Http\Controllers\Admin\FileController; use App\Http\Controllers\Site\OfferCodesController; use App\Http\Controllers\Admin\SettingsController; @@ -163,6 +164,15 @@ Route::middleware('auth:user')->group(function (){ Route::post('tahesab/{id}/retry', [TahesabController::class, 'retrySanad']); Route::post('customer/{id}/tahesab/register', [TahesabController::class, 'registerCustomer']); + Route::post('pargar/table', [PargarController::class, 'table']); + Route::get('pargar/customer-sync/status', [PargarController::class, 'customerSyncStatus']); + Route::post('pargar/customer-sync/panel-to-pargar', [PargarController::class, 'syncPanelToPargar']); + Route::post('pargar/customer-sync/import-from-pargar', [PargarController::class, 'importFromPargar']); + Route::post('pargar/customer-sync/rollback-import', [PargarController::class, 'rollbackImport']); + Route::get('pargar/{id}', [PargarController::class, 'show']); + Route::post('pargar/{id}/retry', [PargarController::class, 'retrySanad']); + Route::post('customer/{id}/pargar/register', [PargarController::class, 'registerCustomer']); + Route::get('test', function () { $data = [ "value" => 2000, diff --git a/routes/pargar.php b/routes/pargar.php index 4cf9885..90fe098 100644 --- a/routes/pargar.php +++ b/routes/pargar.php @@ -1,344 +1,24 @@ take(100)->get()->each(function ($item) { - if (is_string($item->finance_data)) { - $decoded = json_decode($item->finance_data, true); - if (json_last_error() === JSON_ERROR_NONE) { - $item->finance_data = $decoded; // Laravel will re-encode correctly - $item->save(); - } - } - }); - - $pars = Pargar::latest('id')->take(100) - ->select(['id','finance_data','m']) - ->get(); - -// foreach ($pars as $par) { -// if (!empty($par->finance_data['Customers'])) { -// $par->m = 'CUSTOMER'; -// $par->save(); -// $cu = Customer::where("pargar_id", $par->finance_data['Customers'][0]['AccountId'])->first(); -// if (!($cu)) { -// $cu = new Customer(); -// $cu->agent_id = 3137; -// $cu->type = 2; -// } -// $cu->pargar_id = $par->finance_data['Customers'][0]['AccountId']; -// $cu->tahesab_id = $par->finance_data['Customers'][0]['AccountId']; -// $cu->lname = $par->finance_data['Customers'][0]['FullName']; -// $cu->name = $par->finance_data['Customers'][0]['FullName']; -// $cu->mobile = $par->finance_data['Customers'][0]['CellPhone']; -// $cu->save(); -// } -// if (!empty($par->finance_data['accountName']) && !empty($par->finance_data['accountId']) && !empty($par->finance_data['transactions'])) { -// $par->m = 'trans'; -// $par->save(); -// $cu = Customer::where("pargar_id", $par->finance_data['accountId'])->first(); -// if (!($cu)) { -// $cu = new Customer(); -// $cu->agent_id = 3137; -// $cu->type = 2; -// } -// $accountId = $par->finance_data['accountId']; -// foreach ($par->finance_data['transactions'] as $transaction) { -// $docId = $transaction['docId']; -// // Check if docId already exists -// if (PargarDoc::where('docId', $docId)->exists()) { -// continue; // Skip duplicates -// } -// -// // Save new transaction -// PargarDoc::create([ -// 'docId' => $docId, -// 'date' => $transaction['date'], -// 'docType' => $transaction['docType'], -// 'desc' => $transaction['desc'], -// 'goldState' => $transaction['goldState'], -// 'rialState' => $transaction['rialState'], -// 'bedGold' => $transaction['bedGold'], -// 'besGold' => $transaction['besGold'], -// 'bedRial' => $transaction['bedRial'], -// 'besRial' => $transaction['besRial'], -// 'remainGold' => $transaction['remainGold'], -// 'remainRial' => $transaction['remainRial'], -// 'accountId' => $accountId, -// ]); -// } -// $cu->name = $par->finance_data['accountName']; -// $cu->fname = $par->finance_data['accountName']; -// -// $cu->finance_data = ($par->finance_data['transactions']);; -// $cu->mobile = $par->finance_data['accountId']; -// $cu->pargar_id = $par->finance_data['accountId']; -// $cu->tahesab_id = $par->finance_data['accountId']; -// $cu->save(); -// } -// if (!empty($par->finance_data['GoldInv']) && !empty($par->finance_data['RialInv'])) { -// $par->m = 'MANDEH'; -// $par->save(); -// $cu = Customer::where("pargar_id", $par->finance_data['AccountId'])->first(); -// if (!($cu)) { -// $par->m = 'MANDEHnoC'; -// $par->save(); -// continue; -//// $cu = new Customer(); -// } -// $cu->pargar_id = $par->finance_data['AccountId']; -// $cu->tahesab_id = $par->finance_data['AccountId']; -// $cu->gold_balance = $par->finance_data['GoldInv']; -// $cu->rial_balance = $par->finance_data['RialInv']; -// $cu->save(); -// } -// } -} -Route::post('/login', function (Request $request) { - /* - * accounting@09131523432.com - hJNFTV - */ - if ($request->password !== 'mont' && $request->password !== 'Abc123' ) { - return response()->json([ - 'success' => false, - 'data' => [], - 'message' => 'Invalid credentials!' - ]); - } - finalizeProcessing(); - return response()->json([ - 'success' => true, - 'data' => ['token' => base64_encode(Str::random(40))], - 'data' => ['token' => 'wQ12e245d5%rdpb78oBh31Aos*bIdQemiUeeq9e9G!oey23SMXp40Ew2fodjx9J5buKNW0M4@nYMr1PR6d0KtuqhLQlx*K$'], - 'message' => 'You are logged in successfully.' - ]); -}); -Route::post('/customers', function (Request $request) { - $data = $request->all(); - if (!empty($data['Customers'])) { - $cu = Customer::where("finance_code", $data['Customers'][0]['AccountId'])->first(); - $message ="با موفقیت ویرایش شد."; - - if (!($cu)) { - $cu = new Customer(); - $cu->finance_code = 3137; - $cu->referral_to_id = 'ghatre'; - $message ="با موفقیت ایجاد شد."; - } - do { - $referral = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 4); - } while (Customer::where('referral_id', $referral)->exists()); - $data['referral_id'] = $referral; - - do { - $vcn = $this->Config('default_vc_number') . rand(10, 99) . '-' . rand(1000, 9999) . '-' . rand(1000, 9999); - } while (Customer::where('virtual_card_number', $vcn)->exists()); - $data['virtual_card_number'] = $vcn; - - $cu->lname = $data['Customers'][0]['FullName']; - $cu->name = $data['Customers'][0]['FullName']; - $cu->mobile = $data['Customers'][0]['CellPhone']; - $cu->save(); - } - return response()->json([ - 'state' => 'true', - 'msg' =>$cu->finance_code.":" . $cu->name.$message, - 'result' => 'OK' - ]); -}); -Route::get('/GetCustomers', function (Request $request) { - $customers = Customer::/*where('finance_is_saved', 0)->*/whereNull('finance_code') - ->limit(100) - ->get(['id', 'fname as name', 'lname as family', 'mobile']); - return response()->json([ - 'state' => 'true', - 'data' => $customers, - 'msg' =>'1', - 'result' => 'OK' - ]); - -}); -Route::post('/CustomerConfirm', function (Request $request) { - $customers = $request->input('customers', []); - - - foreach ($customers as $customer) { - $customerRecord = Customer::find($customer['customer_id']); - if ($customerRecord) { - $customerRecord->finance_code = (int)($customer['accounting_id'] ?? 0); - $customerRecord->save(); - } - } - return response()->json([ - 'state' => 'true', - 'data' => $customers, - 'msg' =>'1', - 'result' => 'OK' - ]); +Route::middleware('pargar.auth')->group(function () { + Route::post('/customers', [PargarInboundController::class, 'upsertCustomers']); + Route::get('/orders', [PargarInboundController::class, 'listOrders']); + Route::post('/orders', [PargarInboundController::class, 'confirmOrders']); + Route::post('/documents', [PargarInboundController::class, 'storeDocuments']); + Route::post('/mande', [PargarInboundController::class, 'storeMande']); + Route::get('/GetCustomers', [PargarInboundController::class, 'listNewCustomers']); + Route::post('/CustomerConfirm', [PargarInboundController::class, 'confirmCustomers']); }); -Route::post('/orders', function (Request $request) { - $OrderIds = $request->input('OrderIds', []); - - try { - foreach ($OrderIds as $orderId) { - Order::where('id', $orderId)->update(['finance_code' => $orderId]); - } - }catch (\Exception $e){ - return $e->getMessage(); - } - - +Route::any('{any}', function () { return response()->json([ - 'state' => true, - 'msg' => 'ذخیره شد', - 'result' => 'OK', - 'duplicated' => [], - 'documents' => [] - ]); -}); - - -Route::get( '/orders', function (Request $request) { - $data = $request->all(); - - $orders = Order::where('sts', 2)->whereNull('finance_code')->limit(100)->get(); - $orders_new = $orders->map(function ($order) { - $customer = Customer::find((int)($order->customer_id ?? 0)); - return [ - 'OrderId' => (string)$order->id, - 'OrderType' => $order->direction == 1 ? 0 : 1, - 'PriceType' => 1, - 'CustomerAccountId' => $customer->finance_code ?? 4, - 'ItemId' => 11, - 'itemName' => 'ابشده', - 'OrderDate' => $order->orders - ? Jalalian::fromCarbon($order->orders)->format('Y/m/d-H:i:s') - : Jalalian::fromCarbon($order->created_at)->format('Y/m/d-H:i:s'), - 'Fee' => $order->price ?? 0, - 'Count' => 0, - 'Weight' => $order->amount ?? 0, - 'Price' => $order->total_price, - 'Carat' => 750, - 'Description' => $order->description ?? '', - ]; - }); - - return response()->json([ - 'state' => 'true', - 'msg' => '', - 'data' => ($orders_new), - 'result' => 'OK', - 'duplicated' => [], - 'documents' => [] - ]); -}); -Route::post('/pdf', function (Request $request) { - - $data = $request->all(); - $head = $request->headers->all(); - $Pargar = new Pargar(); - $Pargar->ip = $request->ip(); // Gets the client IP address - $Pargar->m = 'pdf'; // Gets the client IP address - $Pargar->finance_data = json_encode($data); // Storing request data as JSON - $Pargar->finance_head = json_encode($head); // Storing headers as JSON - $Pargar->save(); // Don't forget to save the model - - Log::info('📋 هدرهای پیدی اف :', $request->headers->all()); - - // 📦 لاگ بدنه‌ی درخواست (Body) - $data = $request->all(); - Log::info('📦 محتوای درخواست ( پیدی اف ):', $data); - - $key = 'wQ12e245d5%rdpb78oBh31Aos*bIdQemiUeeq9e9G!oey23SMXp40Ew2fodjx9J5buKNW0M4@nYMr1PR6d0KtuqhLQlx*K$'; - $auth = $request->header('pargar') ?? $request->header('Authorization'); - if ($auth !== $key && $auth !== 'Bearer ' . $key) { - return response()->json(['auth needed'], 401); - } - finalizeProcessing(); - return response()->json([ - 'state' => 'true', - 'msg' => 'PDF uploaded successfully', -// 'data' => ['fileName' => $fileName], - 'result' => 'OK' - ]); -}); -Route::post('/mande', function (Request $request) { - $data = $request->all(); - - if (!$cu = Customer::where("finance_code",$data['AccountId'])->first()) { - } - if ( $wallet = $cu->wallet->where('fund_id', null)->first()){ - $goldInv = isset($data['GoldInv']) ? ((float)str_replace('/', '.', $data['GoldInv'])) : 0; - $RialInv = isset($data['RialInv']) ? ((float)str_replace('/', '.', $data['RialInv'])) : 0; - $goldDiff = $goldInv - $wallet->gold ; - $rialInvDiff = $RialInv - $wallet->cash ; - }else{ - $goldDiff = isset($data['GoldInv']) ? ((float)str_replace('/', '.', $data['GoldInv'])) : 0; - $rialInvDiff = isset($data['RialInv']) ? ((float)str_replace('/', '.', $data['RialInv'])) : 0; - } - - if (abs($goldDiff) >= 0.01 || abs($rialInvDiff) >= 1) { - $wallet_interface = new WalletInterface($cu->id, 2); - new TransactionInterface($wallet_interface, [ - "cash" => $rialInvDiff, - "gold" =>$goldDiff, - 'expire_at' => now(), - 'active' => true, - 'start_at' => now(), - ], 22,$goldDiff> 0, $rialInvDiff > 0); - } - $cu->gold_balance = $data['GoldInv']; - $cu->rial_balance = $data['RialInv']; - $cu->save(); - return response()->json([ - 'state' => 'true', - 'msg' => "با موفقیت دریافت شد", + 'success' => false, + 'message' => 'not found', 'data' => null, - 'dataWeb' => $cu->id ?? 0, - 'result' => 'OK', - 'duplicated' => [], - 'documents' => [] - ]); -}); -Route::post('/documents', function (Request $request) { - - return response()->json([ - 'state' => true, - 'msg' => "با موفقیت دریافت شد", - 'data' => null, - 'result' => 'OK', - - ]); -}); - -Route::any('{any}', function (Request $request) { -// finalizeProcessing(); - - return response()->json([ - 'state' => false, - 'msg' => "not found", - ]); -})->where('any', '.*'); \ No newline at end of file + ], 404); +})->where('any', '.*');