Enable gated multi-level referral profit and harden chat/SMS notify paths.

Honor enable_customer_level_profit for order referral payouts, and tighten support-chat webhook/SMS plus SuperAdmin SMS panel sync settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-10 16:48:53 +03:30
co-authored by Cursor
parent f421fcb83f
commit 279e4bc881
8 changed files with 277 additions and 110 deletions
@@ -259,7 +259,7 @@ class SingleOrderController extends Controller
report($e);
}
}
// $response['reward'] = $this->give_order_reward($data, $wallet, $wallet_interface);
$response['reward'] = $this->give_order_reward($data, $wallet, $wallet_interface);
if ((int) $data['direction'] === 1 && $customer) {
$referrer = Customer::where('referral_id', $customer->referral_to_id)->first();
if (!empty($referrer) && $referrer->first_buy_order == 1 && $customer->first_buy_order !== 1) {
@@ -810,64 +810,97 @@ class SingleOrderController extends Controller
private function give_order_reward(&$data, $wallet, $wallet_interface)
{
if (!app(\App\Services\ConfigService::class)->getBool('enable_customer_level_profit', false)) {
return $data;
}
$serviceCharge = (float) ($data['order']['service_charge'] ?? 0);
if ($serviceCharge <= 0) {
return $data;
}
$data['aCustomers'] = [];
$i = 0;
$data['aCustomers'][$i] = Customer::findOrFail($data['customer_id']);
while ($data['aCustomers'][$i + 1] = Customer::where('referral_id', $data['aCustomers'][$i]->referral_to_id)->first()) {
if ($data['aCustomers'][$i + 1]->profit_amount_by_lvl) {
$levels = json_decode(str_replace(['{', '}'], ['[', ']'], $data['aCustomers'][$i + 1]->profit_amount_by_lvl), true);
foreach ($levels as $level) {
if ($level[0] == $i + 1) {
// [$level[1],$data['aCustomers'][$i+1]];
if ($this->Config('has_page_earn_money') == true) {
$gift_for_invite = ($data['order']['service_charge'] * $level[1]) / 100;
$profit_receiver = $data['aCustomers'][$i + 1]->id;
$profit_sender = $data['aCustomers'][0]->id;
$Withdraw = Withdraw::create([
'user_id' => $profit_sender,
'customer_id' => $profit_receiver,
"cash" => 0,
"gold" => $gift_for_invite,
'sts' => 9,
]);
$wallet_interface = new WalletInterface($profit_receiver, 2);
new TransactionInterface($wallet_interface, $_inp = [
"cash" => 0,
"gold" => $gift_for_invite,
'expire_at' => now(),
'active' => true,
'withdraw_id' => $Withdraw->id,
'start_at' => now(),
], 9, true, false);
$transaction = Transaction::where('customer_id', $profit_receiver)->latest()->first();
TransactionsAdmin::create([
'customer_id' => $profit_sender,
'customer_to_id' => $profit_receiver,
'user_id' => $profit_sender,
'order_id' => $data['order']['id'],
'wallet' => null, // یا مقدار مناسب دیگری
'transaction_id' => $transaction->id,
'cash' => 0,
'note' => ' سود بابت سفارش',
'type' => 1, // یا مقدار مناسب دیگری
'gold' => $gift_for_invite,
'balance_cash' => 0, // یا مقدار مناسب دیگری
'balance_gold' => $gift_for_invite, // مقدار صحیح برای `balance_gold`
'withdraw_id' => $Withdraw->id,
]);
}
}
$levels = $this->parseProfitAmountByLevel($data['aCustomers'][$i + 1]->profit_amount_by_lvl);
foreach ($levels as $levelRow) {
$levelNo = (int) ($levelRow['level'] ?? $levelRow[0] ?? 0);
$percent = (float) ($levelRow['present'] ?? $levelRow[1] ?? 0);
if ($levelNo !== ($i + 1) || $percent <= 0) {
continue;
}
$gift_for_invite = ($serviceCharge * $percent) / 100;
if ($gift_for_invite <= 0) {
continue;
}
$profit_receiver = $data['aCustomers'][$i + 1]->id;
$profit_sender = $data['aCustomers'][0]->id;
$Withdraw = Withdraw::create([
'user_id' => $profit_sender,
'customer_id' => $profit_receiver,
'cash' => 0,
'gold' => $gift_for_invite,
'sts' => 9,
]);
$wallet_interface = new WalletInterface($profit_receiver, 2);
new TransactionInterface($wallet_interface, [
'cash' => 0,
'gold' => $gift_for_invite,
'expire_at' => now(),
'active' => true,
'withdraw_id' => $Withdraw->id,
'start_at' => now(),
], 9, true, false);
$transaction = Transaction::where('customer_id', $profit_receiver)->latest()->first();
TransactionsAdmin::create([
'customer_id' => $profit_sender,
'customer_to_id' => $profit_receiver,
'user_id' => $profit_sender,
'order_id' => $data['order']['id'],
'wallet' => null,
'transaction_id' => $transaction->id,
'cash' => 0,
'note' => ' سود بابت سفارش',
'type' => 1,
'gold' => $gift_for_invite,
'balance_cash' => 0,
'balance_gold' => $gift_for_invite,
'withdraw_id' => $Withdraw->id,
]);
}
if ($i == 100) break;
$i++; // برای جلوگیری از حلقه بی‌نهایت
if ($i == 100) {
break;
}
$i++;
}
return $data;
}
/** @return list<array{level?:int,present?:float}|array{0:int,1:float}> */
private function parseProfitAmountByLevel(mixed $raw): array
{
if (is_array($raw)) {
return $raw;
}
if (!is_string($raw) || trim($raw) === '') {
return [];
}
$decoded = json_decode($raw, true);
if (is_array($decoded)) {
return $decoded;
}
// فرمت قدیمی: رشته شبیه {1,5},{2,2}
$legacy = json_decode(str_replace(['{', '}'], ['[', ']'], $raw), true);
return is_array($legacy) ? $legacy : [];
}
private function sendTransactionNotifications(array $data, string $transactionType)
{
$customer = Customer::findOrFail($data['customer_id']);
@@ -880,8 +913,9 @@ class SingleOrderController extends Controller
$totalPrice = $data['total_price'] ?? ($data['payment_amount'] ?? 0);
$subjectTitle = $this->transactionSubjectTitle($data);
$amountLabel = self::formatSmsGoldWeight($amount);
$message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType {$subjectTitle} به مقدار " .
"{$amount} گرم به مبلغ " . number_format($totalPrice) .
"{$amountLabel} گرم به مبلغ " . number_format($totalPrice) .
" ریال کرد. با تشکر، $companyName";
if (self::isSmsNotifEnabled('sms_notif_order_admin')) {
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
@@ -895,9 +929,10 @@ class SingleOrderController extends Controller
$balanceLabel = self::metalTypeLabel();
$goldBalance = $wallet ? ($wallet->gold ?? 0) : 0;
$cashBalance = $wallet ? ($wallet->cash ?? 0) : 0;
$customerMessage = "$companyName\n$transactionType {$subjectTitle}\nگرم: {$amount}\n" .
$goldBalanceLabel = self::formatSmsGoldWeight($goldBalance);
$customerMessage = "$companyName\n$transactionType {$subjectTitle}\nگرم: {$amountLabel}\n" .
"مبلغ کل: " . number_format($totalPrice) . "\n\n" .
"موجودی {$balanceLabel}: {$goldBalance}\n" .
"موجودی {$balanceLabel}: {$goldBalanceLabel}\n" .
"مانده ریالی: " . number_format($cashBalance) . "\n" .
self::publicSiteUrl(request());
@@ -1036,7 +1071,7 @@ class SingleOrderController extends Controller
$userMobile = $customer->mobile; // User's mobile number
$userName = $customer->name; // User's name
$chargedAmount = $data['total_price']; // Total price in Rial
$chargedAmountGold = $data['amount']; // Amount of gold
$chargedAmountGold = self::formatSmsGoldWeight($data['amount']); // Amount of gold
// Company name
$companyName = $this->Config('name_fa'); // Company name from configuration
@@ -1055,15 +1090,16 @@ class SingleOrderController extends Controller
->main()
->first();
$companyurl = self::publicSiteUrl(request());
$weight = $data['amount'];
$weight = (float) $data['amount'];
$weightLabel = self::formatSmsGoldWeight($weight);
$totalAmount = $data['total_price'];
$pricePerGram = $weight > 0 ? $totalAmount / $weight : 0;
$goldBalance = $mainWallet->gold ?? 0;
$goldBalance = self::formatSmsGoldWeight($mainWallet->gold ?? 0);
$remainingBalance = $mainWallet->cash ?? 0;
$message = "$companyName\n";
$message .= "خرید آبشده\n";
$message .= "گرم: $weight\n";
$message .= "گرم: $weightLabel\n";
$message .= "قیمت گرم: " . number_format($pricePerGram) . "\n";
$message .= "مبلغ کل: " . number_format($totalAmount) . "\n\n";
$message .= "موجودی طلایی: $goldBalance\n";
@@ -1110,6 +1146,28 @@ class SingleOrderController extends Controller
return null;
}
/**
* مقدار ضرب‌شونده در قیمت واحد برای مبلغ سفارش.
* قیمت فرمولی = قیمت هر عدد (وزن داخل فرمول است) → فقط تعداد.
* بقیه = تعداد × وزن واحد محصول.
*/
private function resolveProductOrderPricingAmount(Product|array|null $product, float $number): float
{
if ($product instanceof Product && FormulaPriceService::isEnabled($product)) {
return $number;
}
if (is_array($product) && ! empty($product['price_formula_enabled'])) {
return $number;
}
$unitAmount = $product instanceof Product
? (float) ($product->amount ?? 0)
: (float) (is_array($product) ? ($product['amount'] ?? 0) : 0);
return $number * $unitAmount;
}
private function assertMinimumSellCash(array $data): void
{
$minSell = Setting::where('key', 'minimum_sell')->where('is_active', 1)->first();