Merge branch 'dev' of http://103.248.30.24:3000/kent-logistics/Kent-logistics-Laravel into dev
This commit is contained in:
@@ -444,8 +444,10 @@ class AdminInvoiceController extends Controller
|
||||
'grand_total_with_charges'=> $invoice->grand_total_with_charges,
|
||||
]);
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success', 'Charge group saved successfully.');
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'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;
|
||||
}
|
||||
|
||||
/* ── 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 {
|
||||
margin: 1.5rem 2.5rem 1.5rem;
|
||||
border: 1px solid var(--border);
|
||||
@@ -724,105 +683,6 @@
|
||||
</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) ═══════════════════════════ -->
|
||||
<div class="date-strip">
|
||||
<div class="date-row">
|
||||
@@ -925,12 +785,6 @@
|
||||
<i class="fas fa-list"></i> Invoice Items
|
||||
</div>
|
||||
|
||||
<!-- @if($isEmbedded)
|
||||
<form action="{{ route('admin.invoices.items.update', $invoice->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@endif -->
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="invoice-table items-table">
|
||||
<thead>
|
||||
@@ -1185,10 +1039,10 @@
|
||||
<th>Basis</th>
|
||||
<th class="text-end">Basis Value</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 With GST</th>
|
||||
<th class="text-end">GST %</th>
|
||||
<th class="text-center">Tax Type</th>
|
||||
<th class="text-end">Total With GST</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -1229,26 +1083,28 @@
|
||||
{{ number_format($group->rate, 2) }}
|
||||
</td>
|
||||
|
||||
{{-- Base total without GST --}}
|
||||
<td class="text-end price-blue">
|
||||
₹{{ number_format($groupBaseTotal, 2) }}
|
||||
</td>
|
||||
|
||||
{{-- GST % --}}
|
||||
<td class="text-end"
|
||||
style="font-family:'JetBrains Mono',monospace;font-size:0.82rem;">
|
||||
{{ number_format($groupGstPercent, 2) }}%
|
||||
</td>
|
||||
|
||||
{{-- Base total without GST --}}
|
||||
<td class="text-end price-blue">
|
||||
₹{{ number_format($groupBaseTotal, 2) }}
|
||||
{{-- Group tax type --}}
|
||||
<td class="text-center">
|
||||
{{ $group->tax_type ?? '-' }}
|
||||
</td>
|
||||
|
||||
|
||||
{{-- Group total with GST --}}
|
||||
<td class="text-end" style="font-weight:700;color:#16a34a;">
|
||||
₹{{ number_format($groupTotalWithGst, 2) }}
|
||||
</td>
|
||||
|
||||
{{-- Group tax type --}}
|
||||
<td class="text-center">
|
||||
{{ $group->tax_type ?? '-' }}
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
<button type="button"
|
||||
@@ -1381,51 +1237,6 @@
|
||||
</div>
|
||||
@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) ===== --}}
|
||||
<div class="summary-card-compact mt-3">
|
||||
<div class="summary-header-compact">
|
||||
@@ -1750,8 +1561,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// normal form submit, फक्त hidden item_ids तयार करतो
|
||||
if (cgForm) {
|
||||
cgForm.addEventListener('submit', function () {
|
||||
cgForm.addEventListener('submit', function (e) {
|
||||
|
||||
e.preventDefault(); // 🚀 STOP PAGE REFRESH
|
||||
|
||||
const selectedIds = [];
|
||||
|
||||
itemCheckboxes.forEach(cb => {
|
||||
if (cb.checked && !cb.disabled) {
|
||||
selectedIds.push(cb.value);
|
||||
@@ -1760,37 +1575,78 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
if (selectedIds.length === 0) {
|
||||
alert('Please select at least one item for this charge group.');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cgBasisSelect || !cgBasisSelect.value) {
|
||||
alert('Please select a basis for this charge group.');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cgTotalChargeInput ||
|
||||
!cgTotalChargeInput.value ||
|
||||
parseFloat(cgTotalChargeInput.value) <= 0
|
||||
) {
|
||||
parseFloat(cgTotalChargeInput.value) <= 0) {
|
||||
|
||||
alert('Please enter total charges for this group.');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// submit आधी latest GST total कॅलक्युलेट करणे सुरक्षित
|
||||
refreshChargeGroupGst();
|
||||
|
||||
const oldHidden = cgForm.querySelectorAll('input[name="itemids[]"]');
|
||||
oldHidden.forEach(el => el.remove());
|
||||
const formData = new FormData(cgForm);
|
||||
|
||||
selectedIds.forEach(id => {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'itemids[]';
|
||||
input.value = id;
|
||||
cgForm.appendChild(input);
|
||||
formData.append('itemids[]', id);
|
||||
});
|
||||
|
||||
fetch(cgForm.action, {
|
||||
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