260 lines
7.8 KiB
PHP
260 lines
7.8 KiB
PHP
<?php
|
|
// Sanitize POST data
|
|
$from_name = htmlspecialchars($_POST['from_name'] ?? 'N/A');
|
|
$from_address = nl2br(htmlspecialchars($_POST['from_address'] ?? 'N/A'));
|
|
$to_name = htmlspecialchars($_POST['to_name'] ?? 'N/A');
|
|
$to_address = nl2br(htmlspecialchars($_POST['to_address'] ?? 'N/A'));
|
|
|
|
$invoice_number = htmlspecialchars($_POST['invoice_number'] ?? 'N/A');
|
|
$invoice_date = htmlspecialchars($_POST['invoice_date'] ?? date('Y-m-d'));
|
|
$invoice_due_date = htmlspecialchars($_POST['invoice_due_date'] ?? 'N/A');
|
|
|
|
$items = $_POST['items'] ?? [];
|
|
$notes = nl2br(htmlspecialchars($_POST['notes'] ?? ''));
|
|
$currency = htmlspecialchars($_POST['currency'] ?? '$');
|
|
$tax_rate = floatval($_POST['tax_rate'] ?? 0);
|
|
|
|
// Server-side calculation
|
|
$subtotal = 0;
|
|
foreach ($items as $item) {
|
|
$qty = floatval($item['qty'] ?? 0);
|
|
$price = floatval($item['price'] ?? 0);
|
|
$subtotal += $qty * $price;
|
|
}
|
|
$tax_amount = $subtotal * ($tax_rate / 100);
|
|
$total = $subtotal + $tax_amount;
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Инвойс <?= $invoice_number ?></title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
background-color: #f9f9f9;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
.invoice-container {
|
|
max-width: 800px;
|
|
margin: 20px auto;
|
|
padding: 40px;
|
|
background-color: #fff;
|
|
border: 1px solid #ddd;
|
|
box-shadow: 0 0 15px rgba(0,0,0,0.05);
|
|
}
|
|
.invoice-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 40px;
|
|
padding-bottom: 20px;
|
|
border-bottom: 2px solid #eee;
|
|
}
|
|
.invoice-header .from-details,
|
|
.invoice-header .invoice-meta {
|
|
width: 48%;
|
|
}
|
|
.invoice-header h1 {
|
|
margin: 0;
|
|
font-size: 2.5em;
|
|
color: #000;
|
|
}
|
|
.invoice-meta table {
|
|
width: 100%;
|
|
text-align: right;
|
|
}
|
|
.invoice-meta th, .invoice-meta td {
|
|
padding: 4px 0;
|
|
}
|
|
.invoice-meta th {
|
|
color: #777;
|
|
font-weight: normal;
|
|
}
|
|
.client-details {
|
|
margin-bottom: 40px;
|
|
}
|
|
.client-details h5 {
|
|
font-size: 1.1em;
|
|
color: #777;
|
|
margin-bottom: 5px;
|
|
}
|
|
.items-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 30px;
|
|
}
|
|
.items-table th, .items-table td {
|
|
border-bottom: 1px solid #eee;
|
|
padding: 12px;
|
|
text-align: left;
|
|
}
|
|
.items-table th {
|
|
background-color: #f9f9f9;
|
|
font-weight: 600;
|
|
}
|
|
.items-table .text-right {
|
|
text-align: right;
|
|
}
|
|
.totals {
|
|
float: right;
|
|
width: 100%;
|
|
max-width: 300px;
|
|
}
|
|
.totals table {
|
|
width: 100%;
|
|
}
|
|
.totals th, .totals td {
|
|
padding: 8px;
|
|
}
|
|
.totals th {
|
|
text-align: left;
|
|
font-weight: normal;
|
|
color: #555;
|
|
}
|
|
.totals td {
|
|
text-align: right;
|
|
}
|
|
.totals .grand-total th, .totals .grand-total td {
|
|
font-size: 1.4em;
|
|
font-weight: bold;
|
|
padding-top: 15px;
|
|
border-top: 2px solid #333;
|
|
}
|
|
.invoice-notes {
|
|
margin-top: 40px;
|
|
padding-top: 20px;
|
|
border-top: 1px solid #eee;
|
|
}
|
|
.invoice-notes h5 {
|
|
margin-bottom: 5px;
|
|
color: #777;
|
|
}
|
|
.print-button-container {
|
|
text-align: center;
|
|
margin-top: 30px;
|
|
}
|
|
.print-button {
|
|
padding: 12px 25px;
|
|
font-size: 1em;
|
|
background-color: #0d6efd;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
.print-button:hover {
|
|
background-color: #0b5ed7;
|
|
}
|
|
|
|
@media print {
|
|
body {
|
|
background-color: #fff;
|
|
}
|
|
.invoice-container {
|
|
box-shadow: none;
|
|
border: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
max-width: 100%;
|
|
}
|
|
.print-button-container {
|
|
display: none;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="invoice-container">
|
|
<div class="invoice-header">
|
|
<div class="from-details">
|
|
<h1>Инвойс</h1>
|
|
<strong><?= $from_name ?></strong><br>
|
|
<?= $from_address ?>
|
|
</div>
|
|
<div class="invoice-meta">
|
|
<table>
|
|
<tr>
|
|
<th>Номер #</th>
|
|
<td><?= $invoice_number ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Дата</th>
|
|
<td><?= $invoice_date ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Срок оплаты</th>
|
|
<td><?= $invoice_due_date ?></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="client-details">
|
|
<h5>Кому:</h5>
|
|
<strong><?= $to_name ?></strong><br>
|
|
<?= $to_address ?>
|
|
</div>
|
|
|
|
<table class="items-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Описание</th>
|
|
<th class="text-right">Кол-во</th>
|
|
<th class="text-right">Цена</th>
|
|
<th class="text-right">Сумма</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($items as $item): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($item['description'] ?? '') ?></td>
|
|
<td class="text-right"><?= htmlspecialchars($item['qty'] ?? 0) ?></td>
|
|
<td class="text-right"><?= $currency ?> <?= number_format(floatval($item['price'] ?? 0), 2) ?></td>
|
|
<td class="text-right"><?= $currency ?> <?= number_format(floatval($item['qty'] ?? 0) * floatval($item['price'] ?? 0), 2) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="totals">
|
|
<table>
|
|
<tr>
|
|
<th>Подытог:</th>
|
|
<td><?= $currency ?> <?= number_format($subtotal, 2) ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Налог (<?= $tax_rate ?>%):</th>
|
|
<td><?= $currency ?> <?= number_format($tax_amount, 2) ?></td>
|
|
</tr>
|
|
<tr class="grand-total">
|
|
<th>Итого:</th>
|
|
<td><?= $currency ?> <?= number_format($total, 2) ?></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="clear: both;"></div>
|
|
|
|
<?php if (!empty($notes)): ?>
|
|
<div class="invoice-notes">
|
|
<h5>Примечания:</h5>
|
|
<p><?= $notes ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="print-button-container">
|
|
<button class="print-button" onclick="window.print()">Печать / Сохранить в PDF</button>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|