fix notif

This commit is contained in:
2026-07-24 16:49:42 +03:30
parent eacf5181a9
commit 107cf5b291
10 changed files with 105 additions and 11 deletions
@@ -5,13 +5,14 @@ namespace App\Http\Controllers\Admin;
use App\DB\Te\TableEngine;
use App\Http\Controllers\Controller;
use App\Models\AppNotification;
use App\Models\AppNotificationRead;
use Illuminate\Http\Request;
class AppNotificationController extends Controller
{
public function table(Request $request)
{
$query = AppNotification::query();
$query = AppNotification::query()->withCount('reads');
TableEngine::create($query, $request->all())
->initSearch(['title', 'body', 'severity'])
@@ -62,6 +63,36 @@ class AppNotificationController extends Controller
return response()->json(true);
}
/** لیست مشتریانی که این اعلان را سین کرده‌اند */
public function readers(int $id)
{
AppNotification::findOrFail($id);
$rows = AppNotificationRead::query()
->where('notification_id', $id)
->with(['customer:id,name,fname,lname,mobile'])
->orderByDesc('read_at')
->orderByDesc('id')
->get();
$readers = $rows->map(function (AppNotificationRead $read) {
$customer = $read->customer;
$name = trim((string) ($customer?->name ?: trim(($customer?->fname ?? '') . ' ' . ($customer?->lname ?? ''))));
return [
'customer_id' => $read->customer_id,
'name' => $name !== '' ? $name : '—',
'mobile' => $customer?->mobile,
'read_at' => $read->read_at,
];
})->values();
return response()->json([
'reads_count' => $readers->count(),
'readers' => $readers,
]);
}
private function validatedPayload(Request $request, bool $partial = false): array
{
$rules = [
@@ -1357,7 +1357,7 @@ class SingleOrderController extends Controller
if ($hasApp && $hasProduct) {
$source = 'app+product';
$label = 'قیمت اپ + تب اختلاف محصول = ' . number_format($amount) . ' ریال / گرم';
$label = 'قیمت صفحه اصلی اپلیکیشن + تب اختلاف محصول = ' . number_format($amount) . ' ریال / گرم';
} elseif ($hasApp) {
$source = 'settings';
$label = ($lines[0]['label'] ?? 'اختلاف پایه اپ') . ' = ' . number_format($amount) . ' ریال';
@@ -267,10 +267,13 @@ class ReportController extends Controller
if ($config->isOutsideTradingHours()) {
$config->syncAppClosedFlag();
return $zeroResponse();
// نمایش قیمت صفحه اصلی حتی وقتی فروشگاه بسته است — معامله همچنان از سمت اپ بسته می‌ماند
if (! $config->shouldShowHomePriceWhenClosed()) {
return $zeroResponse();
}
} else {
Cnt::where('key', 'app_closed')->update(['value' => 'false']);
}
Cnt::where('key', 'app_closed')->update(['value' => 'false']);
}
/*
+5
View File
@@ -23,4 +23,9 @@ class AppNotificationRead extends Model
{
return $this->belongsTo(AppNotification::class, 'notification_id');
}
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class, 'customer_id');
}
}
+2 -2
View File
@@ -768,8 +768,8 @@ class BalanceReportService
$source = $feeSource ?? $this->resolveOrderFeeSourceKey();
if ($source === 'app+product') {
return $direction === 2
? 'قیمت اپ (sell_fee) + تب اختلاف محصول'
: 'قیمت اپ (buy_fee) + تب اختلاف محصول';
? 'قیمت صفحه اصلی اپلیکیشن (sell_fee) + تب اختلاف محصول'
: 'قیمت صفحه اصلی اپلیکیشن (buy_fee) + تب اختلاف محصول';
}
if ($source === 'settings') {
return $direction === 2
+6
View File
@@ -492,6 +492,12 @@ class ConfigService
return $this->getBool('close_price', false);
}
/** خارج از ساعت کاری، قیمت صفحه اصلی را نشان بده (معامله همچنان بسته) */
public function shouldShowHomePriceWhenClosed(): bool
{
return $this->getBool('show_home_price_when_closed', false);
}
/** @return array{start: string, end: string} */
public function tradingHourBounds(): array
{
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
/**
* سوییچ: خارج از ساعت کاری هم قیمت صفحه اصلی اپ نشان داده شود (بدون پیام «فروشگاه بسته است»).
* معامله همچنان بسته می‌ماند؛ فقط نمایش قیمت صفحه اصلی باز می‌شود.
*/
return new class extends Migration
{
public function up(): void
{
if (! DB::table('settings')->where('key', 'show_home_price_when_closed')->exists()) {
DB::table('settings')->insert([
'key' => 'show_home_price_when_closed',
'value' => 'false',
'title_fa' => 'نمایش قیمت صفحه اصلی خارج از ساعت کاری',
'type' => 'switch',
'can_edit' => 1,
'is_active' => 1,
'description' => 'روشن: وقتی فروشگاه خارج از ساعت کاری است، قیمت صفحه اصلی اپ همچنان نمایش داده می‌شود و پیام «فروشگاه بسته است» نشان داده نمی‌شود. خرید/فروش همچنان بسته می‌ماند. خاموش: مثل قبل، خارج از ساعت پیام بسته بودن و قیمت صفر نشان داده می‌شود.',
'created_at' => now(),
'updated_at' => now(),
]);
}
}
public function down(): void
{
DB::table('settings')->where('key', 'show_home_price_when_closed')->delete();
}
};
+10 -2
View File
@@ -215,6 +215,12 @@ INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `de
SELECT 'show_gold_ounce_price', 'false', 'نمایش قیمت انس طلا', 1, 1, NULL
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_gold_ounce_price' LIMIT 1);
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
SELECT 'show_home_price_when_closed', 'false', 'نمایش قیمت صفحه اصلی خارج از ساعت کاری', 1, 1,
'روشن: وقتی فروشگاه خارج از ساعت کاری است، قیمت صفحه اصلی اپ همچنان نمایش داده می‌شود و پیام «فروشگاه بسته است» نشان داده نمی‌شود. خرید/فروش همچنان بسته می‌ماند. خاموش: مثل قبل، خارج از ساعت پیام بسته بودن و قیمت صفر نشان داده می‌شود.',
'switch'
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_home_price_when_closed' LIMIT 1);
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`)
SELECT 'main_product_price', 'false', 'قیمت از محصول (legacy)', 1, 1, 'از price_provider استفاده کنید'
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_product_price' LIMIT 1);
@@ -949,7 +955,7 @@ UPDATE `settings` SET `type` = 'select', `description` = 'bale,telegram,whatsapp
UPDATE `settings` SET `type` = 'switch' WHERE `key` IN (
'chart_use_local_data',
'jibit_enabled', 'jibit_verification', 'register_jibit_verify', 'open_register', 'auto_active_customer',
'close_price', 'show_last_price', 'show_gold_ounce_price',
'close_price', 'show_last_price', 'show_gold_ounce_price', 'show_home_price_when_closed',
'fee_deduct_from_gold',
'require_zero_main_gold_before_other_buy',
'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw',
@@ -1291,6 +1297,7 @@ UPDATE `settings` SET `description` = 'آدرس سرور(های) فید قیمت
UPDATE `settings` SET `description` = 'کلید یا UUID ردیف قیمت در پاسخ API تابلو. باید با محصول/ردیف موردنظر در سرویس خارجی یکسان باشد.' WHERE `key` = 'zaarbox_price_key';
UPDATE `settings` SET `description` = 'روشن: اگر API قیمت در دسترس نباشد، آخرین قیمت ذخیره‌شده در دیتابیس به کاربر نشان داده می‌شود. خاموش: در قطعی API ممکن است قیمت صفر نمایش داده شود.' WHERE `key` = 'show_last_price';
UPDATE `settings` SET `description` = 'روشن: اگر آدرس API تابلو (zaarbox_api_url) تنظیم شده باشد، قیمت انس طلا در اپ مشتری نمایش داده می‌شود. خاموش: نمایش داده نمی‌شود.' WHERE `key` = 'show_gold_ounce_price';
UPDATE `settings` SET `description` = 'روشن: وقتی فروشگاه خارج از ساعت کاری است، قیمت صفحه اصلی اپ همچنان نمایش داده می‌شود و پیام «فروشگاه بسته است» نشان داده نمی‌شود. خرید/فروش همچنان بسته می‌ماند. خاموش: مثل قبل، خارج از ساعت پیام بسته بودن و قیمت صفر نشان داده می‌شود.' WHERE `key` = 'show_home_price_when_closed';
UPDATE `settings` SET `description` = 'روشن: خارج از بازه «ساعت شروع» تا «ساعت پایان» معامله و نمایش قیمت بسته می‌شود. خاموش: محدودیت ساعتی سراسری اعمال نمی‌شود.' WHERE `key` = 'close_price';
UPDATE `settings` SET `description` = 'ساعت شروع فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۰۹:۰۰).' WHERE `key` = 'startDay';
UPDATE `settings` SET `description` = 'ساعت پایان فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۲۲:۰۰).' WHERE `key` = 'endDay';
@@ -1594,6 +1601,7 @@ UPDATE `settings` SET `title_fa` = 'آدرس API سرور' WHERE `key` = 'server
UPDATE `settings` SET `title_fa` = 'کارمزد درصدی (alias)' WHERE `key` = 'service_charge_percentage';
UPDATE `settings` SET `title_fa` = 'نمایش آخرین قیمت ذخیره‌شده' WHERE `key` = 'show_last_price';
UPDATE `settings` SET `title_fa` = 'نمایش قیمت انس طلا' WHERE `key` = 'show_gold_ounce_price';
UPDATE `settings` SET `title_fa` = 'نمایش قیمت صفحه اصلی خارج از ساعت کاری' WHERE `key` = 'show_home_price_when_closed';
UPDATE `settings` SET `title_fa` = 'مسیر SSE قیمت' WHERE `key` = 'sse_path';
UPDATE `settings` SET `title_fa` = 'ساعت شروع' WHERE `key` = 'startDay';
UPDATE `settings` SET `title_fa` = 'وضعیت فروشگاه' WHERE `key` = 'store_status';
@@ -1695,7 +1703,7 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN (
'open_register',
'referral_id', 'referral_limit', 'referral_gift_on_first_order',
'register_jibit_verify', 'register_referral_bonus_message', 'register_referral_sms_to_referrer',
'sell_fee', 'show_last_price', 'show_gold_ounce_price', 'startDay',
'sell_fee', 'show_last_price', 'show_home_price_when_closed', 'show_gold_ounce_price', 'startDay',
'support_messenger', 'support_messenger_id', 'support_messenger_text',
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
'text_about', 'text_rule',
@@ -165,6 +165,12 @@ INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `de
SELECT 'show_last_price', 'true', 'نمایش آخرین قیمت DB اگر API قطع شد', 1, 1, NULL
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_last_price' LIMIT 1);
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`)
SELECT 'show_home_price_when_closed', 'false', 'نمایش قیمت صفحه اصلی خارج از ساعت کاری', 1, 1,
'روشن: وقتی فروشگاه خارج از ساعت کاری است، قیمت صفحه اصلی اپ همچنان نمایش داده می‌شود و پیام «فروشگاه بسته است» نشان داده نمی‌شود. خرید/فروش همچنان بسته می‌ماند. خاموش: مثل قبل، خارج از ساعت پیام بسته بودن و قیمت صفر نشان داده می‌شود.',
'switch'
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_home_price_when_closed' LIMIT 1);
INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`)
SELECT 'main_product_price', 'false', 'قیمت از محصول (legacy)', 1, 1, 'از price_provider استفاده کنید'
WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_product_price' LIMIT 1);
@@ -820,7 +826,7 @@ UPDATE `settings` SET `type` = 'select', `description` = 'bale,telegram,whatsapp
UPDATE `settings` SET `type` = 'switch' WHERE `key` IN (
'chart_use_local_data',
'jibit_enabled', 'jibit_verification', 'register_jibit_verify', 'open_register', 'auto_active_customer',
'close_price', 'show_last_price',
'close_price', 'show_last_price', 'show_home_price_when_closed',
'fee_deduct_from_gold',
'send_to_tahesab', 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw',
'has_page_earn_money', 'has_page_price_trigger', 'has_page_notification', 'charge_notif', 'group_sms', 'sms_panel', 'customer_direct_sms',
@@ -1178,6 +1184,7 @@ UPDATE `settings` SET `description` = 'شناسه عددی یا نام reading_m
UPDATE `settings` SET `description` = 'آدرس پایه API سرویس تابلو آنلاین (بدون مسیر انتهایی). مثال: https://example.com/api' WHERE `key` = 'zaarbox_api_url';
UPDATE `settings` SET `description` = 'کلید یا UUID ردیف قیمت در پاسخ API تابلو. باید با محصول/ردیف موردنظر در سرویس خارجی یکسان باشد.' WHERE `key` = 'zaarbox_price_key';
UPDATE `settings` SET `description` = 'روشن: اگر API قیمت در دسترس نباشد، آخرین قیمت ذخیره‌شده در دیتابیس به کاربر نشان داده می‌شود. خاموش: در قطعی API ممکن است قیمت صفر نمایش داده شود.' WHERE `key` = 'show_last_price';
UPDATE `settings` SET `description` = 'روشن: وقتی فروشگاه خارج از ساعت کاری است، قیمت صفحه اصلی اپ همچنان نمایش داده می‌شود و پیام «فروشگاه بسته است» نشان داده نمی‌شود. خرید/فروش همچنان بسته می‌ماند. خاموش: مثل قبل، خارج از ساعت پیام بسته بودن و قیمت صفر نشان داده می‌شود.' WHERE `key` = 'show_home_price_when_closed';
UPDATE `settings` SET `description` = 'روشن: خارج از بازه «ساعت شروع» تا «ساعت پایان» معامله و نمایش قیمت بسته می‌شود. خاموش: محدودیت ساعتی سراسری اعمال نمی‌شود.' WHERE `key` = 'close_price';
UPDATE `settings` SET `description` = 'ساعت شروع فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۰۹:۰۰).' WHERE `key` = 'startDay';
UPDATE `settings` SET `description` = 'ساعت پایان فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۲۲:۰۰).' WHERE `key` = 'endDay';
@@ -1400,7 +1407,7 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN (
'open_register',
'referral_id', 'referral_limit', 'referral_gift_on_first_order',
'register_jibit_verify', 'register_referral_bonus_message', 'register_referral_sms_to_referrer',
'sell_fee', 'show_last_price', 'startDay',
'sell_fee', 'show_last_price', 'show_home_price_when_closed', 'startDay',
'support_messenger', 'support_messenger_id', 'support_messenger_text',
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
'text_about', 'text_rule',
+1
View File
@@ -53,6 +53,7 @@ Route::middleware('auth:user')->group(function (){
Route::post('app_notifications', [AdminAppNotificationController::class, 'store']);
Route::put('app_notifications/{id}', [AdminAppNotificationController::class, 'update']);
Route::put('app_notifications/{id}/toggle', [AdminAppNotificationController::class, 'toggleActive']);
Route::get('app_notifications/{id}/readers', [AdminAppNotificationController::class, 'readers']);
Route::delete('app_notifications/{id}', [AdminAppNotificationController::class, 'destroy']);
//------------ConditionalOrder
Route::post('conditional_orders/table', [\App\Http\Controllers\Admin\ConditionalOrderController::class, 'table']);