Poprawki w API rachunków i kds

This commit is contained in:
2026-05-24 22:20:23 +02:00
parent 58fae2f0e6
commit f95f578bab
10 changed files with 597 additions and 53 deletions

View File

@@ -251,27 +251,13 @@ const params = new URLSearchParams(location.search);
});
});
// Pozycje, które były wcześniej, ale zniknęły z WS -> zostają jako gotowe
// Pozycje, które były wcześniej, ale zniknęły z API -> przesyłamy od razu do historii globalnej
persistedMap.forEach((oldItem, name) => {
if (current.has(name)) return;
const qty = Number.isFinite(oldItem?.qty) ? oldItem.qty : 0;
const archivedAt = Number.isFinite(oldItem?.archivedAt) ? oldItem.archivedAt : Date.now();
const shouldMoveToGlobal = (Date.now() - archivedAt) > HOT_WINDOW_MS;
if (shouldMoveToGlobal) {
addItemsToGlobalHistory([{ name, qty }], tableParam);
return;
}
merged.push({
name,
qty,
done: qty,
present: false,
completedByDisappear: true,
archivedAt,
updatedAt: Date.now()
});
// Zniknęło z bieżącego rachunku (np. rachunek został zamknięty), od razu leci do osobnego bloku historii!
addItemsToGlobalHistory([{ name, qty }], tableParam);
});
// Aktywne na górze, gotowe (zniknięte) na dole
@@ -352,38 +338,40 @@ const params = new URLSearchParams(location.search);
// API Fetch Logic
async function fetchOrders() {
try {
const response = await fetch('../api_kds.php');
if (!tableParam) {
updateUI([]);
return;
}
const response = await fetch(`../api_kds.php?table=${encodeURIComponent(tableParam)}`);
const result = await response.json();
if (result.status === 'success') {
if (!tableParam) {
updateUI([]);
return;
}
// API teraz samo filtruje i zwraca tylko to co nas interesuje (za pomocą mocnego wyrażenia regularnego)
const matches = result.data;
const myTable = tableParam.toLowerCase();
// Filtrowanie pozycji dla wybranego stolika
const matches = result.data.filter(item => {
const stolikNazwa = (item.NazwaStolika || '').toLowerCase();
const stolikId = (item.StolikID || '').toLowerCase();
// Sprawdzamy czy nazwa stolika z bazy zawiera numer szukany (np. O-61) lub czy ID się zgadza
return stolikNazwa === myTable || stolikId === myTable || stolikNazwa.includes(myTable);
});
// Grupowanie składników w główne dania, żeby klient widział "Pierogi" a nie "Opakowanie"
// Grupowanie składników w główne dania
const groups = {};
matches.forEach(item => {
const groupId = item.GrupaZestawuID || item.PozycjaID;
if (!groups[groupId]) {
groups[groupId] = {
Name: item.NazwaZestawu || item.NazwaTowaru,
QuantitySet: item.GrupaZestawuID ? 1 : parseFloat(item.Ilosc)
QuantitySet: item.GrupaZestawuID ? 1 : parseFloat(item.Ilosc),
Done: 0
};
}
// StatusRealizacji >= 2 oznacza, że kucharz wcisnął "Gotowe" na swoim ekranie
if (parseInt(item.StatusRealizacji, 10) >= 2) {
groups[groupId].Done = groups[groupId].QuantitySet;
}
});
const transformedArticles = Object.values(groups);
const transformedArticles = Object.values(groups).map(g => ({
Name: g.Name,
QuantitySet: g.QuantitySet,
QuantityDone: g.Done
}));
// Najnowszy czas dodania (do pokazania w stopce)
const latestDate = matches.length > 0
@@ -436,10 +424,93 @@ const params = new URLSearchParams(location.search);
}
};
window.openBillDialog = function() {
billState = { payment: '', doc: '', nip: '', company: null };
window.openBillDialog = async function() {
billState = { payment: '', doc: '', nip: '', company: null, selectedBillId: null };
document.getElementById("billModal").classList.add("active");
goToStep("stepPayment");
document.getElementById("billLoading").classList.remove("hidden");
document.getElementById("billListContainer").classList.add("hidden");
goToStep("stepBillList");
try {
const res = await fetch(`../api_bills.php?table=${encodeURIComponent(tableParam)}`);
const result = await res.json();
if (result.status === 'success' && result.data.length > 0) {
const bills = result.data;
if (bills.length === 1) {
showBillReview(bills[0]);
document.getElementById("btnBackToBills").style.display = 'none';
} else {
renderBillList(bills);
document.getElementById("btnBackToBills").style.display = 'block';
}
} else {
document.getElementById("billLoading").innerHTML = "Brak otwartych rachunków do opłacenia.";
}
} catch (err) {
document.getElementById("billLoading").innerHTML = "Błąd pobierania rachunków.";
}
};
function renderBillList(bills) {
document.getElementById("billLoading").classList.add("hidden");
document.getElementById("billListContainer").classList.remove("hidden");
const container = document.getElementById("billListItems");
container.innerHTML = "";
bills.forEach(b => {
const div = document.createElement("div");
div.className = "option-card";
div.style.flexDirection = "row";
div.style.justifyContent = "space-between";
div.style.padding = "15px";
div.onclick = () => showBillReview(b);
const numerFormat = b.numer ? `#${b.numer}` : "Rachunek";
div.innerHTML = `
<div>
<div style="font-weight:bold;">${numerFormat}</div>
<div style="font-size:12px; color:var(--text-muted);">${b.opis}</div>
</div>
<div style="font-weight:bold; color:var(--primary);">${b.suma.toFixed(2)} PLN</div>
`;
container.appendChild(div);
});
}
window.goBackToBillList = function() {
goToStep("stepBillList");
};
window.showBillReview = function(bill) {
billState.selectedBillId = bill.id;
const content = document.getElementById("billReviewContent");
content.innerHTML = "";
bill.pozycje.forEach(p => {
const div = document.createElement("div");
div.style.display = "flex";
div.style.justifyContent = "space-between";
div.style.marginBottom = "8px";
div.style.borderBottom = "1px solid rgba(255,255,255,0.05)";
div.style.paddingBottom = "8px";
div.innerHTML = `
<div style="flex:1;">
<div style="font-weight:600; font-size: 14px;">${p.nazwa}</div>
<div style="font-size:12px; color:var(--text-muted);">${p.ilosc} x ${p.cena.toFixed(2)} PLN</div>
</div>
<div style="font-weight:600;">${p.wartosc.toFixed(2)} PLN</div>
`;
content.appendChild(div);
});
document.getElementById("billTotalAmount").textContent = bill.suma.toFixed(2) + " PLN";
goToStep("stepBillReview");
};
window.closeBillDialog = function() {
@@ -460,7 +531,7 @@ const params = new URLSearchParams(location.search);
billState.doc = docType;
if (docType === 'paragon') {
closeBillDialog();
sendApiSimulated("CallWaiter_Bill", { table: tableParam, payment: billState.payment, doc: 'paragon' });
sendApiSimulated("CallWaiter_Bill", { table: tableParam, billId: billState.selectedBillId, payment: billState.payment, doc: 'paragon' });
showToast("Kelner przyniesie paragon do opłacenia!");
} else {
goToStep("stepNIP");
@@ -527,6 +598,7 @@ const params = new URLSearchParams(location.search);
closeBillDialog();
sendApiSimulated("CallWaiter_Bill", {
table: tableParam,
billId: billState.selectedBillId,
payment: billState.payment,
doc: 'faktura',
nip: billState.nip,