$response['Sh_factor'] ?? null, 'tahesab_id' => $response['OK'], 'factor_number' => $response['Factor_Number'] ?? null, 'tah_id' => $response['ID'] ?? null, 'res' => json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), 'sync_status' => self::STATUS_SUCCESS, 'sync_log' => null, ]; if ($payload !== null) { $update['data'] = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); } if ($this->hasSyncColumns()) { Tahesab::where('id', $tahesab->id)->update($update); } else { unset($update['sync_status'], $update['sync_log']); Tahesab::where('id', $tahesab->id)->update($update); } } public function markFailed(Tahesab $tahesab, mixed $response = null, ?string $extra = null): void { $update = [ 'res' => is_array($response) ? json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : (is_string($response) ? $response : null), ]; if ($this->hasSyncColumns()) { $update['sync_status'] = self::STATUS_FAILED; $update['sync_log'] = $this->buildLog($response, $extra); } Tahesab::where('id', $tahesab->id)->update($update); } public function isFailed(Tahesab $tahesab): bool { if ($this->hasSyncColumns()) { return ($tahesab->sync_status ?? null) === self::STATUS_FAILED || (empty($tahesab->tahesab_id) && ($tahesab->sync_status ?? null) !== self::STATUS_SUCCESS); } return empty($tahesab->tahesab_id); } public function registerOnCreate(Customer $customer): void { if (! empty($customer->moshtari_code) || ! $this->isSyncEnabled()) { return; } $customerId = (int) $customer->id; dispatch(function () use ($customerId) { $service = app(TahesabSyncService::class); $customer = Customer::find($customerId); if ($customer === null || ! empty($customer->moshtari_code) || ! $service->isSyncEnabled()) { return; } try { $result = $service->registerCustomer($customer); if (! ($result['ok'] ?? false)) { Log::warning('Tahesab auto-register on customer create failed', [ 'customer_id' => $customerId, 'message' => $result['message'] ?? null, ]); } } catch (\Throwable $e) { Log::warning('Tahesab auto-register on customer create threw', [ 'customer_id' => $customerId, 'error' => $e->getMessage(), ]); } })->afterResponse(); } public function registerCustomer(Customer $customer): array { $customer->refresh(); if (! empty($customer->moshtari_code)) { return [ 'ok' => true, 'message' => 'مشتری قبلاً در ته‌حساب ثبت شده است', 'moshtari_code' => $customer->moshtari_code, ]; } $controller = app(TahesabController::class); $result = $controller->createCustomerInTahesab($customer->id); if (is_string($result)) { return ['ok' => false, 'message' => $result]; } $customer->refresh(); if (empty($customer->moshtari_code)) { return ['ok' => false, 'message' => 'ثبت مشتری در ته‌حساب ناموفق بود']; } return [ 'ok' => true, 'message' => 'مشتری با موفقیت در ته‌حساب ثبت شد', 'moshtari_code' => $customer->moshtari_code, ]; } public function retry(Tahesab $tahesab): array { if (! $this->isFailed($tahesab) && ! empty($tahesab->tahesab_id)) { return ['ok' => false, 'message' => 'این سند قبلاً در ته‌حساب ثبت شده است']; } $payload = json_decode((string) $tahesab->data, true) ?: []; $handler = $payload['handler'] ?? $this->inferHandler($tahesab); $controller = app(TahesabController::class); $result = match ($handler) { 'wallet' => $controller->wallet(array_merge($payload, ['_retry_tahesab_id' => $tahesab->id]), $tahesab), 'walletGold' => $controller->walletGold(array_merge($payload, ['_retry_tahesab_id' => $tahesab->id]), $tahesab), 'storeTrade' => $controller->storeTrade(array_merge($payload, ['_retry_tahesab_id' => $tahesab->id]), $tahesab), 'goldReward' => $controller->goldReward(array_merge($payload, ['_retry_tahesab_id' => $tahesab->id]), $tahesab), default => false, }; $tahesab->refresh(); if ($result !== false && ! empty($tahesab->tahesab_id)) { return ['ok' => true, 'message' => 'سند با موفقیت در ته‌حساب ثبت شد', 'tahesab' => $tahesab]; } return [ 'ok' => false, 'message' => $tahesab->sync_log ?: 'ارسال مجدد به ته‌حساب ناموفق بود', 'tahesab' => $tahesab, ]; } private function inferHandler(Tahesab $tahesab): string { if ($tahesab->order_id) { return 'storeTrade'; } if ($tahesab->type === 'ريال') { return 'wallet'; } $desc = (string) $tahesab->desc; if (str_contains($desc, 'شارژ کیف') || str_contains($desc, 'برداشت از کیف')) { return 'walletGold'; } return 'goldReward'; } public function isSyncEnabled(): bool { $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 !== ''; } private function hasSyncColumns(): bool { return Schema::hasTable('tahesab') && Schema::hasColumn('tahesab', 'sync_status'); } }