Files
Kent-logistics-Laravel/app/Http/Controllers/Admin/AdminInvoiceController.php

246 lines
8.8 KiB
PHP
Raw Normal View History

2025-11-17 10:33:11 +05:30
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use Mpdf\Mpdf;
2025-11-25 13:14:53 +05:30
use App\Models\InvoiceInstallment;
use Illuminate\Support\Facades\Log;
2025-11-17 10:33:11 +05:30
class AdminInvoiceController extends Controller
{
// -------------------------------------------------------------
// INVOICE LIST PAGE
// -------------------------------------------------------------
public function index()
{
2025-11-25 13:14:53 +05:30
$invoices = Invoice::with(['order.shipments'])->latest()->get();
2025-11-17 10:33:11 +05:30
return view('admin.invoice', compact('invoices'));
}
// -------------------------------------------------------------
// POPUP VIEW (AJAX)
// -------------------------------------------------------------
2025-11-26 23:07:12 +05:30
public function popup($id)
2025-11-17 10:33:11 +05:30
{
2025-12-23 00:30:18 +05:30
$invoice = Invoice::with(['items', 'order', 'installments'])->findOrFail($id);
2025-11-25 13:14:53 +05:30
2025-12-23 00:30:18 +05:30
$shipment = \App\Models\Shipment::whereHas('items', function ($q) use ($invoice) {
$q->where('order_id', $invoice->order_id);
})->first();
2025-11-25 13:14:53 +05:30
2025-12-23 00:30:18 +05:30
return view('admin.popup_invoice', compact('invoice', 'shipment'));
2025-11-17 10:33:11 +05:30
}
// -------------------------------------------------------------
// EDIT INVOICE PAGE
// -------------------------------------------------------------
public function edit($id)
{
2025-11-25 13:14:53 +05:30
$invoice = Invoice::with(['order.shipments'])->findOrFail($id);
$shipment = $invoice->order?->shipments?->first();
return view('admin.invoice_edit', compact('invoice', 'shipment'));
2025-11-17 10:33:11 +05:30
}
// -------------------------------------------------------------
// UPDATE INVOICE
// -------------------------------------------------------------
2025-11-26 23:07:12 +05:30
public function update(Request $request, $id)
{
Log::info("🟡 Invoice Update Request Received", [
'invoice_id' => $id,
'request' => $request->all()
]);
2025-11-17 10:33:11 +05:30
2025-11-26 23:07:12 +05:30
$invoice = Invoice::findOrFail($id);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$data = $request->validate([
'invoice_date' => 'required|date',
'due_date' => 'required|date|after_or_equal:invoice_date',
'final_amount' => 'required|numeric|min:0',
'tax_type' => 'required|in:gst,igst',
'tax_percent' => 'required|numeric|min:0|max:28',
'status' => 'required|in:pending,paid,overdue',
'notes' => 'nullable|string',
]);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
Log::info("✅ Validated Invoice Update Data", $data);
$finalAmount = floatval($data['final_amount']);
$taxPercent = floatval($data['tax_percent']);
$taxAmount = 0;
if ($data['tax_type'] === 'gst') {
Log::info("🟢 GST Selected", compact('taxPercent'));
$data['cgst_percent'] = $taxPercent / 2;
$data['sgst_percent'] = $taxPercent / 2;
$data['igst_percent'] = 0;
} else {
Log::info("🔵 IGST Selected", compact('taxPercent'));
$data['cgst_percent'] = 0;
$data['sgst_percent'] = 0;
$data['igst_percent'] = $taxPercent;
}
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$taxAmount = ($finalAmount * $taxPercent) / 100;
$data['gst_amount'] = $taxAmount;
$data['final_amount_with_gst'] = $finalAmount + $taxAmount;
$data['gst_percent'] = $taxPercent;
Log::info("📌 Final Calculated Invoice Values", [
'invoice_id' => $invoice->id,
'final_amount' => $finalAmount,
'gst_amount' => $data['gst_amount'],
'final_amount_with_gst' => $data['final_amount_with_gst'],
'tax_type' => $data['tax_type'],
'cgst_percent' => $data['cgst_percent'],
'sgst_percent' => $data['sgst_percent'],
'igst_percent' => $data['igst_percent'],
]);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$invoice->update($data);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
Log::info("✅ Invoice Updated Successfully", [
'invoice_id' => $invoice->id
]);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
// regenerate PDF
$this->generateInvoicePDF($invoice);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
return redirect()
->route('admin.invoices.index')
->with('success', 'Invoice updated & PDF generated successfully.');
}
2025-11-25 13:14:53 +05:30
2025-11-17 10:33:11 +05:30
// -------------------------------------------------------------
// PDF GENERATION USING mPDF
// -------------------------------------------------------------
public function generateInvoicePDF($invoice)
{
2025-11-25 13:14:53 +05:30
$invoice->load(['items', 'order.shipments']);
$shipment = $invoice->order?->shipments?->first();
2025-11-17 10:33:11 +05:30
$fileName = 'invoice-' . $invoice->invoice_number . '.pdf';
$folder = public_path('invoices/');
if (!file_exists($folder)) {
mkdir($folder, 0777, true);
}
$filePath = $folder . $fileName;
if (file_exists($filePath)) {
unlink($filePath);
}
2025-11-26 23:07:12 +05:30
$mpdf = new Mpdf(['mode' => 'utf-8', 'format' => 'A4', 'default_font' => 'sans-serif']);
$html = view('admin.pdf.invoice', ['invoice' => $invoice, 'shipment' => $shipment])->render();
2025-11-17 10:33:11 +05:30
$mpdf->WriteHTML($html);
$mpdf->Output($filePath, 'F');
2025-11-26 23:07:12 +05:30
$invoice->update(['pdf_path' => 'invoices/' . $fileName]);
2025-11-17 10:33:11 +05:30
}
2025-11-25 13:14:53 +05:30
2025-12-23 00:30:18 +05:30
public function downloadInvoice($id)
{
$invoice = Invoice::findOrFail($id);
// Generate PDF if missing
if (
!$invoice->pdf_path ||
!file_exists(public_path($invoice->pdf_path))
) {
$this->generateInvoicePDF($invoice);
$invoice->refresh();
}
return response()->download(public_path($invoice->pdf_path));
}
2025-11-26 23:07:12 +05:30
// -------------------------------------------------------------
// INSTALLMENTS (ADD/DELETE)
// -------------------------------------------------------------
public function storeInstallment(Request $request, $invoice_id)
{
$request->validate([
'installment_date' => 'required|date',
'payment_method' => 'required|string',
'reference_no' => 'nullable|string',
'amount' => 'required|numeric|min:1',
]);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$invoice = Invoice::findOrFail($invoice_id);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$paidTotal = $invoice->installments()->sum('amount');
// Use GST-inclusive total for all calculations/checks
$remaining = $invoice->final_amount_with_gst - $paidTotal;
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
if ($request->amount > $remaining) {
return response()->json([
'status' => 'error',
'message' => 'Installment amount exceeds remaining balance.'
], 422);
}
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$installment = InvoiceInstallment::create([
'invoice_id' => $invoice_id,
'installment_date' => $request->installment_date,
'payment_method' => $request->payment_method,
'reference_no' => $request->reference_no,
'amount' => $request->amount,
]);
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
$newPaid = $paidTotal + $request->amount;
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
// Mark as 'paid' if GST-inclusive total is cleared
if ($newPaid >= $invoice->final_amount_with_gst) {
$invoice->update(['status' => 'paid']);
2025-12-18 12:57:01 +05:30
$this->generateInvoicePDF($invoice);
2025-11-26 23:07:12 +05:30
}
2025-11-25 13:14:53 +05:30
2025-11-26 23:07:12 +05:30
return response()->json([
'status' => 'success',
'message' => 'Installment added successfully.',
'installment' => $installment,
'totalPaid' => $newPaid,
'gstAmount' => $invoice->gst_amount,
'finalAmountWithGst' => $invoice->final_amount_with_gst,
'baseAmount' => $invoice->final_amount,
'remaining' => max(0, $invoice->final_amount_with_gst - $newPaid),
'isCompleted' => $newPaid >= $invoice->final_amount_with_gst
]);
2025-11-25 13:14:53 +05:30
}
2025-11-26 23:07:12 +05:30
public function deleteInstallment($id)
{
$installment = InvoiceInstallment::findOrFail($id);
$invoice = $installment->invoice;
$installment->delete();
$paidTotal = $invoice->installments()->sum('amount');
$remaining = $invoice->final_amount_with_gst - $paidTotal;
// Update status if not fully paid anymore
if ($remaining > 0 && $invoice->status === "paid") {
$invoice->update(['status' => 'pending']);
2025-12-18 12:57:01 +05:30
$this->generateInvoicePDF($invoice);
2025-11-26 23:07:12 +05:30
}
return response()->json([
'status' => 'success',
'message' => 'Installment deleted.',
'totalPaid' => $paidTotal,
'gstAmount' => $invoice->gst_amount,
'finalAmountWithGst' => $invoice->final_amount_with_gst,
'baseAmount' => $invoice->final_amount,
'remaining' => $remaining,
'isZero' => $paidTotal == 0
]);
2025-11-25 13:14:53 +05:30
}
2025-11-26 23:07:12 +05:30
2025-11-17 10:33:11 +05:30
}