You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
606 lines
21 KiB
606 lines
21 KiB
<?php
|
|
if (!defined('pp_allowed_access')) {
|
|
die('Direct access not allowed');
|
|
}
|
|
|
|
$invoice_details = pp_get_invoice($invoice_id);
|
|
$invoice_details_items = pp_get_invoice_items($invoice_id);
|
|
$setting = pp_get_settings();
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Invoice - <?php echo $setting['response'][0]['site_name']?></title>
|
|
<link rel="icon" type="image/x-icon" href="<?php if(isset($setting['response'][0]['favicon'])){if($setting['response'][0]['favicon'] == "--"){echo 'https://cdn.piprapay.com/media/favicon.png';}else{echo $setting['response'][0]['favicon'];};}else{echo 'https://cdn.piprapay.com/media/favicon.png';}?>">
|
|
<!-- Bootstrap CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<!-- Font Awesome -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<!-- Google Fonts -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--primary-color: #635bff;
|
|
--primary-dark: #4a42d4;
|
|
--success-color: #24b47e;
|
|
--error-color: #ff5252;
|
|
--warning-color: #ff9500;
|
|
--text-color: #1a1a1a;
|
|
--light-text: #6b7c93;
|
|
--border-color: #e0e6ed;
|
|
--light-bg: #f6f9fc;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
color: var(--text-color);
|
|
background-color: #f8f9fa;
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
.invoice-container {
|
|
max-width: 800px;
|
|
margin: 2rem auto;
|
|
background: white;
|
|
border-radius: 12px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.02), 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
overflow: hidden;
|
|
border: 1px solid var(--border-color);
|
|
position: relative;
|
|
}
|
|
|
|
/* Status seal - positioned absolutely */
|
|
.status-seal {
|
|
position: absolute;
|
|
top: 20px;
|
|
right: 20px;
|
|
width: 120px;
|
|
height: 120px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
transform: rotate(15deg);
|
|
opacity: 0.9;
|
|
z-index: 1;
|
|
}
|
|
|
|
.status-seal.paid {
|
|
background-color: rgba(36, 180, 126, 0.1);
|
|
border: 4px solid var(--success-color);
|
|
color: var(--success-color);
|
|
}
|
|
|
|
.status-seal.unpaid {
|
|
background-color: rgba(255, 82, 82, 0.1);
|
|
border: 4px solid var(--error-color);
|
|
color: var(--error-color);
|
|
}
|
|
|
|
.status-seal.pending {
|
|
background-color: rgba(255, 149, 0, 0.1);
|
|
border: 4px solid var(--warning-color);
|
|
color: var(--warning-color);
|
|
}
|
|
|
|
.status-seal-content {
|
|
text-align: center;
|
|
font-weight: 700;
|
|
font-size: 16px;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.invoice-header {
|
|
padding: 30px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
background: <?php echo hexToRgba($setting['response'][0]['primary_button_color'], 0.2)?>;
|
|
}
|
|
|
|
.invoice-title {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
margin-bottom: 5px;
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
.invoice-number {
|
|
font-size: 16px;
|
|
color: var(--light-text);
|
|
}
|
|
|
|
.invoice-meta {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-top: 30px;
|
|
}
|
|
|
|
.invoice-from, .invoice-to {
|
|
flex: 1;
|
|
}
|
|
|
|
.meta-label {
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
color: var(--light-text);
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.meta-value {
|
|
font-weight: 500;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.invoice-dates {
|
|
margin-top: 30px;
|
|
display: flex;
|
|
gap: 30px;
|
|
}
|
|
|
|
.date-item {
|
|
flex: 1;
|
|
}
|
|
|
|
.invoice-body {
|
|
padding: 30px;
|
|
}
|
|
|
|
.items-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.items-table th {
|
|
text-align: left;
|
|
padding: 12px 15px;
|
|
background: var(--light-bg);
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
color: var(--light-text);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.items-table td {
|
|
padding: 15px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.items-table tr:last-child td {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.item-description {
|
|
font-weight: 500;
|
|
}
|
|
|
|
.item-notes {
|
|
font-size: 13px;
|
|
color: var(--light-text);
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.text-right {
|
|
text-align: right;
|
|
}
|
|
|
|
.text-center {
|
|
text-align: center;
|
|
}
|
|
|
|
.totals-table {
|
|
width: 300px;
|
|
margin-left: auto;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.totals-table td {
|
|
padding: 10px 15px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.totals-table tr:last-child td {
|
|
border-bottom: none;
|
|
font-weight: 600;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.invoice-footer {
|
|
padding: 30px;
|
|
border-top: 1px solid var(--border-color);
|
|
background: var(--light-bg);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.payment-actions {
|
|
display: flex;
|
|
gap: 15px;
|
|
}
|
|
|
|
.btn-pay {
|
|
background: <?php echo $setting['response'][0]['primary_button_color']?>;
|
|
color: <?php echo $setting['response'][0]['button_text_color']?>;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.btn-pay:hover {
|
|
background: <?php echo $setting['response'][0]['button_hover_color']?>;
|
|
color: <?php echo $setting['response'][0]['button_hover_text_color']?>;
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.btn-pay:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.btn-print {
|
|
background: white;
|
|
color: var(--text-color);
|
|
border: 1px solid var(--border-color);
|
|
padding: 12px 24px;
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.btn-print:hover {
|
|
background: var(--light-bg);
|
|
}
|
|
|
|
.payment-methods {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.payment-method-icon {
|
|
width: 40px;
|
|
height: 25px;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.payment-method-icon img {
|
|
width: 30px;
|
|
height: auto;
|
|
}
|
|
|
|
.notes {
|
|
font-size: 14px;
|
|
color: var(--light-text);
|
|
max-width: 400px;
|
|
}
|
|
|
|
.notes strong {
|
|
color: var(--text-color);
|
|
}
|
|
|
|
/* Watermark for overdue invoices */
|
|
.watermark {
|
|
position: absolute;
|
|
opacity: 0.1;
|
|
font-size: 120px;
|
|
font-weight: 700;
|
|
color: var(--error-color);
|
|
transform: rotate(-30deg);
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%) rotate(-30deg);
|
|
z-index: 0;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
}
|
|
|
|
/* Responsive adjustments */
|
|
@media (max-width: 768px) {
|
|
.invoice-meta {
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
}
|
|
|
|
.invoice-dates {
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.totals-table {
|
|
width: 100%;
|
|
}
|
|
|
|
.invoice-footer {
|
|
padding: 20px;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.status-seal {
|
|
width: 80px;
|
|
height: 80px;
|
|
top: 10px;
|
|
right: 10px;
|
|
}
|
|
|
|
.status-seal-content {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.invoice-body {
|
|
padding: 20px;
|
|
white-space: nowrap;
|
|
}
|
|
.payment-actions{
|
|
width: 100%;
|
|
justify-content: space-between;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="invoice-container" id="invoice">
|
|
<!-- Status Seal - Change class to "paid", "unpaid", or "pending" -->
|
|
<?php
|
|
if($invoice_details['response'][0]['i_status'] == "unpaid"){
|
|
?>
|
|
<div class="status-seal unpaid">
|
|
<div class="status-seal-content">
|
|
<i class="fas fa-exclamation-circle"></i><br>
|
|
Unpaid
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}else{
|
|
if($invoice_details['response'][0]['i_status'] == "paid"){
|
|
?>
|
|
<div class="status-seal paid">
|
|
<div class="status-seal-content">
|
|
<i class="fas fa-check-circle"></i><br>
|
|
Paid
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}else{
|
|
if($invoice_details['response'][0]['i_status'] == "refunded"){
|
|
?>
|
|
<div class="status-seal pending">
|
|
<div class="status-seal-content">
|
|
<i class="fa fa-info-circle"></i><br>
|
|
Refunded
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}else{
|
|
if($invoice_details['response'][0]['i_status'] == "canceled"){
|
|
?>
|
|
<div class="status-seal unpaid">
|
|
<div class="status-seal-content">
|
|
<i class="fa fa-exclamation-triangle"></i><br>
|
|
Canceled
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
|
|
<!-- For overdue invoices, uncomment this: -->
|
|
<!-- <div class="watermark">OVERDUE</div> -->
|
|
|
|
<div class="invoice-header">
|
|
<div class="invoice-title">
|
|
<img src="<?php if(isset($setting['response'][0]['logo'])){if($setting['response'][0]['logo'] == "--"){echo 'https://cdn.piprapay.com/media/logo.png';}else{echo $setting['response'][0]['logo'];};}else{echo 'https://cdn.piprapay.com/media/logo.png';}?>" style=" height: 38px; ">
|
|
</div>
|
|
|
|
<div class="invoice-meta">
|
|
<div class="invoice-from">
|
|
<div class="meta-label">From</div>
|
|
<div class="meta-value"><?php echo $setting['response'][0]['site_name']?></div>
|
|
<div class="meta-value"><?php echo $setting['response'][0]['street_address']?></div>
|
|
<div class="meta-value"><?php echo $setting['response'][0]['city_town'].' '.$setting['response'][0]['postal_zip_code']?></div>
|
|
<div class="meta-value"><?php echo $setting['response'][0]['country']?></div>
|
|
</div>
|
|
|
|
<div class="invoice-to">
|
|
<div class="meta-label">Bill To</div>
|
|
<div class="meta-value"><?php echo $invoice_details['response'][0]['c_name']?></div>
|
|
<div class="meta-value"><?php echo $invoice_details['response'][0]['c_email_mobile']?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="invoice-dates">
|
|
<div class="date-item">
|
|
<div class="meta-label">Invoice Date</div>
|
|
<div class="meta-value"><?php echo convertToReadableDate($invoice_details['response'][0]['created_at'])?></div>
|
|
</div>
|
|
<div class="date-item">
|
|
<div class="meta-label">Due Date</div>
|
|
<div class="meta-value"><?php echo convertToReadableDate($invoice_details['response'][0]['i_due_date'])?></div>
|
|
</div>
|
|
<div class="date-item">
|
|
<div class="meta-label">Terms</div>
|
|
<div class="meta-value">Net 30</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="invoice-body">
|
|
<div style=" border: 1px solid #f6f9fc; overflow-x: auto; border-radius: 4px; ">
|
|
<table class="items-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Description</th>
|
|
<th>Quantity</th>
|
|
<th>Unit Price</th>
|
|
<th>Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$subtotal = 0;
|
|
$total_discount = 0;
|
|
$total_vat = 0;
|
|
|
|
foreach ($invoice_details_items['response'] as $items) {
|
|
$item_subtotal = $items['amount'] * $items['quantity'];
|
|
$item_discount = min($items['discount'], $item_subtotal); // discount capped by subtotal
|
|
$item_amount_after_discount = $item_subtotal - $item_discount;
|
|
$item_vat = $item_amount_after_discount * ($items['vat'] / 100);
|
|
|
|
$subtotal += $item_subtotal;
|
|
$total_discount += $item_discount;
|
|
$total_vat += $item_vat;
|
|
?>
|
|
<tr>
|
|
<td>
|
|
<div class="item-description"><?php echo htmlspecialchars($items['description']); ?></div>
|
|
</td>
|
|
<td class="text-center"><?php echo (int)$items['quantity']; ?></td>
|
|
<td class="text-right"><?php echo number_format($items['amount'], 2) . $invoice_details['response'][0]['i_currency']; ?></td>
|
|
<td class="text-right"><?php echo number_format($item_subtotal, 2) . $invoice_details['response'][0]['i_currency']; ?></td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
|
|
// Shipping cost from invoice details or zero if missing
|
|
$shipping_cost = isset($invoice_details['response'][0]['i_amount_shipping']) ? floatval($invoice_details['response'][0]['i_amount_shipping']) : 0;
|
|
|
|
// Calculate final total amount
|
|
$total_amount = $subtotal - $total_discount + $total_vat + $shipping_cost;
|
|
$currency = $invoice_details['response'][0]['i_currency'];
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
|
|
<table class="totals-table">
|
|
<tr>
|
|
<td>Subtotal</td>
|
|
<td class="text-right"><?php echo number_format($subtotal, 2) . $currency; ?></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Shipping</td>
|
|
<td class="text-right"><?php echo number_format($shipping_cost, 2) . $currency; ?></td>
|
|
</tr>
|
|
|
|
<?php if ($total_vat > 0): ?>
|
|
<tr>
|
|
<td>VAT</td>
|
|
<td class="text-right"><?php echo number_format($total_vat, 2) . $currency; ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($total_discount > 0): ?>
|
|
<tr>
|
|
<td>Discount</td>
|
|
<td class="text-right">-<?php echo number_format($total_discount, 2) . $currency; ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<tr>
|
|
<td><strong>Total Amount</strong></td>
|
|
<td class="text-right"><strong><?php echo number_format(round($total_amount, 2), 2) . $currency; ?></strong></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<span id="response"></span>
|
|
|
|
<div class="invoice-footer">
|
|
<div class="notes">
|
|
<?php
|
|
if($invoice_details['response'][0]['i_note'] == "" || $invoice_details['response'][0]['i_note'] == "--"){
|
|
|
|
}else{
|
|
?>
|
|
<strong>Notes:</strong> <?php echo $invoice_details['response'][0]['i_note']?>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
|
|
<div class="payment-actions">
|
|
<button class="btn-print" onclick="window.print()">
|
|
<i class="fas fa-print"></i> Print
|
|
</button>
|
|
|
|
<?php
|
|
if($invoice_details['response'][0]['i_status'] == "unpaid"){
|
|
?>
|
|
<button class="btn-pay" id="pay-button"><i class="fas fa-credit-card"></i> Pay Now</button>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p style=" text-align: center; margin-bottom: 19px; font-size: 14px; ">Your payment data is secured with <a href="https://piprapay.com" target="blank" style="color:<?php echo $setting['response'][0]['global_text_color']?>;text-decoration: none;"><strong>PipraPay</strong></a> 256-bit encryption</p>
|
|
|
|
<?php
|
|
if($invoice_details['response'][0]['i_status'] == "unpaid"){
|
|
?>
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
|
<script>
|
|
$(document).ready(function () {
|
|
$('#pay-button').click(function (e) {
|
|
e.preventDefault();
|
|
|
|
$("#pay-button").html('<div class="spinner-border spinner-border-sm" role="status"> <span class="visually-hidden">Loading...</span> </div>');
|
|
$("#pay-button").prop("disabled", true);
|
|
|
|
|
|
$.ajax
|
|
({
|
|
type: "POST",
|
|
url: "",
|
|
data: { "action": "pp-invoice-link", "pp-invoiceid": "<?php echo $invoice_id?>" },
|
|
success: function (data) {
|
|
$("#pay-button").html('<i class="fas fa-credit-card"></i> Pay Now');
|
|
$("#pay-button").prop("disabled", true);
|
|
|
|
var response = JSON.parse(data);
|
|
|
|
if (response.status === false) {
|
|
$("#response").html('<div class="alert alert-danger" style="margin-top: 20px; margin-bottom: 20px;" role="alert">'+response.message+'</div>');
|
|
} else {
|
|
$("#response").html('');
|
|
location.href = response.pp_url;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
?>
|
|
</body>
|
|
</html>
|