changes of invoice and shipment

This commit is contained in:
divya abdar
2025-12-23 00:30:18 +05:30
parent 044bfe5563
commit 7fa03688aa
6 changed files with 196 additions and 40 deletions

View File

@@ -26,13 +26,11 @@ class AdminInvoiceController extends Controller
// -------------------------------------------------------------
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) {
$q->where('order_id', $invoice->order_id);
})
->first();
})->first();
return view('admin.popup_invoice', compact('invoice', 'shipment'));
}
@@ -145,6 +143,22 @@ class AdminInvoiceController extends Controller
$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)
// -------------------------------------------------------------

Binary file not shown.

View File

@@ -550,46 +550,71 @@
</div>
</div>
<!-- ============================
SIMPLIFIED INVOICE SUMMARY
============================ -->
<div class="summary-container">
@php
$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="row justify-content-center">
<div class="col-lg-8">
<!-- Subtotal -->
<div class="amount-row mb-2">
<span>Subtotal Amount</span>
<span class="fw-bold">{{ number_format($invoice->final_amount,2) }}</span>
<div class="amount-row">
<span>Total Amount</span>
<span class="fw-bold">{{ number_format($totalAmount,2) }}</span>
</div>
<!-- GST -->
<div class="amount-row mb-2">
<div class="amount-row">
<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>
<!-- 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>
<!-- ============================
FOOTER DOWNLOAD & SHARE
============================ -->
<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
</a>
<button class="btn btn-success" onclick="shareInvoice()">
<i class="fas fa-share me-1"></i> Share
</button>
@endif
</div>
</div>
</div>
@@ -604,7 +629,7 @@
const shareData = {
title: "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) {
@@ -614,6 +639,7 @@
alert("Link copied! Sharing not supported on this browser.");
}
}
</script>
</script>
</body>
</html>

View File

@@ -741,6 +741,13 @@
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 {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
@@ -1135,6 +1142,12 @@
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 {
grid-template-columns: repeat(4, 1fr);
gap: 15px;
@@ -1148,6 +1161,12 @@
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 {
padding: 20px 25px;
}
@@ -1176,6 +1195,14 @@
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 {
padding: 15px 20px;
}
@@ -1210,6 +1237,15 @@
.shipment-total-value {
font-size: 16px;
}
/* Order details modal specific responsive styles */
.order-details-content {
padding: 15px;
}
.order-details-table {
min-width: 1000px;
}
}
@media (max-width: 576px) {
@@ -1224,10 +1260,42 @@
overflow-y: auto;
}
.modal-xl.edge-to-edge.order-details-modal .modal-content {
border-radius: 0;
height: 100vh;
overflow-y: auto;
}
.shipment-details-header {
padding: 20px 25px 15px;
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>
@@ -1849,7 +1917,11 @@ function openShipmentDetails(id) {
html += `
<tr>
<td class="fw-bold">
<a href="javascript:void(0)"
class="text-primary fw-bold"
onclick="openShipmentOrderDetails(${order.id})">
${order.order_id}
</a>
</td>
<td>${order.origin || '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>
<!-- 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

View File

@@ -219,6 +219,10 @@ Route::prefix('admin')
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
->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'])