← Realizacje / 03

Jak powstała aplikacja do rozliczania szkolnej stołówki

Stołówka szkolna to mój własny program dla szkół i przedszkoli. Opisuję, jak z rozproszonych zestawień powstał model miesięcznych rozliczeń, dlaczego aplikacja działa na Windows z lokalną bazą i jak zaprojektowałem licencje oraz aktualizacje, które można wycofać. Program jest przed pierwszym wdrożeniem.

Typ
Produkt własny
Etap
Przygotowanie do pierwszych wdrożeń
Platforma
Windows · .NET · SQLite
Publikacja
8 października 2026

Punkt wyjścia

Rozliczenie szkolnej stołówki wygląda prosto: posiłki razy stawka, minus wpłaty. W praktyce osoba, która je prowadzi, łączy kilka źródeł — listę obecności, wyciąg bankowy, kwity za wpłaty gotówkowe, decyzje GOPS i kontakty do rodziców — zwykle zapisanych w osobnych arkuszach.

Referencją do rozwoju były zestawienia obecności, opłat i kontaktów otrzymane od jednej szkoły. Posłużyły do zrozumienia procesu. Program nie jest w tej szkole wdrożony, a jej materiały nie trafiają do wersji instalacyjnej. Wszystkie zrzuty i testy opisane niżej korzystają z fikcyjnych danych.

Problemy procesu

Analiza zestawień pokazała trudności, które wracają co miesiąc:

  • Rozproszone zestawienia. Obecności, wpłaty, finansowanie i kontakty są w osobnych arkuszach, a saldo dziecka trzeba składać ręcznie.
  • Ręczne wpłaty. Przelewy i wpłaty gotówkowe są przepisywane z wyciągu i kwitów. Łatwo o pominięcie albo podwójny wpis.
  • Nieobecności. Pusta komórka może oznaczać nieobecność, brak informacji albo zapomniany wpis, a spóźnione odwołanie bywa płatne.
  • Korekty. Poprawka nadpisuje komórkę lub formułę. Nie widać, jaka była wcześniejsza wartość i dlaczego ją zmieniono.
  • Historia. Zmiana stawki, klasy albo zakończenie nauki potrafi zmienić wyniki poprzednich miesięcy, które powinny zostać takie, jak je rozliczono.
  • Finansowanie po terminie. Decyzja GOPS przychodzi czasem już po rozliczeniu miesiąca, którego dotyczy.

Projekt rozliczeń

Najważniejszą decyzją było oparcie salda na zapisanych, datowanych wpisach zamiast na komórkach, które można nadpisać. Rozliczenie jest miesięczne i powstaje po zakończeniu miesiąca.

  1. 01

    Dzień jako wpis, nie komórka

    Dzień ma kwotę posiłku albo oznaczenie nb o wartości zero. Brak wpisu oznacza nieuzupełniony dzień, a nie potwierdzoną nieobecność. Kwoty są przechowywane jako całkowita liczba groszy, więc nie powstają błędy zaokrągleń. Stawka dziecka jest tylko podpowiedzią — jej zmiana nie przelicza historii.

  2. 02

    Saldo z wpisów finansowych

    Saldo to wartość posiłków i saldo poprzedniego miesiąca, pomniejszone o wpłaty, GOPS i odpisy; korekta dodatnia je zwiększa. Każdy wpis ma dwa miesiące: ten, w którym wpływa na saldo, i ten, którego dotyczy. Dzięki temu późna wpłata albo decyzja GOPS nie zmienia już zamkniętego okresu.

  3. 03

    Zamknięcie miesiąca jako punkt kontrolny

    Zamknięcie utrwala kwoty i blokuje zmiany obecności oraz wpisów. Program zamyka miesiące po kolei i odmawia zamknięcia, gdy:

    • wcześniejszy miesiąc jest nadal otwarty,
    • w miesiącu są posiłki bez wyceny albo wpisy wymagające sprawdzenia,
    • są nierozstrzygnięte uwagi dotyczące danych,
    • operator nie potwierdził sprawdzenia wpłat papierowych.

    Przed zamknięciem powstaje kopia bazy. GOPS dodany później trafia jako kredyt do pierwszego otwartego miesiąca i zachowuje informację, którego okresu dotyczy.

  4. 04

    Pomyłki bez kasowania

    Wpisów finansowych się nie usuwa. Błąd koryguje opisany wpis przeciwny, a oryginał zostaje w historii dziecka i w historii operacji. Zmiany danych trafiają też do dziennika audytu w bazie.

  5. 05

    Grupy i historia uczniów

    Przeniesienie do nowej grupy i archiwizacja działają od wskazanego miesiąca. Wcześniejsze rozliczenia zachowują dawną grupę, absolwenci nie trafiają automatycznie do nowych miesięcy, a ich późniejsze wpłaty nadal można zapisać.

Windows i lokalna baza

Rozliczenia prowadzi zwykle jedna osoba na jednym szkolnym komputerze. Dlatego program jest aplikacją desktopową dla Windows x64, zbudowaną w .NET i WPF, a dane przechowuje w lokalnej bazie SQLite. Baza to jeden plik, który łatwo skopiować i przywrócić, a dane dzieci nie muszą trafiać na zewnętrzny serwer.

Ta decyzja ma konsekwencje, które warto znać przed wyborem: nie ma panelu rodzica, płatności online ani pracy kilku komputerów na jednej bazie, której nie należy też udostępniać przez dysk sieciowy. Kopie poza komputerem to odpowiedzialność placówki, dlatego program tworzy je automatycznie i ułatwia zapis na innym nośniku.

Internet nie służy do przechowywania bazy szkoły. Program łączy się z nim przy aktywacji i uruchomieniu, przy sprawdzaniu aktualizacji oraz — opcjonalnie — przy wysyłce SMS przez szkolny telefon z aplikacją SMSGate. W trybie Cloud numer i treść są szyfrowane przez program przed przekazaniem do usługi; rodzic otrzymuje zwykły SMS. Sam program nie szyfruje lokalnej bazy ani jej kopii.

W wersji 0.4.13 dodałem wspólny szablon SMS z automatycznym uzupełnianiem danych i trwałymi wyjątkami dla dzieci. Wysyłka zbiorcza obejmuje aktualnie widoczną listę — respektuje placówkę, grupę, wyszukiwanie i pozostałe filtry. Operator sprawdza podgląd, a następnie potwierdza zakres, liczbę wiadomości i pominięcia. Każde dziecko ma osobną wiadomość, także przy wspólnym numerze rodzica.

Własny format wymiany danych

Arkusze szkół różnią się układem, formułami i scalonymi komórkami. Zamiast zgadywać ich strukturę, zdefiniowałem własny kontrakt CSV w wersji 1. Pierwszy wiersz pliku określa format, rodzaj danych i miesiąc, np. STOLOWKA;1;WPLATY;2026-10, a drugi zawiera nazwy kolumn. Pliki są w UTF-8, z separatorem średnik, a puste szablony pobiera się z programu.

Import wyłącznie dodaje. Rekordy mają stałe identyfikatory, więc identyczny wiersz zostaje pominięty, a inna treść pod istniejącym identyfikatorem jest błędem. Jeden błąd blokuje cały plik. Operator widzi podgląd i może zapisać raport błędów. Zatwierdzony import zapisuje dane razem z wpisem audytu w jednej transakcji, po wykonaniu kopii bazy.

Eksport zabezpiecza pola tekstowe, które arkusz mógłby potraktować jak formułę. Raporty finansowe służą do odczytu i nie są przyjmowane z powrotem jako import. Pełne przeniesienie danych, razem z historią grup i archiwum, odbywa się przez kopię bazy.

Licencje i aktualizacje

  1. 01

    Licencja roczna na jedno urządzenie

    Pierwsza aktywacja kodem ustala roczny okres ważności i wiąże licencję z komputerem. Każde uruchomienie wymaga świeżej, podpisanej odpowiedzi serwera powiązanej z jednorazowym wyzwaniem, a w trakcie pracy weryfikacja jest ponawiana. Cofnięcie zegara systemowego nie przedłuża uprawnień.

    Po utracie połączenia sesja działa najwyżej 24 godziny od ostatniego potwierdzenia, nie dłużej niż do końca licencji. Gdy serwer potwierdzi wygaśnięcie lub blokadę, program przechodzi w tryb odczytu: dane można przeglądać, eksportować i skopiować, ale nie zmieniać. Nowe uruchomienie zawsze wymaga połączenia.

    Przeniesienie licencji na inny komputer wykonuje administrator: odłącza urządzenie i wydaje nowy kod z zachowaniem terminu ważności. Licencja nie przenosi danych — te przenosi się kopią bazy.

    Serwer licencji obsługuje dane klienta i licencji, skróty identyfikatorów urządzeń, metadane wydań i dziennik audytu. Bazy szkoły nie otrzymuje, a magazyn wydań przechowuje wyłącznie paczki aktualizacji.

  2. 02

    Aktualizacja z kopią i powrotem do poprzedniej wersji

    Aktualizację uruchamia użytkownik. Paczka ma podpisane metadane i sumę kontrolną SHA-256, a instalacją steruje osobny proces uruchamiający, działający poza katalogiem wymienianej wersji. Kolejne kroki:

    • program kończy operacje zapisu i tworzy spójną kopię bazy oraz ustawień,
    • zachowuje pełną paczkę poprzedniej wersji i prowadzi dziennik odzyskiwania, który pozwala wznowić przerwany proces,
    • nowa wersja ma ograniczony czas na migrację bazy, kontrolę spójności i otwarcie okna,
    • jeśli się to nie uda, wraca poprzednia wersja i baza sprzed aktualizacji, a wadliwe wydanie nie jest proponowane ponownie.

    Po pomyślnym starcie nowa wersja zostaje zatwierdzona. Od tego momentu dane nie są cofane automatycznie — ewentualny błąd naprawia kolejne wydanie.

Jak to sprawdziłem

Stan na 8 października 2026. Scenariusze z danymi dzieci sprawdzałem na osobnej bazie z fikcyjnymi danymi. Poszczególne zakresy weryfikacji mają własne daty; liczby testów nie oznaczają pokrycia kodu:

  • 166 automatycznych testów .NET i build WPF Release bez ostrzeżeń, sprawdzone 8 października: rozliczenia, wymiana danych, uprawnienia zapisu, SMS, podpisy i aktualizacje.
  • 10 testów integracyjnych serwera licencji, odnotowanych w raporcie z 4 października: aktywacja, przypisanie do urządzenia, blokada, wygaśnięcie, przeniesienie, odnowienie i publikacja wydania.
  • Podgląd i potwierdzenie zbiorczych SMS-ów sprawdzone na fikcyjnych danych z testowym transportem, bez wysyłki do rodziców.
  • Po publikacji 0.4.13: pobranie paczki z produkcji, kontrola podpisu manifestu, rozmiaru i SHA-256 oraz podpisów Windows, znaczników czasu i profilu wydawcy.
  • Instalacja, aktywacja kodem i aktualizacje między wersjami testowymi z zachowaniem identycznej zawartości bazy.
  • Celowo wadliwa wersja: automatyczny powrót do poprzedniej wersji, a baza po odzyskaniu zgodna z kopią sprzed aktualizacji.
  • Licencja zablokowana w trakcie pracy: przyciski zapisu wyłączone, eksport i kopia nadal dostępne.
  • Uruchomienie bez połączenia z serwerem licencji: program pokazuje tylko okno licencji i nie otwiera danych.

Stan projektu

8 października 2026 opublikowałem wersję 0.4.13 w kanale stable. Instalator i programy są podpisane przez Azure Artifact Signing. Serwer licencji, panel administracyjny i mechanizm aktualizacji działają; użytkownik sam uruchamia aktualizację.

Produkt przygotowuję do pierwszych wdrożeń. Pakiet dokumentów sprzedaży i informacji o danych jest opracowany, ale pozostaje projektem. Przed pierwszym wdrożeniem trzeba domknąć dokumenty i sprawdzić instalację, kopie oraz konfigurację SMS w docelowej placówce.

To produkt własny przed pierwszym wdrożeniem u klienta. Nie podaję oszczędności czasu ani opinii użytkowników — będzie można je opisać dopiero po pierwszych wdrożeniach.

Technologia

.NET i WPF
Aplikacja desktopowa dla Windows x64.
SQLite
Lokalna baza, kopie zapasowe i migracje schematu.
Velopack
Instalator i pełne paczki aktualizacji.
Własny proces uruchamiający
Kopia przed instalacją, kontrola startu i powrót do poprzedniej wersji.
Cloudflare Workers, D1 i R2
API licencji oraz paczki i metadane wydań — bez danych szkoły.
Podpisy ECDSA i Windows DPAPI
Podpisane odpowiedzi licencyjne i ochrona klucza urządzenia.
Azure Artifact Signing
Podpisy instalatora i programów Windows oraz znaczniki czasu.
SMSGate (opcjonalnie)
SMS z kwotą do zapłaty przez szkolny telefon z Androidem.
Produkt

Program do rozliczania stołówki szkolnej

Co program obejmuje, jakie ma wymagania i ograniczenia oraz jak zacząć.

Zobacz stronę programu

Co możemy usprawnić w Twojej firmie?

Zacznijmy rozmowę

albo napisz na [email protected]