ajax update
This commit is contained in:
@@ -429,8 +429,10 @@ class AdminInvoiceController extends Controller
|
|||||||
'grand_total_with_charges'=> $invoice->grand_total_with_charges,
|
'grand_total_with_charges'=> $invoice->grand_total_with_charges,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()
|
return response()->json([
|
||||||
->back()
|
'success' => true,
|
||||||
->with('success', 'Charge group saved successfully.');
|
'message' => 'Charge group saved successfully.',
|
||||||
|
'group_id' => $group->id,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddChargeColumnsToInvoicesTable extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('invoices', function (Blueprint $table) {
|
||||||
|
$table->decimal('charge_groups_total', 15, 2)->nullable()->after('final_amount_with_gst');
|
||||||
|
$table->decimal('grand_total_with_charges', 15, 2)->nullable()->after('charge_groups_total');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('invoices', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['charge_groups_total', 'grand_total_with_charges']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
public/invoices/invoice-INV-2026-000007.pdf
Normal file
BIN
public/invoices/invoice-INV-2026-000007.pdf
Normal file
Binary file not shown.
@@ -476,47 +476,6 @@
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── SUMMARY ── */
|
|
||||||
/* .summary-wrap {
|
|
||||||
padding: 0 2.5rem 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-card {
|
|
||||||
background: var(--surface);
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: var(--radius);
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: var(--shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-header-row {
|
|
||||||
background: var(--primary);
|
|
||||||
color: white;
|
|
||||||
padding: 0.85rem 1.25rem;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 0.88rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-body { padding: 1.25rem; }
|
|
||||||
|
|
||||||
.summary-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.6rem 0;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
font-size: 0.88rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-row:last-child { border-bottom: none; padding-top: 0.85rem; }
|
|
||||||
.summary-row .label { color: var(--text-secondary); font-weight: 500; }
|
|
||||||
.summary-row .value { font-weight: 700; color: var(--primary); }
|
|
||||||
.summary-row.total .label { font-size: 1rem; font-weight: 700; color: var(--primary); }
|
|
||||||
.summary-row.total .value { font-size: 1.15rem; color: #10b981; }
|
|
||||||
.summary-row .value.red { color: #ef4444; } */
|
|
||||||
.summary-card-compact {
|
.summary-card-compact {
|
||||||
margin: 1.5rem 2.5rem 1.5rem;
|
margin: 1.5rem 2.5rem 1.5rem;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
@@ -724,105 +683,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ═══════════════════════════ ID BOXES ═══════════════════════════ -->
|
|
||||||
<!-- <div class="id-grid">
|
|
||||||
|
|
||||||
<div class="id-box">
|
|
||||||
<div class="id-icon-wrap id-icon-blue">
|
|
||||||
<i class="fas fa-receipt"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="id-label">Invoice ID</div>
|
|
||||||
<div class="id-value">{{ $invoice->invoice_number }}</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- Container ID -->
|
|
||||||
<!-- <div class="id-box">
|
|
||||||
<div class="id-icon-wrap id-icon-green">
|
|
||||||
<i class="fas fa-box"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="id-label">Container ID</div>
|
|
||||||
<div class="id-value">
|
|
||||||
@if($invoice->container && $invoice->container->container_number)
|
|
||||||
{{ $invoice->container->container_number }}
|
|
||||||
@elseif($invoice->container_id)
|
|
||||||
{{ $invoice->container_id }}
|
|
||||||
@else
|
|
||||||
@include('admin.popup_invoice', ['invoice' => $invoice, 'shipment' => $shipment])
|
|
||||||
N/A
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- ═══════════════════════════ DATES ═══════════════════════════ -->
|
|
||||||
<!-- ═══════════════════════════ ID + DATES (ONE ROW) ═══════════════════════════ -->
|
|
||||||
<!-- <div class="date-strip">
|
|
||||||
<div class="date-row">
|
|
||||||
|
|
||||||
{{-- Container ID --}}
|
|
||||||
<div class="date-card" style="flex: 1.2;">
|
|
||||||
<div class="date-icon-wrap" style="background:#ecfeff;color:#0e7490;">
|
|
||||||
<i class="fas fa-box"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="date-label">Container ID</div>
|
|
||||||
<div class="date-value">
|
|
||||||
@if($invoice->container && $invoice->container->container_number)
|
|
||||||
{{ $invoice->container->container_number }}
|
|
||||||
@elseif($invoice->container_id)
|
|
||||||
{{ $invoice->container_id }}
|
|
||||||
@else
|
|
||||||
N/A
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- छोटा arrow --}}
|
|
||||||
<div class="date-arrow">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Invoice Date --}}
|
|
||||||
<div class="date-card">
|
|
||||||
<div class="date-icon-wrap">
|
|
||||||
<i class="fas fa-calendar-alt"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="date-label">Invoice Date</div>
|
|
||||||
<div class="date-value">
|
|
||||||
{{ \Carbon\Carbon::parse($invoice->invoice_date)->format('M d, Y') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- दुसरा arrow --}}
|
|
||||||
<div class="date-arrow">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Due Date --}}
|
|
||||||
<div class="date-card">
|
|
||||||
<div class="date-icon-wrap" style="background:#fff7ed;color:#f59e0b;">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="date-label">Due Date</div>
|
|
||||||
<div class="date-value {{ $invoice->status == 'overdue' ? 'overdue' : '' }}">
|
|
||||||
{{ \Carbon\Carbon::parse($invoice->due_date)->format('M d, Y') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ═══════════════════════════ CONTAINER + INVOICE DATE + DUE DATE (ONE ROW) ═══════════════════════════ -->
|
<!-- ═══════════════════════════ CONTAINER + INVOICE DATE + DUE DATE (ONE ROW) ═══════════════════════════ -->
|
||||||
<div class="date-strip">
|
<div class="date-strip">
|
||||||
<div class="date-row">
|
<div class="date-row">
|
||||||
@@ -920,12 +780,6 @@
|
|||||||
<i class="fas fa-list"></i> Invoice Items
|
<i class="fas fa-list"></i> Invoice Items
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- @if($isEmbedded)
|
|
||||||
<form action="{{ route('admin.invoices.items.update', $invoice->id) }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('PUT')
|
|
||||||
@endif -->
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="invoice-table items-table">
|
<table class="invoice-table items-table">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -1180,10 +1034,10 @@
|
|||||||
<th>Basis</th>
|
<th>Basis</th>
|
||||||
<th class="text-end">Basis Value</th>
|
<th class="text-end">Basis Value</th>
|
||||||
<th class="text-end">Rate</th>
|
<th class="text-end">Rate</th>
|
||||||
<th class="text-end">GST %</th>
|
|
||||||
<th class="text-end">Total Charge</th>
|
<th class="text-end">Total Charge</th>
|
||||||
<th class="text-end">Total With GST</th>
|
<th class="text-end">GST %</th>
|
||||||
<th class="text-center">Tax Type</th>
|
<th class="text-center">Tax Type</th>
|
||||||
|
<th class="text-end">Total With GST</th>
|
||||||
<th class="text-center">Action</th>
|
<th class="text-center">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -1224,27 +1078,29 @@
|
|||||||
{{ number_format($group->rate, 2) }}
|
{{ number_format($group->rate, 2) }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
{{-- Base total without GST --}}
|
||||||
|
<td class="text-end price-blue">
|
||||||
|
₹{{ number_format($groupBaseTotal, 2) }}
|
||||||
|
</td>
|
||||||
|
|
||||||
{{-- GST % --}}
|
{{-- GST % --}}
|
||||||
<td class="text-end"
|
<td class="text-end"
|
||||||
style="font-family:'JetBrains Mono',monospace;font-size:0.82rem;">
|
style="font-family:'JetBrains Mono',monospace;font-size:0.82rem;">
|
||||||
{{ number_format($groupGstPercent, 2) }}%
|
{{ number_format($groupGstPercent, 2) }}%
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{-- Base total without GST --}}
|
{{-- Group tax type --}}
|
||||||
<td class="text-end price-blue">
|
<td class="text-center">
|
||||||
₹{{ number_format($groupBaseTotal, 2) }}
|
{{ $group->tax_type ?? '-' }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
{{-- Group total with GST --}}
|
{{-- Group total with GST --}}
|
||||||
<td class="text-end" style="font-weight:700;color:#16a34a;">
|
<td class="text-end" style="font-weight:700;color:#16a34a;">
|
||||||
₹{{ number_format($groupTotalWithGst, 2) }}
|
₹{{ number_format($groupTotalWithGst, 2) }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{-- Group tax type --}}
|
|
||||||
<td class="text-center">
|
|
||||||
{{ $group->tax_type ?? '-' }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="cg-toggle-btn cg-toggle-items"
|
class="cg-toggle-btn cg-toggle-items"
|
||||||
@@ -1376,51 +1232,6 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
<!-- ═══════════════════════════ SUMMARY ═══════════════════════════ -->
|
|
||||||
<!-- <div class="summary-wrap">
|
|
||||||
<div class="row justify-content-end">
|
|
||||||
<div class="col-md-5">
|
|
||||||
<div class="summary-card">
|
|
||||||
<div class="summary-header-row">
|
|
||||||
<i class="fas fa-calculator"></i> Final Summary
|
|
||||||
</div>
|
|
||||||
<div class="summary-body">
|
|
||||||
<div class="summary-row">
|
|
||||||
<span class="label">Amount</span>
|
|
||||||
<span class="value">₹{{ number_format($invoice->final_amount, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if($invoice->tax_type === 'gst')
|
|
||||||
<div class="summary-row">
|
|
||||||
<span class="label">CGST ({{ $invoice->cgst_percent ?? ($invoice->gst_percent / 2) }}%)</span>
|
|
||||||
<span class="value red">₹{{ number_format($invoice->gst_amount / 2, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="summary-row">
|
|
||||||
<span class="label">SGST ({{ $invoice->sgst_percent ?? ($invoice->gst_percent / 2) }}%)</span>
|
|
||||||
<span class="value red">₹{{ number_format($invoice->gst_amount / 2, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
@elseif($invoice->tax_type === 'igst')
|
|
||||||
<div class="summary-row">
|
|
||||||
<span class="label">IGST ({{ $invoice->igst_percent ?? $invoice->gst_percent }}%)</span>
|
|
||||||
<span class="value red">₹{{ number_format($invoice->gst_amount, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="summary-row">
|
|
||||||
<span class="label">GST ({{ $invoice->gst_percent }}%)</span>
|
|
||||||
<span class="value red">₹{{ number_format($invoice->gst_amount, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="summary-row total">
|
|
||||||
<span class="label">Total Payable</span>
|
|
||||||
<span class="value">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
{{-- ===== FINAL SUMMARY (POPUP) ===== --}}
|
{{-- ===== FINAL SUMMARY (POPUP) ===== --}}
|
||||||
<div class="summary-card-compact mt-3">
|
<div class="summary-card-compact mt-3">
|
||||||
<div class="summary-header-compact">
|
<div class="summary-header-compact">
|
||||||
@@ -1745,8 +1556,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
// normal form submit, फक्त hidden item_ids तयार करतो
|
// normal form submit, फक्त hidden item_ids तयार करतो
|
||||||
if (cgForm) {
|
if (cgForm) {
|
||||||
cgForm.addEventListener('submit', function () {
|
cgForm.addEventListener('submit', function (e) {
|
||||||
|
|
||||||
|
e.preventDefault(); // 🚀 STOP PAGE REFRESH
|
||||||
|
|
||||||
const selectedIds = [];
|
const selectedIds = [];
|
||||||
|
|
||||||
itemCheckboxes.forEach(cb => {
|
itemCheckboxes.forEach(cb => {
|
||||||
if (cb.checked && !cb.disabled) {
|
if (cb.checked && !cb.disabled) {
|
||||||
selectedIds.push(cb.value);
|
selectedIds.push(cb.value);
|
||||||
@@ -1755,37 +1570,78 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
if (selectedIds.length === 0) {
|
if (selectedIds.length === 0) {
|
||||||
alert('Please select at least one item for this charge group.');
|
alert('Please select at least one item for this charge group.');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cgBasisSelect || !cgBasisSelect.value) {
|
if (!cgBasisSelect || !cgBasisSelect.value) {
|
||||||
alert('Please select a basis for this charge group.');
|
alert('Please select a basis for this charge group.');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cgTotalChargeInput ||
|
if (!cgTotalChargeInput ||
|
||||||
!cgTotalChargeInput.value ||
|
!cgTotalChargeInput.value ||
|
||||||
parseFloat(cgTotalChargeInput.value) <= 0
|
parseFloat(cgTotalChargeInput.value) <= 0) {
|
||||||
) {
|
|
||||||
alert('Please enter total charges for this group.');
|
alert('Please enter total charges for this group.');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// submit आधी latest GST total कॅलक्युलेट करणे सुरक्षित
|
|
||||||
refreshChargeGroupGst();
|
refreshChargeGroupGst();
|
||||||
|
|
||||||
const oldHidden = cgForm.querySelectorAll('input[name="itemids[]"]');
|
const formData = new FormData(cgForm);
|
||||||
oldHidden.forEach(el => el.remove());
|
|
||||||
|
|
||||||
selectedIds.forEach(id => {
|
selectedIds.forEach(id => {
|
||||||
const input = document.createElement('input');
|
formData.append('itemids[]', id);
|
||||||
input.type = 'hidden';
|
});
|
||||||
input.name = 'itemids[]';
|
|
||||||
input.value = id;
|
fetch(cgForm.action, {
|
||||||
cgForm.appendChild(input);
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"X-CSRF-TOKEN": document
|
||||||
|
.querySelector('meta[name="csrf-token"]')
|
||||||
|
.getAttribute("content")
|
||||||
|
},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(async res => {
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
|
||||||
|
// Laravel validation errors
|
||||||
|
if (data.errors) {
|
||||||
|
|
||||||
|
let msg = "";
|
||||||
|
|
||||||
|
Object.values(data.errors).forEach(errArr => {
|
||||||
|
msg += errArr.join("\n") + "\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
throw new Error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(data.message || "Something went wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
|
||||||
|
alert("Charge group created successfully!");
|
||||||
|
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
|
||||||
|
alert("Check Group details again");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return true; // normal submit
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user