Poprawki w API rachunków i kds
This commit is contained in:
179
api_bills.php
Normal file
179
api_bills.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = [
|
||||
'Database' => 'Gastro',
|
||||
'Uid' => 'sa',
|
||||
'PWD' => 'karczma!@#26',
|
||||
'CharacterSet' => 'UTF-8',
|
||||
];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
if (!$conn) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd połączenia.']));
|
||||
}
|
||||
|
||||
$tableParam = isset($_GET['table']) ? strtolower(trim($_GET['table'])) : '';
|
||||
// Usunąłem die() na pustym tableParam, aby ułatwić Ci testowanie w przeglądarce!
|
||||
|
||||
// 1. & 2. & 3. Pobranie dzisiejszych rachunków ze statusem 0
|
||||
$tsqlBills = "
|
||||
SELECT
|
||||
r.ID,
|
||||
r.Numer,
|
||||
r.Opis,
|
||||
s.Nazwa as NazwaStolika
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE CAST(r.DataOtwarcia as DATE) = CAST(GETDATE() as DATE)
|
||||
AND r.Status = 0
|
||||
";
|
||||
|
||||
$stmtBills = sqlsrv_query($conn, $tsqlBills);
|
||||
if ($stmtBills === false) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd pobierania rachunków.', 'errors' => sqlsrv_errors()]));
|
||||
}
|
||||
|
||||
$matchedBillIds = [];
|
||||
$bills = [];
|
||||
|
||||
// 4. Filtrujemy rachunki po nazwie stolika (tak jak w JS)
|
||||
while ($row = sqlsrv_fetch_array($stmtBills, SQLSRV_FETCH_ASSOC)) {
|
||||
$stolikNazwa = strtolower($row['NazwaStolika'] ?? '');
|
||||
$opis = strtolower($row['Opis'] ?? '');
|
||||
|
||||
// Elastyczne dopasowanie, uwzględnia literówkę 0 zamiast O
|
||||
$normalizedTableParam = str_replace('o', '0', $tableParam);
|
||||
$normalizedStolikNazwa = str_replace('o', '0', $stolikNazwa);
|
||||
$normalizedOpis = str_replace('o', '0', $opis);
|
||||
|
||||
$isMatched = false;
|
||||
|
||||
if (!$tableParam) {
|
||||
// Jeśli testujesz w przeglądarce bez parametru ?table=, pokażemy WSZYSTKIE otwarte rachunki
|
||||
$isMatched = true;
|
||||
} else {
|
||||
$pattern = '/\b' . preg_quote($normalizedTableParam, '/') . '\b/i';
|
||||
if (
|
||||
$normalizedStolikNazwa === $normalizedTableParam ||
|
||||
$normalizedOpis === $normalizedTableParam ||
|
||||
preg_match($pattern, $normalizedStolikNazwa) ||
|
||||
preg_match($pattern, $normalizedOpis)
|
||||
) {
|
||||
$isMatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isMatched) {
|
||||
$billId = $row['ID'];
|
||||
$matchedBillIds[] = $billId;
|
||||
$bills[$billId] = [
|
||||
'id' => $billId,
|
||||
'numer' => $row['Numer'],
|
||||
'opis' => $row['Opis'],
|
||||
'suma' => 0,
|
||||
'pozycje' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($matchedBillIds)) {
|
||||
die(json_encode(['status' => 'success', 'data' => []]));
|
||||
}
|
||||
|
||||
// 5. Pobranie pozycji dla dopasowanych rachunków
|
||||
$inClause = implode("','", $matchedBillIds);
|
||||
|
||||
$tsqlItems = "
|
||||
SELECT
|
||||
rp.DTRachunekID,
|
||||
rp.ID as PozycjaID,
|
||||
ISNULL(NULLIF(t.NazwaNaZamowieniu, ''), t.NazwaTowaru) as NazwaTowaru,
|
||||
ISNULL(NULLIF(tz.NazwaNaZamowieniu, ''), tz.NazwaTowaru) as NazwaZestawu,
|
||||
rp.GrupaZestawuID,
|
||||
rp.ZestawID,
|
||||
rp.Ilosc,
|
||||
rp.Cena,
|
||||
rp._c_Wartosc
|
||||
FROM dbo.NGastroDTRachunekPozycja rp
|
||||
LEFT JOIN dbo.NGastroTowar t ON t.ID = rp.TowarID
|
||||
LEFT JOIN dbo.NGastroTowar tz ON tz.ID = rp.ZestawID
|
||||
WHERE rp.DTRachunekID IN ('$inClause')
|
||||
";
|
||||
|
||||
$stmtItems = sqlsrv_query($conn, $tsqlItems);
|
||||
if ($stmtItems === false) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd pobierania pozycji.', 'errors' => sqlsrv_errors()]));
|
||||
}
|
||||
|
||||
// 1. Grupujemy najpierw w fizyczne "Dania" (składniki pizzy łączą się w jedną pizzę)
|
||||
$dishes = [];
|
||||
while ($row = sqlsrv_fetch_array($stmtItems, SQLSRV_FETCH_ASSOC)) {
|
||||
$billId = $row['DTRachunekID'];
|
||||
$groupId = !empty($row['GrupaZestawuID']) ? $row['GrupaZestawuID'] : $row['PozycjaID'];
|
||||
|
||||
if (!isset($dishes[$billId])) {
|
||||
$dishes[$billId] = [];
|
||||
}
|
||||
|
||||
$ilosc = floatval($row['Ilosc']);
|
||||
$wartosc = floatval($row['_c_Wartosc']);
|
||||
|
||||
if (!isset($dishes[$billId][$groupId])) {
|
||||
$nazwa = trim(!empty($row['NazwaZestawu']) ? $row['NazwaZestawu'] : $row['NazwaTowaru']);
|
||||
$dishes[$billId][$groupId] = [
|
||||
'nazwa' => $nazwa ?: 'Brak nazwy',
|
||||
'ilosc' => $ilosc,
|
||||
'wartosc' => 0
|
||||
];
|
||||
} else {
|
||||
// Zabezpieczenie: bierzemy największą ilość ze składników (np. jak ktoś usunął składnik i ma ilość 0)
|
||||
if ($ilosc > $dishes[$billId][$groupId]['ilosc']) {
|
||||
$dishes[$billId][$groupId]['ilosc'] = $ilosc;
|
||||
}
|
||||
}
|
||||
|
||||
// Zawsze sumujemy wartość składników (ser 53zł + ciasto 0zł = 53zł)
|
||||
$dishes[$billId][$groupId]['wartosc'] += $wartosc;
|
||||
}
|
||||
|
||||
// 2. Mając pełne dania, redukujemy je (np. dwie takie same pizze "ZADYMIONA BACÓWKA" w jeden wiersz x2)
|
||||
foreach ($dishes as $billId => $billDishes) {
|
||||
$groupedByMenu = [];
|
||||
|
||||
foreach ($billDishes as $dish) {
|
||||
$nazwa = $dish['nazwa'];
|
||||
$ilosc = $dish['ilosc'];
|
||||
$wartosc = $dish['wartosc'];
|
||||
|
||||
// Cena jednostkowa uśredniona
|
||||
$cenaJednostkowa = $ilosc > 0 ? ($wartosc / $ilosc) : $wartosc;
|
||||
|
||||
$key = $nazwa . "_" . number_format($cenaJednostkowa, 2, '.', '');
|
||||
|
||||
if (!isset($groupedByMenu[$key])) {
|
||||
$groupedByMenu[$key] = [
|
||||
'nazwa' => $nazwa,
|
||||
'ilosc' => 0,
|
||||
'cena' => $cenaJednostkowa,
|
||||
'wartosc' => 0
|
||||
];
|
||||
}
|
||||
|
||||
$groupedByMenu[$key]['ilosc'] += $ilosc;
|
||||
$groupedByMenu[$key]['wartosc'] += $wartosc;
|
||||
$bills[$billId]['suma'] += $wartosc;
|
||||
}
|
||||
|
||||
$bills[$billId]['pozycje'] = array_values($groupedByMenu);
|
||||
}
|
||||
|
||||
$finalData = [];
|
||||
foreach ($bills as $bill) {
|
||||
$finalData[] = $bill;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $finalData
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
50
api_kds.php
50
api_kds.php
@@ -22,6 +22,8 @@ if (!$conn) {
|
||||
]));
|
||||
}
|
||||
|
||||
$tableParam = isset($_GET['table']) ? strtolower(trim($_GET['table'])) : '';
|
||||
|
||||
// Zapytanie SQL wyciągające aktywne pozycje (StatusRealizacji < 4)
|
||||
// Łączymy NGastroDTRachunekPozycja z NGastroDTRachunek (żeby mieć stolik) i z NGastroTowar (żeby mieć nazwę)
|
||||
$tsql = "
|
||||
@@ -29,6 +31,7 @@ $tsql = "
|
||||
r.StolikID,
|
||||
s.Nazwa AS NazwaStolika,
|
||||
r.Numer AS NumerRachunku,
|
||||
r.Opis,
|
||||
r.NumerReczny AS NumerRecznyRachunku,
|
||||
rp.ID AS PozycjaID,
|
||||
rp.StatusRealizacji,
|
||||
@@ -47,10 +50,12 @@ $tsql = "
|
||||
LEFT JOIN dbo.NGastroTowar t ON t.ID = rp.TowarID
|
||||
LEFT JOIN dbo.NGastroTowar tz ON tz.ID = rp.ZestawID
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE rp.StatusRealizacji = 1
|
||||
LEFT JOIN dbo.NGastroKonfiguracjaDrukowaniaZamowien kdz ON kdz.ID = ISNULL(rp.KonfiguracjaDrukowaniaZamowienID, t.KonfiguracjaDrukowaniaZamowienID)
|
||||
WHERE r.Status = 0
|
||||
AND rp.StatusRealizacji > 0
|
||||
AND rp.StatusRealizacji < 4
|
||||
AND kdz.ID IS NOT NULL
|
||||
AND CAST(rp.DataDodania AS DATE) = CAST(GETDATE() AS DATE)
|
||||
-- Opcjonalnie: pominięcie usuniętych pozycji, zazwyczaj posiadają DataUsuniecia różną od domyślnej,
|
||||
-- lub oznaczane są poprzez inny mechanizm, ale na razie trzymajmy się StatusRealizacji
|
||||
AND rp.DataUsuniecia = '1900-01-01'
|
||||
ORDER BY rp.DataDodania ASC
|
||||
";
|
||||
@@ -67,17 +72,38 @@ if ($stmt === false) {
|
||||
|
||||
$pozycje = [];
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
// Formatowanie daty dla JSON (obiekt DateTime w PHP do ISO 8601)
|
||||
if ($row['DataDodania'] instanceof DateTime) {
|
||||
$row['DataDodania'] = $row['DataDodania']->format('Y-m-d H:i:s');
|
||||
$stolikNazwa = strtolower($row['NazwaStolika'] ?? '');
|
||||
$opis = strtolower($row['Opis'] ?? '');
|
||||
|
||||
$normalizedTableParam = str_replace('o', '0', $tableParam);
|
||||
$normalizedStolikNazwa = str_replace('o', '0', $stolikNazwa);
|
||||
$normalizedOpis = str_replace('o', '0', $opis);
|
||||
|
||||
$isMatched = false;
|
||||
if (!$tableParam) {
|
||||
$isMatched = true;
|
||||
} else {
|
||||
$pattern = '/\b' . preg_quote($normalizedTableParam, '/') . '\b/i';
|
||||
if (
|
||||
$normalizedStolikNazwa === $normalizedTableParam ||
|
||||
$normalizedOpis === $normalizedTableParam ||
|
||||
preg_match($pattern, $normalizedStolikNazwa) ||
|
||||
preg_match($pattern, $normalizedOpis)
|
||||
) {
|
||||
$isMatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Rzutowanie wartości, aby uniknąć problemów w JSON
|
||||
$row['StolikID'] = $row['StolikID'] ? strtoupper($row['StolikID']) : null;
|
||||
$row['PozycjaID'] = strtoupper($row['PozycjaID']);
|
||||
$row['TowarID'] = strtoupper($row['TowarID']);
|
||||
|
||||
$pozycje[] = $row;
|
||||
if ($isMatched) {
|
||||
if ($row['DataDodania'] instanceof DateTime) {
|
||||
$row['DataDodania'] = $row['DataDodania']->format('Y-m-d H:i:s');
|
||||
}
|
||||
$row['StolikID'] = $row['StolikID'] ? strtoupper($row['StolikID']) : null;
|
||||
$row['PozycjaID'] = strtoupper($row['PozycjaID']);
|
||||
$row['TowarID'] = strtoupper($row['TowarID']);
|
||||
|
||||
$pozycje[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
// Zwracamy czysty JSON
|
||||
|
||||
16
check_o61.php
Normal file
16
check_o61.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = ['Database' => 'Gastro', 'Uid' => 'sa', 'PWD' => 'karczma!@#26', 'CharacterSet' => 'UTF-8'];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
$tsql = "
|
||||
SELECT
|
||||
r.ID, r.Numer, r.Opis, s.Nazwa as NazwaStolika, r.Status, r.FlgRozliczony, r.DataOtwarcia, r.DataZamkniecia
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE (r.Opis LIKE '%61%' OR s.Nazwa LIKE '%61%')
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $tsql);
|
||||
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
echo "Num: {$row['Numer']} | Opis: {$row['Opis']} | Stolik: {$row['NazwaStolika']} | Stat: {$row['Status']} | Rozl: {$row['FlgRozliczony']} | Otw: {$row['DataOtwarcia']->format('Y-m-d H:i')} | Zamkn: {$row['DataZamkniecia']->format('Y-m-d H:i')}\n";
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -84,8 +84,34 @@
|
||||
<button class="close-btn" onclick="closeBillDialog()">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Step 0: Loading or List of Bills -->
|
||||
<div class="step active" id="stepBillList">
|
||||
<div id="billLoading" style="text-align:center; padding: 20px;">
|
||||
⏳ Pobieranie rachunków...
|
||||
</div>
|
||||
<div id="billListContainer" class="hidden">
|
||||
<p style="margin-top:0; color:var(--text-muted); font-size:14px; margin-bottom: 20px;">Mamy kilka otwartych rachunków na tym stoliku. Który chcesz opłacić?</p>
|
||||
<div id="billListItems" style="display:flex; flex-direction:column; gap:10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 0.5: Bill Review -->
|
||||
<div class="step" id="stepBillReview">
|
||||
<p style="margin-top:0; color:var(--text-muted); font-size:14px; margin-bottom: 20px;">Podsumowanie rachunku:</p>
|
||||
<div id="billReviewContent" style="background: var(--surface-light); padding: 15px; border-radius: 12px; max-height: 40vh; overflow-y: auto; margin-bottom: 15px;">
|
||||
</div>
|
||||
<div style="display:flex; justify-content:space-between; font-weight:700; font-size:18px; margin-bottom: 20px;">
|
||||
<span>Do zapłaty:</span>
|
||||
<span id="billTotalAmount" style="color:var(--primary);">0.00 PLN</span>
|
||||
</div>
|
||||
<div style="display:flex; gap:12px;">
|
||||
<button class="btn btn-secondary" style="flex:1;" onclick="goBackToBillList()" id="btnBackToBills">Wróć</button>
|
||||
<button class="btn btn-primary" style="flex:2;" onclick="goToStep('stepPayment')">Dalej</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 1: Payment Method -->
|
||||
<div class="step active" id="stepPayment">
|
||||
<div class="step" id="stepPayment">
|
||||
<p style="margin-top:0; color:var(--text-muted); font-size:14px; margin-bottom: 20px;">Wybierz preferowaną formę płatności:</p>
|
||||
<div class="option-grid">
|
||||
<div class="option-card" onclick="selectPayment('karta')">
|
||||
@@ -97,6 +123,7 @@
|
||||
<span class="option-label">Gotówka</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-secondary" onclick="goToStep('stepBillReview')" style="margin-top: 15px;">Wróć do podsumowania</button>
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Document Type -->
|
||||
|
||||
25
test_all_open.php
Normal file
25
test_all_open.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = ['Database' => 'Gastro', 'Uid' => 'sa', 'PWD' => 'karczma!@#26', 'CharacterSet' => 'UTF-8'];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
$tsql = "
|
||||
SELECT
|
||||
r.ID as RachunekID,
|
||||
r.Numer as RachunekNumer,
|
||||
r.Opis,
|
||||
s.Nazwa as NazwaStolika,
|
||||
r.DataOtwarcia
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE r.Status = 0
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $tsql);
|
||||
$count = 0;
|
||||
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$count++;
|
||||
if ($count <= 20) {
|
||||
echo "Rachunek: " . $row['RachunekNumer'] . " | Opis: " . $row['Opis'] . " | Stolik: " . $row['NazwaStolika'] . " | Otwarcia: " . $row['DataOtwarcia']->format('Y-m-d') . "\n";
|
||||
}
|
||||
}
|
||||
echo "Total open bills: $count\n";
|
||||
134
test_api_bills.php
Normal file
134
test_api_bills.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
$_GET['table'] = 'O-47';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = [
|
||||
'Database' => 'Gastro',
|
||||
'Uid' => 'sa',
|
||||
'PWD' => 'karczma!@#26',
|
||||
'CharacterSet' => 'UTF-8',
|
||||
];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
if (!$conn) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd połączenia.']));
|
||||
}
|
||||
|
||||
$tableParam = isset($_GET['table']) ? strtolower(trim($_GET['table'])) : '';
|
||||
if (!$tableParam) {
|
||||
die(json_encode(['status' => 'success', 'data' => []]));
|
||||
}
|
||||
|
||||
// 1. & 2. & 3. Pobranie dzisiejszych rachunków ze statusem 0
|
||||
$tsqlBills = "
|
||||
SELECT
|
||||
r.ID,
|
||||
r.Numer,
|
||||
r.Opis,
|
||||
s.Nazwa as NazwaStolika
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE CAST(r.DataOtwarcia as DATE) = CAST(GETDATE() as DATE)
|
||||
AND r.Status = 0
|
||||
";
|
||||
|
||||
$stmtBills = sqlsrv_query($conn, $tsqlBills);
|
||||
if ($stmtBills === false) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd pobierania rachunków.', 'errors' => sqlsrv_errors()]));
|
||||
}
|
||||
|
||||
$matchedBillIds = [];
|
||||
$bills = [];
|
||||
|
||||
// 4. Filtrujemy rachunki po nazwie stolika (tak jak w JS)
|
||||
while ($row = sqlsrv_fetch_array($stmtBills, SQLSRV_FETCH_ASSOC)) {
|
||||
$stolikNazwa = strtolower($row['NazwaStolika'] ?? '');
|
||||
$opis = strtolower($row['Opis'] ?? '');
|
||||
|
||||
// Elastyczne dopasowanie, uwzględnia literówkę 0 zamiast O
|
||||
$normalizedTableParam = str_replace('o', '0', $tableParam);
|
||||
$normalizedStolikNazwa = str_replace('o', '0', $stolikNazwa);
|
||||
$normalizedOpis = str_replace('o', '0', $opis);
|
||||
|
||||
if (
|
||||
$stolikNazwa === $tableParam ||
|
||||
strpos($stolikNazwa, $tableParam) !== false ||
|
||||
$opis === $tableParam ||
|
||||
strpos($opis, $tableParam) !== false ||
|
||||
$normalizedStolikNazwa === $normalizedTableParam ||
|
||||
strpos($normalizedStolikNazwa, $normalizedTableParam) !== false ||
|
||||
strpos($normalizedOpis, $normalizedTableParam) !== false
|
||||
) {
|
||||
$billId = $row['ID'];
|
||||
$matchedBillIds[] = $billId;
|
||||
$bills[$billId] = [
|
||||
'id' => $billId,
|
||||
'numer' => $row['Numer'],
|
||||
'opis' => $row['Opis'],
|
||||
'suma' => 0,
|
||||
'pozycje' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($matchedBillIds)) {
|
||||
die(json_encode(['status' => 'success', 'data' => []]));
|
||||
}
|
||||
|
||||
// 5. Pobranie pozycji dla dopasowanych rachunków
|
||||
$inClause = implode("','", $matchedBillIds);
|
||||
|
||||
$tsqlItems = "
|
||||
SELECT
|
||||
rp.DTRachunekID,
|
||||
rp.ID as PozycjaID,
|
||||
ISNULL(NULLIF(t.NazwaNaZamowieniu, ''), t.NazwaTowaru) as NazwaTowaru,
|
||||
rp.Ilosc,
|
||||
rp.Cena,
|
||||
rp._c_Wartosc
|
||||
FROM dbo.NGastroDTRachunekPozycja rp
|
||||
LEFT JOIN dbo.NGastroTowar t ON t.ID = rp.TowarID
|
||||
WHERE rp.DTRachunekID IN ('$inClause')
|
||||
";
|
||||
|
||||
$stmtItems = sqlsrv_query($conn, $tsqlItems);
|
||||
if ($stmtItems === false) {
|
||||
die(json_encode(['status' => 'error', 'message' => 'Błąd pobierania pozycji.', 'errors' => sqlsrv_errors()]));
|
||||
}
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtItems, SQLSRV_FETCH_ASSOC)) {
|
||||
$billId = $row['DTRachunekID'];
|
||||
|
||||
$nazwa = trim($row['NazwaTowaru'] ?? 'Brak nazwy');
|
||||
$ilosc = floatval($row['Ilosc']);
|
||||
$wartosc = floatval($row['_c_Wartosc']);
|
||||
$cena = floatval($row['Cena']);
|
||||
|
||||
// Grouping
|
||||
$key = $nazwa . "_" . $cena;
|
||||
if (!isset($bills[$billId]['pozycje'][$key])) {
|
||||
$bills[$billId]['pozycje'][$key] = [
|
||||
'nazwa' => $nazwa,
|
||||
'ilosc' => 0,
|
||||
'cena' => $cena,
|
||||
'wartosc' => 0
|
||||
];
|
||||
}
|
||||
|
||||
$bills[$billId]['pozycje'][$key]['ilosc'] += $ilosc;
|
||||
$bills[$billId]['pozycje'][$key]['wartosc'] += $wartosc;
|
||||
$bills[$billId]['suma'] += $wartosc;
|
||||
}
|
||||
|
||||
$finalData = [];
|
||||
foreach ($bills as $bill) {
|
||||
$bill['pozycje'] = array_values($bill['pozycje']);
|
||||
$finalData[] = $bill;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $finalData
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
23
test_kdz.php
Normal file
23
test_kdz.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = ['Database' => 'Gastro', 'Uid' => 'sa', 'PWD' => 'karczma!@#26', 'CharacterSet' => 'UTF-8'];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
$tsql = "
|
||||
SELECT TOP 20
|
||||
ISNULL(NULLIF(t.NazwaNaZamowieniu, ''), t.NazwaTowaru) as NazwaTowaru,
|
||||
rp.KonfiguracjaDrukowaniaZamowienID as RP_Konf,
|
||||
t.KonfiguracjaDrukowaniaZamowienID as T_Konf,
|
||||
kdz.SposobDrukowaniaZamowienID,
|
||||
kdz.DrukarkaZamowienID,
|
||||
kdz.DrukarkaFiskalnaID
|
||||
FROM dbo.NGastroDTRachunekPozycja rp
|
||||
LEFT JOIN dbo.NGastroTowar t ON t.ID = rp.TowarID
|
||||
LEFT JOIN dbo.NGastroKonfiguracjaDrukowaniaZamowien kdz ON kdz.ID = ISNULL(rp.KonfiguracjaDrukowaniaZamowienID, t.KonfiguracjaDrukowaniaZamowienID)
|
||||
WHERE CAST(rp.DataDodania AS DATE) = CAST(GETDATE() AS DATE)
|
||||
AND rp.StatusRealizacji = 1
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $tsql);
|
||||
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
print_r($row);
|
||||
}
|
||||
22
test_match.php
Normal file
22
test_match.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = ['Database' => 'Gastro', 'Uid' => 'sa', 'PWD' => 'karczma!@#26', 'CharacterSet' => 'UTF-8'];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
$tableParam = 'O-61';
|
||||
|
||||
$tsql = "
|
||||
SELECT
|
||||
r.ID as RachunekID,
|
||||
r.Numer as RachunekNumer,
|
||||
r.Opis,
|
||||
s.Nazwa as NazwaStolika
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE CAST(r.DataOtwarcia as DATE) = CAST(GETDATE() as DATE)
|
||||
AND r.Status = 0
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $tsql);
|
||||
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
echo "Rachunek: " . $row['RachunekNumer'] . " | Opis: " . $row['Opis'] . " | Stolik: " . $row['NazwaStolika'] . "\n";
|
||||
}
|
||||
20
test_today.php
Normal file
20
test_today.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
$serverName = '192.168.20.20';
|
||||
$connectionOptions = ['Database' => 'Gastro', 'Uid' => 'sa', 'PWD' => 'karczma!@#26', 'CharacterSet' => 'UTF-8'];
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
$tsql = "
|
||||
SELECT
|
||||
r.ID as RachunekID,
|
||||
r.Numer as RachunekNumer,
|
||||
r.Opis,
|
||||
s.Nazwa as NazwaStolika,
|
||||
r.DataOtwarcia
|
||||
FROM dbo.NGastroDTRachunek r
|
||||
LEFT JOIN dbo.NGastroStolik s ON s.ID = r.StolikID
|
||||
WHERE CAST(r.DataOtwarcia as DATE) = CAST(GETDATE() as DATE)
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $tsql);
|
||||
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
echo "Rachunek: " . $row['RachunekNumer'] . " | Opis: " . $row['Opis'] . " | Stolik: " . $row['NazwaStolika'] . " | Otwarcia: " . $row['DataOtwarcia']->format('Y-m-d H:i:s') . "\n";
|
||||
}
|
||||
Reference in New Issue
Block a user