feat(price): broadcast world copper and free-dollar ton and kilo quotes
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -33,3 +33,5 @@
|
||||
- 2026-10-20 | چیدمان درخت دسترسی | `users/components/ManagerPageAccessTree.vue` | هر صفحه یک کالپس؛ وضعیت روی هدر؛ عملیات جدول داخل همان صفحه
|
||||
- 2026-10-20 | مشخصات کارت هدیه | `giftCards/index.vue` تابع `info` | کدهای یکتا در مودال مشخصات نیست؛ همان جدول کدها
|
||||
- 2026-10-20 | کپی کد هدیه | `giftCards/components/GiftCardCodesSheet.vue` | کنار کد هر ردیف آیکون کپی؛ پیام «کد کپی شد»
|
||||
- 2026-11-03 | کد کاربری مشتری | `customers.id` + `customerColumns.tsx` | کد کاربری همان `customers.id` است (type=1)؛ `users` ادمین است. `code` و `moshtari_code` و `referral_id` ستونهای دیگرند
|
||||
- 2026-11-03 | چهار قیمت هیرو | `ZaarboxPriceService::copperDollarReferences` | فید تابلو: مس جهانی کلید `basemetal_london_copper`، دلار آزاد `tgju_usd`؛ تن=ضرب، کیلو=تن/۱۰۰۰ روی payload آخر قیمت
|
||||
|
||||
@@ -80,6 +80,10 @@ class PriceBroadcastService
|
||||
'main_product' => (int) ($payload['main_product'] ?? 0),
|
||||
'montzar' => (int) ($payload['montzar'] ?? 0),
|
||||
'zaarbox' => (int) ($payload['zaarbox'] ?? 0),
|
||||
'copper_world' => (int) ($payload['copper_world'] ?? 0),
|
||||
'dollar_free' => (int) ($payload['dollar_free'] ?? 0),
|
||||
'copper_ton' => (string) ($payload['copper_ton'] ?? '0'),
|
||||
'copper_kilo' => (string) ($payload['copper_kilo'] ?? '0'),
|
||||
'gold_ounce_price' => round((float) ($goldOunce['price'] ?? 0), 2),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -410,10 +410,148 @@ class ZaarboxPriceService
|
||||
public function attachGoldOunceToPayload(array $payload): array
|
||||
{
|
||||
$payload['gold_ounce'] = $this->clientGoldOuncePayload();
|
||||
$refs = $this->copperDollarReferences();
|
||||
$payload['copper_world'] = $refs['copper'];
|
||||
$payload['dollar_free'] = $refs['dollar'];
|
||||
$payload['copper_ton'] = $refs['ton'];
|
||||
$payload['copper_kilo'] = $refs['kilo'];
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* مس جهانی و دلار آزاد از همان فید شناسه ردیف تابلو.
|
||||
* تن = ضرب این دو؛ کیلوگرم = تن / ۱۰۰۰.
|
||||
*
|
||||
* @return array{copper: int, dollar: int, ton: string, kilo: string}
|
||||
*/
|
||||
public function copperDollarReferences(): array
|
||||
{
|
||||
$empty = ['copper' => 0, 'dollar' => 0, 'ton' => '0', 'kilo' => '0'];
|
||||
$prices = $this->getCachedPriceListOnly();
|
||||
if (!is_array($prices) || $prices === []) {
|
||||
$prices = $this->fetchPriceList();
|
||||
if (is_array($prices) && $prices !== []) {
|
||||
$this->storePriceListCache($prices);
|
||||
}
|
||||
}
|
||||
if (!is_array($prices) || $prices === []) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$copper = 0;
|
||||
$dollar = 0;
|
||||
$copperScore = PHP_INT_MAX;
|
||||
$dollarScore = PHP_INT_MAX;
|
||||
|
||||
foreach ($prices as $row) {
|
||||
if (!is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
$total = $this->resolveReferenceProviderTotal($row);
|
||||
if ($total <= 0) {
|
||||
continue;
|
||||
}
|
||||
$rowCopperScore = $this->worldCopperRowScore($row);
|
||||
if ($rowCopperScore !== null && $rowCopperScore < $copperScore) {
|
||||
$copperScore = $rowCopperScore;
|
||||
$copper = $total;
|
||||
}
|
||||
$rowDollarScore = $this->freeDollarRowScore($row);
|
||||
if ($rowDollarScore !== null && $rowDollarScore < $dollarScore) {
|
||||
$dollarScore = $rowDollarScore;
|
||||
$dollar = $total;
|
||||
}
|
||||
}
|
||||
|
||||
$ton = ($copper > 0 && $dollar > 0) ? $this->decimalProduct($copper, $dollar) : '0';
|
||||
|
||||
return [
|
||||
'copper' => $copper,
|
||||
'dollar' => $dollar,
|
||||
'ton' => $ton,
|
||||
'kilo' => $this->divideDecimalByThousand($ton),
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $row */
|
||||
private function worldCopperRowScore(array $row): ?int
|
||||
{
|
||||
$key = strtolower(trim((string) ($row['key'] ?? '')));
|
||||
$name = trim((string) ($row['name'] ?? ''));
|
||||
|
||||
if (str_contains($key, 'basemetal_london_copper')) {
|
||||
return 0;
|
||||
}
|
||||
if ($name === 'TGJU فلز مس') {
|
||||
return 1;
|
||||
}
|
||||
if (mb_strpos($name, 'مس جهانی') !== false) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* دلار آزاد تابلو — نه کاتد دلاری و نه نرخ تومانی فروشگاهها.
|
||||
*
|
||||
* @param array<string, mixed> $row
|
||||
*/
|
||||
private function freeDollarRowScore(array $row): ?int
|
||||
{
|
||||
$key = strtolower(trim((string) ($row['key'] ?? '')));
|
||||
$name = trim((string) ($row['name'] ?? ''));
|
||||
|
||||
if (
|
||||
str_contains($key, 'copper')
|
||||
|| mb_strpos($name, 'کاتد') !== false
|
||||
|| mb_strpos($name, 'مس') !== false
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if ($key === 'tgju_usd') {
|
||||
return 0;
|
||||
}
|
||||
if ($name === 'TGJU دلار' || $name === 'tgju دلار آمریکا') {
|
||||
return 1;
|
||||
}
|
||||
if (mb_strpos($name, 'دلار') !== false && mb_strpos($name, 'آزاد') !== false) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function decimalProduct(int $left, int $right): string
|
||||
{
|
||||
if (function_exists('bcmul')) {
|
||||
return bcmul((string) $left, (string) $right, 0);
|
||||
}
|
||||
|
||||
return sprintf('%.0f', $left * $right);
|
||||
}
|
||||
|
||||
private function divideDecimalByThousand(string $value): string
|
||||
{
|
||||
if ($value === '' || $value === '0') {
|
||||
return '0';
|
||||
}
|
||||
if (strlen($value) <= 3) {
|
||||
$kilo = ((int) $value) / 1000;
|
||||
|
||||
return rtrim(rtrim(number_format($kilo, 3, '.', ''), '0'), '.');
|
||||
}
|
||||
|
||||
$whole = ltrim(substr($value, 0, -3), '0');
|
||||
$fraction = rtrim(substr($value, -3), '0');
|
||||
if ($whole === '') {
|
||||
$whole = '0';
|
||||
}
|
||||
|
||||
return $fraction === '' ? $whole : $whole.'.'.$fraction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{price: int, order_price: int, raw: array<string, mixed>|null}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user