feat(price): broadcast world copper and free-dollar ton and kilo quotes

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-03 19:57:36 +03:30
co-authored by Cursor
parent 9769f2ffad
commit 21da78943c
3 changed files with 144 additions and 0 deletions
@@ -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 آخر قیمت
+4
View File
@@ -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),
];
}
+138
View File
@@ -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}
*/