Plan testów — wszystkie kroki + warianty¶
Kompletny plan testów E2E z konkretnymi krokami, expected behavior i metodą weryfikacji. Szczególnie szczegółowe warianty Kroku 5 (otwarcie skrytki) i Kroku 6 (zamknięcie skrytki).
Setup testowy¶
| Pole | Wartość |
|---|---|
| Maszyna | LOCKER-SZB-SDI-001 (Szubin SDI dev, real Modbus hardware) |
| Kiosk version | v1.1.21 (lub nowszy) |
| Bridge | hid-reader.ps1 + SmartBoxHidReader task musi działać |
| E2E Kurier | PIN 261438 — nadawca, używa "Kod nadania" |
| E2E Pracownik | PIN 517796 — odbiorca |
Przed każdym testem sprawdź panel: https://smartbox.ergoflow.app/dashboard/system/machines/{id} — status ONLINE, currentVersion 1.1.21.
Mapa testów¶
flowchart LR
A[Test 1-3<br/>Login / PIN / Profile] --> B[Test 4 Happy<br/>full deposit cycle]
B --> C[Test 5 KROK 5<br/>otwarcie skrytki<br/>warianty 5.A → 5.F]
C --> D[Test 6 KROK 6<br/>zamknięcie skrytki<br/>warianty 6.A → 6.H]
D --> E[Test 7-11<br/>backend guards]
E --> F[Test 12-20<br/>evil paths + cleanup]
Test 1 — Login PIN¶
Setup: świeży kiosk na ekranie login.
Kroki:
1. Kliknij zakładkę PIN
2. Wpisz 517796
3. Tap ✓
Expected: ekran menu główne usera "E2E Pracownik".
Weryfikacja: Credential.lastUsedAt zaktualizowane w DB.
Test 2 — Wrong PIN (buffer clear)¶
Kroki:
1. PIN tab → wpisz 000000 → ✓
2. Pokaże się: 🔴 "Nie rozpoznano PIN-u"
3. Wpisz drugi PIN 517796 → ✓
Expected: PinPad wyzerowany przed drugim wpisaniem (operator nie powinien widzieć żadnych pozostałych kropek po pierwszej próbie). Drugi login OK.
Test 3 — Profile (edycja telefonu + locale)¶
Kroki:
1. Login PIN 517796
2. Menu → "Mój profil"
3. Zmień telefon na +48 600 100 200
4. Zmień język na EN
5. Tap "Zapisz"
Expected: Toast sukcesu. Wyloguj się i zaloguj ponownie — interfejs w EN.
Test 4 — Deposit happy path (full cycle)¶
Setup: w panelu utwórz świeżą paczkę dla E2E Pracownik (lub użyj jednej z 5 pre-seeded: 995354 / 969031 / 915274 / 146795 / 462257).
Kroki:
1. Login PIN 261438 (Kurier)
2. Menu → "Nadaj paczkę" → "Kod nadania"
3. Wpisz ostatnie 6 cyfr trackingId (np. 995354)
4. Wybierz rozmiar M
5. Pre-confirm → "Otwórz teraz"
6. Drzwi się otwierają → włóż coś (kartka A4)
7. Zamknij drzwi
8. Reopen panel → "Zakończ"
Expected: 🟢 DepositSuccessScreen "Paczka nadana" z QR kodem.
Weryfikacja panel:
- shipment status DEPOSITED
- lockerId ustawiony, depositedAt ≈ NOW
- Timeline: ✅ Utworzono ✅ Przypisano ✅ Złożono w skrytce
- Locker status w panelu: OCCUPIED
Test 5 — KROK 5: Otwarcie skrytki (wszystkie warianty)¶
Krok 5 = moment od tapnięcia "Otwórz teraz" do osiągnięcia stanu "drzwi otwarte, kiosk czeka na zamknięcie". Testujemy każdy realny scenariusz hardware'owy.
Test 5.A — Happy open (sanity)¶
Kroki: Standardowy flow z Test 4 do momentu otwarcia drzwi.
Expected: Pulse Modbus → drzwi otwierają się w <2s → ekran "Skrytka otwarta, włóż paczkę i zamknij" → kiosk czeka.
Weryfikacja: Locker.status = RESERVED (do momentu close).
Test 5.B — Drzwi już otwarte przed pulse (pre-flight detection)¶
Setup: Ręcznie pootwieraj drzwi wybranej skrytki PRZED rozpoczęciem flow.
Kroki:
1. Pełen flow do "Otwórz teraz"
2. _runOpen wywoła hardware.isClosed(N) → zwróci false
3. Kiosk SKIP unlock pulse, przechodzi od razu do phase=open
4. Ekran "Drzwi już otwarte — zamknij gdy gotowe"
Expected: Żadnego E07 z mastera (bo pulse nigdy nie poszedł). Operator zamyka drzwi normalnie → happy path.
Weryfikacja: Brak fault reportu, shipment idzie do DEPOSITED.
Test 5.C — Master Modbus offline (firewall)¶
Setup: Na kiosku jako Admin: netsh advfirewall firewall add rule name="block-modbus-test" dir=out action=block protocol=TCP remoteport=502
Kroki: 1. Deposit flow do "Otwórz teraz" 2. Driver próbuje wysłać Modbus command → po ~12s timeout
Expected: 🟡 Fault dialog "Wystąpił problem techniczny" z _phasePriorToFault=opening → przyciski [🔄 Spróbuj ponownie] [Anuluj] (oba widoczne — retry MA SENS bo drzwi się nie otworzyły).
Weryfikacja:
- W panelu Zgłoszenia: MACHINE-reported, faultCode: E07-DRIVER, currentPhase: opening
- Po Anuluj → shipment CREATED, locker BROKEN
Cleanup: netsh advfirewall firewall delete rule name="block-modbus-test" + admin reset locker'a w panelu.
Test 5.D — Door open timeout E07 (drzwi mechanicznie zacięte)¶
Setup: Wybierz lockera który mechanicznie się nie otwiera, lub trzymaj drzwi siłą zamknięte w momencie pulse.
Kroki: 1. Deposit flow → "Otwórz teraz" 2. Master wyśle pulse, ale sensor nie wykryje otwarcia 3. Master emituje E07 po ~30s
Expected: Fault dialog "Wystąpił problem techniczny" + przyciski [🔄 Spróbuj ponownie] [Anuluj].
Weryfikacja:
- Zgłoszenia: MACHINE-reported, faultCode: E07, sensorByte + masterMW100 zapisane
- Spróbuj ponownie → force re-fire pulse (forceCommand=true)
- Anuluj → locker BROKEN, shipment CREATED
Test 5.E — Driver timeout (brak ACK z mastera, sieć cool)¶
Setup: Trudne do zasymulowania bez modyfikacji hardware. W praktyce dzieje się przy network glitchu Modbus TCP.
Kroki:
1. Deposit flow → "Otwórz teraz"
2. hardware.open() rzuca TimeoutException (12s default)
Expected: Identyczny UI jak 5.D, ale faultCode: E07-DRIVER (rozróżnienie w panel).
Test 5.F — "Zgłoś obsłudze" w opening phase¶
Kroki:
1. Deposit flow → "Otwórz teraz"
2. W trakcie animacji opening, jeśli pojawi się userConfirmOpened dialog (20s bez opened event) — tap "Zgłoś obsłudze"
Expected: USER-reported fault, phase=faultReported, _phasePriorToFault=userConfirmOpened.
Weryfikacja:
- v1.1.21: przyciski TYLKO [Anuluj] (BRAK Spróbuj ponownie — drzwi już są fizycznie w jakimś dziwnym stanie)
- Po Anuluj → shipment CREATED, locker BROKEN, USER fault report z currentPhase: opening
Test 6 — KROK 6: Zamknięcie skrytki (wszystkie warianty)¶
Krok 6 = moment od momentu kiedy drzwi są fizycznie otwarte, do osiągnięcia stanu DEPOSITED/PICKED_UP po reopen panel. Testujemy wszystkie scenariusze close + reopen + Anuluj.
Test 6.A — Happy close: zamknij + "Zakończ"¶
Kroki: 1. Drzwi otwarte → wkładasz coś (deposit) lub wyjmujesz (pickup) → zamknij drzwi 2. Reopen panel pojawia się z 3 przyciskami (deposit) lub 2 (pickup) 3. Tap "Zakończ"
Expected: 🟢 DepositSuccessScreen / "Paczka odebrana".
Weryfikacja: status DEPOSITED/PICKED_UP, locker OCCUPIED/FREE, audit log notification.
Test 6.B — Happy close + auto-pop countdown (10s)¶
Kroki: 1. Zamknij drzwi → reopen panel 2. Nie tap żadnego przycisku przez 10s
Expected: Countdown z 10 do 0, auto-pop, identyczny stan jak Test 6.A.
Test 6.C — "Otwórz ponownie" normalny¶
Kroki: 1. Zamknij drzwi → reopen panel 2. Tap 🔵 "Otwórz ponownie" 3. Drzwi otwierają się znów → zamknij ponownie → reopen panel pojawia się znowu 4. Tap "Zakończ"
Expected:
- Drugi open pulse poszedł do hardware (drzwi się otworzyły)
- Backend: drugi markDeposited zwrócił 409 ConflictException (już DEPOSITED), kiosk zignorował silent
- Audit log: dokładnie JEDEN system.notification_shipment.deposited (nie dwa!)
- Finalny stan: DEPOSITED + OCCUPIED bez korupcji
Test 6.D — Race: "Otwórz ponownie" w trakcie blokowania¶
Cel: Bug operator'a — klikał Otwórz ponownie zaraz po pierwszym kliknięciu (w trakcie animacji blokowania) → komunikat o błędzie z hardware.
Kroki: 1. Zamknij drzwi → reopen panel 2. Tap "Otwórz ponownie" 3. Bardzo szybko (200ms-1s) tap "Otwórz ponownie" ponownie 3-4 razy
Expected (v1.1.14+): Tylko PIERWSZY tap się wykonuje. Kolejne tap'y w trakcie phase=opening są dropowane przez early-return guard if (_phase != _Phase.done) return;.
Weryfikacja:
- agent.log na kiosku: tylko jeden modbus.command.sent
- Brak komunikatów o błędzie z hardware
- Brak E16 z mastera
Test 6.E — "Anuluj — paczki nie ma w skrytce" (czerwony, deposit only)¶
Cel: v1.1.11 NEW endpoint — operator zamknął drzwi, ale po refleksji zorientował się że nie włożył paczki.
Kroki: 1. Deposit flow → zamknij drzwi → reopen panel 2. Tap 🔴 "Anuluj — paczki nie ma w skrytce"
Expected: Kiosk wywoła POST /deposit/cancel-after-deposit → 🔴 DepositFailureScreen.
Weryfikacja krytyczna:
- shipment status CREATED (rollback)
- lockerId: null, depositedAt: null, assignedAt: null, machineId: null
- Locker status FREE (NIE BROKEN! operator EXPLICITNIE potwierdził że pusty)
❌ FAIL jeśli: locker zostaje OCCUPIED, lub shipment dalej DEPOSITED, lub depositedAt nadal ustawione.
Test 6.F — Reopen + Anuluj-paczki-nie-ma (multi-cycle rollback)¶
Kroki: 1. Deposit flow → zamknij drzwi → reopen panel 2. Tap "Otwórz ponownie" → drzwi otwierają się 3. Zamknij ponownie → reopen panel 4. Tap "Anuluj — paczki nie ma w skrytce"
Expected: Identyczne jak 6.E — kompletny rollback nawet po reopen cycle.
Test 6.G — Drzwi przytrzymane (E07 podczas close phase) — krytyczny test¶
Cel: Bug Kevina + Test 3 operator'a — drzwi otwarte, operator nie zamyka, system pokazuje czerwony screen ALE backend marked DEPOSITED.
Setup: Świeża paczka, deposit flow.
Kroki:
1. Login Kurier 261438 → "Nadaj paczkę" → kod nadania (np. 995354) → rozmiar M → "Otwórz teraz"
2. Drzwi się otwierają
3. Trzymaj drzwi otwarte 60s+ — nie zamykaj
4. Po ~20s pojawi się userConfirmClosed dialog "Czy skrytka zamknięta?"
5. Tap "Zgłoś obsłudze"
6. Pojawi się żółty card
Expected (v1.1.21): - Tytuł: "Drzwi nie zostały zamknięte" (NIE "Wystąpił problem techniczny") - Subtitle: "Zamknij drzwi skrytki, aby zakończyć operację. Jeśli drzwi się nie zamykają — anuluj i poproś o pomoc." - Przyciski: TYLKO [Anuluj] (BRAK Spróbuj ponownie!)
- Tap Anuluj
Expected: 🔴 DepositFailureScreen.
Weryfikacja krytyczna w panelu (v1.1.20 fix):
- shipment status CREATED (NIE DEPOSITED!)
- lockerId: null, depositedAt: null ← KLUCZOWE
- Locker: BROKEN (przez abandon-locker)
- Panel Zgłoszenia: USER-reported, currentPhase: userConfirmClosed
❌ FAIL jeśli: shipment DEPOSITED mimo czerwonego screena. To wskazuje że sensor flicker wciąż triggeruje _onCloseDetected w wadliwy sposób.
Test 6.H — Sensor flicker (sztuczne — wymaga modu hardware)¶
Cel: Sprawdzić v1.1.20 guard w _onCloseDetected — gdy phase != open, close event jest SUPPRESSED.
Trudne do zasymulowania bez wstrzyknięcia false-positive close event w driver. Pominąć jeśli brak dostępu.
Test 6.I — Master comm loss mid-cycle (po pulse, przed close)¶
Setup: PO unlock pulse (drzwi otwarte), ZANIM zamkniesz drzwi: netsh advfirewall firewall add rule name="block-modbus-mid" dir=out action=block protocol=TCP remoteport=502
Kroki: 1. Deposit flow → drzwi otwarte 2. Włącz firewall block 3. Zamknij drzwi
Expected:
- Driver event 'closed' nie dochodzi (master nie odpowiada)
- Po 2s fallback poll (UI-side) próbuje isClosed() bezpośrednio → też timeout
- Po 20s (_openPhaseDeadline) → userConfirmClosed dialog
Weryfikacja:
- Tap "DOCIŚNIJ" lub "TAK - sprawdź" → re-poll
- Po unblock firewall: re-poll wykryje closed → onClosed → DEPOSITED OK
- Cleanup: netsh advfirewall firewall delete rule name="block-modbus-mid"
Test 7 — Inactivity overlay → bounce do login¶
Kroki:
1. Login PIN 517796 → wejdź w "Moje przesyłki" lub menu
2. Nie tap przez 5+ sekund (inactivityTimeoutSec)
3. Pojawi się overlay "Wylogowanie za 10s..."
4. Nie tap przez kolejne 10s
Expected: Bounce do LoginScreen, PIN pad wyczyszczony, tab snap na KARTA.
Weryfikacja: Jeśli operator tap w trakcie 10s countdown — countdown anulowany, wraca do operacji.
Test 8 — Pickup happy path (sanity)¶
Setup: Świeżo zdeponowana paczka dla E2E Pracownik.
Kroki: 1. Login PIN 517796 2. Lista DEPOSITED → tap paczka → pre-confirm "Otworzymy skrytkę N" 3. "Otwórz teraz" → drzwi otwierają się 4. Wyjmij paczkę → zamknij 5. Reopen panel → "Zakończ"
Expected: 🟢 "Paczka odebrana".
Weryfikacja: shipment PICKED_UP, locker FREE.
Test 9 — Backend duplicate PIN guard (cross-user)¶
Cel: Sprawdzić że dwóch użytkowników nie może mieć tego samego PIN-u.
```bash
Wewnątrz backend container, test przez NestFactory:¶
docker exec smartbox-backend-1 node /tmp/test-guards.js ```
Expected: creds.create(kurier, { PIN, 517796 }) → 409 ConflictException ("PIN already in use")
Test 10 — Backend duplicate RFID guard (cross-user, case-insensitive)¶
Kroki:
1. Seed RFID abc1234567 dla E2E Pracownik
2. Próba dodać ten sam UID dla E2E Kurier → 409
3. Próba dodać ABC1234567 (uppercase) → 409 (lookup hash jest lowercase)
Test 11 — Reactivation guard¶
Kroki:
1. Dezaktywuj poprzedni RFID Pracownika (set active: false)
2. Dodaj ten sam UID dla Kuriera (succeeds bo unique constraint patrzy tylko na active)
3. Próbuj reaktywować poprzedni Pracownika RFID → 409 ("would create duplicate active")
Test 12 — Kiosk evil-path: short PIN, slow PIN, backspace¶
Kroki:
1. Login → PIN tab → wpisz 123 → ✓ button disabled (canSubmit=false)
2. Wpisz dalej 456 → ✓ aktywne
3. Backspace → znów disabled
4. Skasuj wszystko → tap ✓ — nie powinno nic robić
Expected: Submit dostępny tylko przy pin.length == 6.
Test 13 — Inactive user PIN¶
Setup:
sql
UPDATE "User" SET active=false WHERE email='e2e-employee@test.local';
Kroki: Login PIN 517796
Expected: Backend /pickup/verify zwraca 404 (lub 403). Kiosk: "Nie rozpoznano".
Cleanup: UPDATE "User" SET active=true WHERE email='e2e-employee@test.local';
Test 14 — Deposit lookup: bad tracking number¶
Kroki:
1. Login Kurier → Nadaj paczkę → Kod nadania
2. Próby:
- 000000 (nieistniejący) → 404
- last6 paczki która jest już DEPOSITED gdzie indziej → 409
- last6 paczki CANCELLED → 404 (nie pokazuje terminal status)
Expected: Każdy przypadek pokazuje błąd, operator może spróbować ponownie.
Test 15 — Deposit: brak wolnego lockera¶
Setup: Zajmij wszystkie M lockery (BROKEN lub OCCUPIED w panelu).
Kroki: Nadaj paczkę → kod nadania → rozmiar M → "Otwórz teraz"
Expected: Backend /deposit/begin-existing zwraca 409 "no free locker of size M". Kiosk pokazuje "Brak wolnych skrytek tego rozmiaru".
Test 16 — Double-click race: "Nadaj" 3× szybko¶
Cel: Sprawdzić że szybki potrójny tap nie tworzy 3 orders.
Kroki: Po wpisaniu kodu nadania, tap "Otwórz teraz" 3× szybko (200ms apart).
Expected: Tylko JEDEN assign + jeden open. Następne tap'y są no-op (Flutter setState idempotent + backend transakcja FOR UPDATE).
Weryfikacja: Audit log = jeden shipment.assign_locker event.
Test 17 — Anuluj deposit po pre-flight (drzwi already open z poprzedniej sesji)¶
Setup: Symuluj crash poprzedniej sesji — ręcznie otwórz drzwi.
Kroki:
1. Deposit flow → pre-confirm
2. Tap "Otwórz teraz" → isClosed() zwraca false
3. Caller (deposit_lookup_screen) wywołuje /deposit/abandon-locker automatycznie
Expected: 🔴 DepositFailureScreen "Wybrana skrytka nie spełnia warunków".
Weryfikacja: locker BROKEN, shipment CREATED (cofnięte).
Test 18 — Brak komunikacji z masterem — kill ModbusClient TCP, spróbuj open¶
Setup: Firewall block port 502 PRZED rozpoczęciem flow.
Kroki: Deposit flow → "Otwórz teraz"
Expected: Po ~12s driver timeout → E07-DRIVER fault report → przyciski [Spróbuj ponownie] [Anuluj].
Test 19 — Locale switch w trakcie sesji¶
Kroki: 1. Login (PL UI) 2. W headerze tap flag UK 3. Cały UI przeładowuje się w EN 4. Wyloguj się, zaloguj ponownie
Expected: Po reloginie języka jest zapamiętany jako preferredLocale w User row, kiosk podstawia od razu.
Test 20 — Cleanup (po wszystkich testach)¶
Cel: Po sesji testów pozostawić system w czystym stanie.
bash
ssh smartbox 'docker exec smartbox-postgres-1 psql -U smartbox -d smartbox -c "
-- Cancel all test shipments
UPDATE \"Shipment\" SET status='CANCELLED', \"cancelledAt\"=NOW(), \"lockerId\"=NULL
WHERE \"recipientId\"=(SELECT id FROM \"User\" WHERE email='e2e-employee@test.local')
AND status NOT IN ('PICKED_UP', 'CANCELLED');
-- Reset BROKEN lockers to FREE
UPDATE \"Locker\" SET status='FREE'
WHERE \"machineId\"=(SELECT id FROM \"Machine\" WHERE code='LOCKER-SZB-SDI-001')
AND status IN ('BROKEN','RESERVED','OCCUPIED');
"'
Macierz pokrycia wariantów¶
| Etap | Test | Wariant | Stan testu |
|---|---|---|---|
| Login | 1 | PIN happy | ✓ |
| Login | 2 | wrong PIN | ✓ |
| Login | 12 | short/incomplete PIN | ⚪ TODO |
| Login | 13 | inactive user | ⚪ TODO |
| Krok 5 (open) | 5.A | happy | ✓ |
| Krok 5 | 5.B | drzwi już otwarte (pre-flight) | ⚪ |
| Krok 5 | 5.C | master comm loss (firewall) | ⚪ |
| Krok 5 | 5.D | E07 mechaniczny | ✓ (D zaliczone wcześniej) |
| Krok 5 | 5.E | driver timeout | ⚪ |
| Krok 5 | 5.F | Zgłoś obsłudze podczas opening | ⚪ |
| Krok 6 (close) | 6.A | happy + Zakończ | ✓ |
| Krok 6 | 6.B | auto-pop 10s | ⚪ |
| Krok 6 | 6.C | Otwórz ponownie + Zakończ | ⚪ |
| Krok 6 | 6.D | race Otwórz ponownie w trakcie blokowania | ⚪ |
| Krok 6 | 6.E | NEW Anuluj-paczki-nie-ma | ✓ (v1.1.20 fix verified) |
| Krok 6 | 6.F | reopen + Anuluj-paczki-nie-ma | ⚪ |
| Krok 6 | 6.G | drzwi trzymane otwarte → status korupcja | ✓ (v1.1.20 fix verified) |
| Krok 6 | 6.H | sensor flicker | 🚧 wymaga mocka |
| Krok 6 | 6.I | master comm loss mid-cycle | ⚪ |
| Backend | 9 | duplicate PIN guard | ✓ |
| Backend | 10 | duplicate RFID guard | ✓ |
| Backend | 11 | reactivation guard | ✓ |
| Edge | 14 | bad lookup | ⚪ |
| Edge | 15 | no free locker | ⚪ |
| Edge | 16 | double-click race | ⚪ |
| Edge | 17 | abandon po pre-flight | ⚪ |
| Edge | 18 | brak Modbus | ⚪ |
| UX | 7 | inactivity bounce | ✓ |
| UX | 19 | locale switch | ⚪ |
| Cleanup | 20 | DELETE testowych | ⚪ |
Legenda: ✓ = zaliczone, ⚪ = pending, 🚧 = blokada (wymaga modu hardware/test infra)
Diagram drzewa decyzyjnego dla testów Krok 5 + 6¶
flowchart TD
A[Tap Otwórz teraz] --> B{Drzwi otwierają się?}
B -- TAK --> C{Drzwi się zamykają?}
B -- NIE master E07 --> D[Test 5.D]
B -- NIE driver timeout --> E[Test 5.E]
B -- NIE comm loss --> F[Test 5.C]
B -- już otwarte --> G[Test 5.B]
C -- TAK happy --> H[Test 6.A / 6.B]
C -- nie zamyka --> I{User reakcja?}
I -- Zgłoś obsłudze --> J[Test 6.G - drzwi przytrzymane]
I -- DOCIŚNIJ --> K[re-pulse + czeka]
I -- nic / 20s --> L[userConfirmClosed dialog]
H --> M{Reopen panel akcja?}
M -- Zakończ --> N[🟢 success]
M -- Otwórz ponownie --> O[Test 6.C / 6.D]
M -- Anuluj-paczki-nie-ma --> P[Test 6.E / 6.F]
M -- auto 10s --> N
O --> H
P --> Q[🔴 failure + rollback]
J --> Q
Co notować per test¶
Per test, w issue / ticket:
- PASS / FAIL + numer + nazwa
- Tracking ID paczki testowej
- Screenshot panel detalu (timeline + status)
- Czy pojawił się fault report w System → Zgłoszenia (faultCode, reportedBy, timeline długość)
- flutter-keys.log tail (jeśli problem z input/RFID)
- agent.log tail (jeśli problem z OTA / heartbeat)
- Stan locker'a w panelu (FREE/RESERVED/OCCUPIED/BROKEN)
Szybkie sprawdzanie stanu z bash (per test)¶
bash
ssh smartbox 'docker exec smartbox-postgres-1 psql -U smartbox -d smartbox -c "
SELECT \"trackingId\", status,
\"lockerId\" IS NOT NULL AS has_locker,
\"depositedAt\" IS NOT NULL AS deposited,
\"pickedUpAt\" IS NOT NULL AS picked_up
FROM \"Shipment\"
WHERE \"updatedAt\" > NOW() - INTERVAL '\''10 minutes'\''
ORDER BY \"updatedAt\" DESC LIMIT 8;
SELECT number, status FROM \"Locker\"
WHERE \"machineId\" = (SELECT id FROM \"Machine\" WHERE code='\''LOCKER-SZB-SDI-001'\'')
ORDER BY number;
"'