File: /home/muratemr/theotto.tr/admin/daily_orders.php
<?php
/**
* admin/daily_orders.php
*/
declare(strict_types=1);
$page_title = 'Günlük Siparişler';
$active_menu = 'daily_orders';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/functions.php';
require_once __DIR__ . '/../includes/csrf.php';
require_permission('daily_orders');
require_once __DIR__ . '/../includes/admin_layout.php';
$filter_date = get_str('date');
$filter_supplier = get_int('supplier_id');
$filter_product = get_str('product');
$filter_user = get_int('user_id');
$page = max(1, get_int('page', 1));
$per_page = 20;
$where = ['1=1']; // is_archived filtresi aşağıda sorgu içinde
$params = [];
if ($filter_date) { $where[] = 'do2.order_date=?'; $params[] = $filter_date; }
if ($filter_supplier) { $where[] = 'do2.supplier_id=?'; $params[] = $filter_supplier; }
if ($filter_user) { $where[] = 'do2.created_by=?'; $params[] = $filter_user; }
if ($filter_product !== '') {
$where[] = 'EXISTS(SELECT 1 FROM daily_order_items doi2 WHERE doi2.order_id=do2.id AND doi2.product_name LIKE ?)';
$params[] = '%' . $filter_product . '%';
}
$where_str = implode(' AND ', $where);
$total = (int)db_value("SELECT COUNT(*) FROM daily_orders do2 WHERE ($where_str) AND (do2.is_archived = 0 OR do2.is_archived IS NULL)", $params);
$pg = paginate($total, $page, $per_page);
$orders = db_rows("
SELECT do2.*,
s.company_name AS supplier_name, s.whatsapp AS supplier_whatsapp,
u.full_name AS creator_name,
(SELECT COALESCE(SUM(doi.quantity * COALESCE(doi.approx_price,0)),0)
FROM daily_order_items doi WHERE doi.order_id=do2.id) AS total_price,
(SELECT COUNT(*) FROM daily_order_items doi WHERE doi.order_id=do2.id) AS item_count,
(SELECT GROUP_CONCAT(doi.product_name SEPARATOR ', ')
FROM daily_order_items doi WHERE doi.order_id=do2.id LIMIT 1) AS items_preview
FROM daily_orders do2
JOIN suppliers s ON s.id = do2.supplier_id
JOIN users u ON u.id = do2.created_by
WHERE ($where_str)
AND (do2.is_archived = 0 OR do2.is_archived IS NULL)
ORDER BY do2.order_date DESC, do2.created_at DESC
LIMIT {$pg['limit']} OFFSET {$pg['offset']}
", $params);
$suppliers = db_rows('SELECT id, company_name FROM suppliers WHERE is_active=1 ORDER BY company_name');
$users_list = db_rows('SELECT id, full_name FROM users WHERE is_active=1 ORDER BY full_name');
$now = new DateTime();
?>
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0 text-gold"><i class="bi bi-clipboard-list me-2"></i>Günlük Siparişler</h5>
<div class="d-flex gap-2">
<a href="orders_archive.php" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-archive me-1"></i>Arşivlenen Siparişler
</a>
<button class="btn btn-gold btn-sm" onclick="openNewOrderModal()">
<i class="bi bi-plus-lg me-1"></i>Yeni Sipariş
</button>
</div>
</div>
<!-- Filtreler -->
<div class="card mb-3">
<div class="card-body py-2">
<form method="GET" class="row g-2 align-items-end">
<div class="col-6 col-md-2">
<label class="form-label">Tarih</label>
<input type="date" name="date" class="form-control form-control-sm" value="<?= e($filter_date) ?>">
</div>
<div class="col-6 col-md-3">
<label class="form-label">Tedarikçi</label>
<select name="supplier_id" class="form-select form-select-sm">
<option value="">Tümü</option>
<?php foreach ($suppliers as $s): ?>
<option value="<?= $s['id'] ?>" <?= $filter_supplier==(int)$s['id']?'selected':'' ?>><?= e($s['company_name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-6 col-md-3">
<label class="form-label">Ürün Adı</label>
<input type="text" name="product" class="form-control form-control-sm" value="<?= e($filter_product) ?>" placeholder="Ürün ara...">
</div>
<div class="col-6 col-md-2">
<label class="form-label">Oluşturan</label>
<select name="user_id" class="form-select form-select-sm">
<option value="">Tümü</option>
<?php foreach ($users_list as $u): ?>
<option value="<?= $u['id'] ?>" <?= $filter_user==(int)$u['id']?'selected':'' ?>><?= e($u['full_name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-md-2 d-flex gap-2">
<button type="submit" class="btn btn-sm btn-gold flex-fill">
<i class="bi bi-search me-1"></i>Filtrele
</button>
<a href="daily_orders.php" class="btn btn-sm btn-outline-secondary">
<i class="bi bi-x-lg"></i>
</a>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header d-flex justify-content-between">
<span>Siparişler (<span id="ordersCount"><?= $total ?></span>)</span>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th>Tarih</th>
<th>Tedarikçi</th>
<th>Ürün Özeti</th>
<th>Tahmini Tutar</th>
<th>Oluşturan</th>
<th>Güncelleme</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody id="ordersTbody">
<?php foreach ($orders as $o): ?>
<?php
$orderDate = new DateTime($o['order_date'] . ' 00:00:00');
$diff = $now->diff($orderDate);
$hoursOld = ($now->getTimestamp() - (new DateTime($o['created_at']))->getTimestamp()) / 3600;
$canEdit = $hoursOld <= 24 || is_admin();
?>
<tr>
<td><?= format_date($o['order_date']) ?></td>
<td>
<?= e($o['supplier_name']) ?>
<?php if ($o['supplier_whatsapp']): ?>
<a href="#" onclick="openWhatsApp('<?= e($o['supplier_whatsapp']) ?>','')" class="ms-1" title="WhatsApp">
<i class="bi bi-whatsapp text-success fs-12"></i>
</a>
<?php endif; ?>
</td>
<td class="fs-12">
<span class="badge bg-secondary"><?= $o['item_count'] ?> ürün</span>
</td>
<td>
<span class="text-gold fw-bold"><?= number_format((float)$o['total_price'], 2, ',', '.') ?> ₺</span>
</td>
<td class="fs-12"><?= e($o['creator_name']) ?></td>
<td class="fs-12 text-muted"><?= format_datetime($o['updated_at']) ?></td>
<td>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-secondary btn-action" onclick="viewOrder(<?= $o['id'] ?>)" title="Görüntüle">
<i class="bi bi-eye"></i>
</button>
<?php
$log_count = (int)db_value("SELECT COUNT(*) FROM daily_order_edit_logs WHERE order_id=?", [$o['id']]);
if ($log_count > 0): ?>
<button class="btn btn-sm btn-outline-info btn-action" onclick="viewOrderHistory(<?= $o['id'] ?>)"
title="Düzenleme Geçmişi (<?= $log_count ?> kayıt)">
<i class="bi bi-clock-history"></i>
<span class="badge bg-info ms-1" style="font-size:9px"><?= $log_count ?></span>
</button>
<?php endif; ?>
<?php if ($canEdit): ?>
<button class="btn btn-sm btn-outline-secondary btn-action" onclick="openEditOrder(<?= $o['id'] ?>)" title="Düzenle">
<i class="bi bi-pencil"></i>
</button>
<?php endif; ?>
<?php if ($o['supplier_whatsapp']): ?>
<button class="btn btn-sm btn-outline-success btn-action" onclick="sendOrderWA(<?= $o['id'] ?>)" title="WhatsApp Gönder">
<i class="bi bi-whatsapp"></i>
</button>
<?php endif; ?>
<?php if (is_admin()): ?>
<button class="btn btn-sm btn-outline-danger btn-action" onclick="deleteOrder(<?= $o['id'] ?>)" title="Sil">
<i class="bi bi-trash"></i>
</button>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($orders)): ?>
<tr id="emptyOrdersRow"><td colspan="7" class="text-center text-muted py-4">Sipariş bulunamadı.</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Yeni/Düzenle Sipariş Modalı -->
<div class="modal fade" id="orderModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title" id="orderModalTitle">Yeni Sipariş</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" id="orderId" value="">
<div class="row g-3 mb-3">
<div class="col-md-4">
<label class="form-label">Tedarikçi *</label>
<select id="orderSupplier" class="form-select">
<option value="">— Tedarikçi Seçin —</option>
<?php foreach ($suppliers as $s): ?>
<option value="<?= $s['id'] ?>" data-wa=""><?= e($s['company_name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label">Sipariş Tarihi *</label>
<input type="date" id="orderDate" class="form-control" value="<?= date('Y-m-d') ?>">
</div>
<div class="col-md-5">
<label class="form-label">Genel Not</label>
<input type="text" id="orderNote" class="form-control" placeholder="Opsiyonel not...">
</div>
<!-- Düzenleme sebebi (edit modunda) -->
<div class="col-12 d-none" id="editReasonWrap">
<label class="form-label">Düzenleme Sebebi *</label>
<input type="text" id="editReason" class="form-control" placeholder="Neden düzenliyorsunuz?">
</div>
</div>
<!-- Ürün Satırları -->
<div class="d-flex justify-content-between align-items-center mb-2">
<label class="form-label mb-0">Sipariş Kalemleri</label>
<div>
<span class="text-gold fw-bold me-3">Toplam: <span id="orderTotal">0,00</span> ₺</span>
<button type="button" class="btn btn-sm btn-outline-gold" style="border-color:var(--gold);color:var(--gold)" onclick="addProductRow()">
<i class="bi bi-plus-lg me-1"></i>Ürün Ekle
</button>
</div>
</div>
<div id="productRows"></div>
</div>
<div class="modal-footer d-flex justify-content-between">
<button type="button" class="btn btn-success btn-sm d-none" id="sendWABtn" onclick="sendOrderWAFromModal()">
<i class="bi bi-whatsapp me-1"></i>WhatsApp'tan Tedarikçiye Gönder
</button>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">İptal</button>
<button type="button" class="btn btn-gold btn-sm" id="orderSaveBtn">Kaydet</button>
</div>
</div>
</div>
</div>
</div>
<!-- Görüntüle Modalı -->
<div class="modal fade" id="viewOrderModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title"><i class="bi bi-clipboard-list me-2"></i>Sipariş Detayı</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="viewOrderBody">
<div class="text-center py-4"><div class="spinner-border spinner-border-sm"></div></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger btn-sm" id="viewPdfBtn" onclick="downloadOrderPdf()" style="display:none">
<i class="bi bi-file-earmark-pdf me-1"></i>PDF Olarak Kaydet
</button>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Kapat</button>
</div>
</div>
</div>
</div>
<script>
const UNITS = ['adet','kg','litre','paket','koli','bag','kutu','gram'];
let lastSavedOrderId = null;
let lastSavedSupplierWA = '';
function unitOptions(selected = 'adet') {
return UNITS.map(u => `<option value="${u}" ${u===selected?'selected':''}>${u}</option>`).join('');
}
function addProductRow(data = {}) {
const idx = Date.now();
const row = document.createElement('div');
row.className = 'product-row row g-2 align-items-center';
row.dataset.rowId = idx;
row.innerHTML = `
<div class="col-12 col-md-3">
<input type="text" class="form-control form-control-sm prod-name" placeholder="Ürün adı *" value="${data.product_name||''}">
</div>
<div class="col-6 col-md-2">
<select class="form-select form-select-sm prod-unit">${unitOptions(data.unit||'adet')}</select>
</div>
<div class="col-6 col-md-2">
<input type="number" class="form-control form-control-sm prod-qty" placeholder="Miktar" min="0.01" step="0.01" value="${data.quantity||''}">
</div>
<div class="col-6 col-md-2">
<input type="number" class="form-control form-control-sm prod-price" placeholder="~Fiyat ₺" min="0" step="0.01" value="${data.approx_price||''}">
</div>
<div class="col-6 col-md-2">
<input type="text" class="form-control form-control-sm prod-note" placeholder="Not" value="${data.item_note||''}">
</div>
<div class="col-12 col-md-1 text-end">
<button type="button" class="btn btn-sm btn-outline-danger" onclick="this.closest('.product-row').remove(); calcTotal()">
<i class="bi bi-trash"></i>
</button>
</div>
`;
document.getElementById('productRows').appendChild(row);
row.querySelectorAll('.prod-qty, .prod-price').forEach(i => i.addEventListener('input', calcTotal));
calcTotal();
}
function calcTotal() {
let total = 0;
document.querySelectorAll('.product-row').forEach(row => {
const qty = parseFloat(row.querySelector('.prod-qty').value) || 0;
const price = parseFloat(row.querySelector('.prod-price').value) || 0;
total += qty * price;
});
document.getElementById('orderTotal').textContent = total.toFixed(2).replace('.', ',');
}
function getProductRows() {
const rows = [];
document.querySelectorAll('.product-row').forEach(row => {
rows.push({
product_name: row.querySelector('.prod-name').value.trim(),
unit: row.querySelector('.prod-unit').value,
quantity: row.querySelector('.prod-qty').value,
approx_price: row.querySelector('.prod-price').value,
item_note: row.querySelector('.prod-note').value,
});
});
return rows;
}
function openNewOrderModal() {
document.getElementById('orderId').value = '';
document.getElementById('orderSupplier').value = '';
document.getElementById('orderDate').value = new Date().toISOString().split('T')[0];
document.getElementById('orderNote').value = '';
document.getElementById('productRows').innerHTML = '';
document.getElementById('editReasonWrap').classList.add('d-none');
document.getElementById('sendWABtn').classList.add('d-none');
document.getElementById('orderModalTitle').textContent = 'Yeni Sipariş';
addProductRow();
calcTotal();
openModal('orderModal');
}
async function openEditOrder(id) {
document.getElementById('orderId').value = id;
document.getElementById('productRows').innerHTML = '';
document.getElementById('orderModalTitle').textContent = 'Sipariş Düzenle';
document.getElementById('editReasonWrap').classList.remove('d-none');
document.getElementById('editReason').value = '';
document.getElementById('sendWABtn').classList.add('d-none');
openModal('orderModal');
const data = await apiGet('/api/admin/daily_orders.php?action=get&id=' + id);
if (!data.success) { showToast(data.message, 'error'); return; }
const o = data.order;
document.getElementById('orderSupplier').value = o.supplier_id;
document.getElementById('orderDate').value = o.order_date;
document.getElementById('orderNote').value = o.general_note || '';
data.items.forEach(i => addProductRow(i));
calcTotal();
}
</script>
<?php require_once __DIR__ . '/../includes/admin_layout_end.php'; ?>
<script>
document.getElementById('orderSaveBtn').addEventListener('click', async () => {
const id = document.getElementById('orderId').value;
const supplier = document.getElementById('orderSupplier').value;
const date = document.getElementById('orderDate').value;
const note = document.getElementById('orderNote').value;
const reason = document.getElementById('editReason').value.trim();
const rows = getProductRows();
if (!supplier) { showToast('Tedarikçi seçiniz.', 'error'); return; }
if (!date) { showToast('Tarih giriniz.', 'error'); return; }
if (id && !reason) { showToast('Düzenleme sebebi zorunludur.', 'error'); return; }
const validRows = rows.filter(r => r.product_name && r.quantity);
if (!validRows.length) { showToast('En az 1 ürün satırı ekleyin.', 'error'); return; }
// Butonu devre dışı bırak - çift kayıt engelle
const btn = document.getElementById('orderSaveBtn');
btn.disabled = true;
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Kaydediliyor...';
const res = await apiPost('/api/admin/daily_orders.php', {
action: id ? 'update' : 'create',
id,
supplier_id: supplier,
order_date: date,
general_note:note,
edit_reason: reason,
items: JSON.stringify(validRows),
});
btn.disabled = false;
btn.innerHTML = 'Kaydet';
if (res.success) {
showToast(res.message, 'success');
lastSavedOrderId = res.order_id;
lastSavedSupplierWA = res.supplier_wa || '';
// Modalı hemen kapat
closeModal('orderModal');
if (id) {
// Düzenleme: sayfayı yenile (mevcut satır değişti)
location.reload();
} else {
// Yeni sipariş: satırı DOM'a anında ekle, reload yok
prependOrderRow({
id: res.order_id,
order_date: date,
supplier_id: supplier,
supplier_name: document.getElementById('orderSupplier').options[document.getElementById('orderSupplier').selectedIndex].text,
supplier_wa: lastSavedSupplierWA,
items: validRows,
total_price: validRows.reduce((s,r) => s + (parseFloat(r.quantity)||0)*(parseFloat(r.approx_price)||0), 0),
general_note: note,
});
// WhatsApp toast
if (lastSavedSupplierWA) {
showToast('Sipariş kaydedildi. WhatsApp ile göndermek için butona tıklayın.', 'info', 4000);
}
}
} else {
showToast(res.message, 'error');
}
});
async function sendOrderWA(id) {
const data = await apiGet('/api/admin/daily_orders.php?action=get&id=' + id);
if (!data.success) { showToast(data.message, 'error'); return; }
const o = data.order;
if (!o.supplier_whatsapp) {
showToast('Tedarikci WhatsApp numarasi tanimli degil.', 'warning');
return;
}
var msg = 'Merhaba, asagidaki siparisi olusturmak istiyoruz.\n\n';
msg += 'Tarih: ' + formatDate(o.order_date) + '\n';
msg += 'Tedarikci: ' + (o.supplier_name || '') + '\n\n';
msg += 'Siparis Listesi:\n';
(data.items || []).forEach(function(item, i) {
msg += (i + 1) + '. ' + item.product_name + ' - ' + item.quantity + ' ' + item.unit;
if (item.approx_price) { msg += ' (~' + item.approx_price + ' TL)'; }
msg += '\n';
});
if (o.general_note) { msg += '\nNot: ' + o.general_note; }
msg += '\n\nTesekkurler.';
openWhatsApp(o.supplier_whatsapp, msg);
}
function sendOrderWAFromModal() {
if (lastSavedOrderId) sendOrderWA(lastSavedOrderId);
}
function formatDate(d) {
const [y,m,day] = d.split('-');
return `${day}.${m}.${y}`;
}
async function viewOrderHistory(id) {
document.getElementById('viewOrderBody').innerHTML = '<div class="text-center py-4"><div class="spinner-border spinner-border-sm"></div></div>';
document.getElementById('viewOrderModal').querySelector('.modal-title').textContent = 'Düzenleme Geçmişi';
document.getElementById('viewPdfBtn').style.display = 'none';
openModal('viewOrderModal');
const data = await apiGet('/api/admin/daily_orders.php?action=get&id=' + id);
if (!data.success) {
document.getElementById('viewOrderBody').innerHTML = '<div class="text-danger">Hata: ' + data.message + '</div>';
return;
}
var logs = data.logs || [];
var o = data.order;
var html = '<div class="mb-3 pb-2" style="border-bottom:1px solid rgba(255,255,255,0.1)">';
html += '<span class="text-warning fw-bold">' + (o.supplier_name||'') + '</span>';
html += '<span class="text-muted ms-2">– ' + formatDate(o.order_date) + '</span>';
html += '</div>';
if (logs.length === 0) {
html += '<div class="text-muted text-center py-4"><i class="bi bi-clock-history me-2"></i>Henüz düzenleme yapılmamış.</div>';
} else {
html += '<div class="edit-log-list">';
logs.forEach(function(log, idx) {
var dt = log.created_at ? log.created_at.replace('T',' ').substring(0,16) : '';
html += '<div class="edit-log-item">';
// Başlık satırı
html += '<div class="d-flex justify-content-between align-items-center mb-2">';
html += '<div>';
html += '<span class="badge bg-warning text-dark me-2">#' + (logs.length - idx) + '</span>';
html += '<strong style="font-size:13px">' + (log.editor_name||'Bilinmiyor') + '</strong>';
html += '</div>';
html += '<span style="font-size:11px;color:var(--text-muted)">' + dt + '</span>';
html += '</div>';
// Düzenleme nedeni
html += '<div class="mb-2 p-2" style="background:rgba(201,168,76,0.08);border-radius:4px">';
html += '<i class="bi bi-chat-quote me-1 text-warning"></i>';
html += '<span style="font-size:12px;font-style:italic">"' + (log.edit_reason||'Neden belirtilmedi') + '"</span>';
html += '</div>';
// Değişiklik detayları
if (log.old_data && log.new_data) {
try {
var oldD = JSON.parse(log.old_data);
var newD = JSON.parse(log.new_data);
var changes = [];
if (oldD.supplier_id != newD.supplier_id) {
changes.push('<span class="text-info">Tedarikci degisti</span>');
}
if (oldD.order_date !== newD.order_date) {
changes.push('<span class="text-info">Tarih: ' + (oldD.order_date||'') + ' → ' + (newD.order_date||'') + '</span>');
}
if (oldD.general_note !== newD.general_note) {
changes.push('<span class="text-info">Not guncellendi</span>');
}
// Urun farkliliklari
var oldItems = oldD.items || [];
var newItems = newD.items || [];
if (JSON.stringify(oldItems) !== JSON.stringify(newItems)) {
var added = newItems.filter(function(n){ return !oldItems.find(function(o){ return o.product_name===n.product_name; }); });
var removed = oldItems.filter(function(o){ return !newItems.find(function(n){ return n.product_name===o.product_name; }); });
var changed = newItems.filter(function(n){
var old = oldItems.find(function(o){ return o.product_name===n.product_name; });
return old && (old.quantity!=n.quantity || old.approx_price!=n.approx_price);
});
added.forEach(function(i){ changes.push('<span class="text-success">+ ' + i.product_name + ' (' + i.quantity + ' ' + i.unit + ')</span>'); });
removed.forEach(function(i){ changes.push('<span class="text-danger">- ' + i.product_name + '</span>'); });
changed.forEach(function(i){
var old = oldItems.find(function(o){ return o.product_name===i.product_name; });
changes.push('<span class="text-warning">' + i.product_name + ': ' + old.quantity + ' → ' + i.quantity + ' ' + i.unit + '</span>');
});
}
if (changes.length > 0) {
html += '<div style="font-size:11px;line-height:1.8">';
changes.forEach(function(c){ html += '<div>' + c + '</div>'; });
html += '</div>';
}
} catch(e) {}
}
html += '</div>';
});
html += '</div>';
}
document.getElementById('viewOrderBody').innerHTML = html;
}
async function viewOrder(id) {
document.getElementById('viewOrderBody').innerHTML = '<div class="text-center py-4"><div class="spinner-border spinner-border-sm"></div></div>';
document.getElementById('viewOrderModal').querySelector('.modal-title').textContent = 'Sipariş Detayı';
openModal('viewOrderModal');
const data = await apiGet('/api/admin/daily_orders.php?action=get&id=' + id);
if (!data.success) { document.getElementById('viewOrderBody').innerHTML = '<div class="text-danger">Hata: ' + data.message + '</div>'; return; }
const o = data.order;
let html = `
<div class="row mb-3">
<div class="col"><b>Tedarikçi:</b> ${o.supplier_name}</div>
<div class="col"><b>Tarih:</b> ${formatDate(o.order_date)}</div>
<div class="col"><b>Oluşturan:</b> ${o.creator_name}</div>
</div>
${o.general_note ? `<div class="alert alert-info py-2 mb-3 fs-12"><i class="bi bi-info-circle me-1"></i>${o.general_note}</div>` : ''}
<table class="table table-sm">
<thead><tr><th>#</th><th>Ürün</th><th>Miktar</th><th>~Fiyat</th><th>Toplam</th><th>Not</th></tr></thead>
<tbody>
`;
let total = 0;
data.items.forEach((item, i) => {
const sub = (parseFloat(item.quantity)||0) * (parseFloat(item.approx_price)||0);
total += sub;
html += `<tr>
<td>${i+1}</td>
<td>${item.product_name}</td>
<td>${item.quantity} ${item.unit}</td>
<td>${item.approx_price ? item.approx_price + ' ₺' : '—'}</td>
<td>${sub > 0 ? sub.toFixed(2) + ' ₺' : '—'}</td>
<td class="fs-12 text-muted">${item.item_note||'—'}</td>
</tr>`;
});
html += '</tbody><tfoot><tr><th colspan="4">Toplam Tahmini</th><th class="text-gold">' + total.toFixed(2) + ' TL</th><th></th></tr></tfoot></table>';
// Düzenleme geçmişi
if (data.logs && data.logs.length > 0) {
html += '<hr style="border-color:rgba(255,255,255,0.1);margin:20px 0 14px">';
html += '<div style="font-size:13px;font-weight:600;color:var(--gold);margin-bottom:10px">';
html += '<i class="bi bi-clock-history me-2"></i>Düzenleme Geçmişi (' + data.logs.length + ')';
html += '</div>';
html += '<div class="edit-log-list">';
data.logs.forEach(function(log) {
var dt = log.created_at ? log.created_at.replace('T',' ').substring(0,16) : '';
html += '<div class="edit-log-item">';
html += '<div class="d-flex justify-content-between align-items-start mb-1">';
html += '<span style="font-size:12px;font-weight:600;color:var(--text-primary)">';
html += '<i class="bi bi-person-circle me-1 text-warning"></i>' + (log.editor_name || 'Bilinmiyor');
html += '</span>';
html += '<span style="font-size:11px;color:var(--text-muted)">' + dt + '</span>';
html += '</div>';
html += '<div style="font-size:12px;color:var(--text-muted);margin-bottom:6px">';
html += '<i class="bi bi-chat-left-text me-1"></i><span style="color:var(--text-primary)">' + (log.edit_reason || '—') + '</span>';
html += '</div>';
// Değişiklikler (old_data vs new_data)
if (log.old_data && log.new_data) {
try {
var oldD = JSON.parse(log.old_data);
var newD = JSON.parse(log.new_data);
var changes = [];
if (oldD.supplier_id !== newD.supplier_id) changes.push('Tedarikci degisti');
if (oldD.order_date !== newD.order_date) changes.push('Tarih: ' + (oldD.order_date||'') + ' → ' + (newD.order_date||''));
if (JSON.stringify(oldD.items) !== JSON.stringify(newD.items)) changes.push('Urun listesi guncellendi');
if (oldD.general_note !== newD.general_note) changes.push('Not guncellendi');
if (changes.length > 0) {
html += '<div style="font-size:11px;color:var(--text-muted)">';
html += '<i class="bi bi-arrow-right-circle me-1"></i>' + changes.join(' • ');
html += '</div>';
}
} catch(e) {}
}
html += '</div>';
});
html += '</div>';
}
document.getElementById('viewOrderBody').innerHTML = html;
window._currentViewOrder = { order: o, items: data.items };
document.getElementById('viewPdfBtn').style.display = '';
}
function downloadOrderPdf() {
if (!window._currentViewOrder) return;
const { order, items } = window._currentViewOrder;
// jsPDF CDN'den yükle
if (typeof window.jspdf === 'undefined' && typeof jsPDF === 'undefined') {
const s = document.createElement('script');
s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
s.onload = () => generatePdf(order, items);
document.head.appendChild(s);
} else {
generatePdf(order, items);
}
}
function generatePdf(order, items) {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Başlık
doc.setFontSize(18);
doc.setTextColor(40, 40, 40);
doc.text('Siparis Listesi', 105, 20, { align: 'center' });
// Çizgi
doc.setDrawColor(200, 168, 76);
doc.setLineWidth(0.8);
doc.line(14, 25, 196, 25);
// Sipariş bilgileri
doc.setFontSize(10);
doc.setTextColor(80, 80, 80);
const dateStr = order.order_date ? order.order_date.split('-').reverse().join('.') : '-';
doc.text('Tedarikci: ' + (order.supplier_name || order.company_name || '-'), 14, 33);
doc.text('Tarih: ' + dateStr, 14, 40);
doc.text('Olusturan: ' + (order.creator_name || '-'), 14, 47);
if (order.general_note) doc.text('Not: ' + order.general_note, 14, 54);
// Tablo başlığı
let y = order.general_note ? 62 : 55;
doc.setFillColor(40, 40, 40);
doc.rect(14, y, 182, 8, 'F');
doc.setTextColor(200, 168, 76);
doc.setFontSize(9);
doc.text('#', 16, y + 5.5);
doc.text('Urun Adi', 25, y + 5.5);
doc.text('Miktar', 110, y + 5.5);
doc.text('~Fiyat', 140, y + 5.5);
doc.text('Toplam', 168, y + 5.5);
y += 10;
let grandTotal = 0;
doc.setTextColor(40, 40, 40);
items.forEach((item, i) => {
const sub = (parseFloat(item.quantity) || 0) * (parseFloat(item.approx_price) || 0);
grandTotal += sub;
if (y > 270) { doc.addPage(); y = 20; }
if (i % 2 === 0) {
doc.setFillColor(245, 245, 245);
doc.rect(14, y - 4, 182, 8, 'F');
}
doc.setFontSize(9);
doc.text(String(i + 1), 16, y + 0.5);
doc.text(String(item.product_name || '').substring(0, 38), 25, y + 0.5);
doc.text((item.quantity || '') + ' ' + (item.unit || ''), 110, y + 0.5);
doc.text(item.approx_price ? item.approx_price + ' TL' : '-', 140, y + 0.5);
doc.text(sub > 0 ? sub.toFixed(2) + ' TL' : '-', 168, y + 0.5);
y += 9;
});
// Toplam satırı
doc.setDrawColor(200, 168, 76);
doc.line(14, y + 2, 196, y + 2);
doc.setFontSize(10);
doc.setTextColor(200, 168, 76);
doc.text('Toplam Tahmini: ' + grandTotal.toFixed(2) + ' TL', 196, y + 9, { align: 'right' });
const filename = 'siparis_' + (order.order_date || 'liste').replace(/-/g, '') + '.pdf';
doc.save(filename);
}
function prependOrderRow(o) {
const tbody = document.getElementById('ordersTbody');
if (!tbody) return;
const emptyRow = document.getElementById('emptyOrdersRow');
if (emptyRow) emptyRow.remove();
const countEl = document.getElementById('ordersCount');
if (countEl) countEl.textContent = parseInt(countEl.textContent || 0) + 1;
const itemCount = o.items.length;
const preview = o.items.slice(0, 3).map(function(i){ return i.product_name; }).join(', ');
const totalPrice = typeof o.total_price === 'number'
? o.total_price.toFixed(2).replace('.', ',')
: '0,00';
const dateStr = o.order_date.split('-').reverse().join('.');
const now = new Date().toLocaleString('tr-TR');
const creatorName = <?= json_encode(e(current_user()['full_name'])) ?>;
const isAdmin = <?= is_admin() ? 'true' : 'false' ?>;
const tr = document.createElement('tr');
tr.id = 'order-row-' + o.id;
// Tedarikçi hücresi
var supCell = o.supplier_name || '';
if (o.supplier_wa) {
supCell += ' <a href="#" onclick="openWhatsApp(' + JSON.stringify(o.supplier_wa) + ',\'\')" class="ms-1" title="WhatsApp"><i class="bi bi-whatsapp text-success fs-12"></i></a>';
}
// WA butonu
var waBtn = '';
if (o.supplier_wa) {
waBtn = '<button class="btn btn-sm btn-outline-success btn-action" onclick="sendOrderWA(' + o.id + ')" title="WhatsApp"><i class="bi bi-whatsapp"></i></button>';
}
// Sil butonu
var delBtn = '';
if (isAdmin) {
delBtn = '<button class="btn btn-sm btn-outline-danger btn-action" onclick="deleteOrder(' + o.id + ')" title="Sil"><i class="bi bi-trash"></i></button>';
}
var previewText = preview.length > 50 ? preview.substring(0, 50) + '...' : preview;
tr.innerHTML =
'<td>' + dateStr + '</td>' +
'<td>' + supCell + '</td>' +
'<td class="fs-12"><span class="badge bg-secondary">' + itemCount + ' urun</span></td>' +
'<td><span class="text-gold fw-bold">' + totalPrice + ' TL</span></td>' +
'<td class="fs-12">' + creatorName + '</td>' +
'<td class="fs-12 text-muted">' + now + '</td>' +
'<td><div class="d-flex gap-1">' +
'<button class="btn btn-sm btn-outline-secondary btn-action" onclick="viewOrder(' + o.id + ')" title="Goruntule"><i class="bi bi-eye"></i></button>' +
'<button class="btn btn-sm btn-outline-secondary btn-action" onclick="openEditOrder(' + o.id + ')" title="Duzenle"><i class="bi bi-pencil"></i></button>' +
waBtn + delBtn +
'</div></td>';
tbody.insertBefore(tr, tbody.firstChild);
// Kısa vurgu animasyonu
tr.style.transition = 'background 0.8s';
tr.style.background = 'rgba(201,168,76,0.15)';
setTimeout(() => { tr.style.background = ''; }, 1500);
}
async function deleteOrder(id) {
if (!confirm('Bu siparişi silmek istiyor musunuz?')) return;
const res = await apiPost('/api/admin/daily_orders.php', { action: 'delete', id });
if (res.success) { showToast('Silindi.', 'success'); setTimeout(() => location.reload(), 800); }
else showToast(res.message, 'error');
}
</script>