Gst Updates

This commit is contained in:
Utkarsh Khedkar
2026-03-11 20:02:43 +05:30
parent d5e9113820
commit ff4c006ca4
10 changed files with 664 additions and 519 deletions

View File

@@ -8,10 +8,8 @@ use App\Models\InvoiceItem;
use App\Models\InvoiceInstallment;
use App\Models\InvoiceChargeGroup;
use App\Models\InvoiceChargeGroupItem;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Mpdf\Mpdf;
class AdminInvoiceController extends Controller
@@ -21,9 +19,8 @@ class AdminInvoiceController extends Controller
// -------------------------------------------------------------
public function index(Request $request)
{
// Container relation सह invoices load करतो
$query = Invoice::with(['items', 'customer', 'container']);
if ($request->filled('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
@@ -31,26 +28,26 @@ class AdminInvoiceController extends Controller
->orWhere('customer_name', 'like', "%{$search}%");
});
}
if ($request->filled('status') && $request->status !== 'all') {
$query->where('status', $request->status);
}
if ($request->filled('start_date')) {
$query->whereDate('invoice_date', '>=', $request->start_date);
}
if ($request->filled('end_date')) {
$query->whereDate('invoice_date', '<=', $request->end_date);
}
$invoices = $query->latest()->get();
return view('admin.invoice', compact('invoices'));
}
}
// -------------------------------------------------------------
// POPUP VIEW + CUSTOMER DATA SYNC
// POPUP VIEW
// -------------------------------------------------------------
public function popup($id)
{
@@ -59,7 +56,7 @@ class AdminInvoiceController extends Controller
'chargeGroups.items',
])->findOrFail($id);
// demo update असेल तर ठेव/काढ
// demo update असेल तर
$invoice->update([
'customer_email' => 'test@demo.com',
'customer_address' => 'TEST ADDRESS',
@@ -68,7 +65,6 @@ class AdminInvoiceController extends Controller
$shipment = null;
// आधीच group मध्ये असलेले item ids
$groupedItemIds = $invoice->chargeGroups
->flatMap(fn($group) => $group->items->pluck('invoice_item_id'))
->unique()
@@ -88,6 +84,7 @@ class AdminInvoiceController extends Controller
'customer',
'container',
'chargeGroups.items',
'installments',
])->findOrFail($id);
$shipment = null;
@@ -104,7 +101,7 @@ class AdminInvoiceController extends Controller
}
// -------------------------------------------------------------
// UPDATE INVOICE (HEADER LEVEL)
// UPDATE INVOICE (HEADER ONLY)
// -------------------------------------------------------------
public function update(Request $request, $id)
{
@@ -118,65 +115,20 @@ class AdminInvoiceController extends Controller
$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',
]);
Log::info('✅ Validated Invoice Update Data', $data);
$finalAmount = (float) $data['final_amount'];
$taxPercent = (float) $data['tax_percent'];
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;
}
$gstAmount = ($finalAmount * $taxPercent) / 100;
$data['gst_amount'] = $gstAmount;
$data['final_amount_with_gst'] = $finalAmount + $gstAmount;
$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'],
]);
Log::info('✅ Validated Invoice Header Update Data', $data);
$invoice->update($data);
Log::info('✅ Invoice Updated Successfully', [
'invoice_id' => $invoice->id,
]);
$invoice->refresh();
Log::info('🔍 Invoice AFTER UPDATE (DB values)', [
'invoice_id' => $invoice->id,
'final_amount' => $invoice->final_amount,
'gst_percent' => $invoice->gst_percent,
'gst_amount' => $invoice->gst_amount,
'final_amount_with_gst' => $invoice->final_amount_with_gst,
'tax_type' => $invoice->tax_type,
'cgst_percent' => $invoice->cgst_percent,
'sgst_percent' => $invoice->sgst_percent,
'igst_percent' => $invoice->igst_percent,
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,
]);
$this->generateInvoicePDF($invoice);
@@ -187,7 +139,7 @@ class AdminInvoiceController extends Controller
}
// -------------------------------------------------------------
// UPDATE INVOICE ITEMS
// UPDATE INVOICE ITEMS (फक्त items save)
// -------------------------------------------------------------
public function updateItems(Request $request, Invoice $invoice)
{
@@ -202,9 +154,7 @@ class AdminInvoiceController extends Controller
'items.*.ttl_amount' => ['required', 'numeric', 'min:0'],
]);
$itemsInput = $data['items'];
foreach ($itemsInput as $itemId => $itemData) {
foreach ($data['items'] as $itemId => $itemData) {
$item = InvoiceItem::where('id', $itemId)
->where('invoice_id', $invoice->id)
->first();
@@ -222,47 +172,8 @@ class AdminInvoiceController extends Controller
$item->save();
}
$newBaseAmount = InvoiceItem::where('invoice_id', $invoice->id)
->sum('ttl_amount');
$taxType = $invoice->tax_type;
$cgstPercent = (float) ($invoice->cgst_percent ?? 0);
$sgstPercent = (float) ($invoice->sgst_percent ?? 0);
$igstPercent = (float) ($invoice->igst_percent ?? 0);
$gstPercent = 0;
if ($taxType === 'gst') {
$gstPercent = $cgstPercent + $sgstPercent;
} elseif ($taxType === 'igst') {
$gstPercent = $igstPercent;
}
$gstAmount = $newBaseAmount * $gstPercent / 100;
$finalWithGst = $newBaseAmount + $gstAmount;
$invoice->final_amount = $newBaseAmount;
$invoice->gst_amount = $gstAmount;
$invoice->final_amount_with_gst = $finalWithGst;
$invoice->gst_percent = $gstPercent;
$invoice->save();
// ⭐ Total Charges (groups समावेत) पुन्हा कॅलक्युलेट
$chargeGroupsTotal = $invoice->chargeGroups()->sum('total_charge');
$invoice->charge_groups_total = $chargeGroupsTotal;
$invoice->grand_total_with_charges = $invoice->final_amount_with_gst + $chargeGroupsTotal;
$invoice->save();
Log::info('✅ Invoice items updated & totals recalculated', [
'invoice_id' => $invoice->id,
'final_amount' => $invoice->final_amount,
'gst_amount' => $invoice->gst_amount,
'final_amount_with_gst' => $invoice->final_amount_with_gst,
'tax_type' => $invoice->tax_type,
'cgst_percent' => $invoice->cgst_percent,
'sgst_percent' => $invoice->sgst_percent,
'igst_percent' => $invoice->igst_percent,
'charge_groups_total' => $invoice->charge_groups_total,
'grand_total_with_charges' => $invoice->grand_total_with_charges,
Log::info('✅ Invoice items updated (no totals recalculation)', [
'invoice_id' => $invoice->id,
]);
return back()->with('success', 'Invoice items updated successfully.');
@@ -318,12 +229,12 @@ class AdminInvoiceController extends Controller
'amount' => 'required|numeric|min:1',
]);
$invoice = Invoice::findOrFail($invoice_id);
$invoice = Invoice::findOrFail($invoice_id);
$grandTotal = $invoice->grand_total_with_charges ?? 0;
$paidTotal = $invoice->installments()->sum('amount');
// 👇 Total Charges (grand_total_with_charges) वरून remaining
$grandTotal = $invoice->grand_total_with_charges;
$remaining = $grandTotal - $paidTotal;
$remaining = $grandTotal - $paidTotal;
if ($request->amount > $remaining) {
return response()->json([
@@ -340,24 +251,25 @@ class AdminInvoiceController extends Controller
'amount' => $request->amount,
]);
$newPaid = $paidTotal + $request->amount;
$newPaid = $paidTotal + $request->amount;
$remaining = max(0, $grandTotal - $newPaid);
if ($newPaid >= $invoice->final_amount_with_gst) {
if ($newPaid >= $grandTotal && $grandTotal > 0) {
$invoice->update(['status' => 'paid']);
}
return response()->json([
'status' => 'success',
'message' => 'Installment added successfully.',
'installment' => $installment,
'totalPaid' => $newPaid,
'gstAmount' => $invoice->gst_amount,
'finalAmountWithGst' => $grandTotal, // इथे grand total पाठव
'baseAmount' => $invoice->final_amount,
'remaining' => max(0, $grandTotal - $newPaid),
'isCompleted' => $newPaid >= $grandTotal,
'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,
]);
}
// -------------------------------------------------------------
@@ -369,87 +281,156 @@ class AdminInvoiceController extends Controller
$invoice = $installment->invoice;
$installment->delete();
$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']);
}
$paidTotal = $invoice->installments()->sum('amount');
$grandTotal = $invoice->grand_total_with_charges;
$remaining = $grandTotal - $paidTotal;
return response()->json([
'status' => 'success',
'message' => 'Installment deleted.',
'totalPaid' => $paidTotal,
'gstAmount' => $invoice->gst_amount,
'finalAmountWithGst' => $grandTotal, // इथेही
'baseAmount' => $invoice->final_amount,
'remaining' => $remaining,
'isZero' => $paidTotal == 0,
'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,
]);
}
// -------------------------------------------------------------
// CHARGE GROUP SAVE (no AJAX branch)
// CHARGE GROUP SAVE
// -------------------------------------------------------------
public function storeChargeGroup(Request $request, $invoiceId)
{
$invoice = Invoice::with('items')->findOrFail($invoiceId);
$data = $request->validate([
'group_name' => 'required|string|max:255',
'basis_type' => 'required|in:ttl_qty,amount,ttl_cbm,ttl_kg',
'basis_value' => 'required|numeric',
'rate' => 'required|numeric|min:0.0001',
'auto_total' => 'required|numeric|min:0.01',
'item_ids' => 'required|array',
'item_ids.*' => 'integer|exists:invoice_items,id',
Log::info('🟡 storeChargeGroup HIT', [
'invoice_id' => $invoiceId,
'payload' => $request->all(),
]);
$invoice = Invoice::with('items', 'chargeGroups')->findOrFail($invoiceId);
$data = $request->validate([
'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',
]);
Log::info('✅ storeChargeGroup VALIDATED', $data);
// duplicate name check
$exists = InvoiceChargeGroup::where('invoice_id', $invoice->id)
->where('group_name', $data['group_name'])
->where('group_name', $data['groupname'])
->exists();
if ($exists) {
return back()
->withErrors(['group_name' => 'This group name is already used for this invoice.'])
->withErrors(['groupname' => 'This group name is already used for this invoice.'])
->withInput();
}
$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
$group = InvoiceChargeGroup::create([
'invoice_id' => $invoice->id,
'group_name' => $data['group_name'],
'basis_type' => $data['basis_type'],
'basis_value' => $data['basis_value'],
'rate' => $data['rate'],
'total_charge' => $data['auto_total'],
'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,
]);
foreach ($data['item_ids'] as $itemId) {
// 2) Items link
foreach ($data['itemids'] as $itemId) {
InvoiceChargeGroupItem::create([
'group_id' => $group->id,
'invoice_item_id' => $itemId,
]);
}
// ⭐ Charge groups नुसार Total Charges सेट करा
$chargeGroupsTotal = $invoice->chargeGroups()->sum('total_charge');
$grandTotal = $invoice->final_amount_with_gst + $chargeGroupsTotal;
// 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)
$invoice->update([
'charge_groups_total' => $chargeGroupsTotal,
'grand_total_with_charges' => $grandTotal,
'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,
]);
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,
]);
return redirect()
->back()
->with('success', 'Charge group saved successfully.');
}
public function download(Invoice $invoice)
{
if (!$invoice->pdf_path || !Storage::exists($invoice->pdf_path)) {
return back()->with('error', 'PDF not found.');
}
return Storage::download($invoice->pdf_path, $invoice->invoice_number . '.pdf');
}
}
}