Merge branch 'dev' of http://103.248.30.24:3000/kent-logistics/Kent-logistics-Laravel into dev
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -274,6 +274,30 @@ body {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-info-compact {
|
||||
background: linear-gradient(135deg, #06b6d4 0%, #0ea5e9 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(6, 182, 212, 0.3);
|
||||
}
|
||||
|
||||
.btn-info-compact:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(6, 182, 212, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-warning-compact {
|
||||
background: var(--warning-gradient);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
|
||||
}
|
||||
|
||||
.btn-warning-compact:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(245, 158, 11, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
COMPACT SUMMARY CARDS
|
||||
-------------------------------------------------- */
|
||||
@@ -316,7 +340,7 @@ body {
|
||||
-------------------------------------------------- */
|
||||
.amount-breakdown-compact {
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow-soft);
|
||||
margin-bottom: 1.5rem;
|
||||
@@ -391,6 +415,15 @@ body {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
HEADER ACTION BUTTONS
|
||||
-------------------------------------------------- */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
RESPONSIVE DESIGN
|
||||
-------------------------------------------------- */
|
||||
@@ -422,6 +455,13 @@ body {
|
||||
.table-compact {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
@@ -454,10 +494,21 @@ body {
|
||||
|
||||
<!-- Invoice Preview Section -->
|
||||
<div class="glass-card">
|
||||
<div class="card-header-compact">
|
||||
<div class="card-header-compact d-flex justify-content-between align-items-center">
|
||||
<h4>
|
||||
<i class="fas fa-file-invoice me-2"></i>Invoice Overview
|
||||
</h4>
|
||||
<div class="header-actions">
|
||||
<!-- Share Invoice -->
|
||||
<button class="btn-info-compact btn-compact" id="shareInvoiceBtn">
|
||||
<i class="fas fa-share-alt me-2"></i>Share Invoice
|
||||
</button>
|
||||
<!-- Download Invoice -->
|
||||
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
|
||||
class="btn-warning-compact btn-compact" target="_blank">
|
||||
<i class="fas fa-download me-2"></i>Download Invoice
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body-compact invoice-preview-wrapper">
|
||||
@include('admin.popup_invoice', [
|
||||
@@ -468,6 +519,89 @@ body {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount Breakdown -->
|
||||
<div class="glass-card">
|
||||
<div class="card-header-compact">
|
||||
<h4>
|
||||
<i class="fas fa-calculator me-2"></i>Amount Breakdown
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body-compact">
|
||||
<div class="amount-breakdown-compact">
|
||||
@php
|
||||
$totalPaid = $invoice->installments->sum('amount');
|
||||
$remaining = $invoice->final_amount_with_gst - $totalPaid;
|
||||
|
||||
// Calculate GST/IGST percentage dynamically
|
||||
$taxPercentage = $invoice->tax_type === 'gst'
|
||||
? ($invoice->cgst_percent + $invoice->sgst_percent)
|
||||
: $invoice->igst_percent;
|
||||
@endphp
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">Total Amount (Before Tax):</span>
|
||||
<span class="breakdown-value">₹{{ number_format($invoice->final_amount, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">
|
||||
@if($invoice->tax_type === 'gst')
|
||||
GST ({{ number_format($taxPercentage, 2) }}%)
|
||||
@else
|
||||
IGST ({{ number_format($taxPercentage, 2) }}%)
|
||||
@endif:
|
||||
</span>
|
||||
<span class="breakdown-value text-warning">₹{{ number_format($invoice->gst_amount, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row" style="border-top: 2px solid #e2e8f0; padding-top: 0.75rem;">
|
||||
<span class="breakdown-label fw-bold">Total Invoice Amount (Including GST):</span>
|
||||
<span class="breakdown-value fw-bold text-dark">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label text-success">Total Paid:</span>
|
||||
<span class="breakdown-value fw-bold text-success" id="paidAmount">₹{{ number_format($totalPaid, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row" style="border-bottom: none;">
|
||||
<span class="breakdown-label text-danger">Remaining:</span>
|
||||
<span class="breakdown-value fw-bold text-danger" id="remainingAmount">₹{{ number_format($remaining, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<!-- NEW: Customer's Total Amount Due Across All Invoices -->
|
||||
<div class="breakdown-row" style="border-top: 2px solid #3b82f6; background: rgba(59, 130, 246, 0.05);">
|
||||
<span class="breakdown-label fw-bold text-primary">
|
||||
<i class="fas fa-users me-1"></i>Total Amount Due (Including Tax):
|
||||
<small class="d-block text-muted" style="font-size: 0.75rem; font-weight: normal;">
|
||||
</small>
|
||||
</span>
|
||||
<span class="breakdown-value fw-bold text-primary" style="font-size: 1.1rem;">
|
||||
₹{{ number_format($customerTotalDue, 2) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Installment Summary -->
|
||||
<div class="summary-grid-compact mt-3">
|
||||
<div class="summary-card-compact total">
|
||||
<div class="summary-value-compact text-success">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</div>
|
||||
<div class="summary-label-compact">Total Amount</div>
|
||||
</div>
|
||||
<div class="summary-card-compact paid">
|
||||
<div class="summary-value-compact text-primary">₹{{ number_format($totalPaid, 2) }}</div>
|
||||
<div class="summary-label-compact">Total Paid</div>
|
||||
</div>
|
||||
<div class="summary-card-compact remaining">
|
||||
<div class="summary-value-compact text-warning">₹{{ number_format($remaining, 2) }}</div>
|
||||
<div class="summary-label-compact">Remaining</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Invoice Form -->
|
||||
<div class="glass-card">
|
||||
<div class="card-header-compact">
|
||||
@@ -577,81 +711,6 @@ body {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$totalPaid = $invoice->installments->sum('amount');
|
||||
$remaining = $invoice->final_amount_with_gst - $totalPaid;
|
||||
@endphp
|
||||
|
||||
<!-- Amount Breakdown -->
|
||||
<div class="amount-breakdown-compact">
|
||||
<h6 class="fw-bold mb-3 text-dark">
|
||||
<i class="fas fa-calculator me-2"></i>Amount Breakdown
|
||||
</h6>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">Total Amount (Before Tax):</span>
|
||||
<span class="breakdown-value">₹{{ number_format($invoice->final_amount, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">Tax Type:</span>
|
||||
<span class="breakdown-value text-primary">
|
||||
@if($invoice->tax_type === 'gst')
|
||||
GST (CGST + SGST)
|
||||
@else
|
||||
IGST
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">Tax Percentage:</span>
|
||||
<span class="breakdown-value text-primary">
|
||||
@if($invoice->tax_type === 'gst')
|
||||
{{ $invoice->cgst_percent + $invoice->sgst_percent }}%
|
||||
@else
|
||||
{{ $invoice->igst_percent }}%
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label">GST Amount:</span>
|
||||
<span class="breakdown-value text-warning">₹{{ number_format($invoice->gst_amount, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row" style="border-top: 2px solid #e2e8f0; padding-top: 0.75rem;">
|
||||
<span class="breakdown-label fw-bold">Total Invoice Amount (Including GST):</span>
|
||||
<span class="breakdown-value fw-bold text-dark">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row">
|
||||
<span class="breakdown-label text-success">Total Paid:</span>
|
||||
<span class="breakdown-value fw-bold text-success" id="paidAmount">₹{{ number_format($totalPaid, 2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="breakdown-row" style="border-bottom: none;">
|
||||
<span class="breakdown-label text-danger">Remaining:</span>
|
||||
<span class="breakdown-value fw-bold text-danger" id="remainingAmount">₹{{ number_format($remaining, 2) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Installment Summary -->
|
||||
<div class="summary-grid-compact">
|
||||
<div class="summary-card-compact total">
|
||||
<div class="summary-value-compact text-success">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</div>
|
||||
<div class="summary-label-compact">Total Amount</div>
|
||||
</div>
|
||||
<div class="summary-card-compact paid">
|
||||
<div class="summary-value-compact text-primary">₹{{ number_format($totalPaid, 2) }}</div>
|
||||
<div class="summary-label-compact">Total Paid</div>
|
||||
</div>
|
||||
<div class="summary-card-compact remaining">
|
||||
<div class="summary-value-compact text-warning">₹{{ number_format($remaining, 2) }}</div>
|
||||
<div class="summary-label-compact">Remaining</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Installment Management -->
|
||||
<div class="glass-card">
|
||||
<div class="card-header-compact d-flex justify-content-between align-items-center">
|
||||
@@ -736,6 +795,7 @@ body {
|
||||
<h6 class="fw-bold mb-2 text-dark">
|
||||
<i class="fas fa-history me-2"></i>Installment History
|
||||
</h6>
|
||||
@if($invoice->installments->count() > 0)
|
||||
<div class="table-responsive">
|
||||
<table class="table-compact">
|
||||
<thead>
|
||||
@@ -776,24 +836,87 @@ body {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<div id="noInstallmentsMsg" class="text-center text-muted fw-bold py-4">
|
||||
No installments found. Click "Add Installment" to create one.
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add this just above the table -->
|
||||
<div id="noInstallmentsMsg" class="d-none text-center text-muted fw-bold py-4">
|
||||
No installments found. Click "Add Installment" to create one.
|
||||
</div>
|
||||
<table ...>
|
||||
<tbody id="installmentTable">
|
||||
@foreach($invoice->installments as $i)
|
||||
...
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Share Invoice Functionality
|
||||
const shareInvoiceBtn = document.getElementById('shareInvoiceBtn');
|
||||
if (shareInvoiceBtn) {
|
||||
shareInvoiceBtn.addEventListener('click', function() {
|
||||
const shareUrl = window.location.href;
|
||||
const invoiceNo = "{{ $invoice->invoice_no }}";
|
||||
const message = `Invoice #${invoiceNo} - Total: ₹{{ number_format($invoice->final_amount_with_gst, 2) }}\nView: ${shareUrl}`;
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: `Invoice #${invoiceNo}`,
|
||||
text: `Invoice #${invoiceNo} - Total: ₹{{ number_format($invoice->final_amount_with_gst, 2) }}`,
|
||||
url: shareUrl
|
||||
}).catch(console.error);
|
||||
} else if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(message)
|
||||
.then(() => {
|
||||
alert('Invoice link copied to clipboard!');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to copy: ', err);
|
||||
// Fallback to prompt
|
||||
prompt('Copy this link to share:', shareUrl);
|
||||
});
|
||||
} else {
|
||||
prompt('Copy this link to share:', shareUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Print Invoice Function
|
||||
window.printInvoice = function() {
|
||||
const printWindow = window.open('', '_blank');
|
||||
const invoiceContent = document.querySelector('.invoice-preview-wrapper').innerHTML;
|
||||
const printContent = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Invoice {{ $invoice->invoice_no }}</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
.invoice-container { max-width: 800px; margin: 0 auto; }
|
||||
.text-end { text-align: right; }
|
||||
.fw-bold { font-weight: bold; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th, td { padding: 8px; border: 1px solid #ddd; }
|
||||
th { background-color: #f8f9fa; }
|
||||
.total-row { background-color: #f8f9fa; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="invoice-container">
|
||||
${invoiceContent}
|
||||
</div>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.print();
|
||||
setTimeout(function() {
|
||||
window.close();
|
||||
}, 500);
|
||||
};
|
||||
<\/script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
printWindow.document.write(printContent);
|
||||
printWindow.document.close();
|
||||
};
|
||||
|
||||
// Toggle Installment Form
|
||||
const toggleBtn = document.getElementById("toggleInstallmentForm");
|
||||
const formBox = document.getElementById("installmentForm");
|
||||
@@ -814,82 +937,111 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
|
||||
submitForm.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
if (submitForm) {
|
||||
submitForm.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
fetch("{{ route('admin.invoice.installment.store', $invoice->id) }}", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": submitForm.querySelector("input[name=_token]").value,
|
||||
"Accept": "application/json"
|
||||
},
|
||||
body: new FormData(submitForm)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
||||
submitBtn.disabled = false;
|
||||
fetch("{{ route('admin.invoice.installment.store', $invoice->id) }}", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": submitForm.querySelector("input[name=_token]").value,
|
||||
"Accept": "application/json"
|
||||
},
|
||||
body: new FormData(submitForm)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
||||
submitBtn.disabled = false;
|
||||
|
||||
if (data.status === "error") {
|
||||
alert(data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const table = document.querySelector("#installmentTable");
|
||||
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
|
||||
|
||||
if (noInstallmentsMsg) {
|
||||
noInstallmentsMsg.classList.add("d-none");
|
||||
}
|
||||
|
||||
if (!table) {
|
||||
// Create table if it doesn't exist
|
||||
const tableHTML = `
|
||||
<div class="table-responsive">
|
||||
<table class="table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Date</th>
|
||||
<th>Payment Method</th>
|
||||
<th>Reference No</th>
|
||||
<th>Amount</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="installmentTable">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
const parent = submitForm.closest('.card-body-compact');
|
||||
parent.insertAdjacentHTML('beforeend', tableHTML);
|
||||
}
|
||||
|
||||
const newTable = document.querySelector("#installmentTable");
|
||||
const index = newTable.rows.length + 1;
|
||||
|
||||
newTable.insertAdjacentHTML("beforeend", `
|
||||
<tr data-id="${data.installment.id}">
|
||||
<td class="fw-bold text-muted">${index}</td>
|
||||
<td>${data.installment.installment_date}</td>
|
||||
<td>
|
||||
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
|
||||
${data.installment.payment_method.toUpperCase()}
|
||||
</span>
|
||||
</td>
|
||||
<td>${data.installment.reference_no || '-'}</td>
|
||||
<td class="fw-bold text-success">${formatINR(data.installment.amount)}</td>
|
||||
<td>
|
||||
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
|
||||
<i class="fas fa-trash me-1"></i>Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
|
||||
// Update all displayed values
|
||||
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
|
||||
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
|
||||
|
||||
// Update summary cards
|
||||
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
|
||||
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
|
||||
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
|
||||
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
|
||||
|
||||
submitForm.reset();
|
||||
|
||||
// If fully paid, disable/add display logic
|
||||
if (data.isCompleted) {
|
||||
toggleBtn?.remove();
|
||||
formBox.classList.add("d-none");
|
||||
}
|
||||
|
||||
if (data.status === "error") {
|
||||
alert(data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const table = document.querySelector("#installmentTable");
|
||||
const index = table.rows.length + 1;
|
||||
|
||||
table.insertAdjacentHTML("beforeend", `
|
||||
<tr data-id="${data.installment.id}">
|
||||
<td class="fw-bold text-muted">${index}</td>
|
||||
<td>${data.installment.installment_date}</td>
|
||||
<td>
|
||||
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
|
||||
${data.installment.payment_method.toUpperCase()}
|
||||
</span>
|
||||
</td>
|
||||
<td>${data.installment.reference_no || '-'}</td>
|
||||
<td class="fw-bold text-success">${formatINR(data.installment.amount)}</td>
|
||||
<td>
|
||||
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
|
||||
<i class="fas fa-trash me-1"></i>Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
|
||||
// Update all displayed values using GST fields!
|
||||
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
|
||||
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
|
||||
if (document.getElementById("baseAmount")) document.getElementById("baseAmount").textContent = formatINR(data.baseAmount);
|
||||
if (document.getElementById("gstAmount")) document.getElementById("gstAmount").textContent = formatINR(data.gstAmount);
|
||||
if (document.getElementById("totalInvoiceWithGst")) document.getElementById("totalInvoiceWithGst").textContent = formatINR(data.finalAmountWithGst);
|
||||
if (document.getElementById("invoiceStatus")) document.getElementById("invoiceStatus").textContent = data.isCompleted ? "Paid" : "Pending";
|
||||
|
||||
// Update summary cards if used
|
||||
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
|
||||
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
|
||||
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
|
||||
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
|
||||
|
||||
submitForm.reset();
|
||||
|
||||
// If fully paid, disable/add display logic
|
||||
if (data.isCompleted) {
|
||||
toggleBtn?.remove();
|
||||
formBox.classList.add("d-none");
|
||||
}
|
||||
|
||||
alert(data.message);
|
||||
})
|
||||
.catch(() => {
|
||||
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
||||
submitBtn.disabled = false;
|
||||
alert("Something went wrong. Please try again.");
|
||||
})
|
||||
.catch(() => {
|
||||
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
||||
submitBtn.disabled = false;
|
||||
alert("Something went wrong. Please try again.");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Installment
|
||||
document.addEventListener("click", function (e) {
|
||||
@@ -911,23 +1063,43 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
.then(data => {
|
||||
if (data.status === "success") {
|
||||
row.style.opacity = "0";
|
||||
setTimeout(() => row.remove(), 300);
|
||||
setTimeout(() => {
|
||||
row.remove();
|
||||
|
||||
// Update row numbers
|
||||
const rows = document.querySelectorAll("#installmentTable tr");
|
||||
rows.forEach((row, index) => {
|
||||
row.querySelector("td:first-child").textContent = index + 1;
|
||||
});
|
||||
|
||||
// Show no installments message if empty
|
||||
if (rows.length === 0) {
|
||||
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
|
||||
if (noInstallmentsMsg) {
|
||||
noInstallmentsMsg.classList.remove("d-none");
|
||||
}
|
||||
}
|
||||
}, 300);
|
||||
|
||||
// Update all displayed values using GST fields!
|
||||
// Update all displayed values
|
||||
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
|
||||
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
|
||||
if (document.getElementById("baseAmount")) document.getElementById("baseAmount").textContent = formatINR(data.baseAmount);
|
||||
if (document.getElementById("gstAmount")) document.getElementById("gstAmount").textContent = formatINR(data.gstAmount);
|
||||
if (document.getElementById("totalInvoiceWithGst")) document.getElementById("totalInvoiceWithGst").textContent = formatINR(data.finalAmountWithGst);
|
||||
if (document.getElementById("invoiceStatus")) document.getElementById("invoiceStatus").textContent = data.remaining === 0 ? "Paid" : "Pending";
|
||||
|
||||
|
||||
// Update summary cards
|
||||
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
|
||||
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
|
||||
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
|
||||
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
|
||||
|
||||
|
||||
// Show add installment button if there's remaining amount
|
||||
if (data.remaining > 0 && !document.getElementById("toggleInstallmentForm")) {
|
||||
const header = document.querySelector(".glass-card .card-header-compact");
|
||||
header.innerHTML += `
|
||||
<button id="toggleInstallmentForm" class="btn-primary-compact btn-compact">
|
||||
<i class="fas fa-plus-circle me-2"></i>Add Installment
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
|
||||
alert(data.message);
|
||||
} else {
|
||||
@@ -940,6 +1112,4 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,177 +4,167 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ $invoice->invoice_number }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', 'Roboto', Arial, sans-serif;
|
||||
background: #F7FBFC;
|
||||
color: #1A222B;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.container {
|
||||
max-width: 850px;
|
||||
margin: 24px auto 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 13px;
|
||||
box-shadow: 0 2px 14px rgba(40,105,160,0.08);
|
||||
padding: 35px 32px 18px 32px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
border-bottom: 2px solid #E6EBF0;
|
||||
padding-bottom: 13px;
|
||||
}
|
||||
.logo-company {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.logo {
|
||||
height: 50px;
|
||||
margin-right: 13px;
|
||||
}
|
||||
.company-details {
|
||||
margin-top: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.company-title {
|
||||
font-size: 21px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.company-sub {
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.invoice-details {
|
||||
text-align: right;
|
||||
min-width: 220px;
|
||||
}
|
||||
.invoice-title {
|
||||
font-weight: bold;
|
||||
font-size: 23px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.paid-label {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.paid-tag {
|
||||
background: #23BF47;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
border-radius: 8px;
|
||||
padding: 4px 16px 4px 22px;
|
||||
font-size: 17px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.paid-tag:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 7px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.paid-date {
|
||||
font-size: 14px;
|
||||
color: #23BF47;
|
||||
margin-top: 2px;
|
||||
}
|
||||
body {
|
||||
font-family: 'Segoe UI', 'Roboto', Arial, sans-serif;
|
||||
background: #F7FBFC;
|
||||
color: #1A222B;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.bill-section {
|
||||
background: #F3F7FB;
|
||||
border-radius: 11px;
|
||||
padding: 20px 18px 13px 18px;
|
||||
margin: 28px 0 16px 0;
|
||||
box-shadow: 0 0px 0px #0000;
|
||||
}
|
||||
.bill-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #23355D;
|
||||
margin-bottom: 4px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
.bill-details {
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.container {
|
||||
max-width: 850px;
|
||||
margin: 24px auto 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 13px;
|
||||
box-shadow: 0 2px 14px rgba(40,105,160,0.08);
|
||||
padding: 35px 32px 18px 32px;
|
||||
}
|
||||
|
||||
/* ================= HEADER FIX ================= */
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
overflow: hidden; /* clears floats */
|
||||
border-bottom: 2px solid #E6EBF0;
|
||||
padding-bottom: 13px;
|
||||
}
|
||||
|
||||
/* LEFT SIDE */
|
||||
.logo-company {
|
||||
float: left;
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
/* RIGHT SIDE */
|
||||
.invoice-details {
|
||||
float: right;
|
||||
width: 35%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
.logo {
|
||||
height: 50px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
/* Company text */
|
||||
.company-details {
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.company-title {
|
||||
font-size: 21px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Invoice */
|
||||
.invoice-title {
|
||||
font-weight: bold;
|
||||
font-size: 23px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
/* Paid / Status */
|
||||
.paid-tag {
|
||||
background: #23BF47;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
border-radius: 8px;
|
||||
padding: 4px 16px 4px 22px;
|
||||
font-size: 17px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.paid-tag:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 7px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.paid-date {
|
||||
font-size: 14px;
|
||||
color: #23BF47;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
/* ================= REST ================= */
|
||||
|
||||
.bill-section {
|
||||
background: #F3F7FB;
|
||||
border-radius: 11px;
|
||||
padding: 20px 18px 13px 18px;
|
||||
margin: 28px 0 16px 0;
|
||||
}
|
||||
|
||||
.bill-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #23355D;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.bill-details {
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 9px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #F6F7F9;
|
||||
padding: 10px 0;
|
||||
font-size: 15px;
|
||||
color: #6781A6;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 7px 0;
|
||||
font-size: 15px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
tbody tr:not(:last-child) td {
|
||||
border-bottom: 1px solid #E6EBF0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
border-top: 1.2px solid #E6EBF0;
|
||||
margin-top: 25px;
|
||||
padding-top: 12px;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
text-align: center;
|
||||
}
|
||||
.gst-row td {
|
||||
color: #23BF47;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.total-row td {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
border-top: 2px solid #E6EBF0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 9px;
|
||||
margin-bottom: 13px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
th {
|
||||
background: #F6F7F9;
|
||||
padding: 10px 0;
|
||||
font-size: 15px;
|
||||
color: #6781A6;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
text-align: left;
|
||||
}
|
||||
td {
|
||||
padding: 7px 0;
|
||||
color: #222;
|
||||
font-size: 15px;
|
||||
border: none;
|
||||
text-align: left;
|
||||
}
|
||||
tbody tr:not(:last-child) td {
|
||||
border-bottom: 1px solid #E6EBF0;
|
||||
}
|
||||
tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
.totals-row td {
|
||||
font-weight: bold;
|
||||
color: #23355D;
|
||||
}
|
||||
.gst-row td {
|
||||
font-weight: 500;
|
||||
color: #23BF47;
|
||||
}
|
||||
.total-row td {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #222;
|
||||
}
|
||||
.payment-info {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 9px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.ref-number {
|
||||
font-size: 14px;
|
||||
color: #6781A6;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.footer {
|
||||
border-top: 1.2px solid #E6EBF0;
|
||||
margin-top: 25px;
|
||||
padding-top: 12px;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
text-align: center;
|
||||
}
|
||||
.footer strong {
|
||||
color: #222;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -241,18 +231,47 @@
|
||||
<td>{{ number_format($item->ttl_amount, 0) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
{{-- SUBTOTAL --}}
|
||||
<tr class="totals-row">
|
||||
<td colspan="3" style="text-align:right;">Subtotal:</td>
|
||||
<td>{{ number_format($invoice->subtotal, 0) }}</td>
|
||||
</tr>
|
||||
<tr class="gst-row">
|
||||
<td colspan="3" style="text-align:right;">GST ({{ $invoice->gst_percent }}%):</td>
|
||||
<td>{{ number_format($invoice->gst_amount, 0) }}</td>
|
||||
<td colspan="3" style="text-align:right;">total</td>
|
||||
<td style="text-align:right;">
|
||||
₹ {{ number_format($invoice->final_amount, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{-- TAX --}}
|
||||
@if($invoice->tax_type === 'gst' && $invoice->gst_amount > 0)
|
||||
|
||||
<tr class="gst-row">
|
||||
<td colspan="3" style="text-align:right;">
|
||||
GST ({{ $invoice->gst_percent }}%)
|
||||
</td>
|
||||
<td style="text-align:right;">
|
||||
₹ {{ number_format($invoice->gst_amount, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@elseif($invoice->tax_type === 'igst' && $invoice->gst_amount > 0)
|
||||
|
||||
<tr class="gst-row">
|
||||
<td colspan="3" style="text-align:right;">
|
||||
IGST ({{ $invoice->gst_percent }}%)
|
||||
</td>
|
||||
<td style="text-align:right;">
|
||||
₹ {{ number_format($invoice->gst_amount, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@endif
|
||||
|
||||
{{-- TOTAL --}}
|
||||
<tr class="total-row">
|
||||
<td colspan="3" style="text-align:right;">Total:</td>
|
||||
<td>{{ number_format($invoice->final_amount_with_gst, 0) }}</td>
|
||||
<td colspan="3" style="text-align:right;">Total Amount</td>
|
||||
<td style="text-align:right;">
|
||||
₹ {{ number_format($invoice->final_amount_with_gst, 2) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Payment Info & Reference -->
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
/* ALL YOUR EXISTING CSS STAYS HERE - EXCEPT GST TOTALS SECTION REMOVED */
|
||||
:root {
|
||||
--primary: #2c3e50;
|
||||
--secondary: #3498db;
|
||||
@@ -284,6 +285,8 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* GST Totals Section Styles - COMPLETELY REMOVED */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.invoice-container {
|
||||
margin: 1rem;
|
||||
@@ -346,6 +349,17 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.invoice-container {
|
||||
box-shadow: none;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -356,6 +370,8 @@
|
||||
============================ -->
|
||||
@php
|
||||
$showActions = $showActions ?? true;
|
||||
|
||||
// REMOVED GST CALCULATION LOGIC
|
||||
@endphp
|
||||
|
||||
<div class="compact-header">
|
||||
@@ -440,7 +456,6 @@
|
||||
<div class="id-value">
|
||||
@php
|
||||
$shipmentId = 'N/A';
|
||||
// Try multiple ways to get shipment ID
|
||||
if($invoice->shipment && $invoice->shipment->shipment_id) {
|
||||
$shipmentId = $invoice->shipment->shipment_id;
|
||||
} elseif($invoice->shipment_id) {
|
||||
@@ -550,62 +565,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$totalAmount = $invoice->final_amount;
|
||||
$gstAmount = $invoice->gst_amount;
|
||||
$totalPayable = $invoice->final_amount_with_gst;
|
||||
<!-- ============================
|
||||
GST TOTALS SECTION - COMPLETELY REMOVED
|
||||
============================ -->
|
||||
|
||||
$paidAmount = $invoice->totalPaid();
|
||||
$remaining = $invoice->remainingAmount();
|
||||
@endphp
|
||||
|
||||
<div class="summary-container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
|
||||
<div class="amount-row">
|
||||
<span>Total Amount</span>
|
||||
<span class="fw-bold">₹{{ number_format($totalAmount,2) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="amount-row">
|
||||
<span>GST Amount</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ============================
|
||||
FOOTER — DOWNLOAD & SHARE
|
||||
============================ -->
|
||||
<div class="mt-4 pt-3 border-top text-center">
|
||||
|
||||
<!-- <div class="mt-4 pt-3 border-top text-center">
|
||||
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
|
||||
class="btn btn-primary me-2">
|
||||
<i class="fas fa-download me-1"></i> Download PDF
|
||||
@@ -614,8 +581,7 @@
|
||||
<button class="btn btn-success" onclick="shareInvoice()">
|
||||
<i class="fas fa-share me-1"></i> Share
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -624,22 +590,27 @@
|
||||
<!-- ============================
|
||||
SHARE SCRIPT
|
||||
============================ -->
|
||||
<script>
|
||||
function shareInvoice() {
|
||||
const shareData = {
|
||||
title: "Invoice {{ $invoice->invoice_number }}",
|
||||
text: "Sharing invoice {{ $invoice->invoice_number }}",
|
||||
url: "{{ route('admin.invoices.download', $invoice->id) }}"
|
||||
};
|
||||
<!-- <script>
|
||||
function shareInvoice() {
|
||||
const shareData = {
|
||||
title: "Invoice {{ $invoice->invoice_number }}",
|
||||
text: "Sharing invoice {{ $invoice->invoice_number }}",
|
||||
url: "{{ route('admin.invoices.download', $invoice->id) }}"
|
||||
};
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share(shareData).catch(() => {});
|
||||
} else {
|
||||
navigator.clipboard.writeText(shareData.url);
|
||||
alert("Link copied! Sharing not supported on this browser.");
|
||||
if (navigator.share) {
|
||||
navigator.share(shareData).catch(() => {});
|
||||
} else {
|
||||
navigator.clipboard.writeText(shareData.url);
|
||||
alert("Link copied! Sharing not supported on this browser.");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
// Add print functionality
|
||||
function printInvoice() {
|
||||
window.print();
|
||||
}
|
||||
</script> -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user