diff --git a/app/Http/Controllers/Site/ReportController.php b/app/Http/Controllers/Site/ReportController.php index ac4cd0b..fe925a6 100644 --- a/app/Http/Controllers/Site/ReportController.php +++ b/app/Http/Controllers/Site/ReportController.php @@ -124,6 +124,7 @@ class ReportController extends Controller protected function appendUpPrices(array $payload): array { $payload['up'] = $this->buildUpDownPrices(); + $payload['last_historical'] = app(ProductDisplayPriceService::class)->resolveHistoricalBasePrice(); app(ProductDisplayPriceService::class)->cacheLivePricePayload($payload); return $payload; diff --git a/app/Services/ProductDisplayPriceService.php b/app/Services/ProductDisplayPriceService.php index 1502409..e93f4d2 100644 --- a/app/Services/ProductDisplayPriceService.php +++ b/app/Services/ProductDisplayPriceService.php @@ -65,34 +65,25 @@ class ProductDisplayPriceService private function applyAppPrice(Product $product, int $basePrice): void { - $storedPrice = (int) ($product->price ?? 0); - $useLast = Product::hasUseLastPriceIfZeroColumn() - && ($product->use_last_price_if_zero ?? false); - - if ($basePrice <= 0) { - if ($useLast && $storedPrice > 0) { - return; - } - - $product->setAttribute('price', 0); - if (Schema::hasColumn($product->getTable(), 'price_profit')) { - $product->setAttribute('price_profit', 0); - } - - return; - } - + $useLast = $this->productUsesLastPriceIfZero($product); $offset = Product::hasPriceOffsetColumn() ? (float) ($product->price_offset_percent ?? 0) : 0.0; - $computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset); - if ($computed <= 0) { - if ($useLast && $storedPrice > 0) { - return; - } + if ($basePrice <= 0) { + $this->applyPriceOrFallback($product, 0, $useLast); - $product->setAttribute('price', 0); + return; + } + + $computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset); + $this->applyPriceOrFallback($product, $computed, $useLast); + } + + private function applyPriceOrFallback(Product $product, int $computed, bool $useLast): void + { + if ($computed > 0) { + $product->setAttribute('price', $computed); if (Schema::hasColumn($product->getTable(), 'price_profit')) { $product->setAttribute('price_profit', 0); } @@ -100,12 +91,71 @@ class ProductDisplayPriceService return; } - $product->setAttribute('price', $computed); + if ($useLast) { + $fallback = $this->resolveLastPriceFallback($product); + if ($fallback > 0) { + $product->setAttribute('price', $fallback); + if (Schema::hasColumn($product->getTable(), 'price_profit')) { + $product->setAttribute('price_profit', 0); + } + + return; + } + } + + $product->setAttribute('price', 0); if (Schema::hasColumn($product->getTable(), 'price_profit')) { $product->setAttribute('price_profit', 0); } } + private function productUsesLastPriceIfZero(Product $product): bool + { + return Product::hasUseLastPriceIfZeroColumn() + && ($product->use_last_price_if_zero ?? false); + } + + /** + * آخرین قیمت ذخیره‌شده: اول products.price، بعد جدول prices (تاریخچه مظنه). + */ + public function resolveLastPriceFallback(Product $product): int + { + $stored = (int) ($product->price ?? 0); + if ($stored > 0) { + return $stored; + } + + $storedProfit = (int) ($product->price_profit ?? 0); + if ($storedProfit > 0) { + return $stored + $storedProfit; + } + + $historical = $this->resolveHistoricalBasePrice(); + if ($historical <= 0) { + return 0; + } + + if ($this->usesAppPrice($product) || $product->reading_method) { + $offset = Product::hasPriceOffsetColumn() + ? (float) ($product->price_offset_percent ?? 0) + : 0.0; + + return ProductPriceService::adjustedTotal($historical, 0, $offset); + } + + return $historical; + } + + public function resolveHistoricalBasePrice(): int + { + $last = Price::orderByDesc('id')->first(); + if (!$last || (float) $last->price <= 0) { + return 0; + } + + return (int) $last->price; + } + /** @param array> $feed */ private function applyReferenceFeedPrice(Product $product, array $feed, ZaarboxPriceService $zaarbox): void { @@ -116,12 +166,14 @@ class ProductDisplayPriceService $computed = $zaarbox->computeAdjustedProductPrice($product, $row); if ($computed <= 0) { - if ( - Product::hasUseLastPriceIfZeroColumn() - && ($product->use_last_price_if_zero ?? false) - && (int) ($product->price ?? 0) > 0 - ) { - return; + if ($this->productUsesLastPriceIfZero($product)) { + $fallback = $this->resolveLastPriceFallback($product); + if ($fallback > 0) { + $product->setAttribute('price', $fallback); + if (Schema::hasColumn($product->getTable(), 'price_profit')) { + $product->setAttribute('price_profit', 0); + } + } } return; diff --git a/app/Services/ProductPriceSyncService.php b/app/Services/ProductPriceSyncService.php index 3d6abd6..dcf9d9e 100644 --- a/app/Services/ProductPriceSyncService.php +++ b/app/Services/ProductPriceSyncService.php @@ -3,6 +3,7 @@ namespace App\Services; use App\Models\Product; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -61,7 +62,7 @@ class ProductPriceSyncService $basePrice = $display->resolveAppBasePrice(); if ($basePrice <= 0) { - return false; + return $this->restoreAppProductsFromHistorical($products); } $synced = false; @@ -73,6 +74,30 @@ class ProductPriceSyncService return $synced; } + /** provider صفر ولی use_last_price_if_zero — بازیابی از جدول prices به products.price */ + private function restoreAppProductsFromHistorical(Collection $products): bool + { + $historical = app(ProductDisplayPriceService::class)->resolveHistoricalBasePrice(); + if ($historical <= 0) { + return false; + } + + $synced = false; + foreach ($products as $product) { + if (!Product::hasUseLastPriceIfZeroColumn() || !($product->use_last_price_if_zero ?? false)) { + continue; + } + if ((int) ($product->price ?? 0) > 0) { + continue; + } + + ProductPriceService::syncFromReference($product, $historical, 0); + $synced = true; + } + + return $synced; + } + /** فید قدیمی — reading_method به شکل name (سازگاری با پروژه‌های قدیمی) */ private function syncFromLegacyFeed(bool $forceRefresh = false): bool {