[
MAINHACK
]
Mail Test
BC
Config Scan
HOME
Create...
New File
New Folder
Viewing / Editing File: create.php
<?php require_once '../config/database.php'; require_once '../config/functions.php'; requireAuth('representative'); // Check if user has active shift $active_shift = getActiveShift($pdo, $_SESSION['user_id']); if (!$active_shift) { header("Location: /shifts/request_start.php?error=no_active_shift"); exit; } // Get clients for dropdown $stmt = $pdo->prepare("SELECT * FROM clients ORDER BY name ASC"); $stmt->execute(); $clients = $stmt->fetchAll(); // Get available products in current shift $stmt = $pdo->prepare(" SELECT sp.*, p.name, p.unit, p.price FROM shift_products sp JOIN products p ON sp.product_id = p.id WHERE sp.shift_id = ? AND sp.remaining_quantity > 0 ORDER BY p.name ASC "); $stmt->execute([$active_shift['id']]); $shift_products = $stmt->fetchAll(); $error = ''; $success = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $client_id = $_POST['client_id'] ?? ''; $products = $_POST['products'] ?? []; $quantities = $_POST['quantities'] ?? []; $amount_paid = floatval($_POST['amount_paid'] ?? 0); if (!$client_id) { $error = 'يرجى اختيار العميل'; } elseif (empty($products)) { $error = 'يرجى اختيار المنتجات'; } else { try { $pdo->beginTransaction(); // Get client current balance $stmt = $pdo->prepare("SELECT balance FROM clients WHERE id = ?"); $stmt->execute([$client_id]); $client = $stmt->fetch(); $previous_balance = $client['balance']; // Calculate invoice total $invoice_total = 0; $invoice_items = []; foreach ($products as $index => $product_id) { if (!isset($quantities[$index]) || $quantities[$index] <= 0) continue; $quantity = floatval($quantities[$index]); // Get product info from shift $stmt = $pdo->prepare(" SELECT sp.remaining_quantity, p.price, p.name, p.unit FROM shift_products sp JOIN products p ON sp.product_id = p.id WHERE sp.shift_id = ? AND p.id = ? "); $stmt->execute([$active_shift['id'], $product_id]); $shift_product = $stmt->fetch(); if (!$shift_product || $quantity > $shift_product['remaining_quantity']) { throw new Exception("كمية غير متوفرة للمنتج: " . $shift_product['name']); } $line_total = $quantity * $shift_product['price']; $invoice_total += $line_total; $invoice_items[] = [ 'product_id' => $product_id, 'quantity' => $quantity, 'unit_price' => $shift_product['price'], 'line_total' => $line_total ]; } if ($invoice_total <= 0) { throw new Exception('إجمالي الفاتورة يجب أن يكون أكبر من صفر'); } // Validate payment amount if ($amount_paid < 0) { throw new Exception('مبلغ الدفع لا يمكن أن يكون سالباً'); } if ($amount_paid > $invoice_total) { throw new Exception('مبلغ الدفع لا يمكن أن يكون أكبر من إجمالي الفاتورة'); } // Calculate remaining amount and new debt $remaining_amount = $invoice_total - $amount_paid; $new_total_debt = $previous_balance + $remaining_amount; // Determine invoice status $status = 'unpaid'; if ($amount_paid == $invoice_total) { $status = 'paid'; } elseif ($amount_paid > 0) { $status = 'partially_paid'; } // Generate invoice number $invoice_number = generateInvoiceNumber(); // Insert invoice $stmt = $pdo->prepare(" INSERT INTO invoices (invoice_number, client_id, representative_id, shift_id, invoice_total, amount_paid_at_creation, remaining_amount, previous_balance, new_total_debt, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $stmt->execute([ $invoice_number, $client_id, $_SESSION['user_id'], $active_shift['id'], $invoice_total, $amount_paid, $remaining_amount, $previous_balance, $new_total_debt, $status ]); $invoice_id = $pdo->lastInsertId(); // Insert invoice items foreach ($invoice_items as $item) { $stmt = $pdo->prepare(" INSERT INTO invoice_items (invoice_id, product_id, quantity, unit_price, line_total) VALUES (?, ?, ?, ?, ?) "); $stmt->execute([ $invoice_id, $item['product_id'], $item['quantity'], $item['unit_price'], $item['line_total'] ]); // Update shift product quantities $stmt = $pdo->prepare(" UPDATE shift_products SET remaining_quantity = remaining_quantity - ?, sold_quantity = sold_quantity + ? WHERE shift_id = ? AND product_id = ? "); $stmt->execute([$item['quantity'], $item['quantity'], $active_shift['id'], $item['product_id']]); } // Update client balance $stmt = $pdo->prepare("UPDATE clients SET balance = ? WHERE id = ?"); $stmt->execute([$new_total_debt, $client_id]); // If payment was made, create payment record if ($amount_paid > 0) { $receipt_number = generateReceiptNumber(); $stmt = $pdo->prepare(" INSERT INTO payments (receipt_number, client_id, representative_id, shift_id, amount, previous_balance, new_balance, payment_type, linked_invoice_id) VALUES (?, ?, ?, ?, ?, ?, ?, 'linked_to_invoice', ?) "); $stmt->execute([ $receipt_number, $client_id, $_SESSION['user_id'], $active_shift['id'], $amount_paid, $previous_balance, $new_total_debt, $invoice_id ]); } // Update shift totals $stmt = $pdo->prepare(" UPDATE shifts SET total_sales = total_sales + ? WHERE id = ? "); $stmt->execute([$invoice_total, $active_shift['id']]); // Add audit log addAuditLog($pdo, $_SESSION['user_id'], 'create_invoice', 'invoice', $invoice_id, null, [ 'invoice_number' => $invoice_number, 'client_id' => $client_id, 'total' => $invoice_total, 'paid' => $amount_paid ], "إنشاء فاتورة رقم $invoice_number"); $pdo->commit(); // Redirect to print page header("Location: /invoices/print.php?id=$invoice_id"); exit; } catch (Exception $e) { $pdo->rollBack(); $error = $e->getMessage(); } } } ?> <!DOCTYPE html> <html lang="ar" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>فاتورة جديدة - حسابات عربية بن فريش</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.rtl.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> <style> .product-row { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 8px; margin-bottom: 10px; padding: 15px; } .total-section { background: linear-gradient(135deg, #0d6efd, #198754); color: white; border-radius: 15px; padding: 20px; } </style> </head> <body class="bg-light"> <div class="container-fluid mt-4"> <div class="row"> <div class="col-md-8 mx-auto"> <div class="d-flex justify-content-between align-items-center mb-4"> <h2><i class="fas fa-file-invoice me-2"></i>فاتورة جديدة</h2> <a href="/dashboard.php" class="btn btn-outline-secondary"> <i class="fas fa-arrow-left me-1"></i>العودة </a> </div> <?php if ($error): ?> <div class="alert alert-danger" role="alert"> <i class="fas fa-exclamation-triangle me-2"></i><?= htmlspecialchars($error) ?> </div> <?php endif; ?> <form method="POST" id="invoiceForm"> <div class="card"> <div class="card-header bg-primary text-white"> <h5 class="mb-0">بيانات الفاتورة</h5> </div> <div class="card-body"> <div class="row mb-3"> <div class="col-md-6"> <label for="client_id" class="form-label">العميل *</label> <select class="form-select" id="client_id" name="client_id" required> <option value="">اختر العميل</option> <?php foreach ($clients as $client): ?> <option value="<?= $client['id'] ?>" data-balance="<?= $client['balance'] ?>" data-phone="<?= htmlspecialchars($client['phone']) ?>"> <?= htmlspecialchars($client['name']) ?> - <?= formatCurrency($client['balance']) ?> </option> <?php endforeach; ?> </select> </div> <div class="col-md-6"> <label class="form-label">الرصيد السابق</label> <div class="form-control bg-light" id="previous_balance">0.00 جنيه</div> </div> </div> </div> </div> <div class="card mt-4"> <div class="card-header bg-info text-white d-flex justify-content-between align-items-center"> <h5 class="mb-0">المنتجات</h5> <button type="button" class="btn btn-light btn-sm" onclick="addProductRow()"> <i class="fas fa-plus me-1"></i>إضافة منتج </button> </div> <div class="card-body"> <div id="products_container"> <!-- Product rows will be added here --> </div> </div> </div> <div class="row mt-4"> <div class="col-md-6"> <div class="card"> <div class="card-header bg-success text-white"> <h5 class="mb-0">الدفع</h5> </div> <div class="card-body"> <div class="mb-3"> <label for="amount_paid" class="form-label">المبلغ المدفوع</label> <input type="number" class="form-control" id="amount_paid" name="amount_paid" min="0" step="0.01" value="0" onchange="updateTotals()"> <div class="form-text">اتركه صفر للدفع الآجل</div> </div> </div> </div> </div> <div class="col-md-6"> <div class="total-section"> <h5 class="mb-3">ملخص الفاتورة</h5> <div class="row"> <div class="col-6">إجمالي الفاتورة:</div> <div class="col-6 text-end" id="invoice_total">0.00 جنيه</div> </div> <div class="row"> <div class="col-6">المبلغ المدفوع:</div> <div class="col-6 text-end" id="amount_paid_display">0.00 جنيه</div> </div> <div class="row"> <div class="col-6">المبلغ المتبقي:</div> <div class="col-6 text-end" id="remaining_amount">0.00 جنيه</div> </div> <hr> <div class="row"> <div class="col-6">الرصيد السابق:</div> <div class="col-6 text-end" id="prev_balance_display">0.00 جنيه</div> </div> <div class="row"> <div class="col-6"><strong>إجمالي المديونية:</strong></div> <div class="col-6 text-end" id="new_total_debt"><strong>0.00 جنيه</strong></div> </div> </div> </div> </div> <div class="d-flex justify-content-end gap-2 mt-4 mb-5"> <button type="submit" class="btn btn-primary btn-lg"> <i class="fas fa-save me-2"></i>حفظ الفاتورة </button> <button type="button" class="btn btn-secondary btn-lg" onclick="window.history.back()"> <i class="fas fa-times me-2"></i>إلغاء </button> </div> </form> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script> const shiftProducts = <?= json_encode($shift_products) ?>; let productRowCounter = 0; // Update client balance when client is selected document.getElementById('client_id').addEventListener('change', function() { const selectedOption = this.options[this.selectedIndex]; const balance = selectedOption.getAttribute('data-balance') || 0; document.getElementById('previous_balance').textContent = parseFloat(balance).toFixed(2) + ' جنيه'; updateTotals(); }); function addProductRow() { const container = document.getElementById('products_container'); const rowHtml = ` <div class="product-row" id="product_row_${productRowCounter}"> <div class="row"> <div class="col-md-4"> <label class="form-label">المنتج</label> <select class="form-select" name="products[]" onchange="updateProductInfo(${productRowCounter})" required> <option value="">اختر المنتج</option> ${shiftProducts.map(p => `<option value="${p.product_id}" data-price="${p.price}" data-unit="${p.unit}" data-available="${p.remaining_quantity}"> ${p.name} - ${p.remaining_quantity} ${p.unit} متاح - ${p.price} جنيه </option>` ).join('')} </select> </div> <div class="col-md-2"> <label class="form-label">الكمية</label> <input type="number" class="form-control" name="quantities[]" min="0.01" step="0.01" placeholder="0" onchange="updateRowTotal(${productRowCounter})" required> <small class="text-muted" id="available_${productRowCounter}"></small> </div> <div class="col-md-2"> <label class="form-label">السعر</label> <div class="form-control bg-light" id="price_${productRowCounter}">0.00</div> </div> <div class="col-md-2"> <label class="form-label">الإجمالي</label> <div class="form-control bg-light" id="line_total_${productRowCounter}">0.00</div> </div> <div class="col-md-2"> <label class="form-label"> </label> <button type="button" class="btn btn-danger btn-sm w-100" onclick="removeProductRow(${productRowCounter})"> <i class="fas fa-trash"></i> </button> </div> </div> </div> `; container.insertAdjacentHTML('beforeend', rowHtml); productRowCounter++; } function removeProductRow(rowId) { document.getElementById(`product_row_${rowId}`).remove(); updateTotals(); } function updateProductInfo(rowId) { const select = document.querySelector(`#product_row_${rowId} select[name="products[]"]`); const selectedOption = select.options[select.selectedIndex]; const price = selectedOption.getAttribute('data-price') || 0; const unit = selectedOption.getAttribute('data-unit') || ''; const available = selectedOption.getAttribute('data-available') || 0; document.getElementById(`price_${rowId}`).textContent = parseFloat(price).toFixed(2); document.getElementById(`available_${rowId}`).textContent = `متاح: ${available} ${unit}`; // Update quantity input max const quantityInput = document.querySelector(`#product_row_${rowId} input[name="quantities[]"]`); quantityInput.setAttribute('max', available); updateRowTotal(rowId); } function updateRowTotal(rowId) { const select = document.querySelector(`#product_row_${rowId} select[name="products[]"]`); const quantityInput = document.querySelector(`#product_row_${rowId} input[name="quantities[]"]`); const selectedOption = select.options[select.selectedIndex]; const price = parseFloat(selectedOption.getAttribute('data-price') || 0); const quantity = parseFloat(quantityInput.value || 0); const available = parseFloat(selectedOption.getAttribute('data-available') || 0); // Validate quantity if (quantity > available) { alert(`الكمية المطلوبة (${quantity}) أكبر من المتاح (${available})`); quantityInput.value = available; return; } const lineTotal = price * quantity; document.getElementById(`line_total_${rowId}`).textContent = lineTotal.toFixed(2); updateTotals(); } function updateTotals() { // Calculate invoice total let invoiceTotal = 0; document.querySelectorAll('[id^="line_total_"]').forEach(element => { const value = parseFloat(element.textContent || 0); invoiceTotal += value; }); const amountPaid = parseFloat(document.getElementById('amount_paid').value || 0); const remainingAmount = invoiceTotal - amountPaid; // Get previous balance const clientSelect = document.getElementById('client_id'); const selectedOption = clientSelect.options[clientSelect.selectedIndex]; const previousBalance = parseFloat(selectedOption.getAttribute('data-balance') || 0); const newTotalDebt = previousBalance + remainingAmount; // Update display document.getElementById('invoice_total').textContent = invoiceTotal.toFixed(2) + ' جنيه'; document.getElementById('amount_paid_display').textContent = amountPaid.toFixed(2) + ' جنيه'; document.getElementById('remaining_amount').textContent = remainingAmount.toFixed(2) + ' جنيه'; document.getElementById('prev_balance_display').textContent = previousBalance.toFixed(2) + ' جنيه'; document.getElementById('new_total_debt').textContent = newTotalDebt.toFixed(2) + ' جنيه'; } // Add first product row on load document.addEventListener('DOMContentLoaded', function() { addProductRow(); }); // Update amount paid display document.getElementById('amount_paid').addEventListener('input', updateTotals); </script> </body> </html>
Save Changes
Cancel / Back
Close ×
Server Info
Hostname: premium320.web-hosting.com
Server IP: 66.29.153.54
PHP Version: 8.2.29
Server Software: LiteSpeed
System: Linux premium320.web-hosting.com 4.18.0-553.50.1.lve.el8.x86_64 #1 SMP Thu Apr 17 19:10:24 UTC 2025 x86_64
HDD Total: 97.87 GB
HDD Free: 76.87 GB
Domains on IP: N/A (Requires external lookup)
System Features
Safe Mode:
Off
disable_functions:
None
allow_url_fopen:
On
allow_url_include:
Off
magic_quotes_gpc:
Off
register_globals:
Off
open_basedir:
None
cURL:
Enabled
ZipArchive:
Enabled
MySQLi:
Enabled
PDO:
Enabled
wget:
Yes
curl (cmd):
Yes
perl:
Yes
python:
Yes (py3)
gcc:
Yes
pkexec:
No
git:
Yes
User Info
Username: aoneqssk
User ID (UID): 1285
Group ID (GID): 1290
Script Owner UID: 1285
Current Dir Owner: 1285