initial: bootstrap from BukidBountyApp base
This commit is contained in:
269
app/Http/Controllers/Market/CreditController.php
Normal file
269
app/Http/Controllers/Market/CreditController.php
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Market;
|
||||
|
||||
use App\Http\Controllers\Helpers\ResponseHelper;
|
||||
use App\Http\Controllers\Helpers\PaymentProcessor;
|
||||
use App\Http\Controllers\Helpers\QrphDecoder;
|
||||
use App\Models\SystemSetting;
|
||||
use App\Models\Accounting\MemberLedger;
|
||||
use App\Models\User;
|
||||
use App\Models\GlobalTransaction;
|
||||
use Hypervel\Http\Request;
|
||||
use Hypervel\Support\Facades\Auth;
|
||||
use Hypervel\Support\Facades\DB;
|
||||
use Hypervel\Support\Str;
|
||||
use App\Enums\Market\ProductTransactionType;
|
||||
use App\Enums\Market\TransactionFlow;
|
||||
|
||||
class CreditController
|
||||
{
|
||||
public function getWalletData(Request $request)
|
||||
{
|
||||
$user = User::find(Auth::id());
|
||||
if (!$user) return ResponseHelper::returnUnauthorized();
|
||||
|
||||
$history = MemberLedger::where('user_id', $user->id)
|
||||
->where('is_active', true)
|
||||
->orderBy('created_at', 'desc')
|
||||
->limit(20)
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'balance' => $user->total_balance,
|
||||
'credit' => $user->total_credit,
|
||||
'history' => $history
|
||||
]);
|
||||
}
|
||||
|
||||
public function topUp(Request $request)
|
||||
{
|
||||
// Check if Top Up is enabled globally
|
||||
if (!(\App\Models\SystemSetting::getValue('top_up_enabled', true))) {
|
||||
return ResponseHelper::returnError('Credit top-up is currently disabled by administrators.');
|
||||
}
|
||||
|
||||
$amount = (float) $request->input('amount');
|
||||
$method = $request->input('method', 'GCASH');
|
||||
|
||||
if ($amount <= 0) {
|
||||
return ResponseHelper::returnError('Amount must be greater than zero');
|
||||
}
|
||||
|
||||
$user = User::find(Auth::id());
|
||||
if (!$user) return ResponseHelper::returnUnauthorized();
|
||||
|
||||
// Start Transaction
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// 1. Simulate Payment Success (in real life this would be a webhook/callback)
|
||||
$payment = PaymentProcessor::initiatePayment($amount, $method, $user->hashkey);
|
||||
|
||||
if (!$payment['success']) {
|
||||
throw new \Exception('Payment initiation failed');
|
||||
}
|
||||
|
||||
// 2. Update User Balance
|
||||
$user->total_balance += $amount;
|
||||
$user->save();
|
||||
|
||||
// 3. Record in MemberLedger
|
||||
$ledger = new MemberLedger([
|
||||
'hashkey' => Str::random(64),
|
||||
'user_id' => $user->id,
|
||||
'amount' => $amount,
|
||||
'transaction_type' => 'TOP_UP',
|
||||
'flow' => 'IN',
|
||||
'balance_after' => $user->total_balance,
|
||||
'description' => "Credit Top-up via {$method}",
|
||||
'reference_id' => $payment['transaction_id'],
|
||||
'created_by' => $user->id,
|
||||
'is_active' => true,
|
||||
]);
|
||||
$ledger->save();
|
||||
|
||||
// 4. Record in GlobalTransaction (for compatibility with existing reports)
|
||||
$globalTxn = new GlobalTransaction([
|
||||
'hashkey' => Str::random(64),
|
||||
'user_id' => $user->id,
|
||||
'amount' => $amount,
|
||||
'type' => ProductTransactionType::TOP_UP,
|
||||
'status' => 'COMPLETED',
|
||||
'description' => "Credit Top-up via {$method}",
|
||||
'flow' => TransactionFlow::INCOME,
|
||||
'created_by' => $user->id,
|
||||
]);
|
||||
$globalTxn->save();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Top-up successful',
|
||||
'balance' => $user->total_balance,
|
||||
'transaction_id' => $payment['transaction_id']
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return ResponseHelper::returnError('Top-up failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function transferCredit(Request $request)
|
||||
{
|
||||
$recipientHash = $request->input('recipient_hash');
|
||||
$amount = (float) $request->input('amount');
|
||||
|
||||
if ($amount <= 0) return ResponseHelper::returnError('Invalid amount');
|
||||
|
||||
$sender = User::find(Auth::id());
|
||||
if (!$sender) return ResponseHelper::returnUnauthorized();
|
||||
|
||||
if ($sender->total_balance < $amount) {
|
||||
return ResponseHelper::returnError('Insufficient balance');
|
||||
}
|
||||
|
||||
$recipient = User::where('hashkey', $recipientHash)->first();
|
||||
if (!$recipient) return ResponseHelper::returnError('Recipient not found');
|
||||
|
||||
if ($sender->id === $recipient->id) {
|
||||
return ResponseHelper::returnError('Cannot transfer to yourself');
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Deduct from sender
|
||||
$sender->total_balance -= $amount;
|
||||
$sender->save();
|
||||
|
||||
// Add to recipient
|
||||
$recipient->total_balance += $amount;
|
||||
$recipient->save();
|
||||
|
||||
$txnRef = Str::random(12);
|
||||
|
||||
// Record Ledger for Sender
|
||||
MemberLedger::create([
|
||||
'hashkey' => Str::random(64),
|
||||
'user_id' => $sender->id,
|
||||
'amount' => $amount,
|
||||
'transaction_type' => 'TRANSFER_OUT',
|
||||
'flow' => 'OUT',
|
||||
'balance_after' => $sender->total_balance,
|
||||
'description' => "Credit Transfer to {$recipient->fullname}",
|
||||
'reference_id' => $txnRef,
|
||||
'created_by' => $sender->id,
|
||||
]);
|
||||
|
||||
// Record Ledger for Recipient
|
||||
MemberLedger::create([
|
||||
'hashkey' => Str::random(64),
|
||||
'user_id' => $recipient->id,
|
||||
'amount' => $amount,
|
||||
'transaction_type' => 'TRANSFER_IN',
|
||||
'flow' => 'IN',
|
||||
'balance_after' => $recipient->total_balance,
|
||||
'description' => "Credit Transfer from {$sender->fullname}",
|
||||
'reference_id' => $txnRef,
|
||||
'created_by' => $sender->id,
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
return response()->json(['success' => true, 'message' => 'Transfer successful']);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return ResponseHelper::returnError('Transfer failed');
|
||||
}
|
||||
}
|
||||
|
||||
public function searchUsers(Request $request)
|
||||
{
|
||||
$query = $request->input('q');
|
||||
if (empty($query)) return response()->json(['success' => true, 'data' => []]);
|
||||
|
||||
$users = User::where('fullname', 'like', "%{$query}%")
|
||||
->orWhere('name', 'like', "%{$query}%")
|
||||
->orWhere('mobile_number', 'like', "%{$query}%")
|
||||
->where('id', '!=', Auth::id())
|
||||
->limit(10)
|
||||
->get(['hashkey', 'fullname', 'name', 'mobile_number']);
|
||||
|
||||
return response()->json(['success' => true, 'data' => $users]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET the current QRPH payment code (available to all authenticated users for top-up display).
|
||||
*/
|
||||
public function getQrphCode(Request $request)
|
||||
{
|
||||
$raw = SystemSetting::getValue('qrph_payment_code', null);
|
||||
$imgHashkey = SystemSetting::getValue('qrph_payment_image_hashkey', null);
|
||||
|
||||
if (empty($raw)) {
|
||||
return response()->json(['success' => true, 'qrph' => null, 'decoded' => null, 'image_url' => null]);
|
||||
}
|
||||
|
||||
$decoded = QrphDecoder::decode($raw);
|
||||
$imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'qrph' => $raw,
|
||||
'decoded' => $decoded,
|
||||
'image_url' => $imageUrl,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SET the QRPH payment code — ULTIMATE only (enforced by route middleware).
|
||||
* Accepts optional image_hashkey from a prior /File/Upload/QrphPayment call.
|
||||
*/
|
||||
public function setQrphCode(Request $request)
|
||||
{
|
||||
$raw = trim($request->input('qrph_code', ''));
|
||||
$imgHashkey = trim($request->input('image_hashkey', ''));
|
||||
|
||||
if (empty($raw)) {
|
||||
SystemSetting::setValue('qrph_payment_code', '');
|
||||
SystemSetting::setValue('qrph_payment_image_hashkey', '');
|
||||
return response()->json(['success' => true, 'message' => 'QRPH code cleared.']);
|
||||
}
|
||||
|
||||
$decoded = QrphDecoder::decode($raw);
|
||||
|
||||
SystemSetting::setValue('qrph_payment_code', $raw);
|
||||
if (!empty($imgHashkey)) {
|
||||
SystemSetting::setValue('qrph_payment_image_hashkey', $imgHashkey);
|
||||
}
|
||||
|
||||
$imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'QRPH code saved.',
|
||||
'decoded' => $decoded,
|
||||
'image_url' => $imageUrl,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a QRPH string without saving — for preview before saving.
|
||||
*/
|
||||
public function decodeQrph(Request $request)
|
||||
{
|
||||
$raw = trim($request->input('qrph_code', ''));
|
||||
if (empty($raw)) {
|
||||
return ResponseHelper::returnError('No QR string provided.');
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'decoded' => QrphDecoder::decode($raw),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user