From 47a2f8e6bf9f449c91b82ba67e469d002a5b5085 Mon Sep 17 00:00:00 2001 From: mohammad sedighi Date: Fri, 10 Jul 2026 23:29:36 +0330 Subject: [PATCH] change transition structure 2 --- .../Controllers/Admin/DashboardController.php | 121 +++++++++++++++++- .../Single/SingleOrderController.php | 6 + app/Models/Order.php | 1 + app/Models/ProfitConversion.php | 27 ++++ ...0_000001_add_fee_asset_to_orders_table.php | 35 +++++ ...000002_create_profit_conversions_table.php | 33 +++++ routes/admin.php | 4 + 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 app/Models/ProfitConversion.php create mode 100644 database/migrations/2026_07_10_000001_add_fee_asset_to_orders_table.php create mode 100644 database/migrations/2026_07_10_000002_create_profit_conversions_table.php diff --git a/app/Http/Controllers/Admin/DashboardController.php b/app/Http/Controllers/Admin/DashboardController.php index 24ed2e3..9bd43ff 100644 --- a/app/Http/Controllers/Admin/DashboardController.php +++ b/app/Http/Controllers/Admin/DashboardController.php @@ -8,6 +8,7 @@ use App\Models\Customer; use App\Models\Order; use App\Models\Price; use App\Models\Product; +use App\Models\ProfitConversion; use App\Models\TransactionsAdmin; use App\Models\Withdraw; use App\Services\BalanceReportService; @@ -320,7 +321,12 @@ class DashboardController extends Controller "orderCount" => $ords->count(), "Gifts" => 0, "GiftsPrise" => 0, - "sumAll" => 0 + "sumAll" => 0, + // تفکیک سود بر اساس سمت کسر کارمزد + "profitGoldGrams" => 0, // سود طلایی: مجموع کارمزدهای کسرشده از طلا (گرم) + "profitRial" => 0, // سود ریالی: مجموع کارمزدهای کسرشده از ریال (ریال) + "profitGoldValueRial" => 0, + "daily" => [], ]; // Calculate total gold gifts from transactions @@ -333,12 +339,50 @@ class DashboardController extends Controller $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']++; } + + // مرتب‌سازی نزولی بر اساس تاریخ و گرد کردن گرم‌ها + krsort($daily); + $response['daily'] = array_map(function ($row) { + $row['profit_gold'] = round($row['profit_gold'], 4); + return $row; + }, array_values($daily)); + + $response['profitGoldGrams'] = round($response['profitGoldGrams'], 4); + $response['profitGoldValueRial'] = $lastGoldPrice > 0 + ? (int) floor($response['profitGoldGrams'] * $lastGoldPrice) + : 0; + $response['totalTradingProfit'] = $response['fullPriceSood'] + $response['fullPriceKarmozd']; $response['sumAll'] = $response['fullPriceM1'] - $response['GiftsPrise']; return $response; @@ -462,4 +506,79 @@ class DashboardController extends Controller '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]); + } } diff --git a/app/Http/Controllers/Single/SingleOrderController.php b/app/Http/Controllers/Single/SingleOrderController.php index 7c7b090..6a6a06e 100644 --- a/app/Http/Controllers/Single/SingleOrderController.php +++ b/app/Http/Controllers/Single/SingleOrderController.php @@ -275,6 +275,9 @@ class SingleOrderController extends Controller $data['payment_amount'] = $data['total_price'] + $data['service_charge_price']; } + // سمت کسر کارمزد برای گزارش تفکیک‌شده در داشبورد + $data['fee_asset'] = $rialLocked ? 'gold' : 'rial'; + $this->enforceProductOrderLimits($data); if (!empty($data['first_buy']) && ($minFirstBuy = Setting::where('is_active', 1)->where('key', 'min_first_buy')->value('value'))) { @@ -514,6 +517,9 @@ class SingleOrderController extends Controller $goldDebit = $data['amount']; } + // سمت کسر کارمزد برای گزارش تفکیک‌شده در داشبورد + $data['fee_asset'] = $rialLocked ? 'gold' : 'rial'; + $grossTotal = $data['amount'] * $data['price']; $this->enforceProductOrderLimits($data, (float) $grossTotal); diff --git a/app/Models/Order.php b/app/Models/Order.php index 5711ef0..dc02351 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -25,6 +25,7 @@ class Order extends Model 'service_charge_percentage',//درصد کارمزد 'service_charge',//میزان کارمزد 'service_charge_price',//مبلغ کارمزد به ریال + 'fee_asset',//سمت کسر کارمزد: gold یا rial 'payment_sts', 'payment_amount',//میزان پرداخت شده 'payment_remind',//میزان مبلغ باقی مانده diff --git a/app/Models/ProfitConversion.php b/app/Models/ProfitConversion.php new file mode 100644 index 0000000..7f2fe3d --- /dev/null +++ b/app/Models/ProfitConversion.php @@ -0,0 +1,27 @@ + 'float', + 'gram_amount' => 'float', + 'unit_price' => 'float', + 'converted_at' => 'datetime', + ]; +} diff --git a/database/migrations/2026_07_10_000001_add_fee_asset_to_orders_table.php b/database/migrations/2026_07_10_000001_add_fee_asset_to_orders_table.php new file mode 100644 index 0000000..b7e0c1c --- /dev/null +++ b/database/migrations/2026_07_10_000001_add_fee_asset_to_orders_table.php @@ -0,0 +1,35 @@ +string('fee_asset', 8)->nullable()->after('service_charge_price'); + } + }); + } + + public function down(): void + { + if (!Schema::hasTable('orders')) { + return; + } + + Schema::table('orders', function (Blueprint $table) { + if (Schema::hasColumn('orders', 'fee_asset')) { + $table->dropColumn('fee_asset'); + } + }); + } +}; diff --git a/database/migrations/2026_07_10_000002_create_profit_conversions_table.php b/database/migrations/2026_07_10_000002_create_profit_conversions_table.php new file mode 100644 index 0000000..cb79fdc --- /dev/null +++ b/database/migrations/2026_07_10_000002_create_profit_conversions_table.php @@ -0,0 +1,33 @@ +id(); + $table->unsignedBigInteger('user_id')->nullable(); + $table->decimal('rial_amount', 20, 0)->default(0); // مبلغ ریالی سود که تبدیل شد + $table->decimal('gram_amount', 16, 4)->default(0); // معادل طلا (گرم) + $table->decimal('unit_price', 20, 0)->default(0); // مظنه/قیمت هر گرم هنگام تبدیل + $table->dateTime('converted_at')->nullable(); // تاریخ سند + $table->string('description', 500)->nullable(); + $table->timestamps(); + + $table->index('converted_at'); + }); + } + + public function down(): void + { + Schema::dropIfExists('profit_conversions'); + } +}; diff --git a/routes/admin.php b/routes/admin.php index 73f0bd2..e2cf582 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -157,6 +157,10 @@ Route::middleware('auth:user')->group(function (){ Route::post('dashboard/customer/single/all_sell', [DashboardController::class, 'sumSellToCustomerSingle']); Route::post('dashboard/customer/flow', [DashboardController::class, 'flow']); Route::post('dashboard/customer/order-peak-hours', [DashboardController::class, 'orderPeakHours']); + // سند تبدیل سود ریالی به طلا + Route::post('dashboard/profit-conversions', [DashboardController::class, 'profitConversions']); + Route::post('dashboard/profit-conversions/store', [DashboardController::class, 'storeProfitConversion']); + Route::delete('dashboard/profit-conversions/{id}', [DashboardController::class, 'deleteProfitConversion']); //bank account Route::post('account/table', [BankAccountController::class, 'table']);