2026-01-24 14:03:11 +00:00
<? php
namespace App\Http\Controllers\Admin ;
use App\DB\Te\TableEngine ;
use App\Http\Controllers\Controller ;
use App\Models\Customer ;
use App\Models\Order ;
use App\Models\Price ;
use App\Models\Product ;
use Illuminate\Support\Facades\DB ;
use App\Models\Withdraw ;
use Illuminate\Http\Request ;
use Illuminate\Support\Facades\Log ;
use Rooyesh\Wallet\interfaces\TransactionInterface ;
use Rooyesh\Wallet\interfaces\WalletInterface ;
use Rooyesh\Wallet\models\Transaction ;
use Rooyesh\Wallet\models\Wallet ;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException ;
use App\Http\Controllers\Admin\TahesabController ;
2026-02-09 14:09:19 +03:30
use App\Models\Setting ;
2026-02-19 16:20:36 +03:30
use App\Models\User ;
2026-06-25 23:06:29 +03:30
use App\Models\TransactionsAdmin ;
2026-06-23 21:21:04 +03:30
use App\Services\BalanceReportService ;
2026-06-24 01:17:34 +03:30
use App\Services\ConfigService ;
2026-06-23 21:04:29 +03:30
use App\Services\WalletBalanceService ;
2026-06-27 15:51:44 +03:30
use App\Services\WalletBroadcastService ;
2026-06-09 20:43:01 +03:30
use Hekmatinasser\Verta\Verta ;
2026-01-24 14:03:11 +00:00
class WalletController extends Controller
{
public function charge2 ( Request $request )
{
$data = $request -> all ();
$customer = Customer :: findOrFail ( $data [ 'customer_id' ]);
$deposit = false ;
if ( $data [ 'value' ] > 0 ) {
$deposit = true ;
}
2026-06-15 11:25:10 +03:30
$wallet_interface = new WalletInterface ( $data [ 'customer_id' ], ( int ) $customer -> type );
$wallet = $wallet_interface -> wallet ;
2026-01-24 14:03:11 +00:00
if ( is_null ( $wallet ) && ! $deposit ) {
throw new UnprocessableEntityHttpException ( 'مقدار موجودی کمتر از درخواست شماست' );
}
if ( ! is_null ( $wallet ) && $wallet -> cash < abs ( $data [ 'value' ]) && ! $deposit ) {
throw new UnprocessableEntityHttpException ( 'مقدار موجودی کمتر از درخواست شماست' );
}
$orders = Order :: where ( 'customer_id' , $data [ 'customer_id' ]) -> where ( 'sts' , 1 ) -> get ();
$gold_block = 0 ;
if ( count ( $orders ) > 0 ) {
$value = $data [ 'value' ];
foreach ( $orders as $order ) {
if ( $value < $order -> payment_remind ) {
$order -> payment_amount += $value ;
$order -> payment_remind -= $value ;
$order -> save ();
break ;
} else {
$value -= $order -> payment_remind ;
$order -> payment_amount = $order -> total_price ;
$order -> payment_remind = 0 ;
$order -> sts = 2 ;
$gold_block -= $order -> amount ;
$order -> save ();
}
}
}
$user = auth () -> user ();
$customer = Customer :: findOrFail ( $data [ "customer_id" ]);
$Withdraw = Withdraw :: create ([
'user_id' => $user -> id ,
'customer_id' => $customer -> id ,
"cash" => $data [ 'value' ],
'sts' => 4 ,
]);
new TransactionInterface ( $wallet_interface , $_inp = [
'cash' => $data [ 'value' ],
'expire_at' => now (),
'withdraw_id' => $Withdraw -> id ,
'active' => true
], 3 , false , true , $gold_block );
2026-06-16 20:38:48 +03:30
$message = 'کیف پول شما به مبلغ ' . self :: formatSmsRialAmount ( $data [ 'value' ]) . " ریال در تاریخ " . verta () -> format ( 'Y/n/j H:i:s' ) . " شارژ شد " . " \n "
2026-01-24 14:03:11 +00:00
. $this -> Config ( 'name_fa' );
$this -> Send ( $customer -> mobile , $message );
return response () -> json ( true );
}
public function charge ( Request $request )
{
$data = $request -> all ();
$customer = Customer :: findOrFail ( $data [ 'customer_id' ]);
$deposit = false ;
if ( $data [ 'value' ] > 0 ) {
$deposit = true ;
}
2026-06-15 11:25:10 +03:30
$wallet_interface = new WalletInterface ( $data [ 'customer_id' ], ( int ) $customer -> type );
$wallet = $wallet_interface -> wallet ;
2026-01-24 14:03:11 +00:00
if ( is_null ( $wallet ) && ! $deposit ) {
throw new UnprocessableEntityHttpException ( 'مقدار موجودی کمتر از درخواست شماست' );
}
if ( ! is_null ( $wallet ) && $wallet -> cash < abs ( $data [ 'value' ]) && ! $deposit ) {
throw new UnprocessableEntityHttpException ( 'مقدار موجودی کمتر از درخواست شماست' );
}
$orders = Order :: where ( 'customer_id' , $data [ 'customer_id' ]) -> where ( 'sts' , 1 ) -> get ();
$gold_block = 0 ;
$user = auth () -> user ();
$customer = Customer :: findOrFail ( $data [ "customer_id" ]);
$Withdraw = Withdraw :: create ([
'user_id' => $user -> id ,
'customer_id' => $customer -> id ,
"cash" => $data [ 'value' ],
"note" => $data [ 'note' ],
'sts' => 4 ,
]);
2026-06-07 12:25:32 +03:30
$type = $deposit ? 3 : 4 ;
2026-01-24 14:03:11 +00:00
new TransactionInterface ( $wallet_interface , $_inp = [
'gold' => 0 ,
'cash' => $data [ 'value' ],
'expire_at' => now (),
"note" => $data [ 'note' ],
'withdraw_id' => $Withdraw -> id ,
'active' => true
2026-06-07 12:25:32 +03:30
], $type , true , $deposit , $gold_block );
2026-01-24 14:03:11 +00:00
2026-06-25 23:06:29 +03:30
$this -> recordAccountingTransaction ( $customer , $Withdraw , ( int ) $user -> id , ( float ) $data [ 'value' ], 0 , $data [ 'note' ] ?? null );
2026-07-05 16:43:34 +03:30
if ( app ( ConfigService :: class ) -> isTahesabAccounting ()) {
2026-02-09 14:09:19 +03:30
try {
2026-03-14 11:08:30 +03:30
$data [ 'direction' ] = $deposit ? 0 : 1 ;
2026-06-25 22:20:40 +03:30
$data [ 'withdraw_id' ] = $Withdraw -> id ;
app ( TahesabController :: class ) -> wallet ( $data );
} catch ( \Exception $e ) {
report ( $e );
2026-02-09 14:09:19 +03:30
}
}
2026-02-19 16:20:36 +03:30
//send sms to users and customer
2026-01-25 09:58:32 +00:00
$status = $data [ 'value' ] > 0 ? " شارژ شد " : " کسر شد " ;
2026-02-19 16:20:36 +03:30
if ( $this -> Config ( 'charge_notif' ) == "true" ){
2026-06-16 20:38:48 +03:30
$message = 'کیف پول کاربر ' . $customer -> name . ' به مقدار ' . self :: formatSmsRialAmount ( $data [ 'value' ]) . " ریال در تاریخ " . verta () -> format ( 'Y/n/j H:i:s' ) . $status . "بابت" . " \n "
2026-02-19 16:20:36 +03:30
. $data [ 'note' ]
. " \n "
. $this -> Config ( 'name_fa' );
User :: where ( 'send_sms' , 1 ) -> get () -> each ( function ( $admin ) use ( $message , $data ) {
$this -> send ( $admin -> mobile , $message );
});
}
2026-06-16 20:38:48 +03:30
$message = 'کیف پول شما به اندازه ' . self :: formatSmsRialAmount ( $data [ 'value' ]) . " ریال در تاریخ " . verta () -> format ( 'Y/n/j H:i:s' ) . $status . "بابت" . " \n "
2026-01-24 14:03:11 +00:00
. $data [ 'note' ]
2026-01-25 09:58:32 +00:00
. " \n "
2026-01-24 14:03:11 +00:00
. $this -> Config ( 'name_fa' );
$this -> Send ( $customer -> mobile , $message );
2026-06-27 15:51:44 +03:30
$this -> broadcastCustomerWalletAssets ( $customer );
2026-01-24 14:03:11 +00:00
return response () -> json ( true );
}
public function charge_gold ( Request $request )
{
$data = $request -> all ();
$customer = Customer :: findOrFail ( $data [ 'customer_id' ]);
$deposit = false ;
if ( $data [ 'value' ] > 0 ) {
$deposit = true ;
}
2026-06-15 11:25:10 +03:30
$wallet_interface = new WalletInterface ( $data [ 'customer_id' ], ( int ) $customer -> type );
$wallet = $wallet_interface -> wallet ;
2026-01-24 14:03:11 +00:00
// if (is_null($wallet) && !$deposit) {
// throw new UnprocessableEntityHttpException('مقدار موجودی کمتر از درخواست شماست');
// }
// if (!is_null($wallet) && $wallet->cash < abs($data['value']) && !$deposit) {
// throw new UnprocessableEntityHttpException('مقدار موجودی کمتر از درخواست شماست');
// }
$gold_block = 0 ;
$user = auth () -> user ();
$customer = Customer :: findOrFail ( $data [ "customer_id" ]);
$Withdraw = Withdraw :: create ([
'user_id' => $user -> id ,
'customer_id' => $customer -> id ,
"gold" => $data [ 'value' ],
"note" => $data [ 'note' ],
'sts' => 4 ,
]);
2026-06-24 01:17:34 +03:30
$representative = app ( ConfigService :: class ) -> mainWalletRepresentativeProduct ();
2026-01-24 14:03:11 +00:00
new TransactionInterface ( $wallet_interface , $_inp = [
'cash' => 0 ,
'gold' => $data [ 'value' ],
'expire_at' => now (),
"note" => $data [ 'note' ],
'withdraw_id' => $Withdraw -> id ,
2026-06-24 01:17:34 +03:30
'product_id' => $representative ?-> id ,
2026-01-24 14:03:11 +00:00
'active' => true
], 7 , $deposit , false , $gold_block );
2026-06-25 23:06:29 +03:30
$this -> recordAccountingTransaction ( $customer , $Withdraw , ( int ) $user -> id , 0 , ( float ) $data [ 'value' ], $data [ 'note' ] ?? null );
2026-06-09 20:08:06 +03:30
//send to tahesab
2026-07-05 16:43:34 +03:30
if ( app ( ConfigService :: class ) -> isTahesabAccounting ()) {
2026-03-14 11:08:30 +03:30
try {
2026-06-07 14:30:26 +03:30
$data [ 'direction' ] = $deposit ? 1 : 0 ;
2026-06-25 22:20:40 +03:30
$data [ 'withdraw_id' ] = $Withdraw -> id ;
app ( TahesabController :: class ) -> walletGold ( $data );
} catch ( \Exception $e ) {
report ( $e );
2026-03-14 11:08:30 +03:30
}
}
2026-02-19 16:20:36 +03:30
//send sms to users and customer
$status = $data [ 'value' ] > 0 ? " شارژ شد " : " کسر شد " ;
2026-06-24 01:17:34 +03:30
$weightUnit = self :: tradeWeightUnit ();
2026-02-19 16:20:36 +03:30
if ( $this -> Config ( 'charge_notif' ) == "true" ){
2026-06-24 01:17:34 +03:30
$message = 'کیف پول کاربر ' . $customer -> name . ' به مقدار ' . self :: formatSmsGoldWeight ( $data [ 'value' ]) . " { $weightUnit } در تاریخ " . verta () -> format ( 'Y/n/j H:i:s' ) . $status . "بابت" . " \n "
2026-02-19 16:20:36 +03:30
. $data [ 'note' ]
. " \n "
. $this -> Config ( 'name_fa' );
User :: where ( 'send_sms' , 1 ) -> get () -> each ( function ( $admin ) use ( $message , $data ) {
$this -> send ( $admin -> mobile , $message );
});
}
2026-06-24 01:17:34 +03:30
$message = 'کیف پول شما به اندازه ' . self :: formatSmsGoldWeight ( $data [ 'value' ]) . " { $weightUnit } در تاریخ " . verta () -> format ( 'Y/n/j H:i:s' ) . $status . " بابت" . " \n "
2026-01-24 14:03:11 +00:00
. $data [ 'note' ]
. $this -> Config ( 'name_fa' );
$this -> Send ( $customer -> mobile , $message );
2026-06-27 15:51:44 +03:30
$this -> broadcastCustomerWalletAssets ( $customer );
2026-01-24 14:03:11 +00:00
return response () -> json ( true );
}
2026-06-23 21:59:38 +03:30
/** گزینههای شارژ کیف پول — نقدی + محصولات فعال */
public function chargeTargets ()
2026-01-24 14:03:11 +00:00
{
2026-06-23 21:59:38 +03:30
$configService = app ( ConfigService :: class );
$mainWalletProductIds = $configService -> mainWalletProductIds ();
$balanceReport = app ( BalanceReportService :: class );
$targets = [
[
'key' => 'money' ,
'kind' => 'money' ,
'label' => 'نقدی (ریال)' ,
'unit' => 'ریال' ,
],
];
$products = Product :: query ()
-> where ( 'active' , 1 )
-> orderBy ( 'metal_id' )
-> orderBy ( 'id' )
-> get ([ 'id' , 'title' , 'unit' , 'metal_id' , 'group_type' , 'trade_by_quantity' , 'amount' , 'direct_price' ]);
foreach ( $products as $product ) {
$usesMainWallet = in_array (( int ) $product -> id , $mainWalletProductIds , true );
$label = ( string ) $product -> title ;
if ( $usesMainWallet ) {
$label .= ' (کیف اصلی)' ;
}
$targets [] = [
'key' => 'product:' . $product -> id ,
'kind' => 'metal' ,
'product_id' => ( int ) $product -> id ,
'label' => $label ,
'unit' => $this -> resolveProductChargeUnit ( $product ),
'metal_id' => max ( 1 , ( int ) ( $product -> metal_id ?? 1 )),
'uses_main_wallet' => $usesMainWallet ,
'trade_by_quantity' => ( bool ) $product -> trade_by_quantity ,
'group_type' => ( string ) ( $product -> group_type ?? '' ),
];
}
return response () -> json ([
'targets' => $targets ,
'catalogMetals' => $balanceReport -> catalogMetalsMeta (),
]);
}
/**
* شارژ یکپارچه کیف پول — نقدی یا محصول (با رعایت کیف اصلی برای آبشده).
*/
public function charge_wallet ( Request $request )
{
$productId = ( int ) $request -> input ( 'product_id' , 0 );
if ( $productId > 0 ) {
return $this -> chargeProductMetal ( $request , $productId );
}
return $this -> charge ( $request );
}
private function chargeProductMetal ( Request $request , int $productId )
{
$data = $request -> all ();
$product = Product :: findOrFail ( $productId );
$customer = Customer :: findOrFail ( $data [ 'customer_id' ]);
$deposit = (( float ) ( $data [ 'value' ] ?? 0 )) > 0 ;
$effectiveProductId = Controller :: effectiveProductWalletId ( $productId );
$wallet_interface = new WalletInterface (
( int ) $data [ 'customer_id' ],
( int ) $customer -> type ,
null ,
$effectiveProductId
);
$wallet = $wallet_interface -> wallet ;
if ( ! $deposit && $wallet !== null && ( float ) $wallet -> gold < abs (( float ) $data [ 'value' ])) {
throw new UnprocessableEntityHttpException ( 'مقدار موجودی کمتر از درخواست شماست' );
}
$goldBlock = 0 ;
$user = auth () -> user ();
$unitLabel = $this -> resolveProductChargeUnit ( $product );
$Withdraw = Withdraw :: create ([
'user_id' => $user -> id ,
'customer_id' => $customer -> id ,
'gold' => $data [ 'value' ],
'note' => $data [ 'note' ] ?? null ,
'sts' => 4 ,
]);
new TransactionInterface ( $wallet_interface , [
'cash' => 0 ,
'gold' => $data [ 'value' ],
'product_id' => $productId ,
'expire_at' => now (),
'note' => $data [ 'note' ] ?? null ,
'withdraw_id' => $Withdraw -> id ,
'active' => true ,
], 7 , $deposit , false , $goldBlock );
2026-06-25 23:06:29 +03:30
$this -> recordAccountingTransaction (
$customer ,
$Withdraw ,
( int ) $user -> id ,
0 ,
( float ) $data [ 'value' ],
( $data [ 'note' ] ?? null ) ?: ( 'شارژ ' . $product -> title )
);
2026-07-05 16:43:34 +03:30
if ( app ( ConfigService :: class ) -> isTahesabAccounting ()) {
2026-06-23 21:59:38 +03:30
try {
$data [ 'direction' ] = $deposit ? 1 : 0 ;
2026-06-25 22:20:40 +03:30
$data [ 'withdraw_id' ] = $Withdraw -> id ;
app ( TahesabController :: class ) -> walletGold ( $data );
2026-06-23 21:59:38 +03:30
} catch ( \Exception $e ) {
2026-06-25 22:20:40 +03:30
report ( $e );
2026-06-23 21:59:38 +03:30
}
}
$status = $deposit ? ' شارژ شد ' : ' کسر شد ' ;
$formatted = self :: formatSmsGoldWeight ( $data [ 'value' ]);
if ( $this -> Config ( 'charge_notif' ) == 'true' ) {
$message = 'کیف پول کاربر ' . $customer -> name . ' به مقدار ' . $formatted . ' ' . $unitLabel . ' در تاریخ ' . verta () -> format ( 'Y/n/j H:i:s' ) . $status . 'بابت' . " \n "
. ( $data [ 'note' ] ?? '' )
. " \n "
. $this -> Config ( 'name_fa' );
User :: where ( 'send_sms' , 1 ) -> get () -> each ( function ( $admin ) use ( $message ) {
$this -> send ( $admin -> mobile , $message );
});
}
$message = 'کیف پول شما به اندازه ' . $formatted . ' ' . $unitLabel . ' در تاریخ ' . verta () -> format ( 'Y/n/j H:i:s' ) . $status . ' بابت' . " \n "
. ( $data [ 'note' ] ?? '' )
. " \n "
. $this -> Config ( 'name_fa' );
$this -> Send ( $customer -> mobile , $message );
2026-06-27 15:51:44 +03:30
$this -> broadcastCustomerWalletAssets ( $customer );
2026-06-23 21:59:38 +03:30
return response () -> json ( true );
}
private function resolveProductChargeUnit ( Product $product ) : string
{
$payload = Controller :: productUnitPayload ( $product );
if (
Controller :: usesQuantityTrade ( $payload )
&& ! Controller :: isWeightBasedProductUnit ( $payload [ 'unit' ] ?? null )
) {
$unit = trim (( string ) ( $payload [ 'unit' ] ?? '' ));
return $unit !== '' ? $unit : 'عدد' ;
}
if ( Controller :: isWeightBasedProductUnit ( $payload [ 'unit' ] ?? null )) {
return trim (( string ) $payload [ 'unit' ]);
}
return Controller :: productStorageWeightUnit ( $product );
}
2026-01-24 14:03:11 +00:00
public function index ( Request $request )
{
2026-06-23 21:21:04 +03:30
$balanceReport = app ( BalanceReportService :: class );
$balanceService = app ( WalletBalanceService :: class );
$catalogMetalIds = $balanceService -> catalogMetalIds ();
$records = Transaction :: with ([
'customer' ,
2026-06-24 01:32:32 +03:30
'wallet.product:id,title,metal_id' ,
2026-06-23 21:21:04 +03:30
'product:id,title,metal_id,group_type,unit,amount,trade_by_quantity,direct_price' ,
]) -> whereNull ( 'fund_id' );
2026-01-24 14:03:11 +00:00
TableEngine :: create ( $records , $request -> all ())
-> initSearch ([ 'order_id' , 'customer.name' ])
-> select ([
'*' , Transaction :: $SELECT_CAJ , Transaction :: $SELECT_TYPE_STR , Transaction :: $SELECT_SAJ , Transaction :: $SELECT_EAJ
]) -> export ( $records );
2026-06-24 01:17:34 +03:30
if ( isset ( $records [ 'rows' ])) {
2026-06-24 01:44:38 +03:30
$records [ 'rows' ] = collect ( $records [ 'rows' ]) -> map ( function ( $row ) use ( $balanceReport , $catalogMetalIds ) {
2026-06-23 21:21:04 +03:30
$balanceReport -> enrichTransactionTableRow ( $row , $catalogMetalIds );
2026-06-24 01:44:38 +03:30
if ( $row instanceof Transaction ) {
$array = $row -> toArray ();
$rawTypeStr = $row -> getAttributes ()[ 'type_str' ] ?? null ;
if ( is_string ( $rawTypeStr ) && ! is_numeric ( trim ( $rawTypeStr ))) {
$array [ 'type_str' ] = $rawTypeStr ;
}
return $array ;
}
return is_array ( $row ) ? $row : ( array ) $row ;
}) -> values () -> all ();
2026-06-24 01:17:34 +03:30
}
2026-06-23 21:21:04 +03:30
$records [ 'catalogMetals' ] = $balanceReport -> catalogMetalsMeta ();
2026-01-24 14:03:11 +00:00
return response () -> json ( $records );
}
public function updateTransaction ( Request $request )
{
$message = 'تراکنش تغیری نکرده.' ;
$transaction = Transaction :: find ( $request -> id );
$product = Product :: find ( $transaction -> product_id );
if ( ! $transaction ) return response () -> json ([ 'error' => 'تراکنش یافت نشد.' ], 404 );
$difference = $request -> input ( 'number' ) - $transaction -> number ;
if ( abs ( $difference ) < 0.0001 ) {
return response () -> json ([ 'message' => $message ], 422 );
}
$transaction -> number = $request -> input ( 'number' );
$wallet_interface = new WalletInterface ( $transaction -> customer_id , 2 );
if ( $wallet_interface -> wallet -> gold < $difference ) {
if ( ! ( isset ( $request -> force ) && $request -> force === true )){
return response () -> json ([ 'message' => "کاربر مورد نظر موجودی ندارد. موجودی فعلی: " . $wallet_interface -> wallet -> gold . " مقدار مورد نیاز: " . $difference , 'type' => 406 ], 422 );
}
}
$isDiposit = $difference > 0 ? 0 : 1 ;
new TransactionInterface ( $wallet_interface , [
"title" => "اصلاح سند " . $transaction -> withdraw_id ,
"note" => $product -> title ,
"product_id" => $product -> id ,
"number" => 0 ,
"gold" => $difference ,
'expire_at' => now (),
'active' => true ,
'withdraw_id' => $transaction -> withdraw_id ,
'start_at' => now (),
], 51 , $isDiposit , false );
$transaction -> save ();
$message = 'تراکنش با موفقیت بهروزرسانی شد.' ;
2026-06-27 15:51:44 +03:30
$customer = Customer :: find ( $transaction -> customer_id );
if ( $customer ) {
$this -> broadcastCustomerWalletAssets ( $customer );
}
2026-01-24 14:03:11 +00:00
return response () -> json ([
'message' => $message ,
'transaction' => $transaction ,
// 'previous_amount' => $previousAmount,
// 'new_amount' => $newAmount,
'difference' => $difference ,
'wallet' => $wallet_interface -> wallet ,
]);
}
public function indexWallet ( Request $request )
{
2026-06-09 20:32:27 +03:30
$lastPrice = ( float ) ( Price :: latest () -> first () ?-> price ?? 0 );
2026-06-23 21:04:29 +03:30
$balanceService = app ( WalletBalanceService :: class );
$catalogMetalIds = $balanceService -> catalogMetalIds ();
$mainWalletMetalId = $balanceService -> resolveMainWalletMetalId ();
2026-06-09 20:32:27 +03:30
// همان فیلتر/جستجوی جدول — بدون صفحهبندی — برای مجموع ردیفهای قابل مشاهده
$sumQuery = Wallet :: query ();
TableEngine :: create ( $sumQuery , $request -> all ())
-> initSearch ([ 'customer.name' ]);
2026-07-01 20:59:24 +03:30
$walletTableWith = [
'customer:id,name,mobile' ,
'fund:id,title' ,
'product:id,metal_id,unit,amount,group_type,trade_by_quantity,direct_price,title' ,
];
$sumRows = ( clone $sumQuery ) -> with ( $walletTableWith ) -> get ();
2026-06-23 21:04:29 +03:30
$metalBalances = $balanceService -> buildWalletMetalSums ( $sumRows , $catalogMetalIds );
$totalGold = array_sum ( array_column ( $metalBalances , 'gold' ));
$totalGoldToCash = array_sum ( array_column ( $metalBalances , 'goldToCash' ));
2026-06-09 20:32:27 +03:30
$totalCash = ( float ) ( clone $sumQuery ) -> sum ( 'cash' );
$sums = [
'gold' => round ( $totalGold , 2 ),
2026-06-23 21:04:29 +03:30
'goldToCash' => round ( $totalGoldToCash , 2 ),
2026-06-09 20:32:27 +03:30
'cash' => round ( $totalCash , 2 ),
'cashToGold' => $lastPrice > 0 ? round ( $totalCash / $lastPrice , 2 ) : 0 ,
2026-06-23 21:04:29 +03:30
'metalBalances' => $metalBalances ,
2026-06-09 20:32:27 +03:30
];
2026-07-01 20:59:24 +03:30
$records = Wallet :: with ( $walletTableWith );
2026-01-24 14:03:11 +00:00
TableEngine :: create ( $records , $request -> all ())
2026-07-01 20:59:24 +03:30
-> initSearch ([ 'customer.name' , 'customer.mobile' , 'product.title' , 'fund.title' ])
2026-01-24 14:03:11 +00:00
-> select ([ '*' ])
-> export ( $records );
2026-06-23 21:04:29 +03:30
if ( isset ( $records [ 'rows' ])) {
foreach ( $records [ 'rows' ] as & $row ) {
$balanceService -> enrichWalletTableRow ( $row , $catalogMetalIds , $mainWalletMetalId );
}
unset ( $row );
}
2026-01-24 14:03:11 +00:00
$records [ 'sums' ] = $sums ;
return response () -> json ( $records );
}
public function indexWithdraw ( Request $request )
{
$records = Withdraw :: with ([ 'customer' , 'bank_account' , 'Address' , "Transaction" ]);
2026-06-09 20:43:01 +03:30
Withdraw :: applyFlowFilter ( $records , $request -> input ( 'flow_type' , 'all' ));
2026-01-24 14:03:11 +00:00
TableEngine :: create ( $records , $request -> all ())
-> initSearch ([ 'customer.name' ])
-> select ([
'*' , Withdraw :: $SELECT_STS_STR , Withdraw :: $SELECT_DAJ
]) -> export ( $records );
2026-06-25 22:20:40 +03:30
2026-07-05 16:43:34 +03:30
if ( app ( ConfigService :: class ) -> isTahesabAccounting () && isset ( $records [ 'rows' ]) && is_array ( $records [ 'rows' ])) {
2026-06-25 22:20:40 +03:30
$withdrawIds = collect ( $records [ 'rows' ]) -> pluck ( 'id' ) -> filter () -> values () -> all ();
if ( $withdrawIds !== []) {
$failedByWithdraw = \App\Models\Tahesab :: query ()
-> whereIn ( 'withdraw_id' , $withdrawIds )
-> where ( function ( $query ) {
$query -> whereNull ( 'tahesab_id' );
if ( \Illuminate\Support\Facades\Schema :: hasColumn ( 'tahesab' , 'sync_status' )) {
$query -> orWhere ( 'sync_status' , \App\Services\TahesabSyncService :: STATUS_FAILED );
}
})
-> orderByDesc ( 'id' )
-> get ()
-> unique ( 'withdraw_id' )
-> keyBy ( 'withdraw_id' );
foreach ( $records [ 'rows' ] as & $row ) {
$tahesab = $failedByWithdraw -> get ( $row [ 'id' ] ?? null );
if ( $tahesab ) {
$row [ 'tahesab_failed_id' ] = $tahesab -> id ;
}
}
unset ( $row );
}
}
2026-01-24 14:03:11 +00:00
return response () -> json ( $records );
}
2026-06-09 20:43:01 +03:30
public function exportWithdrawReport ( Request $request )
{
$flowType = $request -> input ( 'flow_type' , 'all' );
$query = Withdraw :: with ([ 'customer' , 'bank_account' ]);
Withdraw :: applyFlowFilter ( $query , $flowType );
TableEngine :: create ( $query , $request -> all ())
-> initSearch ([ 'customer.name' ]);
$rows = $query -> orderBy ( 'id' , 'desc' ) -> get ();
$titles = [
'all' => 'گزارش برداشت و واریز' ,
'withdraw' => 'گزارش برداشت' ,
'deposit' => 'گزارش واریز' ,
];
return response () -> view ( 'admin.withdrawReport' , [
'rows' => $rows ,
'title' => $titles [ $flowType ] ?? $titles [ 'all' ],
'flowType' => $flowType ,
'generatedAt' => Verta :: now () -> format ( 'Y/n/j H:i:s' ),
]) -> header ( 'Content-Type' , 'text/html; charset=UTF-8' );
}
2026-01-24 14:03:11 +00:00
public function updateWithdraw ( Request $request , $id )
{
// پیدا کردن رکورد Withdraw با استفاده از شناسه
$withdraw = Withdraw :: find ( $id );
// بررسی وجود رکورد
if ( ! $withdraw ) {
return response () -> json ([ 'error' => 'Withdraw not found' ], 404 );
}
$withdraw -> sts = $request -> sts ;
$withdraw -> save ();
return response () -> json ([ 'message' => 'Withdraw updated successfully' , 'withdraw' => $withdraw ]);
}
public function getWithdraw ( Request $request , $id )
{
2026-06-09 20:08:06 +03:30
$withdraw = Withdraw :: with ([ 'customer' , 'bank_account' , 'Address' , "Transaction" ]) -> find ( $id );
2026-01-24 14:03:11 +00:00
if ( ! $withdraw ) {
return response () -> json ([ 'error' => 'Withdraw not found' ], 404 );
}
2026-06-09 20:08:06 +03:30
return response () -> json ( $withdraw );
2026-01-24 14:03:11 +00:00
}
public function completeWithdraw ( Request $request )
{
2026-06-09 20:08:06 +03:30
$request -> validate ([
'id' => 'required|integer|exists:withdraws,id' ,
'tracked_number' => 'required|string|max:50' ,
'date_at' => 'nullable|date' ,
]);
$data = $request -> only ([ 'tracked_number' , 'date_at' ]);
2026-01-24 14:03:11 +00:00
$data [ 'user_id' ] = auth ( 'user' ) -> id ();
$data [ 'sts' ] = 2 ;
2026-06-09 20:08:06 +03:30
$data [ 'tracked_number' ] = ( string ) $data [ 'tracked_number' ];
if ( empty ( $data [ 'date_at' ])) {
$data [ 'date_at' ] = now ();
}
$withdraw = Withdraw :: findOrFail ( $request -> id );
2026-01-24 14:03:11 +00:00
$withdraw -> update ( $data );
// $tahesab = new TahesabController();
// $tahesab->wallet([
// 'customer_id' => $withdraw->customer_id,
// 'value' => $withdraw->cash,
// 'direction' => 1,
// 'note' => 'برداشت از کیف پول شماره ' . $withdraw->id,
// ]);
return response () -> json ( true );
}
2026-06-25 23:06:29 +03:30
private function recordAccountingTransaction (
Customer $customer ,
Withdraw $withdraw ,
int $adminUserId ,
float $cash = 0 ,
float $gold = 0 ,
? string $note = null
) : void {
$transaction = Transaction :: where ( 'withdraw_id' , $withdraw -> id ) -> latest ( 'id' ) -> first ();
TransactionsAdmin :: create ([
'customer_id' => $customer -> id ,
'customer_to_id' => $customer -> id ,
'user_id' => $adminUserId ,
'wallet' => null ,
'transaction_id' => $transaction ?-> id ,
'cash' => $cash ,
'note' => $note ?? $withdraw -> note ,
'type' => 1 ,
'gold' => $gold ,
'balance_cash' => 0 ,
'withdraw_id' => $withdraw -> id ,
]);
}
2026-06-27 15:51:44 +03:30
private function broadcastCustomerWalletAssets ( Customer $customer ) : void
{
app ( WalletBroadcastService :: class ) -> broadcastForCustomer (
( int ) $customer -> id ,
( int ) $customer -> type
);
}
2026-01-24 14:03:11 +00:00
}