fix bug
This commit is contained in:
@@ -6,15 +6,19 @@ use App\Models\Price;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* قیمت نمایشی محصولات آبشده با منبع «قیمت اپ» — در DB صفر است، برای API پر میشود.
|
||||
* قیمت نمایشی محصولات برای API — فقط از کش/تنظیمات (بدون HTTP روی list).
|
||||
*
|
||||
* • آبشده با «قیمت اپ» → montzar_live_price / کش /api/price/last
|
||||
* • محصول با reading_method → ردیف فید zaarbox از کش کران (۳۰ث)
|
||||
*/
|
||||
class ProductDisplayPriceService
|
||||
{
|
||||
public const LIVE_PRICE_CACHE_KEY = 'live_price_api_payload';
|
||||
|
||||
public const LIVE_PRICE_CACHE_SECONDS = 15;
|
||||
public const LIVE_PRICE_CACHE_SECONDS = 45;
|
||||
|
||||
public function usesAppPrice(Product $product): bool
|
||||
{
|
||||
@@ -29,44 +33,81 @@ class ProductDisplayPriceService
|
||||
return $this->isMeltedTradeProduct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* پر کردن price روی مدلها برای پاسخ JSON — بدون UPDATE دیتابیس
|
||||
*/
|
||||
public function enrichForApi(Collection|iterable $products): void
|
||||
{
|
||||
$needsLivePrice = false;
|
||||
$collection = collect($products);
|
||||
$zaarbox = app(ZaarboxPriceService::class);
|
||||
$zaarboxFeed = $zaarbox->getCachedPriceListOnly();
|
||||
|
||||
foreach ($products as $product) {
|
||||
if ($product instanceof Product && $this->usesAppPrice($product)) {
|
||||
$needsLivePrice = true;
|
||||
break;
|
||||
$baseAppPrice = 0;
|
||||
if ($collection->contains(fn ($p) => $p instanceof Product && $this->usesAppPrice($p))) {
|
||||
$baseAppPrice = $this->resolveAppBasePrice();
|
||||
}
|
||||
|
||||
foreach ($collection as $product) {
|
||||
if (!$product instanceof Product) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->usesAppPrice($product)) {
|
||||
$this->applyAppPrice($product, $baseAppPrice);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($product->reading_method && is_array($zaarboxFeed)) {
|
||||
$this->applyReferenceFeedPrice($product, $zaarboxFeed, $zaarbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$needsLivePrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
$basePrice = $this->resolveAppBasePrice();
|
||||
private function applyAppPrice(Product $product, int $basePrice): void
|
||||
{
|
||||
if ($basePrice <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($products as $product) {
|
||||
if (!$product instanceof Product || !$this->usesAppPrice($product)) {
|
||||
continue;
|
||||
$offset = Product::hasPriceOffsetColumn()
|
||||
? (float) ($product->price_offset_percent ?? 0)
|
||||
: 0.0;
|
||||
|
||||
$computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset);
|
||||
if ($computed <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product->setAttribute('price', $computed);
|
||||
if (Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param array<int, array<string, mixed>> $feed */
|
||||
private function applyReferenceFeedPrice(Product $product, array $feed, ZaarboxPriceService $zaarbox): void
|
||||
{
|
||||
$row = $zaarbox->findFeedRow($feed, (string) $product->reading_method);
|
||||
if ($row === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$computed = $zaarbox->computeAdjustedProductPrice($product, $row);
|
||||
if ($computed <= 0) {
|
||||
if (
|
||||
Product::hasUseLastPriceIfZeroColumn()
|
||||
&& ($product->use_last_price_if_zero ?? false)
|
||||
&& (int) ($product->price ?? 0) > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$offset = Product::hasPriceOffsetColumn()
|
||||
? (float) ($product->price_offset_percent ?? 0)
|
||||
: 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
$computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset);
|
||||
if ($computed <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$product->setAttribute('price', $computed);
|
||||
if (\Illuminate\Support\Facades\Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
$product->setAttribute('price', $computed);
|
||||
if (Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +124,12 @@ class ProductDisplayPriceService
|
||||
|
||||
public function resolveAppBasePrice(): int
|
||||
{
|
||||
$payload = $this->livePricePayload();
|
||||
return $this->extractBaseFromPayload($this->livePricePayload());
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $payload */
|
||||
private function extractBaseFromPayload(array $payload): int
|
||||
{
|
||||
$price = (int) ($payload['price'] ?? 0);
|
||||
if ($price > 0) {
|
||||
return $price;
|
||||
@@ -96,7 +141,12 @@ class ProductDisplayPriceService
|
||||
return (int) round(($buy + $sell) / 2);
|
||||
}
|
||||
|
||||
return (int) ($payload['price_last'] ?? 0);
|
||||
$priceLast = (int) ($payload['price_last'] ?? 0);
|
||||
if ($priceLast > 0) {
|
||||
return $priceLast;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @return array{price: int, buy: int, sell: int, price_last: int} */
|
||||
@@ -120,8 +170,7 @@ class ProductDisplayPriceService
|
||||
if ($provider === 'montzar') {
|
||||
$price = $config->getInt('montzar_live_price', 0);
|
||||
} elseif ($provider === 'zaarbox') {
|
||||
$zaarbox = app(ZaarboxPriceService::class)->fetchPrice();
|
||||
$price = (int) ($zaarbox['order_price'] ?? 0);
|
||||
$price = $this->resolveZaarboxBoardPriceFromCache($config);
|
||||
} elseif ($provider === 'main_product') {
|
||||
$main = $config->mainProduct();
|
||||
if ($main) {
|
||||
@@ -131,7 +180,7 @@ class ProductDisplayPriceService
|
||||
$price = $config->getInt('taban_gohar_live_price', 0);
|
||||
}
|
||||
|
||||
if ($price <= 0) {
|
||||
if ($price <= 0 && $config->getBool('show_last_price', false)) {
|
||||
$last = Price::orderByDesc('id')->first();
|
||||
if ($last && (float) $last->price > 0) {
|
||||
$price = (int) $last->price;
|
||||
@@ -141,12 +190,40 @@ class ProductDisplayPriceService
|
||||
$diffBuy = (int) $config->displayBuySpreadRial();
|
||||
$diffSell = (int) $config->displaySellSpreadRial();
|
||||
|
||||
return [
|
||||
$payload = [
|
||||
'price' => $price,
|
||||
'buy' => $price > 0 ? $price + $diffBuy : 0,
|
||||
'sell' => $price > 0 ? max(0, $price - $diffSell) : 0,
|
||||
'price_last' => $price > 0 ? $price + $diffBuy : 0,
|
||||
];
|
||||
|
||||
if ($this->extractBaseFromPayload($payload) > 0) {
|
||||
$this->cacheLivePricePayload($payload);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private function resolveZaarboxBoardPriceFromCache(ConfigService $config): int
|
||||
{
|
||||
$identifier = trim($config->getString('zaarbox_price_key', ''));
|
||||
if ($identifier === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$feed = app(ZaarboxPriceService::class)->getCachedPriceListOnly();
|
||||
if (!is_array($feed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$row = app(ZaarboxPriceService::class)->findFeedRow($feed, $identifier);
|
||||
if ($row === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$row = app(ZaarboxPriceService::class)->normalizeFeedRow($row);
|
||||
|
||||
return (int) round((float) ($row['price'] ?? 0) + (float) ($row['profit'] ?? 0));
|
||||
}
|
||||
|
||||
private function isMeltedTradeProduct(Product $product): bool
|
||||
|
||||
Reference in New Issue
Block a user