Files
kulakpos_web/Modules/Business/App/Http/Controllers/BankTransactionController.php

400 lines
16 KiB
PHP

<?php
namespace Modules\Business\App\Http\Controllers;
use App\Helpers\HasUploader;
use App\Http\Controllers\Controller;
use App\Models\PaymentType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class BankTransactionController extends Controller
{
use HasUploader;
public function index()
{
$business_id = auth()->user()->business_id;
$payment_type_id = request('payment_type_id');
$payment_type = PaymentType::where('business_id', $business_id)->findOrFail($payment_type_id);
$transactions = Transaction::with('user:id,name', 'branch:id,name')
->where('business_id', $business_id)
->whereDate('date', Carbon::today())
->where(function ($query) use ($payment_type_id) {
$query->where('payment_type_id', $payment_type_id)
->orWhere('from_bank', $payment_type_id)
->orWhere('to_bank', $payment_type_id);
})
->latest()
->paginate(20);
return view('business::banks.transactions.index', compact('transactions', 'payment_type'));
}
public function acnooFilter(Request $request)
{
$payment_type_id = request('payment_type_id');
$transaction = Transaction::with('user:id,name')
->where('business_id', auth()->user()->business_id)
->where(function ($q) use ($payment_type_id) {
$q->where('payment_type_id', $payment_type_id)
->orWhere('from_bank', $payment_type_id)
->orWhere('to_bank', $payment_type_id);
});
// Default to today
$startDate = Carbon::today()->format('Y-m-d');
$endDate = Carbon::today()->format('Y-m-d');
if ($request->custom_days === 'yesterday') {
$startDate = Carbon::yesterday()->format('Y-m-d');
$endDate = Carbon::yesterday()->format('Y-m-d');
} elseif ($request->custom_days === 'last_seven_days') {
$startDate = Carbon::today()->subDays(6)->format('Y-m-d');
} elseif ($request->custom_days === 'last_thirty_days') {
$startDate = Carbon::today()->subDays(29)->format('Y-m-d');
} elseif ($request->custom_days === 'current_month') {
$startDate = Carbon::now()->startOfMonth()->format('Y-m-d');
$endDate = Carbon::now()->endOfMonth()->format('Y-m-d');
} elseif ($request->custom_days === 'last_month') {
$startDate = Carbon::now()->subMonth()->startOfMonth()->format('Y-m-d');
$endDate = Carbon::now()->subMonth()->endOfMonth()->format('Y-m-d');
} elseif ($request->custom_days === 'current_year') {
$startDate = Carbon::now()->startOfYear()->format('Y-m-d');
$endDate = Carbon::now()->endOfYear()->format('Y-m-d');
} elseif ($request->custom_days === 'custom_date' && $request->from_date && $request->to_date) {
$startDate = Carbon::parse($request->from_date)->format('Y-m-d');
$endDate = Carbon::parse($request->to_date)->format('Y-m-d');
}
$transaction->whereDate('date', '>=', $startDate)
->whereDate('date', '<=', $endDate);
$transactions = $transaction->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('date', 'like', '%' . $request->search . '%')
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhereHas('user', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
})
->latest()
->paginate($request->per_page ?? 20);
if ($request->ajax()) {
return response()->json([
'data' => view('business::banks.transactions.datas', compact('transactions'))->render()
]);
}
return redirect(url()->previous());
}
public function store(Request $request)
{
$request->validate([
'from' => 'required|exists:payment_types,id',
'type' => 'nullable|in:credit,debit',
'transaction_type' => 'required|in:bank_to_bank,bank_to_cash,adjust_bank',
'amount' => 'required|numeric|min:0.01',
'date' => 'nullable|date',
'image' => 'nullable|image|mimes:jpg,png,jpeg,svg',
'note' => 'nullable|string',
]);
$business_id = auth()->user()->business_id;
$amount = $request->amount ?? 0;
$type = 'transfer';
DB::beginTransaction();
try {
$fromBank = PaymentType::find($request->from);
// Prevent transferring to the same bank
if ($request->transaction_type == 'bank_to_bank' && $request->from == $request->to) {
return response()->json([
'message' => 'Cannot transfer between the same bank account.'
], 400);
}
// Update balances based on transaction type
if ($request->transaction_type == 'bank_to_bank') {
$toBank = PaymentType::find($request->to);
if ($fromBank->balance < $amount) {
return response()->json([
'message' => 'Insufficient balance in source bank account.'
], 400);
}
$fromBank->decrement('balance', $amount);
$toBank->increment('balance', $amount);
} elseif ($request->transaction_type == 'bank_to_cash') {
if ($fromBank->balance < $amount) {
return response()->json([
'message' => 'Insufficient balance in selected bank.'
], 400);
}
$fromBank->decrement('balance', $amount);
} elseif ($request->transaction_type == 'adjust_bank') {
$type = $request->type;
if ($type == 'credit' && $fromBank->balance < $amount) {
return response()->json([
'message' => 'Cannot decrease below zero balance.'
], 400);
}
if ($type == 'credit') {
$fromBank->increment('balance', $amount);
} else {
$fromBank->decrement('balance', $amount);
}
}
Transaction::create([
'business_id' => $business_id,
'user_id' => auth()->id(),
'type' => $type,
'platform' => 'bank',
'transaction_type' => $request->transaction_type,
'amount' => $amount,
'from_bank' => $request->from,
'to_bank' => ($request->transaction_type == 'bank_to_bank') ? $request->to : null,
'date' => $request->date ?? now(),
'image' => $request->image ? $this->upload($request, 'image') : NULL,
'note' => $request->note,
]);
DB::commit();
return response()->json([
'message' => __('Transaction completed successfully.'),
'redirect' => route('business.bank-transactions.index', ['payment_type_id' => $request->from]),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => 'Error: ' . $e->getMessage(),
], 500);
}
}
public function update(Request $request, $id)
{
$request->validate([
'from' => 'required|exists:payment_types,id',
'type' => 'nullable|in:credit,debit',
'transaction_type' => 'required|in:bank_to_bank,bank_to_cash,adjust_bank',
'amount' => 'required|numeric|min:0.01',
'date' => 'nullable|date',
'image' => 'nullable|image|mimes:jpg,png,jpeg,svg',
'note' => 'nullable|string',
]);
$transaction = Transaction::findOrFail($id);
$fromBank = PaymentType::find($request->from);
$newAmount = $request->amount;
$newType = $request->transaction_type;
DB::beginTransaction();
try {
// Transaction type Same
if ($transaction->transaction_type === $request->transaction_type) {
if ($newType === 'bank_to_bank') {
$toBank = PaymentType::find($request->to);
// Adjust balance difference
$diff = $newAmount - $transaction->amount;
if ($fromBank->balance < $diff && $diff > 0) {
return response()->json(['message' => 'Insufficient balance.'], 400);
}
$fromBank->decrement('balance', $diff);
$toBank->increment('balance', $diff);
} elseif ($newType === 'bank_to_cash') {
$diff = $newAmount - $transaction->amount;
if ($fromBank->balance < $diff && $diff > 0) {
return response()->json(['message' => 'Insufficient balance.'], 400);
}
$fromBank->decrement('balance', $diff);
} elseif ($newType === 'adjust_bank') {
$bankType = $request->type;
$oldType = $transaction->type;
$oldAmount = $transaction->amount;
if ($bankType === $oldType) {
// Same type: adjust by difference
$diff = $newAmount - $oldAmount;
if ($bankType == 'credit') {
$fromBank->increment('balance', $diff);
} else {
$fromBank->decrement('balance', $diff);
}
} else {
// Different type: reverse old and apply new
if ($oldType == 'credit') $fromBank->decrement('balance', $oldAmount);
else $fromBank->increment('balance', $oldAmount);
if ($bankType == 'credit') $fromBank->increment('balance', $newAmount);
else $fromBank->decrement('balance', $newAmount);
}
}
} // Transaction type changed
else {
// Reverse old transaction completely
if ($transaction->transaction_type === 'bank_to_bank') {
$oldFrom = PaymentType::find($transaction->from_bank);
$oldTo = PaymentType::find($transaction->to_bank);
$oldFrom->increment('balance', $transaction->amount);
$oldTo->decrement('balance', $transaction->amount);
} elseif ($transaction->transaction_type === 'bank_to_cash') {
$oldFrom = PaymentType::find($transaction->from_bank);
$oldFrom->increment('balance', $transaction->amount);
} elseif ($transaction->transaction_type === 'adjust_bank') {
$oldFrom = PaymentType::find($transaction->from_bank);
$transaction->type === 'credit'
? $oldFrom->decrement('balance', $transaction->amount)
: $oldFrom->increment('balance', $transaction->amount);
}
// Apply new transaction
if ($newType === 'bank_to_bank') {
$toBank = PaymentType::find($request->to);
if ($fromBank->balance < $newAmount) {
return response()->json(['message' => 'Insufficient balance.'], 400);
}
$fromBank->decrement('balance', $newAmount);
$toBank->increment('balance', $newAmount);
} elseif ($newType === 'bank_to_cash') {
if ($fromBank->balance < $newAmount) {
return response()->json(['message' => 'Insufficient balance.'], 400);
}
$fromBank->decrement('balance', $newAmount);
} elseif ($newType === 'adjust_bank') {
if ($request->type == 'credit') $fromBank->increment('balance', $newAmount);
else $fromBank->decrement('balance', $newAmount);
}
}
// Update transaction record
$transaction->update([
'type' => $newType === 'adjust_bank' ? $request->type : 'transfer',
'transaction_type' => $newType,
'amount' => $newAmount,
'from_bank' => $request->from,
'to_bank' => $newType === 'bank_to_bank' ? $request->to : null,
'date' => $request->date ?? now(),
'image' => $request->image ? $this->upload($request, 'image', $transaction->image) : $transaction->image,
'note' => $request->note,
]);
DB::commit();
return response()->json([
'message' => __('Transaction updated successfully.'),
'redirect' => route('business.bank-transactions.index', ['payment_type_id' => $request->from]),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['message' => 'Error: ' . $e->getMessage()], 500);
}
}
public function destroy(string $id)
{
$transaction = Transaction::findOrFail($id);
DB::beginTransaction();
try {
$fromBank = PaymentType::find($transaction->from_bank);
$toBank = PaymentType::find($transaction->to_bank);
$amount = $transaction->amount;
// Allow only "bank" platform transactions to be deleted
if ($transaction->platform !== 'bank') {
return response()->json([
'message' => 'Cannot delete here, please delete from ' . ucfirst($transaction->platform) . ' section.',
], 400);
}
// Reverse balance changes based on transaction type
switch ($transaction->transaction_type) {
case 'bank_to_bank':
if ($toBank && $fromBank) {
// Ensure receiver bank has enough balance before reversing
if ($toBank->balance < $amount) {
return response()->json([
'message' => 'Insufficient balance in ' . $toBank->name . ' to reverse this transaction.',
], 400);
}
$fromBank->increment('balance', $amount);
$toBank->decrement('balance', $amount);
}
break;
case 'bank_to_cash':
if ($fromBank) {
$fromBank->increment('balance', $amount);
}
break;
case 'adjust_bank':
if ($fromBank) {
if ($transaction->type === 'credit') {
// Previously increased, so now decrease
if ($fromBank->balance < $amount) {
return response()->json([
'message' => 'Insufficient balance in ' . $fromBank->name . ' to reverse this transaction.',
], 400);
}
$fromBank->decrement('balance', $amount);
} else {
// Previously decreased, so now increase
$fromBank->increment('balance', $amount);
}
}
break;
}
if (file_exists($transaction->image)) {
Storage::delete($transaction->image);
}
$transaction->delete();
DB::commit();
return response()->json([
'message' => __('Transaction reversed and deleted successfully.'),
'redirect' => url()->previous(),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => 'Error: ' . $e->getMessage(),
], 500);
}
}
}