first(); // $talla->update_date = Verta::instance(Carbon::parse($talla->updated_at))->format('Y/n/j-H:i'); $new_customer_major = Customer::where('type',1)->whereDate('created_at','<=',now())->whereDate('created_at','>=',now()->subMonths(3)) ->count(); $new_customer_single = Customer::where('type',2)->whereDate('created_at','<=',now())->whereDate('created_at','>=',now()->subMonths(3)) ->count(); $all_customer_major = Customer::where('type',1)->count(); $all_customer_single = Customer::where('type',2)->count(); $archive_customer_major = Customer::where('type',1)->where('is_archive',true)->count(); $archive_customer_single = Customer::where('type',2)->where('is_archive',true)->count(); $all_gold = Order::where('direction',2)->where('type',1)->sum('amount');// جمع طلاهایی که از مشتری خریدیم $all_gold_single = Order::where('direction',2)->where('type',2)->sum('amount');// جمع طلاهایی که از مشتری خریدیم $await_list = Order::where('direction',1)->where('sts',1)->get(); $best_customer_major=Order::with('customer')->where('type',1)->where('sts',2)->select('customer_id',DB::raw('sum(amount) as amount')) ->groupBy('customer_id')->limit(10)->get(); $best_customer_single=Wallet::with('customer')->whereNull('fund_id')->where('owner_type',2)->orderBy('gold','desc')->limit(10)->get(); // GT $GT_all_customers = Customer::where('type',2)->where('is_archive',false)->count(); $GT_no_login_customers = Customer::where('type',2)->where('is_archive',false)->where('last_seen_at',null)->count(); $GT_no_valid_customers = Customer::where('type',2)->where('is_archive',false)->where('is_legal',0)->count(); $GT_no_valid_customers_data = Customer::where('type',2)->where('is_archive',false)->where('is_legal',0)->get(['id','name','mobile']); $GT_active_customers = Customer::where('type', 2) ->where('is_archive', false) ->whereIn('id', function($query) { $query->select('owner') ->from('wallets'); })->count(); $GT_active_customers_data = Customer::where('type', 2) ->where('is_archive', false) ->whereIn('id', function($query) { $query->select('owner') ->from('wallets'); })->get(['id','name','mobile']); $transactions_admins = TransactionsAdmin::with(['withdraw','order',"user",'customerTo','customer'])->get(); $startDate = $request->startDateProduct ? Carbon::parse($request->startDateProduct)->startOfDay() : now()->subMonth()->startOfDay(); $endDate = $request->endDateProduct ? Carbon::parse($request->endDateProduct)->endOfDay() : now()->endOfDay(); $products_report = Product::with(['limitedTransactions' => function ($query) use ($startDate, $endDate) { $query->whereBetween('created_at', [$startDate, $endDate]); }]) ->whereHas('limitedTransactions', function ($query) use ($startDate, $endDate) { $query->whereBetween('created_at', [$startDate, $endDate]); }) ->get(); $products_report->each(function ($product) { $product->transaction_sum_gold_buy = $product->limitedTransactions ->where('gold', '>', 0) ->sum('gold'); $product->total_negative_gold_sell = $product->limitedTransactions ->where('gold', '<', 0) ->sum('gold'); $product->total_gold = $product->limitedTransactions->sum('gold'); }); $gramPrice = (int) ($tallaPrice->price ?? 0); $FPrices = []; $mainProductId = app(ConfigService::class)->mainProductId(); if ($mainProductId) { $mainProduct = Product::find($mainProductId); if ($mainProduct) { $gramPrice = (int) ($mainProduct->price + ($mainProduct->price_profit ?? 0)); $FPrices[] = [ 'id' => 'main_product', 'name' => $mainProduct->title ?? 'محصول اصلی', 'price' => $gramPrice, 'profit' => 0, ]; } } $FPrices[] = ['id' => '1', 'name' => 'افجو', 'price' => $gramPrice, 'profit' => 0]; $gatewayRow = Cnt::where('key', 'is_gateway_open')->first(); return response()->json([ 'GT_all_customers'=>$GT_all_customers, 'GT_no_login_customers'=>$GT_no_login_customers, 'GT_no_valid_customers'=>$GT_no_valid_customers, 'GT_no_valid_customers_data'=>$GT_no_valid_customers_data, 'GT_active_customers'=>$GT_active_customers, 'GT_active_customers_data'=>$GT_active_customers_data, 'GT_deActive_customers'=>$GT_all_customers-$GT_active_customers, 'GT_transactions_admins'=>$transactions_admins, 'GT_products_report' => $products_report, 'update_date' => now()->timezone('Asia/Tehran')->format('Y-m-d H:i:s'), 'pricem' => round($gramPrice * 4.331802 / 10000) * 10000, 'prices' => $FPrices, 'is_gateway_open' => $gatewayRow && (string) $gatewayRow->value === '1', 'price'=>$tallaPrice?->price ?? $gramPrice, 'new_customer_major'=>$new_customer_major, 'new_customer_single'=>$new_customer_single, 'all_customer_major'=>$all_customer_major, 'all_customer_single'=>$all_customer_single, 'archive_customer_major'=>$archive_customer_major, 'archive_customer_single'=>$archive_customer_single, 'all_gold'=>$all_gold, 'all_gold_single'=>$all_gold_single, 'await_order'=>$await_list, 'best_customer'=>$best_customer_major, 'best_customer_single'=>$best_customer_single, ]); } public function gateway() { $cnt = Cnt::where('key', 'is_gateway_open')->first(); if (!$cnt) { $cnt = Cnt::create([ 'key' => 'is_gateway_open', 'value' => '1', ]); } else { $cnt->value = ((string) $cnt->value === '0') ? '1' : '0'; $cnt->save(); } return $cnt; } public function getBalance(Request $request, BalanceReportService $balanceReportService) { $startDate = Carbon::parse($request->startDate)->startOfDay(); $endDate = Carbon::parse($request->endDate)->endOfDay(); $response=[]; $response["liman"]=[]; $response["kalhor"]=[]; $excludeCustomerId = (int) app(ConfigService::class)->getInt('balance_report_exclude_customer_id', 4); $catalogMetalIds = $balanceReportService->catalogMetalIds(); if ($catalogMetalIds === []) { $catalogMetalIds = [1]; } $limanMetalBuckets = $balanceReportService->initMetalBalanceBuckets($catalogMetalIds); $kalhorMetalBuckets = $balanceReportService->initMetalBalanceBuckets($catalogMetalIds); $response["pay_at_update"] = Order::whereNull('pay_at')->update(['pay_at' => DB::raw('created_at')]); //liman $response["liman"]["orders"] = Order::with(['transactions.product', 'customer']) ->where('customer_id', '!=', $excludeCustomerId) ->where('sts', 2) ->whereBetween('pay_at', [$startDate, $endDate]) ->get(); $response["liman"]["balance"]["gold"] = 0; $response["liman"]["balance"]["cash"] = 0; $response["liman"]["balance_abs"]["gold"] = 0; $response["liman"]["balance_abs"]["cash"] = 0; foreach ($response["liman"]["orders"] as $OrderGoldBalanceRow) { $balanceReportService->applyOrderToBuckets($limanMetalBuckets, $OrderGoldBalanceRow); if ($OrderGoldBalanceRow->direction == 1){ $response["liman"]["balance"]["gold"] += $OrderGoldBalanceRow->amount; $response["liman"]["balance"]["cash"] -= $OrderGoldBalanceRow->total_price; } if ($OrderGoldBalanceRow->direction == 2){ $response["liman"]["balance"]["gold"] -= $OrderGoldBalanceRow->amount; $response["liman"]["balance"]["cash"] += $OrderGoldBalanceRow->total_price; } $response["liman"]["balance_abs"]["gold"] += $OrderGoldBalanceRow->amount; $response["liman"]["balance_abs"]["cash"] += $OrderGoldBalanceRow->total_price; } $response['goldBalanceOfLiman']= -$response["liman"]["balance"]["gold"]; $response['cashBalanceOfLiman']= -$response["liman"]["balance"]["cash"]; //kalhor // $response["kalhor"]["orders"] = Cache::remember("kalhor_orders_" . md5($startDate . $endDate), 900, function () use ($startDate, $endDate) { // $body = [ // 'FromDate' => Jalalian::forge($startDate)->format('Y/m/d'), // 'ItemId' => 0, // 'OrderIndex' => 0, // 'ToDate' => Jalalian::forge($endDate)->format('Y/m/d'), // ]; // // return Http::withHeaders(config('kalhor.headers')) // ->withCookies(config('kalhor.cookies'), 'b750.ir') // ->post('https://b750.ir/Deal/DealsList', $body)->json(); // }); $response["kalhor"]["balance"]["gold"] = 0; $response["kalhor"]["balance"]["cash"] = 0; $response["kalhor"]["balance_abs"]["gold"] = 0; $response["kalhor"]["balance_abs"]["cash"] = 0; if (!empty($response["kalhor"]["orders"]['Data'])) { foreach ($response["kalhor"]["orders"]['Data'] as &$data) { $data['0_save_in_liman']= 0; if ($data['DeclineReason'] == 0 and $data['OrderStatusStr'] !="لغو شده") { //رد نشده بود $data['0_save_in_liman']= 1; if ($data['DealTypeStr'] == "خرید" or $data['DealTypeStr'] == "خرید _ دستی") { $response["kalhor"]["balance"]['gold'] += $data['Count']; $response["kalhor"]["balance"]['cash'] -= $data['TotalPrice']; $direction =2; $balanceReportService->applyKalhorSlice( $kalhorMetalBuckets, (float) $data['Count'], (float) $data['TotalPrice'], 2 ); } elseif ($data['DealTypeStr'] == "فروش" or $data['DealTypeStr'] == "فروش _ دستی") { $response["kalhor"]["balance"]['gold'] -= $data['Count']; $response["kalhor"]["balance"]['cash'] += $data['TotalPrice']; $direction =1; $balanceReportService->applyKalhorSlice( $kalhorMetalBuckets, (float) $data['Count'], (float) $data['TotalPrice'], 1 ); } $response["kalhor"]["balance_abs"]['gold'] += $data['Count']; $response["kalhor"]["balance_abs"]['cash'] += $data['TotalPrice']; if (Order::where('ref_id', $data['OrderCode'])->doesntExist()){ $request = new Request([ 'amount' => $data['Count'], 'customer_id' => 12, 'method' => "liman", 'direction' => $direction, 'product_id' => 2, "price"=>$data['Mazane'], "cash"=>$data['TotalPrice'], 'ref_id' => $data['OrderCode'], 'pay_at' =>Jalalian::fromFormat('Y/m/d', explode('_', $data['ModifiedDateStr'])[0])->toCarbon()->format('Y-m-d') . ' ' . explode('_', $data['ModifiedDateStr'])[1], 'description' => "FROM KALHOR" ]); // $AdminOrderController = new AdminOrderController(); // $response["kalhor"]["newOrders"][$data['OrderCode']] = $AdminOrderController->store($request); } } } } $response['goldBalanceOfKalhor']= $response["kalhor"]["balance"]["gold"]; $response['cashBalanceOfKalhor']= $response["kalhor"]["balance"]["cash"]; //main $response['cashBalance']= -$response["liman"]["balance"]["cash"]+$response["kalhor"]["balance"]["cash"]; $response['goldBalance']= -$response["liman"]["balance"]["gold"]+$response["kalhor"]["balance"]["gold"]; $metalBalances = $balanceReportService->buildMetalBalancesResponse($limanMetalBuckets, $kalhorMetalBuckets); $response['metalBalances'] = $metalBalances['items']; if (!empty($metalBalances['items'])) { $response['goldBalance'] = $metalBalances['totalGoldBalance']; } //mazaneh $changeMesghal = config('change_mesghal'); /* $response['mazanehBalanceOfKalhor'] = $response["kalhor"]["balance_abs"]["gold"] != 0 ? ( $response["kalhor"]["balance_abs"]["cash"] / $response["kalhor"]["balance_abs"]["gold"]) * $changeMesghal : 0; $response['mazanehBalanceOfLiman'] = $response["kalhor"]["balance_abs"]["gold"] != 0 ? ( $response["liman"]["balance_abs"]["cash"] / $response["liman"]["balance_abs"]["gold"]) * $changeMesghal : 0; $response['mazanehBalance'] = $response["kalhor"]["balance_abs"]["gold"] != 0 ? (($response["liman"]["balance_abs"]["cash"]+$response["kalhor"]["balance_abs"]["cash"]) / ($response["liman"]["balance_abs"]["gold"]+$response["kalhor"]["balance_abs"]["gold"])) * $changeMesghal : 0;*/ $response['mazanehBalanceOfKalhor'] = $response["kalhor"]["balance_abs"]["gold"] != 0 ? ($response["kalhor"]["balance_abs"]["cash"] / $response["kalhor"]["balance_abs"]["gold"]) * $changeMesghal : 0; $response['mazanehBalanceOfLiman'] = $response["liman"]["balance_abs"]["gold"] != 0 ? ($response["liman"]["balance_abs"]["cash"] / $response["liman"]["balance_abs"]["gold"]) * $changeMesghal : 0; $totalGold = $response["liman"]["balance_abs"]["gold"] + $response["kalhor"]["balance_abs"]["gold"]; $response['mazanehBalance'] = $totalGold != 0 ? (($response["liman"]["balance_abs"]["cash"] + $response["kalhor"]["balance_abs"]["cash"]) / $totalGold) * $changeMesghal : 0; $response['income_money'] = Withdraw::whereNotNull('zify_code')->where('sts',2)->whereBetween('updated_at', [$startDate, $endDate])->sum('cash'); return $response; } public function finance(Request $request) { $startDate = $request->startDate ? Carbon::parse($request->startDate)->startOfDay() : Carbon::now()->subDays(30)->startOfDay(); $endDate = $request->endDate ? Carbon::parse($request->endDate)->endOfDay() : Carbon::now()->endOfDay(); // Fetch orders and transactions within the date range $ords = Order::whereBetween('created_at', [$startDate, $endDate])->get(); $TransactionsAdmin = TransactionsAdmin::whereBetween('created_at', [$startDate, $endDate])->get(); // Initialize response data $response = [ "fullPriceM1" => 0, "fullPriceM2" => 0, "fullPriceSood" => 0, "fullPriceKarmozd" => 0, "orderCount" => $ords->count(), "Gifts" => 0, "GiftsPrise" => 0, "sumAll" => 0, // تفکیک سود بر اساس سمت کسر کارمزد "profitGoldGrams" => 0, // سود طلایی: مجموع کارمزدهای کسرشده از طلا (گرم) "profitRial" => 0, // سود ریالی: مجموع کارمزدهای کسرشده از ریال (ریال) "profitGoldValueRial" => 0, "daily" => [], ]; // Calculate total gold gifts from transactions $giftsGold = 0.0; foreach ($TransactionsAdmin as $TransactionAdmin) { $giftsGold += (float) $TransactionAdmin->gold; } $response['Gifts'] = number_format($giftsGold, 3); $lastGoldPrice = (float) (Price::latest()->first()?->price ?? 0); $response['GiftsPrise'] = $lastGoldPrice > 0 ? (int) floor($giftsGold * $lastGoldPrice) : 0; // Calculate order-related sums $daily = []; foreach ($ords as $ord) { $response['fullPriceM1'] += abs($ord->total_price_original - $ord->payment_amount); $response['fullPriceM2'] += $ord->service_charge_price + $ord->total_fee; $response['fullPriceSood'] += $ord->total_fee; $response['fullPriceKarmozd'] += $ord->service_charge_price; // تفکیک کارمزد به طلا/ریال بر اساس سمت کسر // fee_asset === 'gold' → کارمزد از طلا گرفته شده (گرم)؛ در غیر این صورت ریالی محسوب می‌شود. $feeFromGold = $ord->fee_asset === 'gold'; $goldFeeGrams = $feeFromGold ? (float) $ord->service_charge : 0.0; $rialFee = $feeFromGold ? 0.0 : (float) $ord->service_charge_price; $response['profitGoldGrams'] += $goldFeeGrams; $response['profitRial'] += $rialFee; $dateKey = $ord->created_at ? Carbon::parse($ord->created_at)->toDateString() : 'نامشخص'; if (!isset($daily[$dateKey])) { $daily[$dateKey] = [ 'date' => $dateKey, 'profit_gold' => 0.0, // گرم 'profit_rial' => 0.0, // ریال (کارمزد ریالی) 'spread_rial' => 0.0, // سود اختلاف قیمت (ریال) 'order_count' => 0, ]; } $daily[$dateKey]['profit_gold'] += $goldFeeGrams; $daily[$dateKey]['profit_rial'] += $rialFee; $daily[$dateKey]['spread_rial'] += (float) $ord->total_fee; $daily[$dateKey]['order_count']++; } $response['profitGoldGrams'] = round($response['profitGoldGrams'], 4); // سندهای تبدیل سود ریالی به طلا: از سود ریالی کم و به سود طلایی (گرم) اضافه می‌شود. $conversions = ProfitConversion::whereBetween('converted_at', [$startDate, $endDate])->get(); $convertedRial = 0.0; $convertedGram = 0.0; foreach ($conversions as $conversion) { $rialAmount = (float) $conversion->rial_amount; $gramAmount = (float) $conversion->gram_amount; $convertedRial += $rialAmount; $convertedGram += $gramAmount; $dateKey = $conversion->converted_at ? Carbon::parse($conversion->converted_at)->toDateString() : null; if (!$dateKey) { continue; } if (!isset($daily[$dateKey])) { $daily[$dateKey] = [ 'date' => $dateKey, 'profit_gold' => 0.0, 'profit_rial' => 0.0, 'spread_rial' => 0.0, 'order_count' => 0, ]; } $daily[$dateKey]['profit_rial'] -= $rialAmount; $daily[$dateKey]['profit_gold'] += $gramAmount; } $response['profitRialGross'] = $response['profitRial']; $response['profitGoldGramsGross'] = $response['profitGoldGrams']; $response['profitRialConverted'] = round($convertedRial, 0); $response['profitGoldConvertedGram'] = round($convertedGram, 4); $response['profitRial'] = round($response['profitRial'] - $convertedRial, 0); $response['profitGoldGrams'] = round($response['profitGoldGrams'] + $convertedGram, 4); $response['profitGoldValueRial'] = $lastGoldPrice > 0 ? (int) floor($response['profitGoldGrams'] * $lastGoldPrice) : 0; krsort($daily); $response['daily'] = array_map(function ($row) { $row['profit_gold'] = round($row['profit_gold'], 4); $row['profit_rial'] = round($row['profit_rial'], 0); return $row; }, array_values($daily)); $response['totalTradingProfit'] = $response['fullPriceSood'] + $response['fullPriceKarmozd']; $response['sumAll'] = $response['fullPriceM1'] - $response['GiftsPrise']; return $response; } public function sumSellToCustomerMajor(Request $request){ $data = $request->all(); $order = Order::where('direction',1) ->where('sts',2) ->whereDate('created_at','>=',Carbon::parse($data['start_at'])) ->whereDate('created_at','<=',Carbon::parse($data['end_at'])) ->where('type',1) ->sum('amount'); return response()->json($order); } public function sumSellToCustomerSingle(Request $request){ $data = $request->all(); $order = Order::where('direction',1) ->where('sts',2) ->whereDate('created_at','>=',Carbon::parse($data['start_at'])) ->whereDate('created_at','<=',Carbon::parse($data['end_at'])) ->where('type',2) ->sum('amount'); return response()->json($order); } public function flow(Request $request){ $data = $request->all(); if ($data['type'] == 'week'){ $query=Order::where('sts',2) ->whereDate('created_at','<=',now()) ->whereDate('created_at','>=',now()->subWeek()) ->select(['direction',DB::raw('Date(created_at) as date'),DB::raw('sum(amount) as total')]) ->groupBy(['date','direction']) ->get(); } elseif ($data['type'] == 'month'){ $query=Order::where('sts',2) ->whereDate('created_at','<=',now()) ->whereDate('created_at','>=',now()->subMonth()) ->select(['direction',DB::raw('Date(created_at) as date'),DB::raw('sum(amount) as total')]) ->groupBy(['date','direction']) ->get(); } if (in_array($data['type'],['week','month'])){ $send = []; foreach ($query as $i){ if(in_array($i['date'],array_keys($send))){ $send[$i['date']][$i['direction']] = $i['total']; }else{ $send[$i['date']]['date'] =$i['date']; $send[$i['date']][$i['direction']] = $i['total']; } } } else{ $query=Order::where('sts',2) ->whereDate('created_at','<=',now()) ->whereDate('created_at','>=',now()->subYear()) ->select(['direction',DB::raw('MONTH(created_at) as month'),DB::raw('sum(amount) as total')]) ->groupBy(['month','direction']) ->get(); for ($i=0;$iformat('%B'); } } return response()->json(array_values($send)); } public function orderPeakHours(Request $request) { $days = (int) $request->input('days', 30); $days = min(max($days, 7), 90); $start = now()->subDays($days)->startOfDay(); $rows = Order::query() ->where('sts', 2) ->where('type', 2) ->where('created_at', '>=', $start) ->select([ DB::raw('HOUR(created_at) as hour'), 'direction', DB::raw('COUNT(*) as count'), ]) ->groupBy('hour', 'direction') ->get(); $hours = []; for ($h = 0; $h < 24; $h++) { $hours[$h] = ['hour' => $h, 'buy' => 0, 'sell' => 0, 'total' => 0]; } foreach ($rows as $row) { $h = (int) $row->hour; if ($h < 0 || $h > 23) { continue; } $count = (int) $row->count; if ((int) $row->direction === 1) { $hours[$h]['buy'] += $count; } elseif ((int) $row->direction === 2) { $hours[$h]['sell'] += $count; } $hours[$h]['total'] += $count; } $peakHour = 0; $peakCount = 0; foreach ($hours as $slot) { if ($slot['total'] > $peakCount) { $peakCount = $slot['total']; $peakHour = $slot['hour']; } } return response()->json([ 'hours' => array_values($hours), 'peak_hour' => $peakCount > 0 ? $peakHour : null, 'peak_count' => $peakCount, 'days' => $days, 'total_orders' => array_sum(array_column($hours, 'total')), ]); } /** * لیست سندهای تبدیل سود ریالی به طلا در یک بازه + جمع کل. */ public function profitConversions(Request $request) { $query = ProfitConversion::query(); if ($request->filled('startDate')) { $query->where('converted_at', '>=', Carbon::parse($request->startDate)->startOfDay()); } if ($request->filled('endDate')) { $query->where('converted_at', '<=', Carbon::parse($request->endDate)->endOfDay()); } $items = $query->orderByDesc('converted_at')->orderByDesc('id')->get(); return response()->json([ 'items' => $items, 'totalRial' => (float) $items->sum('rial_amount'), 'totalGram' => round((float) $items->sum('gram_amount'), 4), ]); } /** * ثبت سند تبدیل سود ریالی به طلا. * اگر گرم ارسال نشود از روی مبلغ و قیمت واحد محاسبه می‌شود و بالعکس. */ public function storeProfitConversion(Request $request) { $data = $request->validate([ 'rial_amount' => 'nullable|numeric|min:0', 'gram_amount' => 'nullable|numeric|min:0', 'unit_price' => 'nullable|numeric|min:0', 'converted_at' => 'nullable|date', 'description' => 'nullable|string|max:500', ]); $unitPrice = (float) ($data['unit_price'] ?? 0); if ($unitPrice <= 0) { $unitPrice = (float) (Price::latest()->first()?->price ?? 0); } $rial = (float) ($data['rial_amount'] ?? 0); $gram = (float) ($data['gram_amount'] ?? 0); if ($gram <= 0 && $rial > 0 && $unitPrice > 0) { $gram = round($rial / $unitPrice, 4); } elseif ($rial <= 0 && $gram > 0 && $unitPrice > 0) { $rial = round($gram * $unitPrice); } if ($rial <= 0 && $gram <= 0) { throw new \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException('مبلغ ریالی یا وزن طلا را وارد کنید.'); } $conversion = ProfitConversion::create([ 'user_id' => optional($request->user())->id, 'rial_amount' => $rial, 'gram_amount' => $gram, 'unit_price' => $unitPrice, 'converted_at' => !empty($data['converted_at']) ? Carbon::parse($data['converted_at']) : now(), 'description' => $data['description'] ?? null, ]); return response()->json($conversion, 201); } public function deleteProfitConversion($id) { $conversion = ProfitConversion::findOrFail($id); $conversion->delete(); return response()->json(['deleted' => true]); } }