2025-11-17 10:33:11 +05:30
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use App\Models\Invoice;
|
|
|
|
|
use App\Models\InvoiceItem;
|
2025-11-25 13:14:53 +05:30
|
|
|
use App\Models\InvoiceInstallment;
|
2026-02-27 10:51:26 +05:30
|
|
|
use App\Models\InvoiceChargeGroup;
|
|
|
|
|
use App\Models\InvoiceChargeGroupItem;
|
|
|
|
|
use Illuminate\Http\Request;
|
2025-11-25 13:14:53 +05:30
|
|
|
use Illuminate\Support\Facades\Log;
|
2026-02-27 10:51:26 +05:30
|
|
|
use Mpdf\Mpdf;
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2025-11-17 10:33:11 +05:30
|
|
|
class AdminInvoiceController extends Controller
|
|
|
|
|
{
|
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
// INVOICE LIST PAGE
|
|
|
|
|
// -------------------------------------------------------------
|
2026-02-27 10:51:26 +05:30
|
|
|
public function index(Request $request)
|
2025-11-17 10:33:11 +05:30
|
|
|
{
|
2026-02-27 10:51:26 +05:30
|
|
|
$query = Invoice::with(['items', 'customer', 'container']);
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
if ($request->filled('search')) {
|
|
|
|
|
$search = $request->search;
|
|
|
|
|
$query->where(function ($q) use ($search) {
|
|
|
|
|
$q->where('invoice_number', 'like', "%{$search}%")
|
|
|
|
|
->orWhere('customer_name', 'like', "%{$search}%");
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
if ($request->filled('status') && $request->status !== 'all') {
|
|
|
|
|
$query->where('status', $request->status);
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
if ($request->filled('start_date')) {
|
|
|
|
|
$query->whereDate('invoice_date', '>=', $request->start_date);
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
if ($request->filled('end_date')) {
|
|
|
|
|
$query->whereDate('invoice_date', '<=', $request->end_date);
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoices = $query->latest()->get();
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2025-11-17 10:33:11 +05:30
|
|
|
return view('admin.invoice', compact('invoices'));
|
2026-03-11 20:02:43 +05:30
|
|
|
}
|
2025-11-17 10:33:11 +05:30
|
|
|
|
|
|
|
|
// -------------------------------------------------------------
|
2026-03-11 20:02:43 +05:30
|
|
|
// POPUP VIEW
|
2025-11-17 10:33:11 +05:30
|
|
|
// -------------------------------------------------------------
|
2025-11-26 23:07:12 +05:30
|
|
|
public function popup($id)
|
2025-11-17 10:33:11 +05:30
|
|
|
{
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice = Invoice::with([
|
|
|
|
|
'items',
|
2026-03-09 10:24:44 +05:30
|
|
|
'chargeGroups.items',
|
2026-02-27 10:51:26 +05:30
|
|
|
])->findOrFail($id);
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
// demo update असेल तर
|
2026-03-09 10:24:44 +05:30
|
|
|
$invoice->update([
|
|
|
|
|
'customer_email' => 'test@demo.com',
|
|
|
|
|
'customer_address' => 'TEST ADDRESS',
|
|
|
|
|
'pincode' => '999999',
|
|
|
|
|
]);
|
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
$shipment = null;
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
$groupedItemIds = $invoice->chargeGroups
|
|
|
|
|
->flatMap(fn($group) => $group->items->pluck('invoice_item_id'))
|
|
|
|
|
->unique()
|
|
|
|
|
->values()
|
|
|
|
|
->toArray();
|
|
|
|
|
|
|
|
|
|
return view('admin.popup_invoice', compact('invoice', 'shipment', 'groupedItemIds'));
|
2025-11-17 10:33:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
// EDIT INVOICE PAGE
|
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
public function edit($id)
|
|
|
|
|
{
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice = Invoice::with([
|
|
|
|
|
'items',
|
|
|
|
|
'customer',
|
|
|
|
|
'container',
|
|
|
|
|
'chargeGroups.items',
|
2026-03-11 20:02:43 +05:30
|
|
|
'installments',
|
2026-02-27 10:51:26 +05:30
|
|
|
])->findOrFail($id);
|
|
|
|
|
|
|
|
|
|
$shipment = null;
|
|
|
|
|
|
|
|
|
|
$groupedItemIds = $invoice->chargeGroups
|
|
|
|
|
->flatMap(function ($group) {
|
|
|
|
|
return $group->items->pluck('invoice_item_id');
|
|
|
|
|
})
|
|
|
|
|
->unique()
|
|
|
|
|
->values()
|
|
|
|
|
->toArray();
|
|
|
|
|
|
|
|
|
|
return view('admin.invoice_edit', compact('invoice', 'shipment', 'groupedItemIds'));
|
2025-11-17 10:33:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------
|
2026-03-11 20:02:43 +05:30
|
|
|
// UPDATE INVOICE (HEADER ONLY)
|
2025-11-17 10:33:11 +05:30
|
|
|
// -------------------------------------------------------------
|
2025-11-26 23:07:12 +05:30
|
|
|
public function update(Request $request, $id)
|
|
|
|
|
{
|
2026-02-27 10:51:26 +05:30
|
|
|
Log::info('🟡 Invoice Update Request Received', [
|
2025-11-26 23:07:12 +05:30
|
|
|
'invoice_id' => $id,
|
2026-02-27 10:51:26 +05:30
|
|
|
'request' => $request->all(),
|
2025-11-26 23:07:12 +05:30
|
|
|
]);
|
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([
|
2026-02-27 10:51:26 +05:30
|
|
|
'invoice_date' => 'required|date',
|
|
|
|
|
'due_date' => 'required|date|after_or_equal:invoice_date',
|
|
|
|
|
'status' => 'required|in:pending,paid,overdue',
|
|
|
|
|
'notes' => 'nullable|string',
|
2025-11-26 23:07:12 +05:30
|
|
|
]);
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
Log::info('✅ Validated Invoice Header Update Data', $data);
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
$invoice->update($data);
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice->refresh();
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
Log::info('🔍 Invoice AFTER HEADER UPDATE', [
|
|
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'charge_groups_total' => $invoice->charge_groups_total,
|
|
|
|
|
'gst_amount' => $invoice->gst_amount,
|
|
|
|
|
'grand_total_with_charges'=> $invoice->grand_total_with_charges,
|
2025-11-26 23:07:12 +05:30
|
|
|
]);
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
$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
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
// -------------------------------------------------------------
|
2026-03-11 20:02:43 +05:30
|
|
|
// UPDATE INVOICE ITEMS (फक्त items save)
|
2026-02-27 10:51:26 +05:30
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
public function updateItems(Request $request, Invoice $invoice)
|
|
|
|
|
{
|
|
|
|
|
Log::info('🟡 Invoice Items Update Request', [
|
|
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'payload' => $request->all(),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$data = $request->validate([
|
|
|
|
|
'items' => ['required', 'array'],
|
|
|
|
|
'items.*.price' => ['required', 'numeric', 'min:0'],
|
|
|
|
|
'items.*.ttl_amount' => ['required', 'numeric', 'min:0'],
|
|
|
|
|
]);
|
|
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
foreach ($data['items'] as $itemId => $itemData) {
|
2026-02-27 10:51:26 +05:30
|
|
|
$item = InvoiceItem::where('id', $itemId)
|
|
|
|
|
->where('invoice_id', $invoice->id)
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (!$item) {
|
|
|
|
|
Log::warning('Invoice item not found or mismatched invoice', [
|
|
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'item_id' => $itemId,
|
|
|
|
|
]);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$item->price = $itemData['price'];
|
|
|
|
|
$item->ttl_amount = $itemData['ttl_amount'];
|
|
|
|
|
$item->save();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
Log::info('✅ Invoice items updated (no totals recalculation)', [
|
|
|
|
|
'invoice_id' => $invoice->id,
|
2026-02-27 10:51:26 +05:30
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return back()->with('success', 'Invoice items updated successfully.');
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-17 10:33:11 +05:30
|
|
|
// -------------------------------------------------------------
|
2026-03-09 10:24:44 +05:30
|
|
|
// PDF GENERATION
|
2025-11-17 10:33:11 +05:30
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
public function generateInvoicePDF($invoice)
|
|
|
|
|
{
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice->load(['items', 'customer', 'container']);
|
|
|
|
|
$shipment = null;
|
|
|
|
|
|
2025-11-17 10:33:11 +05:30
|
|
|
$fileName = 'invoice-' . $invoice->invoice_number . '.pdf';
|
2026-02-27 10:51:26 +05:30
|
|
|
$folder = public_path('invoices/');
|
2025-11-17 10:33:11 +05:30
|
|
|
|
|
|
|
|
if (!file_exists($folder)) {
|
|
|
|
|
mkdir($folder, 0777, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$filePath = $folder . $fileName;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
2025-11-17 10:33:11 +05:30
|
|
|
if (file_exists($filePath)) {
|
|
|
|
|
unlink($filePath);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 10:51:26 +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-25 13:14:53 +05:30
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice->update(['pdf_path' => 'invoices/' . $fileName]);
|
2025-12-23 00:30:18 +05:30
|
|
|
}
|
|
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
// -------------------------------------------------------------
|
2026-02-27 10:51:26 +05:30
|
|
|
// INSTALLMENTS (ADD)
|
2025-11-26 23:07:12 +05:30
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
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
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
$invoice = Invoice::findOrFail($invoice_id);
|
|
|
|
|
|
|
|
|
|
$grandTotal = $invoice->grand_total_with_charges ?? 0;
|
|
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
$paidTotal = $invoice->installments()->sum('amount');
|
2026-03-11 20:02:43 +05:30
|
|
|
$remaining = $grandTotal - $paidTotal;
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
if ($request->amount > $remaining) {
|
|
|
|
|
return response()->json([
|
2026-02-27 10:51:26 +05:30
|
|
|
'status' => 'error',
|
|
|
|
|
'message' => 'Installment amount exceeds remaining balance.',
|
2025-11-26 23:07:12 +05:30
|
|
|
], 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
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
$newPaid = $paidTotal + $request->amount;
|
|
|
|
|
$remaining = max(0, $grandTotal - $newPaid);
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2026-03-11 20:02:43 +05:30
|
|
|
if ($newPaid >= $grandTotal && $grandTotal > 0) {
|
2025-11-26 23:07:12 +05:30
|
|
|
$invoice->update(['status' => 'paid']);
|
|
|
|
|
}
|
2025-11-25 13:14:53 +05:30
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
return response()->json([
|
2026-03-11 20:02:43 +05:30
|
|
|
'status' => 'success',
|
|
|
|
|
'message' => 'Installment added successfully.',
|
|
|
|
|
'installment' => $installment,
|
|
|
|
|
'chargeGroupsTotal' => $invoice->charge_groups_total ?? 0,
|
|
|
|
|
'gstAmount' => $invoice->gst_amount ?? 0,
|
|
|
|
|
'grandTotal' => $grandTotal,
|
|
|
|
|
'totalPaid' => $newPaid,
|
|
|
|
|
'remaining' => $remaining,
|
|
|
|
|
'isCompleted' => $remaining <= 0,
|
|
|
|
|
'isZero' => $newPaid == 0,
|
2025-11-26 23:07:12 +05:30
|
|
|
]);
|
2025-11-25 13:14:53 +05:30
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
// INSTALLMENTS (DELETE)
|
|
|
|
|
// -------------------------------------------------------------
|
2025-11-26 23:07:12 +05:30
|
|
|
public function deleteInstallment($id)
|
|
|
|
|
{
|
|
|
|
|
$installment = InvoiceInstallment::findOrFail($id);
|
2026-02-27 10:51:26 +05:30
|
|
|
$invoice = $installment->invoice;
|
|
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
$installment->delete();
|
2026-03-11 20:02:43 +05:30
|
|
|
$invoice->refresh();
|
|
|
|
|
|
|
|
|
|
$grandTotal = $invoice->grand_total_with_charges ?? 0;
|
|
|
|
|
|
|
|
|
|
$paidTotal = $invoice->installments()->sum('amount');
|
|
|
|
|
$remaining = max(0, $grandTotal - $paidTotal);
|
|
|
|
|
|
|
|
|
|
if ($paidTotal <= 0 && $grandTotal > 0) {
|
|
|
|
|
$invoice->update(['status' => 'pending']);
|
|
|
|
|
} elseif ($paidTotal > 0 && $paidTotal < $grandTotal) {
|
|
|
|
|
$invoice->update(['status' => 'pending']);
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
2025-11-26 23:07:12 +05:30
|
|
|
return response()->json([
|
2026-03-11 20:02:43 +05:30
|
|
|
'status' => 'success',
|
|
|
|
|
'message' => 'Installment deleted.',
|
|
|
|
|
'chargeGroupsTotal' => $invoice->charge_groups_total ?? 0,
|
|
|
|
|
'gstAmount' => $invoice->gst_amount ?? 0,
|
|
|
|
|
'grandTotal' => $grandTotal,
|
|
|
|
|
'totalPaid' => $paidTotal,
|
|
|
|
|
'remaining' => $remaining,
|
|
|
|
|
'isZero' => $paidTotal == 0,
|
2026-02-27 10:51:26 +05:30
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------
|
2026-03-11 20:02:43 +05:30
|
|
|
// CHARGE GROUP SAVE
|
2026-02-27 10:51:26 +05:30
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
public function storeChargeGroup(Request $request, $invoiceId)
|
|
|
|
|
{
|
2026-03-11 20:02:43 +05:30
|
|
|
Log::info('🟡 storeChargeGroup HIT', [
|
|
|
|
|
'invoice_id' => $invoiceId,
|
|
|
|
|
'payload' => $request->all(),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$invoice = Invoice::with('items', 'chargeGroups')->findOrFail($invoiceId);
|
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
$data = $request->validate([
|
2026-03-11 20:02:43 +05:30
|
|
|
'groupname' => 'required|string|max:255',
|
|
|
|
|
'basistype' => 'required|in:ttl_qty,amount,ttl_cbm,ttl_kg',
|
|
|
|
|
'basisvalue' => 'required|numeric',
|
|
|
|
|
'rate' => 'required|numeric|min:0.0001',
|
|
|
|
|
'autototal' => 'required|numeric|min:0.01',
|
|
|
|
|
'itemids' => 'required|array',
|
|
|
|
|
'itemids.*' => 'integer|exists:invoice_items,id',
|
|
|
|
|
|
|
|
|
|
'tax_type' => 'nullable|in:none,gst,igst',
|
|
|
|
|
'gst_percent' => 'nullable|numeric|min:0|max:28',
|
|
|
|
|
'total_with_gst' => 'nullable|numeric|min:0',
|
2026-02-27 10:51:26 +05:30
|
|
|
]);
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
Log::info('✅ storeChargeGroup VALIDATED', $data);
|
|
|
|
|
|
|
|
|
|
// duplicate name check
|
2026-03-09 10:24:44 +05:30
|
|
|
$exists = InvoiceChargeGroup::where('invoice_id', $invoice->id)
|
2026-03-11 20:02:43 +05:30
|
|
|
->where('group_name', $data['groupname'])
|
2026-03-09 10:24:44 +05:30
|
|
|
->exists();
|
2026-03-11 20:02:43 +05:30
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
if ($exists) {
|
|
|
|
|
return back()
|
2026-03-11 20:02:43 +05:30
|
|
|
->withErrors(['groupname' => 'This group name is already used for this invoice.'])
|
2026-03-09 10:24:44 +05:30
|
|
|
->withInput();
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
$taxType = $data['tax_type'] ?? 'gst';
|
|
|
|
|
$gstPercent = $data['gst_percent'] ?? 0;
|
|
|
|
|
$baseTotal = $data['autototal'];
|
|
|
|
|
|
|
|
|
|
$totalWithGst = $data['total_with_gst'] ?? $baseTotal;
|
|
|
|
|
if ($totalWithGst == 0 && $gstPercent > 0) {
|
|
|
|
|
$gstAmount = ($baseTotal * $gstPercent) / 100;
|
|
|
|
|
$totalWithGst = $baseTotal + $gstAmount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1) Group create
|
2026-02-27 10:51:26 +05:30
|
|
|
$group = InvoiceChargeGroup::create([
|
2026-03-11 20:02:43 +05:30
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'group_name' => $data['groupname'],
|
|
|
|
|
'basis_type' => $data['basistype'],
|
|
|
|
|
'basis_value' => $data['basisvalue'],
|
|
|
|
|
'rate' => $data['rate'],
|
|
|
|
|
'total_charge' => $baseTotal,
|
|
|
|
|
'tax_type' => $taxType,
|
|
|
|
|
'gst_percent' => $gstPercent,
|
|
|
|
|
'total_with_gst' => $totalWithGst,
|
2025-11-26 23:07:12 +05:30
|
|
|
]);
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
// 2) Items link
|
|
|
|
|
foreach ($data['itemids'] as $itemId) {
|
2026-02-27 10:51:26 +05:30
|
|
|
InvoiceChargeGroupItem::create([
|
|
|
|
|
'group_id' => $group->id,
|
|
|
|
|
'invoice_item_id' => $itemId,
|
|
|
|
|
]);
|
|
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
// 3) सर्व groups वरून invoice level totals
|
|
|
|
|
$invoice->load('chargeGroups');
|
|
|
|
|
|
|
|
|
|
$chargeGroupsBase = $invoice->chargeGroups->sum('total_charge'); // base
|
|
|
|
|
$chargeGroupsWithG = $invoice->chargeGroups->sum('total_with_gst'); // base + gst
|
|
|
|
|
$chargeGroupsGst = $chargeGroupsWithG - $chargeGroupsBase; // gst only
|
|
|
|
|
|
|
|
|
|
$invoiceGstPercent = $group->gst_percent ?? 0;
|
|
|
|
|
$invoiceTaxType = $group->tax_type ?? 'gst';
|
|
|
|
|
|
|
|
|
|
$cgstPercent = 0;
|
|
|
|
|
$sgstPercent = 0;
|
|
|
|
|
$igstPercent = 0;
|
|
|
|
|
|
|
|
|
|
if ($invoiceTaxType === 'gst') {
|
|
|
|
|
$cgstPercent = $invoiceGstPercent / 2;
|
|
|
|
|
$sgstPercent = $invoiceGstPercent / 2;
|
|
|
|
|
} elseif ($invoiceTaxType === 'igst') {
|
|
|
|
|
$igstPercent = $invoiceGstPercent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 🔴 इथे main fix:
|
|
|
|
|
// final_amount = base (total_charge sum)
|
|
|
|
|
// final_amount_with_gst = base + gst (total_with_gst sum)
|
|
|
|
|
// grand_total_with_charges = final_amount_with_gst (same)
|
2026-03-09 10:24:44 +05:30
|
|
|
$invoice->update([
|
2026-03-11 20:02:43 +05:30
|
|
|
'charge_groups_total' => $chargeGroupsBase,
|
|
|
|
|
'gst_amount' => $chargeGroupsGst,
|
|
|
|
|
'gst_percent' => $invoiceGstPercent,
|
|
|
|
|
'tax_type' => $invoiceTaxType,
|
|
|
|
|
'cgst_percent' => $cgstPercent,
|
|
|
|
|
'sgst_percent' => $sgstPercent,
|
|
|
|
|
'igst_percent' => $igstPercent,
|
|
|
|
|
|
|
|
|
|
'final_amount' => $chargeGroupsBase,
|
|
|
|
|
'final_amount_with_gst' => $chargeGroupsWithG,
|
|
|
|
|
'grand_total_with_charges' => $chargeGroupsWithG,
|
2026-03-09 10:24:44 +05:30
|
|
|
]);
|
2026-03-11 20:02:43 +05:30
|
|
|
|
|
|
|
|
Log::info('✅ Invoice updated from Charge Group (CG total + GST)', [
|
|
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'charge_groups_total' => $chargeGroupsBase,
|
|
|
|
|
'gst_amount' => $chargeGroupsGst,
|
|
|
|
|
'gst_percent' => $invoiceGstPercent,
|
|
|
|
|
'tax_type' => $invoiceTaxType,
|
|
|
|
|
'cgst_percent' => $cgstPercent,
|
|
|
|
|
'sgst_percent' => $sgstPercent,
|
|
|
|
|
'igst_percent' => $igstPercent,
|
|
|
|
|
'final_amount' => $invoice->final_amount,
|
|
|
|
|
'final_amount_with_gst' => $invoice->final_amount_with_gst,
|
|
|
|
|
'grand_total_with_charges'=> $invoice->grand_total_with_charges,
|
|
|
|
|
]);
|
|
|
|
|
|
2026-03-12 11:48:42 +05:30
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'message' => 'Charge group saved successfully.',
|
|
|
|
|
'group_id' => $group->id,
|
|
|
|
|
]);
|
2026-02-27 10:51:26 +05:30
|
|
|
}
|
2026-03-11 20:02:43 +05:30
|
|
|
}
|