From 21da78943c191f34f6a203fee449bc985627fae7 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Tue, 3 Nov 2026 19:57:36 +0330 Subject: [PATCH] feat(price): broadcast world copper and free-dollar ton and kilo quotes Co-authored-by: Cursor --- .../abshode-domain-lookup/learned-notes.md | 2 + app/Services/PriceBroadcastService.php | 4 + app/Services/ZaarboxPriceService.php | 138 ++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/.cursor/skills/abshode-domain-lookup/learned-notes.md b/.cursor/skills/abshode-domain-lookup/learned-notes.md index 3ff66cd..739d8f3 100644 --- a/.cursor/skills/abshode-domain-lookup/learned-notes.md +++ b/.cursor/skills/abshode-domain-lookup/learned-notes.md @@ -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 آخر قیمت diff --git a/app/Services/PriceBroadcastService.php b/app/Services/PriceBroadcastService.php index 871aa30..c5c713d 100644 --- a/app/Services/PriceBroadcastService.php +++ b/app/Services/PriceBroadcastService.php @@ -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), ]; } diff --git a/app/Services/ZaarboxPriceService.php b/app/Services/ZaarboxPriceService.php index 9d470bf..2830fd9 100644 --- a/app/Services/ZaarboxPriceService.php +++ b/app/Services/ZaarboxPriceService.php @@ -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 $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 $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|null} */