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

354 lines
14 KiB
PHP
Raw Normal View History

2026-03-15 17:08:23 +07:00
<?php
namespace Modules\Business\App\Http\Controllers;
use App\Models\DueCollect;
use App\Models\Income;
use App\Models\Party;
use App\Models\PaymentType;
use App\Models\Sale;
use App\Models\Transaction;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AcnooChequeController extends Controller
{
public function index(Request $request)
{
$business_id = auth()->user()->business_id;
$banks = PaymentType::where('business_id', $business_id)->latest()->get();
$cheque = Transaction::with('user:id,name')
->where('business_id', auth()->user()->business_id)
->whereIn('transaction_type', ['cheque_payment', 'cheque_reopen']);
// 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');
}
$cheque->whereDate('date', '>=', $startDate)
->whereDate('date', '<=', $endDate);
$cheques = $cheque->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 . '%')
->orWhere('meta->cheque_number', 'like', '%' . $request->search . '%')
->orWhereHas('user', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
})
->latest()
->paginate($request->per_page ?? 20)->appends($request->query());
if ($request->ajax()) {
return response()->json([
'data' => view('business::cheques.datas', compact('cheques'))->render()
]);
}
return view('business::cheques.index', compact('cheques', 'banks'));
}
// Deposit cheque
public function store(Request $request)
{
$request->validate([
'transaction_id' => 'required|exists:transactions,id',
'date' => 'nullable|date',
'note' => 'nullable|string',
'payment_type' => [
'required',
function ($attribute, $value, $fail) {
if ($value !== 'cash' && !PaymentType::where('id', $value)->exists()) {
$fail(__('The selected payment type is invalid.'));
}
},
],
]);
$business_id = auth()->user()->business_id;
DB::beginTransaction();
try {
$transaction = Transaction::findOrFail($request->transaction_id);
$amount = $transaction->amount;
$platform = strtolower($transaction->platform);
$transaction->update([
'type' => 'deposit',
]);
$newTransactionData = [
'business_id' => $business_id,
'user_id' => auth()->id(),
'type' => 'credit',
'platform' => 'cheque',
'amount' => $amount,
'date' => $request->date ?? now(),
'note' => $request->note,
'meta' => [
'source_transaction_id' => $request->transaction_id ?? null,
],
];
// Cheque deposited into Cash
if ($request->payment_type === 'cash') {
$newTransactionData['transaction_type'] = 'cheque_to_cash';
$newTransactionData['payment_type_id'] = null;
} else {
// Cheque deposited into Bank
$toBank = PaymentType::findOrFail($request->payment_type);
$toBank->increment('balance', $amount);
$newTransactionData['transaction_type'] = 'cheque_to_bank';
$newTransactionData['payment_type_id'] = $toBank->id;
}
Transaction::create($newTransactionData);
// update related platform
if ($platform == 'sale') {
$sale = Sale::find($transaction->reference_id);
updateBalance($amount, 'increment');
$newPaid = $sale->paidAmount + $amount;
$expectedTotal = $sale->paidAmount + $sale->dueAmount;
$newChange = max($newPaid - $expectedTotal, 0);
$newDue = max($sale->dueAmount - $amount, 0);
$sale->update([
'paidAmount' => $newPaid,
'change_amount' => $sale->change_amount + $newChange,
'dueAmount' => $newDue,
'isPaid' => $newDue > 0 ? 0 : 1,
]);
// update party due
if ($sale->party_id) {
$party = Party::find($sale->party_id);
if ($party) {
$party->decrement('due', min($amount, $party->due));
}
}
}
elseif ($transaction->platform == 'income') {
$income = Income::find($transaction->reference_id);
$income->increment('amount', $transaction->amount);
}
elseif ($transaction->platform == 'due_collect'){
$due = DueCollect::find($transaction->reference_id);
if ($due) {
if ($due->sale_id) {
$invoice = Sale::find($due->sale_id);
if ($invoice) {
$invoice->update([
'dueAmount' => max($invoice->dueAmount - $amount, 0),
]);
}
}
// Update DueCollect
$due->update([
'dueAmountAfterPay' => max($due->dueAmountAfterPay - $amount, 0),
]);
if ($due->party_id) {
$party = Party::find($due->party_id);
if ($party) {
// Reduce customer's due
$party->decrement('due', min($amount, $party->due));
// Opening balance reduce (if due type)
if ($party->opening_balance_type == 'due') {
$party->update([
'opening_balance' => max(0, $party->opening_balance - $amount),
]);
}
}
}
updateBalance($amount, 'increment');
}
}
DB::commit();
return response()->json([
'message' => __('Cheque data saved successfully'),
'redirect' => route('business.cheques.index'),
]);
} catch (\Exception $e) {
DB::rollback();
return response()->json([
'message' => $e->getMessage()
], 406);
}
}
// Reopen cheque
public function reopen(Request $request)
{
$request->validate([
'transaction_id' => 'required|exists:transactions,id',
]);
DB::beginTransaction();
try {
// original cheque payment
$originalTxn = Transaction::findOrFail($request->transaction_id);
// Must be cheque_payment
if ($originalTxn->transaction_type !== 'cheque_payment') {
return response()->json(['message' => __('This transaction cannot be reopened.')], 400);
}
$amount = $originalTxn->amount;
$business_id = auth()->user()->business_id;
$depositTxn = Transaction::where('platform', 'cheque')
->where('meta->source_transaction_id', $originalTxn->id)
->first();
if (!$depositTxn) {
return response()->json(['message' => __('Deposited cheque record not found.')], 400);
}
// Reverse bank balance only if cheque_to_bank
if ($depositTxn->transaction_type === 'cheque_to_bank' && $depositTxn->payment_type_id) {
$bank = PaymentType::find($depositTxn->payment_type_id);
if ($bank) {
$bank->decrement('balance', $amount);
}
}
$platform = strtolower($originalTxn->platform);
// Reverse Sale or Income
if ($platform == 'sale') {
$sale = Sale::find($originalTxn->reference_id);
if ($sale) {
// Reverse paid, change, and due amounts
$newPaid = $sale->paidAmount - $amount;
$newDue = $sale->dueAmount + $amount;
$newChange = max($sale->change_amount - max($sale->paidAmount - ($sale->paidAmount + $sale->dueAmount - $amount), 0), 0);
$sale->update([
'paidAmount' => max($newPaid, 0),
'change_amount' => max($newChange, 0),
'dueAmount' => $newDue,
'isPaid' => $newDue > 0 ? 0 : 1,
]);
// Reverse party due if exists
if ($sale->party_id) {
$party = Party::find($sale->party_id);
if ($party) {
$party->increment('due', $amount);
}
}
}
} elseif ($platform == 'income') {
$income = Income::find($originalTxn->reference_id);
if ($income) {
$income->decrement('amount', $amount);
}
} elseif ($platform == 'due_collect') {
$due = DueCollect::find($originalTxn->reference_id);
if ($due) {
if ($due->sale_id) {
$invoice = Sale::find($due->sale_id);
if ($invoice) {
$invoice->update([
'dueAmount' => $invoice->dueAmount + $amount,
]);
}
}
$due->update([
'dueAmountAfterPay' => $due->dueAmountAfterPay + $amount,
]);
if ($due->party_id) {
$party = Party::find($due->party_id);
if ($party) {
$party->increment('due', $amount);
if ($party->opening_balance_type == 'due') {
$party->update([
'opening_balance' => $party->opening_balance + $amount,
]);
}
}
}
updateBalance($amount, 'decrement');
}
}
$reverseType = $depositTxn->transaction_type === 'cheque_to_cash' ? 'cash_to_cheque' : 'bank_to_cheque';
// Create reverse debit transaction
Transaction::create([
'business_id' => $business_id,
'user_id' => auth()->id(),
'type' => 'debit',
'platform' => 'cheque',
'amount' => $amount,
'date' => now(),
'note' => 'Cheque reopened',
'transaction_type' => $reverseType,
'payment_type_id' => $depositTxn->payment_type_id,
'meta' => [
'reverted_transaction_id' => $depositTxn->id
]
]);
$originalTxn->update([
'type' => 'pending',
]);
DB::commit();
return response()->json([
'message' => __('Cheque reopened successfully'),
'redirect' => route('business.cheques.index'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => $e->getMessage()
], 406);
}
}
}