File: /home/workzeni/agency-erp-05.workzenix.com/app/Http/Controllers/FundTransferController.php
<?php
namespace App\Http\Controllers;
use App\Models\CompanyInfo;
use App\Models\FundTreansfer;
use App\Models\TransactionHistory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class FundTransferController extends Controller
{
public function fundTransferList()
{
$agencies = CompanyInfo::latest()->get();
$fundTransfers = FundTreansfer::orderBy('status', 'asc')
->orderBy('created_at', 'desc')
->get();
return view('admin.fund_transfer.list', compact('fundTransfers', 'agencies'));
}
public function fundTransferStore(Request $request)
{
$validated = $request->validate([
'agency_id' => 'required|exists:company_infos,id',
'bdt_amount' => 'required|numeric|min:0',
'currency_rate' => 'required|numeric|min:0',
'sar_amount' => 'required|numeric|min:0',
'transaction_id' => 'required|string|max:255',
'transferred_date' => 'required|date',
'proof' => 'required|file|mimes:jpg,jpeg,png,pdf',
'additional' => 'nullable|string|max:1000',
'status' => 'required|in:0,1,2',
]);
// Handle proof file upload with unique name
$proofFile = $request->file('proof');
$proofPath = $proofFile->storeAs(
'fund_transfer',
Str::uuid().'.'.$proofFile->getClientOriginalExtension(),
'public'
);
if (! $proofPath) {
$errorMessage = 'Failed to upload proof file.';
return $request->ajax()
? response()->json(['success' => false, 'message' => $errorMessage], 500)
: redirect()->back()->with('error', $errorMessage);
}
DB::beginTransaction();
$agency = CompanyInfo::findOrFail($validated['agency_id']);
// Check BDT balance if status is approved
if ((int) $validated['status'] === FundTreansfer::STATUS_APPROVED && $validated['bdt_amount'] > $agency->bdt_acct) {
throw new \Exception('Insufficient BDT balance for this transfer.');
}
$approvedBy = null;
if ((int) $validated['status'] === FundTreansfer::STATUS_APPROVED && in_array(auth()->user()->role, [1, 2, 3])) {
$approvedBy = auth()->id();
}
// Create fund transfer record
$fund = FundTreansfer::create([
'agency_id' => $validated['agency_id'],
'user_id' => auth()->id(),
'bdt_amount' => $validated['bdt_amount'],
'currency_rate' => $validated['currency_rate'],
'sar_amount' => $validated['sar_amount'],
'transaction_id' => $validated['transaction_id'],
'transferred_date' => $validated['transferred_date'],
'proof' => $proofPath,
'additional' => $validated['additional'],
'status' => $validated['status'],
'approved_by' => $approvedBy,
]);
// If approved and user has permission
$checkTransfer = TransactionHistory::where('source_table', 'fund_transfers')
->where('source_id', $fund->id)
->exists();
if ((int) $validated['status'] === FundTreansfer::STATUS_APPROVED && in_array(auth()->user()->role, [1, 2, 3]) && $checkTransfer === false) {
$oldBdtBalance = $agency->bdt_acct;
$oldSarBalance = $agency->sar_acct;
$newBdtBalance = $oldBdtBalance - $validated['bdt_amount'];
$newSarBalance = $oldSarBalance + $validated['sar_amount'];
// Transaction: Deduct BDT
TransactionHistory::create([
'agency_id' => $agency->id,
'source_table' => 'fund_transfers',
'source_id' => $fund->id,
'tnx_type' => 'Transfer Out',
'currency' => 'BDT',
'amount' => $validated['bdt_amount'],
'old_balance' => $oldBdtBalance,
'new_balance' => $newBdtBalance,
'note' => 'Fund Transfer Approved: Deducted '.$validated['bdt_amount'].' BDT for transfer to SAR. Approved by '.auth()->user()->name,
'created_at' => $validated['transferred_date'] ?? now(),
]);
// Transaction: Add SAR
TransactionHistory::create([
'agency_id' => $agency->id,
'source_table' => 'fund_transfers',
'source_id' => $fund->id,
'tnx_type' => 'Transfer In',
'currency' => 'SAR',
'amount' => $validated['sar_amount'],
'old_balance' => $oldSarBalance,
'new_balance' => $newSarBalance,
'note' => 'Fund Transfer Approved: Converted '.$validated['bdt_amount'].' BDT to '.$validated['sar_amount'].' SAR. Approved by '.auth()->user()->name,
'created_at' => $validated['transferred_date'] ?? now(),
]);
// Update balances
$agency->bdt_acct = $newBdtBalance;
$agency->sar_acct = $newSarBalance;
$agency->save();
// Update approver
$fund->approved_by = auth()->id();
$fund->save();
}
DB::commit();
$fund->load('agency');
return $request->ajax()
? response()->json([
'success' => true,
'message' => 'Fund Transfer added successfully.',
'fundTransfer' => $fund,
])
: redirect()->back()->with('success', 'Fund Transfer added successfully.');
}
public function fundTransferShow($id)
{
$fundTransfer = FundTreansfer::findOrFail($id);
return view('admin.fund_transfer.show', compact('fundTransfer'));
}
public function fundTransferEdit($id)
{
$agencies = CompanyInfo::latest()->get();
$fundTransfer = FundTreansfer::findOrFail($id);
return view('admin.fund_transfer.edit', compact('fundTransfer', 'agencies'));
}
public function fundTransferUpdate(Request $request, $id)
{
$fundTransfer = FundTreansfer::findOrFail($id);
// ✅ Step 1: Validate the request
$validated = $request->validate([
'agency_id' => 'required|exists:company_infos,id',
'bdt_amount' => 'required|numeric|min:0',
'currency_rate' => 'required|numeric|min:0',
'sar_amount' => 'required|numeric|min:0',
'transaction_id' => 'required|string|max:255',
'transferred_date' => 'required|date',
'additional' => 'nullable|string',
'status' => 'required|in:0,1,2',
'proof' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
]);
$checkTransfer = TransactionHistory::where('source_table', 'fund_transfers')
->where('source_id', $fundTransfer->id)
->exists();
// ✅ Step 2: Handle proof file upload
if ($request->hasFile('proof')) {
if ($fundTransfer->proof && Storage::disk('public')->exists($fundTransfer->proof)) {
Storage::disk('public')->delete($fundTransfer->proof);
}
$proofPath = $request->file('proof')->store('fund_transfer', 'public');
if (! $proofPath) {
$errorMessage = 'Failed to upload proof file.';
return $request->ajax()
? response()->json(['success' => false, 'message' => $errorMessage], 500)
: redirect()->back()->with('error', $errorMessage);
}
$fundTransfer->proof = $proofPath;
}
// ✅ Step 3: Handle approval status & balance adjustment
$oldStatus = (int) $fundTransfer->status;
$newStatus = (int) $validated['status'];
if (in_array(auth()->user()->role, [1, 2, 3])) {
if ($newStatus === 1 && $oldStatus !== 1) {
// balance check
$agency = CompanyInfo::find($validated['agency_id']);
// check balance
if ($validated['bdt_amount'] > $agency->bdt_acct) {
return $request->ajax()
? response()->json(['success' => false, 'message' => 'Insufficient BDT balance for this transfer.'], 400)
: redirect()->back()->with('error', 'Insufficient BDT balance for this transfer.');
}
$oldBDTBalance = $agency->bdt_acct;
$newBdtBalance = $oldBDTBalance - $validated['bdt_amount'];
$oldSARBalance = $agency->sar_acct;
$newSarBalance = $oldSARBalance + $validated['sar_amount'];
// Create transaction history
if ($checkTransfer) {
return $request->ajax()
? response()->json(['success' => false, 'message' => 'This fund transfer has already been approved and recorded in transaction history.'], 400)
: redirect()->back()->with('error', 'This fund transfer has already been approved and recorded in transaction history.');
}
// Transaction: Deduct BDT
TransactionHistory::create([
'agency_id' => $agency->id,
'source_table' => 'fund_transfers',
'source_id' => $fundTransfer->id,
'tnx_type' => 'Transfer Out',
'currency' => 'BDT',
'amount' => $validated['bdt_amount'],
'old_balance' => $oldBDTBalance,
'new_balance' => $newBdtBalance,
'note' => 'Fund Transfer Approved: Deducted '.$validated['bdt_amount'].' BDT for transfer to SAR. Approved by '.auth()->user()->name,
'created_at' => $validated['transferred_date'] ?? now(),
]);
// Transaction: Add SAR
TransactionHistory::create([
'agency_id' => $agency->id,
'source_table' => 'fund_transfers',
'source_id' => $fundTransfer->id,
'tnx_type' => 'Transfer In',
'currency' => 'SAR',
'amount' => $validated['sar_amount'],
'old_balance' => $oldSARBalance,
'new_balance' => $newSarBalance,
'note' => 'Fund Transfer Approved: Converted '.$validated['bdt_amount'].' BDT to '.$validated['sar_amount'].' SAR. Approved by '.auth()->user()->name,
'created_at' => $validated['transferred_date'] ?? now(),
]);
// Approved -> Deduct BDT, Add SAR
if ($agency) {
$agency->bdt_acct = $newBdtBalance;
$agency->sar_acct = $newSarBalance;
$agency->save();
}
$fundTransfer->approved_by = auth()->id();
} elseif (in_array($newStatus, [0, 2]) && $oldStatus === 1) {
// Revert approved balances
$agency = CompanyInfo::find($fundTransfer->agency_id);
// Revert balances
$oldBdtBalance = $agency->bdt_acct;
$newBdtBalance = $oldBdtBalance + $fundTransfer->bdt_amount;
$oldSarBalance = $agency->sar_acct;
$newSarBalance = $oldSarBalance - $fundTransfer->sar_amount;
// delete transaction histories related to this fund transfer
TransactionHistory::where('source_table', 'fund_transfers')
->where('source_id', $fundTransfer->id)
->delete();
if ($agency) {
$agency->bdt_acct = $newBdtBalance;
$agency->sar_acct = $newSarBalance;
$agency->save();
}
$fundTransfer->approved_by = null;
}
} elseif ($newStatus !== $oldStatus) {
return $request->ajax()
? response()->json(['success' => false, 'message' => 'You are not authorized to change the status.'], 403)
: redirect()->back()->with('error', 'You are not authorized to change the status.');
}
// ✅ Step 4: Update fund transfer record
$fundTransfer->agency_id = $validated['agency_id'];
$fundTransfer->bdt_amount = $validated['bdt_amount'];
$fundTransfer->currency_rate = $validated['currency_rate'];
$fundTransfer->sar_amount = $validated['sar_amount'];
$fundTransfer->transaction_id = $validated['transaction_id'];
$fundTransfer->transferred_date = $validated['transferred_date'];
$fundTransfer->additional = $validated['additional'];
$fundTransfer->status = $validated['status'];
$fundTransfer->save();
$fundTransfer->load('agency');
// ✅ Step 5: Return response
if ($request->ajax()) {
return response()->json([
'success' => true,
'message' => 'Fund Transfer updated successfully.',
'fundTransfer' => $fundTransfer,
]);
}
return redirect()->back()->with('success', 'Fund Transfer updated successfully.');
}
}