fixed provider price 2
This commit is contained in:
@@ -45,7 +45,7 @@ class PriceStreamController extends Controller
|
||||
$send('last', $last);
|
||||
}
|
||||
|
||||
$list = app(PriceBroadcastService::class)->buildListPayload(true);
|
||||
$list = app(PriceBroadcastService::class)->buildListPayload(false);
|
||||
if (is_array($list) && $list !== []) {
|
||||
$send('list', $list);
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ class PriceBroadcastService
|
||||
'price_profit' => (int) ($product['price_profit'] ?? 0),
|
||||
'show' => (bool) ($product['show'] ?? true),
|
||||
'active' => (bool) ($product['active'] ?? true),
|
||||
'reference_provider_active' => (bool) ($product['reference_provider_active'] ?? false),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* قیمت نمایشی محصولات برای API — فقط از کش/تنظیمات (بدون HTTP روی list).
|
||||
* قیمت نمایشی محصولات برای API.
|
||||
*
|
||||
* • آبشده با «قیمت اپ» → montzar_live_price / کش /api/price/last
|
||||
* • محصول با reading_method → ردیف فید zaarbox از کش کران (۳۰ث)
|
||||
* • محصول با reading_method → فید zaarbox (کش ۱۵ث + fetch روی cache miss)
|
||||
*/
|
||||
class ProductDisplayPriceService
|
||||
{
|
||||
@@ -51,12 +51,16 @@ class ProductDisplayPriceService
|
||||
/**
|
||||
* پر کردن price روی مدلها برای پاسخ JSON — بدون UPDATE دیتابیس
|
||||
*/
|
||||
/** پر کردن کش مظنه اگر خالی باشد (قبل از enrich لیست مشتری) */
|
||||
/** پر کردن کش مظنه و فید zaarbox اگر خالی باشند (قبل از enrich لیست مشتری) */
|
||||
public function warmLivePriceCache(): void
|
||||
{
|
||||
if (! is_array(Cache::get(self::LIVE_PRICE_CACHE_KEY))) {
|
||||
$this->resolveFallbackPayload();
|
||||
}
|
||||
|
||||
if (! app(ConfigService::class)->isStore()) {
|
||||
app(ZaarboxPriceService::class)->cachedPriceList(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function enrichForApi(Collection|iterable $products): void
|
||||
@@ -438,7 +442,7 @@ class ProductDisplayPriceService
|
||||
return 0;
|
||||
}
|
||||
|
||||
$feed = app(ZaarboxPriceService::class)->getCachedPriceListOnly();
|
||||
$feed = app(ZaarboxPriceService::class)->cachedPriceList(false);
|
||||
if (!is_array($feed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Services\ConfigService;
|
||||
use App\Services\ProductDisplayPriceService;
|
||||
use App\Services\ZaarboxPriceService;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProductDisplayPriceServiceTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Cache::flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_reference_product_gets_live_price_from_fetched_feed(): void
|
||||
{
|
||||
$this->mock(ConfigService::class, function ($mock) {
|
||||
$mock->shouldReceive('isStore')->andReturn(false);
|
||||
});
|
||||
|
||||
$row = [
|
||||
'key' => 'tala18',
|
||||
'name' => 'گرم ۱۸ tala.ir',
|
||||
'price' => 165_000_000,
|
||||
'profit' => 58_400,
|
||||
];
|
||||
$feed = [$row];
|
||||
|
||||
$this->mock(ZaarboxPriceService::class, function ($mock) use ($feed, $row) {
|
||||
$mock->shouldReceive('cachedPriceList')->with(false)->once()->andReturn($feed);
|
||||
$mock->shouldReceive('findFeedRow')->with($feed, 'tala18')->andReturn($row);
|
||||
$mock->shouldReceive('resolveReferenceProviderTotal')->with($row)->andReturn(165_058_400);
|
||||
$mock->shouldReceive('computeAdjustedProductPrice')->andReturn(165_058_400);
|
||||
});
|
||||
|
||||
$product = new Product([
|
||||
'id' => 13,
|
||||
'reading_method' => 'tala18',
|
||||
'use_last_price_if_zero' => false,
|
||||
'price' => 0,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
app(ProductDisplayPriceService::class)->enrichForApi(collect([$product]));
|
||||
|
||||
$this->assertSame(165_058_400, (int) $product->price);
|
||||
$this->assertTrue($product->getAttribute('reference_provider_active'));
|
||||
}
|
||||
|
||||
public function test_reference_product_with_zero_provider_and_toggle_off_stays_unpriced(): void
|
||||
{
|
||||
$this->mock(ConfigService::class, function ($mock) {
|
||||
$mock->shouldReceive('isStore')->andReturn(false);
|
||||
});
|
||||
|
||||
$row = [
|
||||
'key' => 'tala18',
|
||||
'name' => 'گرم ۱۸ tala.ir',
|
||||
'price' => 0,
|
||||
'profit' => 58_400,
|
||||
];
|
||||
$feed = [$row];
|
||||
|
||||
$this->mock(ZaarboxPriceService::class, function ($mock) use ($feed, $row) {
|
||||
$mock->shouldReceive('cachedPriceList')->with(false)->once()->andReturn($feed);
|
||||
$mock->shouldReceive('findFeedRow')->with($feed, 'tala18')->andReturn($row);
|
||||
$mock->shouldReceive('resolveReferenceProviderTotal')->with($row)->andReturn(0);
|
||||
});
|
||||
|
||||
$product = new Product([
|
||||
'id' => 13,
|
||||
'reading_method' => 'tala18',
|
||||
'use_last_price_if_zero' => false,
|
||||
'price' => 99_000_000,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$service = app(ProductDisplayPriceService::class);
|
||||
$service->enrichForApi(collect([$product]));
|
||||
|
||||
$this->assertSame(0, (int) $product->price);
|
||||
$this->assertFalse($product->getAttribute('reference_provider_active'));
|
||||
$this->assertFalse($service->resolveCustomerShow($product));
|
||||
}
|
||||
|
||||
public function test_reference_product_with_zero_provider_and_toggle_on_uses_stored_fallback(): void
|
||||
{
|
||||
if (! Product::hasUseLastPriceIfZeroColumn()) {
|
||||
$this->markTestSkipped('use_last_price_if_zero column not present');
|
||||
}
|
||||
|
||||
$this->mock(ConfigService::class, function ($mock) {
|
||||
$mock->shouldReceive('isStore')->andReturn(false);
|
||||
$mock->shouldReceive('isProductWithinTradingHours')->andReturn(true);
|
||||
$mock->shouldReceive('getBool')->with('show_last_price', false)->andReturn(false);
|
||||
});
|
||||
|
||||
$row = [
|
||||
'key' => 'tala18',
|
||||
'name' => 'گرم ۱۸ tala.ir',
|
||||
'price' => 0,
|
||||
'profit' => 0,
|
||||
];
|
||||
$feed = [$row];
|
||||
|
||||
$this->mock(ZaarboxPriceService::class, function ($mock) use ($feed, $row) {
|
||||
$mock->shouldReceive('cachedPriceList')->with(false)->once()->andReturn($feed);
|
||||
$mock->shouldReceive('findFeedRow')->with($feed, 'tala18')->andReturn($row);
|
||||
$mock->shouldReceive('resolveReferenceProviderTotal')->with($row)->andReturn(0);
|
||||
$mock->shouldReceive('computeAdjustedProductPrice')->andReturn(0);
|
||||
});
|
||||
|
||||
$product = new Product([
|
||||
'id' => 13,
|
||||
'reading_method' => 'tala18',
|
||||
'use_last_price_if_zero' => true,
|
||||
'price' => 150_000_000,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$service = app(ProductDisplayPriceService::class);
|
||||
$service->enrichForApi(collect([$product]));
|
||||
|
||||
$this->assertSame(150_000_000, (int) $product->price);
|
||||
$this->assertTrue($product->getAttribute('reference_provider_active'));
|
||||
$this->assertTrue($service->resolveCustomerShow($product));
|
||||
}
|
||||
|
||||
public function test_missing_feed_with_toggle_off_zeros_reference_product(): void
|
||||
{
|
||||
$this->mock(ConfigService::class, function ($mock) {
|
||||
$mock->shouldReceive('isStore')->andReturn(false);
|
||||
});
|
||||
|
||||
$this->mock(ZaarboxPriceService::class, function ($mock) {
|
||||
$mock->shouldReceive('cachedPriceList')->with(false)->once()->andReturn(null);
|
||||
});
|
||||
|
||||
$product = new Product([
|
||||
'id' => 13,
|
||||
'reading_method' => 'tala18',
|
||||
'use_last_price_if_zero' => false,
|
||||
'price' => 120_000_000,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
app(ProductDisplayPriceService::class)->enrichForApi(collect([$product]));
|
||||
|
||||
$this->assertSame(0, (int) $product->price);
|
||||
$this->assertFalse($product->getAttribute('reference_provider_active'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user