fix some handling 3
This commit is contained in:
@@ -611,29 +611,32 @@ class ProductController extends SuperController
|
|||||||
|
|
||||||
if (!Product::hasOrderLimitColumns()) {
|
if (!Product::hasOrderLimitColumns()) {
|
||||||
unset($data['order_limit_enabled'], $data['min_order_cash'], $data['max_order_cash']);
|
unset($data['order_limit_enabled'], $data['min_order_cash'], $data['max_order_cash']);
|
||||||
} elseif (empty($data['order_limit_enabled'])) {
|
|
||||||
$data['order_limit_enabled'] = false;
|
|
||||||
$data['min_order_cash'] = null;
|
|
||||||
$data['max_order_cash'] = null;
|
|
||||||
} else {
|
} else {
|
||||||
$min = $data['min_order_cash'] ?? null;
|
$min = $this->normalizeOrderLimitCash($data['min_order_cash'] ?? null);
|
||||||
$max = $data['max_order_cash'] ?? null;
|
$max = $this->normalizeOrderLimitCash($data['max_order_cash'] ?? null);
|
||||||
$hasMin = $min !== null && $min !== '';
|
$orderLimitEnabled = filter_var($data['order_limit_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN)
|
||||||
$hasMax = $max !== null && $max !== '';
|
|| $min !== null
|
||||||
|
|| $max !== null;
|
||||||
|
|
||||||
if (!$hasMin && !$hasMax) {
|
if (!$orderLimitEnabled) {
|
||||||
throw new UnprocessableEntityHttpException(
|
$data['order_limit_enabled'] = false;
|
||||||
'با فعال بودن محدودیت مبلغ سفارش، حداقل یکی از حداقل یا حداکثر مبلغ باید وارد شود'
|
$data['min_order_cash'] = null;
|
||||||
);
|
$data['max_order_cash'] = null;
|
||||||
|
} else {
|
||||||
|
if ($min === null && $max === null) {
|
||||||
|
throw new UnprocessableEntityHttpException(
|
||||||
|
'با فعال بودن محدودیت مبلغ سفارش، حداقل یکی از حداقل یا حداکثر مبلغ باید وارد شود'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($min !== null && $max !== null && $min > $max) {
|
||||||
|
throw new UnprocessableEntityHttpException('حداقل مبلغ نمیتواند بیشتر از حداکثر باشد');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['order_limit_enabled'] = true;
|
||||||
|
$data['min_order_cash'] = $min;
|
||||||
|
$data['max_order_cash'] = $max;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasMin && $hasMax && (float) $min > (float) $max) {
|
|
||||||
throw new UnprocessableEntityHttpException('حداقل مبلغ نمیتواند بیشتر از حداکثر باشد');
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['order_limit_enabled'] = true;
|
|
||||||
$data['min_order_cash'] = $hasMin ? (int) $min : null;
|
|
||||||
$data['max_order_cash'] = $hasMax ? (int) $max : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Product::hasShowInAssetsColumn()) {
|
if (!Product::hasShowInAssetsColumn()) {
|
||||||
@@ -704,4 +707,39 @@ class ProductController extends SuperController
|
|||||||
|
|
||||||
return (float) $value;
|
return (float) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function normalizeOrderLimitCash(mixed $value): ?int
|
||||||
|
{
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_int($value)) {
|
||||||
|
return $value >= 0 ? $value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_float($value)) {
|
||||||
|
return $value >= 0 ? (int) $value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_string($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = $this->normalizeAsciiDigits(trim(str_replace([' ', ',', '٬'], '', $value)));
|
||||||
|
if ($value === '' || ! ctype_digit($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function normalizeAsciiDigits(string $value): string
|
||||||
|
{
|
||||||
|
$persian = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
|
||||||
|
$arabic = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
|
||||||
|
$latin = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||||
|
|
||||||
|
return str_replace(array_merge($persian, $arabic), array_merge($latin, $latin), $value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,10 +146,10 @@ class Product extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
static::$orderLimitColumnsExist = Schema::hasColumn(
|
$table = (new static)->getTable();
|
||||||
(new static)->getTable(),
|
static::$orderLimitColumnsExist = Schema::hasColumn($table, 'order_limit_enabled')
|
||||||
'order_limit_enabled'
|
&& Schema::hasColumn($table, 'min_order_cash')
|
||||||
);
|
&& Schema::hasColumn($table, 'max_order_cash');
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
static::$orderLimitColumnsExist = false;
|
static::$orderLimitColumnsExist = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Services;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use Hekmatinasser\Verta\Verta;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -29,6 +30,22 @@ class PriceChannelBroadcastService
|
|||||||
/** وزن هر مثقال به گرم — ضریب تبدیل قیمت هر گرم به هر مثقال (مثقال = گرم × این عدد) */
|
/** وزن هر مثقال به گرم — ضریب تبدیل قیمت هر گرم به هر مثقال (مثقال = گرم × این عدد) */
|
||||||
private const DEFAULT_CHANGE_MESGHAL = 4.3318;
|
private const DEFAULT_CHANGE_MESGHAL = 4.3318;
|
||||||
|
|
||||||
|
/** قالب پیشفرض پیام کانال — وقتی price_channel_message_text خالی باشد */
|
||||||
|
private const DEFAULT_MESSAGE_TEMPLATE = <<<'TXT'
|
||||||
|
سلام 👋
|
||||||
|
%عنوان
|
||||||
|
📅 %تاریخ 🕐 %ساعت
|
||||||
|
|
||||||
|
🔴 خرید گرم: %گرم_خرید
|
||||||
|
🟢 فروش گرم: %گرم_فروش
|
||||||
|
🔴 خرید مثقال: %مثقال_خرید
|
||||||
|
🟢 فروش مثقال: %مثقال_فروش
|
||||||
|
|
||||||
|
📞 %شماره
|
||||||
|
%آیدی
|
||||||
|
%لینک
|
||||||
|
TXT;
|
||||||
|
|
||||||
public function __construct(private readonly ConfigService $config)
|
public function __construct(private readonly ConfigService $config)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -66,19 +83,19 @@ class PriceChannelBroadcastService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$products = $this->eligibleProducts();
|
$products = $this->eligibleProducts();
|
||||||
if ($products === []) {
|
$boardProduct = $this->resolveBoardProduct($products);
|
||||||
Log::debug('PriceChannel: محصول واجد شرایطی نیست (active/قیمت/ساعت کاری)');
|
if ($boardProduct === null || (int) ($boardProduct->price ?? 0) <= 0) {
|
||||||
|
Log::debug('PriceChannel: محصول تابلو (آبشده) واجد شرایطی نیست');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// شرط ۲: قیمتِ نمایشی نسبت به آخرین ارسال واقعاً تغییر کرده باشد؛ وگرنه چیزی نفرست
|
// شرط ۲: قیمت تابلو نسبت به آخرین ارسال واقعاً تغییر کرده باشد
|
||||||
// و تایمر را هم دست نزن (تا سرِ اولین تغییرِ بعدی بلافاصله بفرستد).
|
$signature = $this->priceSignature($boardProduct);
|
||||||
$signature = $this->priceSignature($products);
|
|
||||||
if ($signature === Cache::get(self::SIGNATURE_CACHE_KEY)) {
|
if ($signature === Cache::get(self::SIGNATURE_CACHE_KEY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$message = $this->buildMessage($products);
|
$message = $this->buildMessage($products, $boardProduct);
|
||||||
if ($message === '') {
|
if ($message === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -111,9 +128,16 @@ class PriceChannelBroadcastService
|
|||||||
*
|
*
|
||||||
* @param array<int, Product> $products
|
* @param array<int, Product> $products
|
||||||
*/
|
*/
|
||||||
private function priceSignature(array $products): string
|
private function priceSignature(Product $boardProduct): string
|
||||||
{
|
{
|
||||||
return md5($this->buildPriceBody($products));
|
$prices = $this->computeDisplayPrices($boardProduct);
|
||||||
|
|
||||||
|
return md5(implode('|', [
|
||||||
|
$prices['gram_buy'],
|
||||||
|
$prices['gram_sell'],
|
||||||
|
$prices['mesghal_buy'],
|
||||||
|
$prices['mesghal_sell'],
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,8 +161,9 @@ class PriceChannelBroadcastService
|
|||||||
if ($message !== '' && $targets !== []) {
|
if ($message !== '' && $targets !== []) {
|
||||||
$this->markSent();
|
$this->markSent();
|
||||||
$products = $this->eligibleProducts();
|
$products = $this->eligibleProducts();
|
||||||
if ($products !== []) {
|
$boardProduct = $this->resolveBoardProduct($products);
|
||||||
Cache::put(self::SIGNATURE_CACHE_KEY, $this->priceSignature($products), now()->addDay());
|
if ($boardProduct !== null) {
|
||||||
|
Cache::put(self::SIGNATURE_CACHE_KEY, $this->priceSignature($boardProduct), now()->addDay());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,27 +264,135 @@ class PriceChannelBroadcastService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ساخت متن پیام قیمت — مرتب و بر اساس دادهی هر محصول.
|
* ساخت متن پیام قیمت — قالب از price_channel_message_text (یا پیشفرض داخلی).
|
||||||
*/
|
*/
|
||||||
public function buildMessage(?array $products = null): string
|
public function buildMessage(?array $products = null, ?Product $boardProduct = null): string
|
||||||
{
|
{
|
||||||
$products = $products ?? $this->eligibleProducts();
|
$products = $products ?? $this->eligibleProducts();
|
||||||
$body = $this->buildPriceBody($products);
|
$boardProduct = $boardProduct ?? $this->resolveBoardProduct($products);
|
||||||
if ($body === '') {
|
if ($boardProduct === null || (int) ($boardProduct->price ?? 0) <= 0) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return trim($this->header() . "\n\n" . $body);
|
return $this->renderMessageTemplate($this->messageTemplate(), $products, $boardProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function messageTemplate(): string
|
||||||
|
{
|
||||||
|
$fromConfig = trim((string) $this->config->getString('price_channel_message_text', ''));
|
||||||
|
|
||||||
|
return $fromConfig !== '' ? $fromConfig : self::DEFAULT_MESSAGE_TEMPLATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* بدنهٔ قیمت (بدون هدر/ساعت) — همان چیزی که «تغییر قیمت» را میسازد.
|
* جایگزینی متغیرهای قالب.
|
||||||
* امضای تشخیص تغییر روی همین بدنهی نمایشیِ رُندشده گرفته میشود تا اختلاف چند ریالی
|
* قیمت تابلو: %گرم_خرید %گرم_فروش %مثقال_خرید %مثقال_فروش
|
||||||
* که به یک عدد نمایشیِ یکسان میرسد، پیام تکراری نفرستد.
|
* زمان: %تاریخ %ساعت — اپ: %اسم_اپ %نام %عنوان
|
||||||
|
* تماس: %آیدی %شماره %لینک — اختیاری: %محصولات %فوتر
|
||||||
*
|
*
|
||||||
* @param array<int, Product> $products
|
* @param array<int, Product> $products
|
||||||
*/
|
*/
|
||||||
private function buildPriceBody(array $products): string
|
private function renderMessageTemplate(string $template, array $products, Product $boardProduct): string
|
||||||
|
{
|
||||||
|
$name = trim((string) $this->config->getString('name_fa', ''));
|
||||||
|
$title = $name !== '' ? "📊 قیمت لحظهای {$name}" : '📊 قیمت لحظهای';
|
||||||
|
$prices = $this->computeDisplayPrices($boardProduct);
|
||||||
|
|
||||||
|
$message = $this->applyTemplatePlaceholders($template, [
|
||||||
|
'مثقال_فروش' => $prices['mesghal_sell'],
|
||||||
|
'مثقال_خرید' => $prices['mesghal_buy'],
|
||||||
|
'گرم_فروش' => $prices['gram_sell'],
|
||||||
|
'گرم_خرید' => $prices['gram_buy'],
|
||||||
|
'اسم_اپ' => $name,
|
||||||
|
'محصولات' => $this->buildProductLines($products),
|
||||||
|
'عنوان' => $title,
|
||||||
|
'تاریخ' => Verta::now()->format('Y/n/j'),
|
||||||
|
'ساعت' => now()->format('H:i'),
|
||||||
|
'آیدی' => trim((string) $this->config->getString('price_channel_footer_id', '')),
|
||||||
|
'شماره' => trim((string) $this->config->getString('price_channel_footer_phone', '')),
|
||||||
|
'لینک' => trim((string) $this->config->getString('price_channel_footer_link', '')),
|
||||||
|
'فوتر' => $this->buildFooterBlock(),
|
||||||
|
'نام' => $name,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return preg_replace("/\n{3,}/", "\n\n", trim($message)) ?? trim($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, string> $replacements */
|
||||||
|
private function applyTemplatePlaceholders(string $template, array $replacements): string
|
||||||
|
{
|
||||||
|
$keys = array_keys($replacements);
|
||||||
|
usort($keys, static fn (string $a, string $b): int => mb_strlen($b) <=> mb_strlen($a));
|
||||||
|
|
||||||
|
$message = $template;
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$message = preg_replace(
|
||||||
|
'/[%٪]\s*' . preg_quote($key, '/') . '/u',
|
||||||
|
$replacements[$key],
|
||||||
|
$message
|
||||||
|
) ?? $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* محصول مرجع قیمت تابلو — اول آبشده (گرم)، بعد اولین محصول گرم، بعد اولین واجد شرایط.
|
||||||
|
*
|
||||||
|
* @param array<int, Product> $products
|
||||||
|
*/
|
||||||
|
private function resolveBoardProduct(array $products): ?Product
|
||||||
|
{
|
||||||
|
if ($products === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($products as $product) {
|
||||||
|
if (trim((string) ($product->group_type ?? '')) === 'آبشده' && $this->isGramUnit($product)) {
|
||||||
|
return $product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($products as $product) {
|
||||||
|
if ($this->isGramUnit($product)) {
|
||||||
|
return $product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $products[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* قیمتهای نمایشی تابلو (گرم + مثقال) — همان منطق اپ + price_channel_diff.
|
||||||
|
*
|
||||||
|
* @return array{gram_buy: string, gram_sell: string, mesghal_buy: string, mesghal_sell: string}
|
||||||
|
*/
|
||||||
|
private function computeDisplayPrices(Product $product): array
|
||||||
|
{
|
||||||
|
$channelDiff = (float) $this->config->getInt('price_channel_diff', 0);
|
||||||
|
$diffBuy = (float) $this->config->displayBuyPriceDiffRial();
|
||||||
|
$diffSell = (float) $this->config->displaySellPriceDiffRial();
|
||||||
|
$mesghal = $this->changeMesghal();
|
||||||
|
$base = (float) ($product->price ?? 0);
|
||||||
|
|
||||||
|
// 🔴 خرید (مشتری میفروشد، پایینتر) — 🟢 فروش (مشتری میخرد، بالاتر)
|
||||||
|
$gramBuy = $base - $diffSell - $channelDiff;
|
||||||
|
$gramSell = $base + $diffBuy + $channelDiff;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'gram_buy' => $this->formatPrice($gramBuy),
|
||||||
|
'gram_sell' => $this->formatPrice($gramSell),
|
||||||
|
'mesghal_buy' => $mesghal > 0 ? $this->formatPrice($gramBuy * $mesghal) : '',
|
||||||
|
'mesghal_sell' => $mesghal > 0 ? $this->formatPrice($gramSell * $mesghal) : '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* بدنهٔ قیمت محصولات (بدون فوتر) — مبنای تشخیص تغییر قیمت.
|
||||||
|
*
|
||||||
|
* @param array<int, Product> $products
|
||||||
|
*/
|
||||||
|
private function buildProductLines(array $products): string
|
||||||
{
|
{
|
||||||
if ($products === []) {
|
if ($products === []) {
|
||||||
return '';
|
return '';
|
||||||
@@ -283,7 +416,6 @@ class PriceChannelBroadcastService
|
|||||||
$lines[] = '🔴 خرید ' . $this->formatPrice($low) . ' 🟢 فروش ' . $this->formatPrice($high);
|
$lines[] = '🔴 خرید ' . $this->formatPrice($low) . ' 🟢 فروش ' . $this->formatPrice($high);
|
||||||
|
|
||||||
if ($this->isGramUnit($product) && $mesghal > 0) {
|
if ($this->isGramUnit($product) && $mesghal > 0) {
|
||||||
// قیمت پایه «هر گرم» است؛ مثقال = گرم × ضریب (کنوانسیون اپ: مثقال = گرم × 4.3318)
|
|
||||||
$lines[] = '💰 هر مثقال: ' . $this->formatPrice($low * $mesghal)
|
$lines[] = '💰 هر مثقال: ' . $this->formatPrice($low * $mesghal)
|
||||||
. ' / ' . $this->formatPrice($high * $mesghal);
|
. ' / ' . $this->formatPrice($high * $mesghal);
|
||||||
}
|
}
|
||||||
@@ -291,25 +423,22 @@ class PriceChannelBroadcastService
|
|||||||
$lines[] = '';
|
$lines[] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$footer = $this->footerLines();
|
|
||||||
if ($footer !== []) {
|
|
||||||
$lines[] = '➖➖➖➖➖➖';
|
|
||||||
foreach ($footer as $line) {
|
|
||||||
$lines[] = $line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return trim(implode("\n", $lines));
|
return trim(implode("\n", $lines));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function header(): string
|
private function buildFooterBlock(): string
|
||||||
{
|
{
|
||||||
$name = trim((string) $this->config->getString('name_fa', ''));
|
$footer = $this->footerLines();
|
||||||
$time = now()->format('H:i');
|
if ($footer === []) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$title = $name !== '' ? "📊 قیمت لحظهای {$name}" : '📊 قیمت لحظهای';
|
$lines = ['➖➖➖➖➖➖'];
|
||||||
|
foreach ($footer as $line) {
|
||||||
|
$lines[] = $line;
|
||||||
|
}
|
||||||
|
|
||||||
return $title . "\n🕐 ساعت " . $time;
|
return implode("\n", $lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,6 +42,22 @@ SET @invite_link_desc = 'متن پیام اشتراکگذاری دعوت در
|
|||||||
SET @deposit_guide_desc = 'متن راهنمای واریز در مودال شارژ حساب. متغیرها: ٪نام یا %نام = نام صاحب حساب؛ ٪کارت یا %کارت = شماره کارت؛ ٪شبا یا %شبا = شبا. فاصله بعد از ٪ اختیاری است. اگر خالی باشد از متن پیشفرض اپ استفاده میشود.';
|
SET @deposit_guide_desc = 'متن راهنمای واریز در مودال شارژ حساب. متغیرها: ٪نام یا %نام = نام صاحب حساب؛ ٪کارت یا %کارت = شماره کارت؛ ٪شبا یا %شبا = شبا. فاصله بعد از ٪ اختیاری است. اگر خالی باشد از متن پیشفرض اپ استفاده میشود.';
|
||||||
SET @deposit_support_msg_desc = 'متن پیام هنگام کلیک روی «پیام به پشتیبانی» و «پیام به پشتیبانی (sms)» در مودال واریز. همان متغیرهای ٪نام، ٪کارت و ٪شبا. پیشفرض: «شماره حساب».';
|
SET @deposit_support_msg_desc = 'متن پیام هنگام کلیک روی «پیام به پشتیبانی» و «پیام به پشتیبانی (sms)» در مودال واریز. همان متغیرهای ٪نام، ٪کارت و ٪شبا. پیشفرض: «شماره حساب».';
|
||||||
|
|
||||||
|
SET @price_channel_message_desc = 'قالب متن پیام ارسالی به کانال. متغیرهای قیمت تابلو: ٪گرم_خرید ٪گرم_فروش ٪مثقال_خرید ٪مثقال_فروش (یا با %). زمان: ٪تاریخ ٪ساعت. اپ: ٪اسم_اپ یا ٪نام (نام فارسی)؛ ٪عنوان = خط «📊 قیمت لحظهای + نام». تماس جدا: ٪آیدی ٪شماره ٪لینک. اختیاری: ٪محصولات (لیست همه محصولات)؛ ٪فوتر (ترکیب آیدی+شماره+لینک). فاصله بعد از ٪ اختیاری است. خالی = قالب پیشفرض.';
|
||||||
|
SET @price_channel_default_text = CONCAT(
|
||||||
|
'سلام 👋', CHAR(10),
|
||||||
|
'%عنوان', CHAR(10),
|
||||||
|
'📅 %تاریخ 🕐 %ساعت', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'🔴 خرید گرم: %گرم_خرید', CHAR(10),
|
||||||
|
'🟢 فروش گرم: %گرم_فروش', CHAR(10),
|
||||||
|
'🔴 خرید مثقال: %مثقال_خرید', CHAR(10),
|
||||||
|
'🟢 فروش مثقال: %مثقال_فروش', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'📞 %شماره', CHAR(10),
|
||||||
|
'%آیدی', CHAR(10),
|
||||||
|
'%لینک'
|
||||||
|
);
|
||||||
|
|
||||||
-- ستونهای اختیاری settings (بعضی DBهای قدیمی ندارند)
|
-- ستونهای اختیاری settings (بعضی DBهای قدیمی ندارند)
|
||||||
SET @sql = IF(
|
SET @sql = IF(
|
||||||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||||
@@ -379,6 +395,10 @@ SELECT 'price_channel_min_seconds', '120', 'حداقل فاصله ارسال (ث
|
|||||||
'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را میگیرد. صفر = هر تغییر قیمت.', 'number'
|
'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را میگیرد. صفر = هر تغییر قیمت.', 'number'
|
||||||
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1);
|
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1);
|
||||||
|
|
||||||
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
||||||
|
SELECT 'price_channel_message_text', @price_channel_default_text, 'قالب متن پیام کانال', 1, 1, @price_channel_message_desc, 'longtext'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_message_text' LIMIT 1);
|
||||||
|
|
||||||
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
||||||
SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1,
|
SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1,
|
||||||
'اگر پر باشد در انتهای پیام نمایش داده میشود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمیشود.', 'text'
|
'اگر پر باشد در انتهای پیام نمایش داده میشود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمیشود.', 'text'
|
||||||
@@ -706,7 +726,7 @@ WHERE `key` = 'main_product';
|
|||||||
-- longtext
|
-- longtext
|
||||||
UPDATE `settings` SET `type` = 'longtext' WHERE `key` IN (
|
UPDATE `settings` SET `type` = 'longtext' WHERE `key` IN (
|
||||||
'text_rule', 'text_about', 'support_messenger_text', 'invite_link_text',
|
'text_rule', 'text_about', 'support_messenger_text', 'invite_link_text',
|
||||||
'deposit_support_message_text',
|
'deposit_support_message_text', 'price_channel_message_text',
|
||||||
'montzar_order_response', 'montzar_last_product_log'
|
'montzar_order_response', 'montzar_last_product_log'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1127,6 +1147,13 @@ UPDATE `settings` SET `description` = 'نوع پیامرسان برای دک
|
|||||||
UPDATE `settings` SET `description` = 'شناسه تماس پشتیبانی: یوزرنیم (تلگرام)، شماره (واتساپ/بله) یا آیدی بسته به پیامرسان انتخابشده.' WHERE `key` = 'support_messenger_id';
|
UPDATE `settings` SET `description` = 'شناسه تماس پشتیبانی: یوزرنیم (تلگرام)، شماره (واتساپ/بله) یا آیدی بسته به پیامرسان انتخابشده.' WHERE `key` = 'support_messenger_id';
|
||||||
UPDATE `settings` SET `description` = @deposit_guide_desc WHERE `key` = 'support_messenger_text';
|
UPDATE `settings` SET `description` = @deposit_guide_desc WHERE `key` = 'support_messenger_text';
|
||||||
UPDATE `settings` SET `description` = @deposit_support_msg_desc WHERE `key` = 'deposit_support_message_text';
|
UPDATE `settings` SET `description` = @deposit_support_msg_desc WHERE `key` = 'deposit_support_message_text';
|
||||||
|
UPDATE `settings` SET `description` = @price_channel_message_desc WHERE `key` = 'price_channel_message_text';
|
||||||
|
UPDATE `settings` SET
|
||||||
|
`title_fa` = 'قالب متن پیام کانال',
|
||||||
|
`type` = 'longtext',
|
||||||
|
`can_edit` = 1,
|
||||||
|
`description` = @price_channel_message_desc
|
||||||
|
WHERE `key` = 'price_channel_message_text';
|
||||||
UPDATE `settings` SET `description` = 'متن پیام اشتراکگذاری دعوت در اپ کاربر (دکمه «اشتراک با دوستان» در صفحه اصلی، بخش معرف در پروفایل، صفحه کسب درآمد و مودال اشتراک). متغیرهای جایگزین: ٪نام یا %نام = نام کامل کاربر دعوتکننده؛ ٪لینک یا %لینک = آدرس کامل صفحه ثبتنام همراه با کد معرف (بر اساس تنظیم app_url یا دامنه فعلی مرورگر). فاصله اختیاری بعد از ٪ یا % مجاز است (مثلاً ٪ نام). اگر این فیلد خالی باشد، اپ از متن پیشفرض داخلی استفاده میکند.' WHERE `key` = 'invite_link_text';
|
UPDATE `settings` SET `description` = 'متن پیام اشتراکگذاری دعوت در اپ کاربر (دکمه «اشتراک با دوستان» در صفحه اصلی، بخش معرف در پروفایل، صفحه کسب درآمد و مودال اشتراک). متغیرهای جایگزین: ٪نام یا %نام = نام کامل کاربر دعوتکننده؛ ٪لینک یا %لینک = آدرس کامل صفحه ثبتنام همراه با کد معرف (بر اساس تنظیم app_url یا دامنه فعلی مرورگر). فاصله اختیاری بعد از ٪ یا % مجاز است (مثلاً ٪ نام). اگر این فیلد خالی باشد، اپ از متن پیشفرض داخلی استفاده میکند.' WHERE `key` = 'invite_link_text';
|
||||||
UPDATE `settings` SET `description` = 'شماره تماس پشتیبانی؛ در صفحه واریز، درباره ما و قوانین نمایش داده میشود. متن پیامک/پشتیبانی از «متن پیام به پشتیبانی (واریز)» خوانده میشود.' WHERE `key` = 'deposit_sms_support_number';
|
UPDATE `settings` SET `description` = 'شماره تماس پشتیبانی؛ در صفحه واریز، درباره ما و قوانین نمایش داده میشود. متن پیامک/پشتیبانی از «متن پیام به پشتیبانی (واریز)» خوانده میشود.' WHERE `key` = 'deposit_sms_support_number';
|
||||||
|
|
||||||
@@ -1166,10 +1193,21 @@ UPDATE `settings` SET
|
|||||||
`description` = @deposit_support_msg_desc
|
`description` = @deposit_support_msg_desc
|
||||||
WHERE `key` = 'deposit_support_message_text';
|
WHERE `key` = 'deposit_support_message_text';
|
||||||
|
|
||||||
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
||||||
|
SELECT 'price_channel_message_text', @price_channel_default_text, 'قالب متن پیام کانال', 1, 1, @price_channel_message_desc, 'longtext'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_message_text' LIMIT 1);
|
||||||
|
|
||||||
|
UPDATE `settings` SET
|
||||||
|
`title_fa` = 'قالب متن پیام کانال',
|
||||||
|
`type` = 'longtext',
|
||||||
|
`can_edit` = 1,
|
||||||
|
`description` = @price_channel_message_desc
|
||||||
|
WHERE `key` = 'price_channel_message_text';
|
||||||
|
|
||||||
UPDATE `settings` SET `type` = 'longtext'
|
UPDATE `settings` SET `type` = 'longtext'
|
||||||
WHERE `key` IN (
|
WHERE `key` IN (
|
||||||
'text_rule', 'text_about', 'support_messenger_text', 'invite_link_text',
|
'text_rule', 'text_about', 'support_messenger_text', 'invite_link_text',
|
||||||
'deposit_support_message_text',
|
'deposit_support_message_text', 'price_channel_message_text',
|
||||||
'montzar_order_response', 'montzar_last_product_log'
|
'montzar_order_response', 'montzar_last_product_log'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1360,7 +1398,8 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN (
|
|||||||
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
|
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
|
||||||
'text_about', 'text_rule',
|
'text_about', 'text_rule',
|
||||||
'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff',
|
'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff',
|
||||||
'price_channel_min_seconds', 'price_channel_footer_id', 'price_channel_footer_phone',
|
'price_channel_min_seconds', 'price_channel_message_text',
|
||||||
|
'price_channel_footer_id', 'price_channel_footer_phone',
|
||||||
'price_channel_footer_link', 'change_mesghal'
|
'price_channel_footer_link', 'change_mesghal'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,22 @@ SET @invite_link_desc = 'متن پیام اشتراکگذاری دعوت در
|
|||||||
SET @deposit_guide_desc = 'متن راهنمای واریز در مودال شارژ حساب. متغیرها: ٪نام یا %نام = نام صاحب حساب؛ ٪کارت یا %کارت = شماره کارت؛ ٪شبا یا %شبا = شبا. فاصله بعد از ٪ اختیاری است. اگر خالی باشد از متن پیشفرض اپ استفاده میشود.';
|
SET @deposit_guide_desc = 'متن راهنمای واریز در مودال شارژ حساب. متغیرها: ٪نام یا %نام = نام صاحب حساب؛ ٪کارت یا %کارت = شماره کارت؛ ٪شبا یا %شبا = شبا. فاصله بعد از ٪ اختیاری است. اگر خالی باشد از متن پیشفرض اپ استفاده میشود.';
|
||||||
SET @deposit_support_msg_desc = 'متن پیام هنگام کلیک روی «پیام به پشتیبانی» و «پیام به پشتیبانی (sms)» در مودال واریز. همان متغیرهای ٪نام، ٪کارت و ٪شبا. پیشفرض: «شماره حساب».';
|
SET @deposit_support_msg_desc = 'متن پیام هنگام کلیک روی «پیام به پشتیبانی» و «پیام به پشتیبانی (sms)» در مودال واریز. همان متغیرهای ٪نام، ٪کارت و ٪شبا. پیشفرض: «شماره حساب».';
|
||||||
|
|
||||||
|
SET @price_channel_message_desc = 'قالب متن پیام ارسالی به کانال. متغیرهای قیمت تابلو: ٪گرم_خرید ٪گرم_فروش ٪مثقال_خرید ٪مثقال_فروش (یا با %). زمان: ٪تاریخ ٪ساعت. اپ: ٪اسم_اپ یا ٪نام (نام فارسی)؛ ٪عنوان = خط «📊 قیمت لحظهای + نام». تماس جدا: ٪آیدی ٪شماره ٪لینک. اختیاری: ٪محصولات (لیست همه محصولات)؛ ٪فوتر (ترکیب آیدی+شماره+لینک). فاصله بعد از ٪ اختیاری است. خالی = قالب پیشفرض.';
|
||||||
|
SET @price_channel_default_text = CONCAT(
|
||||||
|
'سلام 👋', CHAR(10),
|
||||||
|
'%عنوان', CHAR(10),
|
||||||
|
'📅 %تاریخ 🕐 %ساعت', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'🔴 خرید گرم: %گرم_خرید', CHAR(10),
|
||||||
|
'🟢 فروش گرم: %گرم_فروش', CHAR(10),
|
||||||
|
'🔴 خرید مثقال: %مثقال_خرید', CHAR(10),
|
||||||
|
'🟢 فروش مثقال: %مثقال_فروش', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'📞 %شماره', CHAR(10),
|
||||||
|
'%آیدی', CHAR(10),
|
||||||
|
'%لینک'
|
||||||
|
);
|
||||||
|
|
||||||
-- ستونهای اختیاری settings (بعضی DBهای قدیمی ندارند)
|
-- ستونهای اختیاری settings (بعضی DBهای قدیمی ندارند)
|
||||||
SET @sql = IF(
|
SET @sql = IF(
|
||||||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||||
|
|||||||
@@ -11,6 +11,22 @@
|
|||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
SET @price_channel_message_desc = 'قالب متن پیام ارسالی به کانال. متغیرهای قیمت تابلو: ٪گرم_خرید ٪گرم_فروش ٪مثقال_خرید ٪مثقال_فروش (یا با %). زمان: ٪تاریخ ٪ساعت. اپ: ٪اسم_اپ یا ٪نام (نام فارسی)؛ ٪عنوان = خط «📊 قیمت لحظهای + نام». تماس جدا: ٪آیدی ٪شماره ٪لینک. اختیاری: ٪محصولات (لیست همه محصولات)؛ ٪فوتر (ترکیب آیدی+شماره+لینک). فاصله بعد از ٪ اختیاری است. خالی = قالب پیشفرض.';
|
||||||
|
SET @price_channel_default_text = CONCAT(
|
||||||
|
'سلام 👋', CHAR(10),
|
||||||
|
'%عنوان', CHAR(10),
|
||||||
|
'📅 %تاریخ 🕐 %ساعت', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'🔴 خرید گرم: %گرم_خرید', CHAR(10),
|
||||||
|
'🟢 فروش گرم: %گرم_فروش', CHAR(10),
|
||||||
|
'🔴 خرید مثقال: %مثقال_خرید', CHAR(10),
|
||||||
|
'🟢 فروش مثقال: %مثقال_فروش', CHAR(10),
|
||||||
|
CHAR(10),
|
||||||
|
'📞 %شماره', CHAR(10),
|
||||||
|
'%آیدی', CHAR(10),
|
||||||
|
'%لینک'
|
||||||
|
);
|
||||||
|
|
||||||
-- توکن روبیکا (توکن بله/تلگرام از قبل موجودند) — سیستمی (can_edit=0)
|
-- توکن روبیکا (توکن بله/تلگرام از قبل موجودند) — سیستمی (can_edit=0)
|
||||||
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`)
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`)
|
||||||
SELECT 'rubika_bot_token', '', 'توکن بات روبیکا', 0, 1, NULL
|
SELECT 'rubika_bot_token', '', 'توکن بات روبیکا', 0, 1, NULL
|
||||||
@@ -39,6 +55,17 @@ SELECT 'price_channel_min_seconds', '120', 'حداقل فاصله ارسال (ث
|
|||||||
'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را میگیرد. صفر = هر تغییر قیمت.', 'number'
|
'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را میگیرد. صفر = هر تغییر قیمت.', 'number'
|
||||||
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1);
|
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1);
|
||||||
|
|
||||||
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
||||||
|
SELECT 'price_channel_message_text', @price_channel_default_text, 'قالب متن پیام کانال', 1, 1, @price_channel_message_desc, 'longtext'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_message_text' LIMIT 1);
|
||||||
|
|
||||||
|
UPDATE `settings` SET
|
||||||
|
`title_fa` = 'قالب متن پیام کانال',
|
||||||
|
`type` = 'longtext',
|
||||||
|
`can_edit` = 1,
|
||||||
|
`description` = @price_channel_message_desc
|
||||||
|
WHERE `key` = 'price_channel_message_text';
|
||||||
|
|
||||||
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
|
||||||
SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1,
|
SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1,
|
||||||
'اگر پر باشد در انتهای پیام نمایش داده میشود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمیشود.', 'text'
|
'اگر پر باشد در انتهای پیام نمایش داده میشود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمیشود.', 'text'
|
||||||
@@ -82,7 +109,8 @@ UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN (
|
|||||||
);
|
);
|
||||||
UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN (
|
UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN (
|
||||||
'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff',
|
'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff',
|
||||||
'price_channel_min_seconds', 'price_channel_footer_id', 'price_channel_footer_phone',
|
'price_channel_min_seconds', 'price_channel_message_text',
|
||||||
|
'price_channel_footer_id', 'price_channel_footer_phone',
|
||||||
'price_channel_footer_link', 'change_mesghal'
|
'price_channel_footer_link', 'change_mesghal'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user