System dla firmy · Tomasz Pagacz - Jubiler Pagacz · 2026 · 5 miesięcy (rozwijany)

Jubi-Prog - system magazynowy salonu jubilerskiego zamiast desktopowego JUBI 2.20

Trzynaście modułów, które wcześniej były desktopowym programem na jednym stanowisku i stosem papieru obok niego - magazyn, zlecenia, komis, skup metali, raty i faktury, z wydrukiem umowy generowanym przez aplikację, nie przepisywanym w Wordzie.

  • Next.js 16
  • React 19
  • TypeScript
  • PostgreSQL 16
  • Prisma 7
  • Tailwind CSS 4
  • shadcn/ui
  • jsPDF
  • Docker
  • SMSAPI
Jubi-Prog - system magazynowy salonu jubilerskiego zamiast desktopowego JUBI 2.20

Wyzwanie

Salon jubilerski to nie jeden rodzaj ewidencji, tylko kilka naraz. Towar na stanie ma numer, masę, próbę i marżę. Zlecenie od klienta ma termin, zadatek i wyrób powierzony, za który jubiler odpowiada. Komis to umowa z osobą trzecią. Skup złota od osoby fizycznej to transakcja z danymi wrażliwymi i obowiązkiem informacyjnym. Do tego raty, zadatki, bony i faktury. Punktem wyjścia był desktopowy JUBI 2.20 - program instalowany na stanowisku w salonie, przy którym dostęp spoza lady i kopia zapasowa zależą od jednego komputera, a wszystko, czego program nie drukuje, ktoś przepisuje ręcznie.

Nasze rozwiązanie

Jedna aplikacja webowa z trzynastoma modułami i wspólną bazą PostgreSQL. Każdy rodzaj ewidencji dostał własny moduł, ale numerację, wydruki, zgody RODO i historię zmian dzielą wszystkie. Dokumenty - zlecenie, umowa komisowa, umowa skupu metalu, faktura i karta złocenia - generuje aplikacja jako PDF, z kodem kreskowym i miejscem na podpisy. Etykiety na towar idą na drukarkę DYMO w salonie, a system stoi w Dockerze na VPS z nocnym backupem.

13

Modułów w systemie

66

Endpointów API

5

Wzorów dokumentów PDF

Co zbudowaliśmy

  • 01 Magazyn z auto-numeracją, marżą liczoną z ceny zakupu i widokiem tabela/galeria
  • 02 Zdjęcia produktów kompresowane do WebP, z konwersją HEIC z iPhone'a po stronie przeglądarki
  • 03 Zlecenia z terminem, zadatkiem i kolorowaniem wierszy po terminie realizacji
  • 04 Wydruk zlecenia: dwie kopie na A4 z kodem kreskowym Code128 i klauzulą RODO
  • 05 Komis wielopozycyjny z umową PDF - paragrafy, kwota słownie, podpisy stron
  • 06 Skup i sprzedaż metali z automatycznym stanem magazynu i umową dla klienta
  • 07 Raty z listą wpłat i automatycznym zamknięciem planu po ostatniej racie
  • 08 Faktury VAT, zadatki, bony i zaliczki jako osobne ewidencje z własną numeracją
  • 09 Etykiety jubilerskie 50×10 mm z kodem QR na DYMO LabelWriter 550
  • 10 SMS do klienta z szablonami i znacznikami numeru, nazwiska i terminu
  • 11 Historia zmian: każde dodanie, edycja, sprzedaż i wysłany SMS z datą i szczegółem
  • 12 Wyszukiwanie globalne Ctrl+K przez produkty, zlecenia, transakcje i faktury
Spis treści +

Punkt wyjścia

Ten sam klient ma u nas już sklep WooCommerce z wyszukiwarką diamentów i bota, który prowadzi mu blog. Sklep obsługuje to, co widać z zewnątrz. Ten projekt jest o tym, co dzieje się po drugiej stronie lady.

Salon jubilerski prowadzi kilka ewidencji naraz i każda rządzi się czym innym. Towar na stanie to numer, metal, próba, masa, cena zakupu i marża. Zlecenie to termin, zadatek i cudza własność w rękach jubilera. Komis to umowa z osobą, która zostawia swój wyrób do sprzedaży. Skup złota od osoby fizycznej to transakcja, przy której zbiera się dane wrażliwe. Raty, zadatki, bony i faktury to jeszcze cztery osobne rzeczy.

Punktem wyjścia był desktopowy JUBI 2.20, program instalowany na stanowisku w salonie. Przy takim układzie dostęp do danych kończy się tam, gdzie stoi komputer, kopia zapasowa zależy od tego jednego dysku, a wszystko, czego program nie drukuje, ktoś przepisuje ręcznie.

Decyzje, które ukształtowały projekt

Aplikacja webowa, nie kolejny program na jednym komputerze

System jest stroną, którą otwiera się w przeglądarce - z lady, z zaplecza i z domu. Baza jest jedna, backup robi się w nocy po stronie serwera, a wersji „u mnie jest nowsza” nie ma, bo nie ma czego instalować. Kosztem jest zależność od sieci i od tego, że serwer stoi: przy programie na dysku awaria internetu nie zatrzymuje pracy, tutaj zatrzymuje. Ta wymiana jest świadoma, a nie przemilczana - wybór między WordPressem a aplikacją pisaną od zera rozkładamy na czynniki w tekście o tym, kiedy bierze się WordPressa, a kiedy Next.js.

Trzynaście modułów, jedna warstwa wspólna

Każdy rodzaj ewidencji ma własny moduł i własny formularz, bo komis naprawdę potrzebuje innych pól niż skup złota. Wspólne są cztery rzeczy: numeracja, wydruki, zgody RODO i historia zmian. Gdyby trzymać je osobno w każdym module, po pół roku istniałoby trzynaście wariantów tego samego wydruku i trzynaście miejsc, w których trzeba poprawić adres firmy.

Dokumenty generuje program, nie człowiek w edytorze tekstu

Pięć wzorów - zlecenie, umowa komisowa, umowa skupu metalu, faktura i karta złocenia - powstaje w kodzie przez jsPDF. Umowy mają paragrafy, kwotę słownie, klauzulę informacyjną i miejsca na podpisy. Zlecenie wychodzi w dwóch kopiach na jednej kartce A4 z kodem kreskowym Code128.

To nie jest wygoda, tylko powtarzalność. Dokument składany ręcznie w Wordzie różni się między egzemplarzami dokładnie tam, gdzie nie powinien: w dacie, w kwocie, w akapicie, który ktoś skasował, bo „nie mieściło się na stronie”.

Zgoda RODO jako pole, które blokuje zapis

Przy zleceniu i przy transakcji metalem checkbox zgody jest wymagany do zapisu. Można to było zrobić jako kartkę do podpisu obok programu - i wtedy po roku nie ma jak sprawdzić, przy których transakcjach ją odebrano. Pole w bazie odpowiada na to pytanie zawsze, a klauzula jedzie automatycznie na wydruk.

Historia zmian od pierwszego dnia, nie po pierwszym sporze

Osobny moduł zapisuje każde dodanie, edycję, usunięcie, sprzedaż, pożyczenie, transakcję metalem, rozliczony zadatek i wysłany SMS - z datą, obiektem i szczegółem. Audyt dopisany po fakcie ma jedną wadę: zaczyna się w dniu wdrożenia, a pytania dotyczą zwykle tego, co było wcześniej.

Etykiety przez lokalny serwis drukarki

Etykiety jubilerskie 50×10 mm z numerem i kodem QR drukuje DYMO LabelWriter 550, przez serwis DYMO Connect działający na komputerze kasjera pod https://localhost:41951. Serwis ma certyfikat self-signed, więc przeglądarka blokuje połączenie, dopóki użytkownik raz ręcznie go nie zaakceptuje - i trzeba to powtórzyć po zmianie przeglądarki albo reinstalacji sterownika. To jest realna niedogodność integracji i jest opisana w instrukcji dla stanowiska, a nie zamieciona pod dywan.

SMS na gotowych szablonach

Zawiadomienie o gotowym wyrobie to zdanie, które pisze się kilkanaście razy w tygodniu. Szablony siedzą w ustawieniach, mają znaczniki numeru zlecenia, nazwiska i terminu, a wysyłka idzie przez SMSAPI i ląduje w historii. Treść zawsze można nadpisać ręcznie - szablon ma skracać pisanie, nie zabierać możliwości napisania czegoś innego.

Co z tego wyszło

System działa w salonie i jest rozwijany dalej: trzynaście modułów, 29 ekranów, 66 endpointów API, pięć wzorów dokumentów PDF, 84 commity od kwietnia do września 2026.

Uczciwa uwaga do tych liczb: to jest opis zakresu, a nie dowód oszczędności. Nie mierzyliśmy, ile minut zajmowało wystawienie umowy komisowej przed wdrożeniem, więc nie napiszemy, że skróciliśmy je o połowę. Policzalne jest co innego - że umowa, faktura, etykieta i zawiadomienie SMS-em wychodzą dziś z tego samego miejsca co ewidencja, i że każda zmiana zostawia ślad w historii.

Zrzuty w galerii pochodzą z instancji demonstracyjnej z danymi wymyślonymi na potrzeby tej strony. Ewidencja klientów salonu nie opuszcza systemu i nie trafia do portfolio - to samo dotyczyłoby każdego systemu, który dla kogoś budujemy.

Technicznie

Next.js 16 (App Router) z React 19 i TypeScriptem, Tailwind CSS 4 i shadcn/ui na froncie. Dane w PostgreSQL 16 przez Prismę 7. Sesje na iron-session w ciasteczku httpOnly, hasło hashowane bcryptem, middleware odcina każdą ścieżkę poza logowaniem i odczytem plików. Zdjęcia przechodzą przez sharp do WebP, a pliki HEIC z iPhone’a konwertuje przeglądarka, zanim cokolwiek poleci na serwer. PDF-y składa jsPDF z jsbarcode (Code128) i qrcode (etykiety DYMO). Całość jedzie w Docker Compose na VPS za nginksem, pod program.jubilerpagacz.pl, z nocnym zrzutem bazy o 3:00.

Zrzuty ekranu

Panel otwiera się od tego, co wymaga reakcji: czerwony baner zlecenia po terminie, potem stan i wartość magazynu, sprzedaż miesięczna i stan metali w gramach.
Magazyn z sortowaniem po każdej kolumnie, filtrem metalu i statusu oraz przełącznikiem na widok galerii - przy biżuterii zdjęcie bywa szybszym identyfikatorem niż numer.
Karta produktu: cena sprzedaży liczy się sama z ceny zakupu i marży, a etykietę, pożyczenie, raty i sprzedaż ma się w pasku na górze, bez wchodzenia w osobne ekrany.
Zlecenia kolorują się terminem: bursztyn na trzy dni przed, czerwień po terminie. Dzięki temu lista sama mówi, co robić dziś, zamiast czekać, aż ktoś to policzy.
Wydruk zlecenia wychodzi z aplikacji: kod kreskowy Code128, dane firmy, pozycje, klauzula RODO i podpisy. Na jednej kartce A4 są dwie takie kopie - jedna zostaje u jubilera, druga u klienta.
Umowa komisowa przyjmuje wiele przedmiotów naraz, każdy z własną próbą, masą i ceną minimalną. Zgoda RODO jest polem w formularzu, bez którego umowa się nie zapisze.
Skup i sprzedaż metali: karty stanu magazynu przeliczają się po każdej transakcji, a do każdej z nich system drukuje umowę.
Historia zmian notuje dodania, edycje, sprzedaże, transakcje metali i rozliczone zadatki. Przy towarze o takiej wartości pytanie „kto to zmienił" musi mieć odpowiedź.

Podobny problem do rozwiązania?

Napisz krótko, o co chodzi — wycena wraca w 24 godziny.

Zapytaj o wycenę