diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index dc32f75..f652323 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -29,7 +29,9 @@ class SettingsController extends Controller if ($setting) { $setting->value = $request->value; $setting->description = $request->description; - $setting->is_active = $request->is_active; + if ($request->has('is_active')) { + $setting->is_active = filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN) ? 1 : 0; + } $setting->title_fa = $request->title_fa ?? ''; if (Setting::hasTypeColumn()) { $setting->type = $request->type ?? ''; @@ -41,7 +43,7 @@ class SettingsController extends Controller $setting->title_fa = $request->title_fa ?? ''; $setting->value = $request->value; $setting->description = $request->description; - $setting->is_active = $request->is_active; + $setting->is_active = filter_var($request->is_active ?? true, FILTER_VALIDATE_BOOLEAN) ? 1 : 0; $setting->can_edit = 1; if (Setting::hasTypeColumn()) { $setting->type = $request->type ?? ''; diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 3709572..a4c206f 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -152,7 +152,13 @@ class Controller extends BaseController } public static function Config($name) { - return Setting::where('key',$name)->first()->value ?? false; + $row = Setting::where('key', $name)->first(); + + if ($row && $row->is_active && $row->value !== null && $row->value !== '') { + return $row->value; + } + + return false; } protected static function metalTypeSettingValue(): ?string diff --git a/app/Http/Controllers/Site/ReportController.php b/app/Http/Controllers/Site/ReportController.php index 29e0f1a..d71be10 100644 --- a/app/Http/Controllers/Site/ReportController.php +++ b/app/Http/Controllers/Site/ReportController.php @@ -10,7 +10,6 @@ use App\Models\Setting; use App\Models\ConfigStatic; use App\Models\Customer; use App\Services\MontzarService; -use App\Services\EtehadiePriceService; use App\Services\ZaarboxPriceService; use App\Models\Price; use App\Models\PriceCandle; @@ -331,15 +330,12 @@ class ReportController extends Controller if ($pr_product && !$closed) { if ($priceProvider === 'main_product') { if (Product::hasStoredPriceColumns()) { - app(EtehadiePriceService::class)->syncProductFromApi($pr_product->fresh()); + app(ZaarboxPriceService::class)->syncProductFromApi($pr_product->fresh()); $pr_product->refresh(); $pr_price = (float) $pr_product->price + (float) ($pr_product->price_profit ?? 0); } else { - $apiUrl = $config->getString('zaarbox_api_url', '') - ?: $config->getString('etehadie_api_url', 'https://price.zaarbox.ir/api/free'); - $live = app(EtehadiePriceService::class)->fetchLiveOrderPrice( - $pr_product->reading_method, - $apiUrl + $live = app(ZaarboxPriceService::class)->fetchLiveOrderPrice( + $pr_product->reading_method ); $pr_price = (float) ($live['order_price'] ?? 0); } diff --git a/app/Services/ConfigService.php b/app/Services/ConfigService.php index 9a9103c..16d0eef 100644 --- a/app/Services/ConfigService.php +++ b/app/Services/ConfigService.php @@ -8,7 +8,7 @@ use App\Models\Setting; class ConfigService { - public const PRICE_PROVIDERS = ['montzar', 'etehadie', 'taban_gohar', 'main_product', 'zaarbox']; + public const PRICE_PROVIDERS = ['montzar', 'taban_gohar', 'main_product', 'zaarbox']; public function Config($name) { @@ -22,7 +22,7 @@ class ConfigService { $row = Setting::where('key', $key)->first(); - if ($row !== null && $row->value !== null && $row->value !== '') { + if ($row !== null && $row->is_active && $row->value !== null && $row->value !== '') { return $row->value; } @@ -91,7 +91,7 @@ class ConfigService } /** - * تنها منبع فعال قیمت — فقط یکی از: montzar | etehadie | taban_gohar | main_product + * تنها منبع فعال قیمت — montzar | taban_gohar | main_product | zaarbox * * اولویت: * 1) price_provider (یا price_primary_source قدیمی) @@ -156,7 +156,7 @@ class ConfigService { $provider = $this->priceProvider(); - return in_array($provider, ['montzar', 'etehadie'], true) ? $provider : 'montzar'; + return in_array($provider, ['montzar'], true) ? $provider : 'montzar'; } public function usesMontzarPricing(): bool @@ -164,9 +164,10 @@ class ConfigService return $this->priceProvider() === 'montzar'; } + /** @deprecated منبع etehadie حذف شده */ public function usesEtehadiePricing(): bool { - return $this->priceProvider() === 'etehadie'; + return false; } public function usesMainProductPricing(): bool diff --git a/app/Services/EtehadiePriceService.php b/app/Services/EtehadiePriceService.php deleted file mode 100644 index 2085d6e..0000000 --- a/app/Services/EtehadiePriceService.php +++ /dev/null @@ -1,216 +0,0 @@ -config->usesEtehadiePricing(); - } - - public function apiUrl(): string - { - $url = trim((string) $this->config->getString( - 'etehadie_api_url', - (string) config('price_providers.etehadie_api_url', 'http://109.122.246.48:4949/api/free') - )); - - return $url !== '' ? $url : 'http://109.122.246.48:4949/api/free'; - } - - /** کلید محصول در پاسخ API اتحادیه (همان price_method گلد علی) */ - public function priceKey(): string - { - $key = trim((string) $this->config->getString( - 'price_method', - (string) config('price_providers.price_method', '') - )); - - return $key; - } - - /** - * @return array{price: int, raw: array|null} - */ - public function fetchMainGramPrice(): array - { - if (!$this->isEnabled() && $this->priceKey() === '') { - return ['price' => 0, 'order_price' => 0, 'raw' => null]; - } - - try { - $prices = Http::withoutVerifying() - ->timeout(20) - ->get($this->apiUrl()) - ->json(); - - if (!is_array($prices)) { - return ['price' => 0, 'order_price' => 0, 'raw' => null]; - } - - $key = $this->priceKey(); - $collection = collect($prices); - $row = $key !== '' - ? $collection->firstWhere('key', $key) - : $collection->first(); - - if (empty($row)) { - return ['price' => 0, 'order_price' => 0, 'raw' => null]; - } - - $base = (float) ($row['price'] ?? 0); - $profit = (float) ($row['profit'] ?? 0); - $gramPrice = (int) round($base / 10 + $profit); - // همان مقیاسی که سفارش/جدول prices گلد علی استفاده می‌کند (base + profit) - $orderPrice = (int) round($base + $profit); - - return ['price' => $gramPrice, 'order_price' => $orderPrice, 'raw' => $row]; - } catch (\Throwable $e) { - Log::warning('Etehadie price fetch failed', ['message' => $e->getMessage()]); - - return ['price' => 0, 'order_price' => 0, 'raw' => null]; - } - } - - /** @return array>|null */ - public function fetchPriceList(): ?array - { - try { - $prices = Http::withoutVerifying() - ->timeout(20) - ->get($this->apiUrl()) - ->json(); - - return is_array($prices) ? $prices : null; - } catch (\Throwable $e) { - Log::warning('Etehadie price list fetch failed', ['message' => $e->getMessage()]); - - return null; - } - } - - public function syncProductsFromApi(): bool - { - $prices = $this->fetchPriceList(); - if ($prices === null) { - return false; - } - - $products = \App\Models\Product::with([])->whereNotNull('reading_method')->get(); - $collection = collect($prices); - $copper = null; - $dollar = null; - - foreach ($products as $product) { - $RPrice = $collection->firstWhere('key', $product->reading_method); - if (empty($RPrice)) { - continue; - } - - if (($RPrice['name'] ?? '') === 'TGJU فلز مس') { - $copper = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0); - } - if (($RPrice['name'] ?? '') === 'TGJU دلار') { - $dollar = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0); - } - if (($RPrice['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') { - $RPrice['price'] = ($RPrice['price'] ?? 0) / 4.3318; - } - - ProductPriceService::syncFromReference( - $product, - (int) $RPrice['price'], - (int) ($RPrice['profit'] ?? 0) - ); - } - - if ($copper !== null && $dollar !== null) { - $cp = ($copper / 1000000) * $dollar; - $copperProduct = \App\Models\Product::find(33); - if ($copperProduct) { - ProductPriceService::syncFromReference($copperProduct, (int) round($cp), 0); - } - } - - return true; - } - - /** - * قیمت زنده از API بدون نوشتن در products (برای DB بدون ستون price). - * - * @return array{order_price: int, raw: array|null} - */ - public function fetchLiveOrderPrice(?string $readingMethod, ?string $apiUrl = null): array - { - $empty = ['order_price' => 0, 'raw' => null]; - $readingMethod = trim((string) $readingMethod); - if ($readingMethod === '') { - return $empty; - } - - try { - $url = $apiUrl ?: $this->apiUrl(); - $prices = Http::withoutVerifying()->timeout(20)->get($url)->json(); - if (!is_array($prices)) { - return $empty; - } - - $row = collect($prices)->firstWhere('key', $readingMethod) - ?? collect($prices)->firstWhere('id', $readingMethod); - if (empty($row)) { - return $empty; - } - - $orderPrice = (int) round((float) ($row['price'] ?? 0) + (float) ($row['profit'] ?? 0)); - - return ['order_price' => $orderPrice, 'raw' => $row]; - } catch (\Throwable $e) { - Log::warning('Live board price fetch failed', ['message' => $e->getMessage()]); - - return $empty; - } - } - - /** به‌روز قیمت یک محصول از API با reading_method */ - public function syncProductFromApi(Product $product): bool - { - if (!Product::hasStoredPriceColumns()) { - return false; - } - - if (!$product->reading_method) { - return false; - } - - $prices = $this->fetchPriceList(); - if ($prices === null) { - return false; - } - - $RPrice = collect($prices)->firstWhere('key', $product->reading_method); - if (empty($RPrice)) { - return false; - } - - if (($RPrice['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') { - $RPrice['price'] = ($RPrice['price'] ?? 0) / 4.3318; - } - - ProductPriceService::syncFromReference( - $product, - (int) $RPrice['price'], - (int) ($RPrice['profit'] ?? 0) - ); - - return true; - } -} diff --git a/app/Services/ZaarboxPriceService.php b/app/Services/ZaarboxPriceService.php index 3de03e3..170d838 100644 --- a/app/Services/ZaarboxPriceService.php +++ b/app/Services/ZaarboxPriceService.php @@ -2,6 +2,7 @@ namespace App\Services; +use App\Models\Product; use Carbon\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; @@ -149,6 +150,135 @@ class ZaarboxPriceService } } + /** @return array>|null */ + public function fetchPriceList(): ?array + { + try { + $prices = Http::withoutVerifying() + ->timeout(20) + ->get($this->apiUrl()) + ->json(); + + return is_array($prices) ? $prices : null; + } catch (\Throwable $e) { + Log::warning('Zaarbox price list fetch failed', ['message' => $e->getMessage()]); + + return null; + } + } + + /** + * @return array{order_price: int, raw: array|null} + */ + public function fetchLiveOrderPrice(?string $readingMethod, ?string $apiUrl = null): array + { + $empty = ['order_price' => 0, 'raw' => null]; + $readingMethod = trim((string) $readingMethod); + if ($readingMethod === '') { + return $empty; + } + + try { + $url = $apiUrl ?: $this->apiUrl(); + $prices = Http::withoutVerifying()->timeout(20)->get($url)->json(); + if (!is_array($prices)) { + return $empty; + } + + $row = $this->findRow(collect($prices), $readingMethod); + if (empty($row)) { + return $empty; + } + + $orderPrice = (int) round((float) ($row['price'] ?? 0) + (float) ($row['profit'] ?? 0)); + + return ['order_price' => $orderPrice, 'raw' => $row]; + } catch (\Throwable $e) { + Log::warning('Zaarbox live board price fetch failed', ['message' => $e->getMessage()]); + + return $empty; + } + } + + public function syncProductsFromApi(): bool + { + $prices = $this->fetchPriceList(); + if ($prices === null) { + return false; + } + + $products = Product::with([])->whereNotNull('reading_method')->get(); + $collection = collect($prices); + $copper = null; + $dollar = null; + + foreach ($products as $product) { + $RPrice = $collection->firstWhere('key', $product->reading_method); + if (empty($RPrice)) { + continue; + } + + if (($RPrice['name'] ?? '') === 'TGJU فلز مس') { + $copper = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0); + } + if (($RPrice['name'] ?? '') === 'TGJU دلار') { + $dollar = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0); + } + if (($RPrice['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') { + $RPrice['price'] = ($RPrice['price'] ?? 0) / 4.3318; + } + + ProductPriceService::syncFromReference( + $product, + (int) $RPrice['price'], + (int) ($RPrice['profit'] ?? 0) + ); + } + + if ($copper !== null && $dollar !== null) { + $cp = ($copper / 1000000) * $dollar; + $copperProduct = Product::find(33); + if ($copperProduct) { + ProductPriceService::syncFromReference($copperProduct, (int) round($cp), 0); + } + } + + return true; + } + + public function syncProductFromApi(Product $product): bool + { + if (!Product::hasStoredPriceColumns()) { + return false; + } + + if (!$product->reading_method) { + return false; + } + + $prices = $this->fetchPriceList(); + if ($prices === null) { + return false; + } + + $RPrice = collect($prices)->firstWhere('key', $product->reading_method); + if (empty($RPrice)) { + return false; + } + + if (($RPrice['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') { + $RPrice['price'] = ($RPrice['price'] ?? 0) / 4.3318; + } + + ProductPriceService::syncFromReference( + $product, + (int) $RPrice['price'], + (int) ($RPrice['profit'] ?? 0) + ); + + return true; + } + /** * @return array{DAILY: array, WEEKLY: array, MONTHLY: array} */ diff --git a/config/price_providers.php b/config/price_providers.php index 7fbf1aa..b7686d6 100644 --- a/config/price_providers.php +++ b/config/price_providers.php @@ -4,7 +4,7 @@ * پیش‌فرض وقتی کلید در جدول settings نیست. * * منبع قیمت: یک کلید → price_provider - * montzar | etehadie | taban_gohar | main_product | zaarbox + * montzar | taban_gohar | main_product | zaarbox * * سازگاری قدیمی (بدون price_provider): * montzar_price=true → montzar @@ -13,7 +13,6 @@ */ return [ 'price_provider' => 'montzar', - 'etehadie_api_url' => 'http://109.122.246.48:4949/api/free', 'zaarbox_api_url' => 'https://price.zaarbox.ir/api/free', 'zaarbox_price_key' => '', /** UUID نمودار Zaarbox — خالی = پیش‌فرض ca3800a0-... در ZaarboxPriceService */ diff --git a/routes/web.php b/routes/web.php index aa6c950..99f1892 100644 --- a/routes/web.php +++ b/routes/web.php @@ -16,7 +16,7 @@ use App\Models\Message; use Illuminate\Http\Request; Route::get('/refPricer', function () { - $ok = app(\App\Services\EtehadiePriceService::class)->syncProductsFromApi(); + $ok = app(\App\Services\ZaarboxPriceService::class)->syncProductsFromApi(); return response()->json($ok); });