changes of invoice and shipment
This commit is contained in:
@@ -26,13 +26,11 @@ class AdminInvoiceController extends Controller
|
|||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
public function popup($id)
|
public function popup($id)
|
||||||
{
|
{
|
||||||
$invoice = Invoice::with(['items', 'order'])->findOrFail($id);
|
$invoice = Invoice::with(['items', 'order', 'installments'])->findOrFail($id);
|
||||||
|
|
||||||
// Find actual Shipment record
|
|
||||||
$shipment = \App\Models\Shipment::whereHas('items', function ($q) use ($invoice) {
|
$shipment = \App\Models\Shipment::whereHas('items', function ($q) use ($invoice) {
|
||||||
$q->where('order_id', $invoice->order_id);
|
$q->where('order_id', $invoice->order_id);
|
||||||
})
|
})->first();
|
||||||
->first();
|
|
||||||
|
|
||||||
return view('admin.popup_invoice', compact('invoice', 'shipment'));
|
return view('admin.popup_invoice', compact('invoice', 'shipment'));
|
||||||
}
|
}
|
||||||
@@ -145,6 +143,22 @@ class AdminInvoiceController extends Controller
|
|||||||
$invoice->update(['pdf_path' => 'invoices/' . $fileName]);
|
$invoice->update(['pdf_path' => 'invoices/' . $fileName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// INSTALLMENTS (ADD/DELETE)
|
// INSTALLMENTS (ADD/DELETE)
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
|
|||||||
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000031.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000031.pdf
Normal file
Binary file not shown.
@@ -550,46 +550,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ============================
|
@php
|
||||||
SIMPLIFIED INVOICE SUMMARY
|
$totalAmount = $invoice->final_amount;
|
||||||
============================ -->
|
$gstAmount = $invoice->gst_amount;
|
||||||
|
$totalPayable = $invoice->final_amount_with_gst;
|
||||||
|
|
||||||
|
$paidAmount = $invoice->totalPaid();
|
||||||
|
$remaining = $invoice->remainingAmount();
|
||||||
|
@endphp
|
||||||
|
|
||||||
<div class="summary-container">
|
<div class="summary-container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<!-- Subtotal -->
|
|
||||||
<div class="amount-row mb-2">
|
<div class="amount-row">
|
||||||
<span>Subtotal Amount</span>
|
<span>Total Amount</span>
|
||||||
<span class="fw-bold">₹{{ number_format($invoice->final_amount,2) }}</span>
|
<span class="fw-bold">₹{{ number_format($totalAmount,2) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- GST -->
|
<div class="amount-row">
|
||||||
<div class="amount-row mb-2">
|
|
||||||
<span>GST Amount</span>
|
<span>GST Amount</span>
|
||||||
<span class="fw-bold text-danger">₹{{ number_format($invoice->gst_amount, 2) }}</span>
|
<span class="fw-bold text-danger">
|
||||||
|
+ ₹{{ number_format($gstAmount,2) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="amount-row border-top pt-2">
|
||||||
|
<span class="fw-bold">Total Payable</span>
|
||||||
|
<span class="fw-bold text-success">
|
||||||
|
₹{{ number_format($totalPayable,2) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="amount-row">
|
||||||
|
<span>Paid Amount</span>
|
||||||
|
<span class="fw-bold text-primary">
|
||||||
|
− ₹{{ number_format($paidAmount,2) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="amount-row border-top pt-2">
|
||||||
|
<span class="fw-bold text-danger">Remaining Amount</span>
|
||||||
|
<span class="fw-bold text-danger fs-5">
|
||||||
|
₹{{ number_format($remaining,2) }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Total Payable -->
|
|
||||||
<div class="amount-row mb-2 pt-2 border-top">
|
|
||||||
<span class="fw-bold">Total Payable Amount</span>
|
|
||||||
<span class="fw-bold text-success fs-5">₹{{ number_format($invoice->final_amount_with_gst,2) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- ============================
|
<!-- ============================
|
||||||
FOOTER — DOWNLOAD & SHARE
|
FOOTER — DOWNLOAD & SHARE
|
||||||
============================ -->
|
============================ -->
|
||||||
<div class="mt-4 pt-3 border-top text-center">
|
<div class="mt-4 pt-3 border-top text-center">
|
||||||
@if($invoice->pdf_path)
|
|
||||||
<a href="{{ asset($invoice->pdf_path) }}" class="btn btn-primary me-2" download>
|
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
|
||||||
|
class="btn btn-primary me-2">
|
||||||
<i class="fas fa-download me-1"></i> Download PDF
|
<i class="fas fa-download me-1"></i> Download PDF
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<button class="btn btn-success" onclick="shareInvoice()">
|
<button class="btn btn-success" onclick="shareInvoice()">
|
||||||
<i class="fas fa-share me-1"></i> Share
|
<i class="fas fa-share me-1"></i> Share
|
||||||
</button>
|
</button>
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -604,7 +629,7 @@
|
|||||||
const shareData = {
|
const shareData = {
|
||||||
title: "Invoice {{ $invoice->invoice_number }}",
|
title: "Invoice {{ $invoice->invoice_number }}",
|
||||||
text: "Sharing invoice {{ $invoice->invoice_number }}",
|
text: "Sharing invoice {{ $invoice->invoice_number }}",
|
||||||
url: "{{ asset($invoice->pdf_path) }}"
|
url: "{{ route('admin.invoices.download', $invoice->id) }}"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
@@ -615,5 +640,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -741,6 +741,13 @@
|
|||||||
margin: 1vh auto !important;
|
margin: 1vh auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* UPDATED: Shipment Order Details Modal - ALSO EDGE-TO-EDGE */
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
margin: 1vh auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.shipment-details-header {
|
.shipment-details-header {
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
color: white;
|
color: white;
|
||||||
@@ -1135,6 +1142,12 @@
|
|||||||
margin: 2vh auto !important;
|
margin: 2vh auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal {
|
||||||
|
max-width: 96vw !important;
|
||||||
|
width: 96vw !important;
|
||||||
|
margin: 2vh auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.shipment-totals-row {
|
.shipment-totals-row {
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
@@ -1148,6 +1161,12 @@
|
|||||||
margin: 2.5vh auto !important;
|
margin: 2.5vh auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
margin: 2.5vh auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.shipment-details-body {
|
.shipment-details-body {
|
||||||
padding: 20px 25px;
|
padding: 20px 25px;
|
||||||
}
|
}
|
||||||
@@ -1176,6 +1195,14 @@
|
|||||||
max-height: 100vh !important;
|
max-height: 100vh !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal {
|
||||||
|
max-width: 100vw !important;
|
||||||
|
width: 100vw !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
height: 100vh !important;
|
||||||
|
max-height: 100vh !important;
|
||||||
|
}
|
||||||
|
|
||||||
.shipment-details-body {
|
.shipment-details-body {
|
||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
}
|
}
|
||||||
@@ -1210,6 +1237,15 @@
|
|||||||
.shipment-total-value {
|
.shipment-total-value {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Order details modal specific responsive styles */
|
||||||
|
.order-details-content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-details-table {
|
||||||
|
min-width: 1000px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 576px) {
|
@media (max-width: 576px) {
|
||||||
@@ -1224,10 +1260,42 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal .modal-content {
|
||||||
|
border-radius: 0;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.shipment-details-header {
|
.shipment-details-header {
|
||||||
padding: 20px 25px 15px;
|
padding: 20px 25px 15px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.order-details-header {
|
||||||
|
padding: 20px 15px 10px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-details-body {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.modal-xl.edge-to-edge,
|
||||||
|
.modal-xl.edge-to-edge.order-details-modal {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-details-body,
|
||||||
|
.order-details-body {
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -1849,7 +1917,11 @@ function openShipmentDetails(id) {
|
|||||||
html += `
|
html += `
|
||||||
<tr>
|
<tr>
|
||||||
<td class="fw-bold">
|
<td class="fw-bold">
|
||||||
|
<a href="javascript:void(0)"
|
||||||
|
class="text-primary fw-bold"
|
||||||
|
onclick="openShipmentOrderDetails(${order.id})">
|
||||||
${order.order_id}
|
${order.order_id}
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>${order.origin || 'N/A'}</td>
|
<td>${order.origin || 'N/A'}</td>
|
||||||
<td>${order.destination || 'N/A'}</td>
|
<td>${order.destination || 'N/A'}</td>
|
||||||
@@ -1962,6 +2034,46 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function openShipmentOrderDetails(orderId) {
|
||||||
|
const modal = new bootstrap.Modal(
|
||||||
|
document.getElementById('shipmentOrderDetailsModal')
|
||||||
|
);
|
||||||
|
|
||||||
|
const body = document.getElementById('shipmentOrderDetailsBody');
|
||||||
|
body.innerHTML = "<p class='text-center text-muted'>Loading...</p>";
|
||||||
|
|
||||||
|
modal.show();
|
||||||
|
|
||||||
|
fetch(`/admin/orders/view/${orderId}`)
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(html => {
|
||||||
|
body.innerHTML = html;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
body.innerHTML =
|
||||||
|
"<p class='text-danger text-center'>Failed to load order details.</p>";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- SHIPMENT ORDER DETAILS MODAL - UPDATED TO EDGE-TO-EDGE -->
|
||||||
|
<div class="modal fade" id="shipmentOrderDetailsModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-xl edge-to-edge order-details-modal modal-dialog-scrollable">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header shipment-details-header order-details-header">
|
||||||
|
<h5 class="modal-title fw-bold"><i class="bi bi-file-text me-2"></i>Order Details</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body shipment-details-body order-details-body" id="shipmentOrderDetailsBody">
|
||||||
|
<p class="text-center text-muted">Loading order details...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
@@ -219,6 +219,10 @@ Route::prefix('admin')
|
|||||||
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
|
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
|
||||||
->name('admin.invoice.installment.store');
|
->name('admin.invoice.installment.store');
|
||||||
|
|
||||||
|
Route::get(
|
||||||
|
'/admin/invoices/{id}/download',
|
||||||
|
[AdminInvoiceController::class, 'downloadInvoice']
|
||||||
|
)->name('admin.invoices.download');
|
||||||
|
|
||||||
|
|
||||||
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
||||||
|
|||||||
Reference in New Issue
Block a user