O projekcie
System CRM zbudowany dla importera sprowadzającego towar z Chin — z magazynem, zakupami i sprzedażą w jednym miejscu oraz agentami AI wpiętymi w kontrolę zdarzeń. Nie jest to CRM z doklejonym czatem: agenci nie rozmawiają z użytkownikiem, tylko obserwują strumień zdarzeń i reagują na to, czego człowiek nie zdąży zauważyć.
Import z Chin łamie założenie, na którym stoi każdy gotowy CRM i większość gotowych magazynów: że stan magazynowy to jedna liczba. Przy czterdziestu dniach od zamówienia do rampy towar żyje jednocześnie w kilku stanach — zamówiony u dostawcy, w produkcji, na wodzie z terminem przypłynięcia, w odprawie celnej, na magazynie, zarezerwowany pod zamówienie, wydany. Handlowiec sprzedaje z tego, co przypłynie za trzy tygodnie, a zakupowiec zamawia pod prognozę sprzed dwóch miesięcy. Jedna liczba nie odpowiada na żadne z ich pytań.
Dlatego rdzeniem systemu nie jest tabela stanów, tylko DZIENNIK ZDARZEŃ. Każde przyjęcie, korekta, rezerwacja, wydanie, zamówienie i zmiana terminu są zapisanym faktem, a stan magazynowy jest funkcją tych faktów, liczoną na żądanie w dowolnym przekroju i na dowolny moment. To kosztuje więcej pracy przy budowie i oddaje ją z nawiązką: rozbieżność inwentaryzacyjna przestaje być zagadką, bo widać ciąg zdarzeń, który do niej doprowadził.
Na tym dzienniku siedzą agenci. Każdy ma wyzwalacz, zakres uprawnień i próg pewności ustalone przed uruchomieniem — i to rozróżnienie jest tu najważniejsze: agent albo WYKONUJE działanie w swoim zakresie, albo tylko PROPONUJE je człowiekowi. Nie ma trzeciej możliwości i nie ma agenta, który dostaje uprawnienia „na wszelki wypadek”. Poniżej progu pewności agent nie zgaduje, tylko zakłada zadanie z kompletem ustaleń — to ta sama zasada, którą ten zespół deklaruje przy usłudze agentów AI.
Drugą rzeczą, której gotowe systemy nie robią uczciwie, jest koszt. Towar kupowany jest w dolarach, sprzedawany w złotówkach, a między jednym a drugim stoją fracht, cło, ubezpieczenie, przeładunek i transport krajowy — koszty wspólne dla całego kontenera, które trzeba rozbić na pojedyncze indeksy. Dopóki tego nie ma, marża na karcie produktu jest zgadywanką opartą o cenę zakupu FOB. System liczy koszt wyładowany per partia, po kursie z dnia zdarzenia, i dopiero on trafia do marży.
Trzecia rzecz to dokumenty. Dostawca przysyła proformę i packing listę w arkuszu, spedytor terminy mailem, agencja celna SAD w PDF-ie. Model pracuje wyłącznie na tej krawędzi — zamienia dokument w pola i klasyfikuje go — a wszystkie obliczenia, reguły i decyzje o stanie magazynu dzieją się poza nim, w kodzie, który da się przetestować. Rozbieżność między fakturą a packing listą wykrywa reguła, nie intuicja modelu.
Efektem nie jest „mniej klikania”, tylko przesunięcie roli człowieka: od przepisywania i pilnowania do rozstrzygania spraw, które agent celowo mu oddał. Każde działanie agenta jest zapisane z wyzwalaczem, wejściem i skutkiem, więc po miesiącach da się odtworzyć, dlaczego zamówienie poszło wtedy, a nie tydzień później.
Problem
Import z Chin oznacza czterdzieści dni między zamówieniem a rampą i towar żyjący w kilku stanach naraz. Gotowy CRM pokazuje jedną liczbę stanu magazynowego, marżę liczy od ceny FOB, a o tym, że dostawa się spóźni albo rezerwacja przeterminuje, dowiaduje się ten, kto akurat zajrzy.
Rozwiązanie
Dziennik zdarzeń jako źródło prawdy zamiast tabeli stanów, koszt wyładowany liczony per partia po kursie z dnia zdarzenia, i agenci z ustalonym zakresem uprawnień oraz progiem pewności, którzy pilnują strumienia zdarzeń zamiast czekać, aż ktoś zajrzy.
Funkcje
- stan magazynowy w siedmiu stanach: od zamówienia u dostawcy po wydanie
- sprzedaż z towaru w drodze, z terminem przypłynięcia widocznym przy rezerwacji
- marża liczona od kosztu wyładowanego, nie od ceny zakupu
- kurs walut brany z dnia zdarzenia, nie z dnia oglądania raportu
- agent zgłasza spóźnioną dostawę i przeterminowaną rezerwację sam z siebie
- propozycja zamówienia liczona z rotacji i czasu dostawy, do zatwierdzenia
- rozbieżność faktury z packing listą wychwytywana przy wczytaniu dokumentu
- każde działanie agenta odtwarzalne: wyzwalacz, wejście, skutek, moment
Moduły
crm-dziennik
rdzeń systemuDziennik zdarzeń i widoki odczytowe. Stan magazynu jest funkcją faktów, nie polem w tabeli.
- przyjęcia, korekty, rezerwacje, wydania i zmiany terminu jako niezmienne zdarzenia
- siedem stanów towaru naraz: zamówiony, w produkcji, na wodzie, w odprawie, na magazynie, zarezerwowany, wydany
- stan na dowolny moment i w dowolnym przekroju — inwentaryzacja przestaje być zagadką
- partie z identyfikatorem dostawy: reklamacja u dostawcy wraca do konkretnego kontenera
- widoki odczytowe przeliczane przyrostowo, nie od nowa przy każdym zapytaniu
crm-agenci
warstwa kontroliAgenci wpięci w strumień zdarzeń: wyzwalacz, zakres uprawnień, próg pewności, ślad.
- agent magazynowy: rozbieżność stanu, braki w dostawie, przeterminowana rezerwacja
- agent zakupowy: próg ponownego zamówienia z rotacji i czasu dostawy, propozycja zamówienia
- agent sprzedażowy: zamówienie bez pokrycia w dostawie, cena poniżej progu marży, klient bez kontaktu
- agent dokumentowy: brak dokumentu przed terminem przypłynięcia, faktura niezgodna z packing listą
- rozdział „wykonuje” od „proponuje” zapisany per agent — nie ma uprawnień na wszelki wypadek
- poniżej progu pewności agent zakłada zadanie z ustaleniami, zamiast zgadywać
crm-koszt
warstwa kosztowaKoszt wyładowany per partia: zakup, fracht, cło, ubezpieczenie i transport rozbite na indeksy.
- koszty wspólne kontenera rozbijane na indeksy według wagi albo wartości, wybór per rodzaj kosztu
- kurs walutowy brany z dnia zdarzenia i zamrażany przy partii
- koszt domykany etapami — partia ma koszt wstępny, zanim spłynie faktura za fracht
- marża na karcie produktu i na zamówieniu liczona od kosztu wyładowanego
- widoczność danych kosztowych na uprawnieniach — handlowiec widzi próg, nie strukturę
crm-dokumenty
warstwa wejściaProformy, packing listy, terminy od spedytora i dokumenty celne zamieniane w pola.
- odczyt arkuszy i PDF-ów do pól — jedyne miejsce w systemie, w którym pracuje model
- dopasowanie dokumentu do zamówienia i partii po numerze, nie po nazwie pliku
- reguły zgodności (faktura kontra packing lista) w kodzie, nie w ocenie modelu
- terminy przypłynięcia aktualizowane ze strumienia spedytora i wywołujące zdarzenie
- dokument nierozpoznany trafia do kolejki z powodem, nie do kosza
Architektura
- Podstawa
- aplikacja TypeScript/Next.js wdrożona w sieci klienta; brak zależności od usług, które musiałyby zobaczyć jego dane
- Model danych
- dziennik zdarzeń jako źródło prawdy, widoki odczytowe jako pochodna — stan magazynu nigdzie nie jest zapisany jako liczba
- Uprawnienia agenta
- deklarowane per agent przed uruchomieniem: co wolno wykonać, co wolno tylko zaproponować
- Próg pewności
- poniżej progu agent nie działa i nie zgaduje — zakłada zadanie z kompletem ustaleń
- Rola modelu
- odczyt i klasyfikacja dokumentów; obliczenia, reguły i decyzje o stanie magazynu w kodzie, który da się przetestować
- Waluty i koszt
- kurs z dnia zdarzenia zamrażany przy partii; koszty kontenera rozbijane na indeksy wagą albo wartością
- Integracje
- arkusze i poczta dostawcy, strumień terminów od spedytora, dokumenty agencji celnej, księgowość, sklep
- Audyt
- każde działanie agenta zapisane z wyzwalaczem, wejściem, skutkiem i momentem — decyzję da się odtworzyć po miesiącach
- Dostęp
- role z osobną widocznością danych kosztowych i progiem kwotowym wymagającym zatwierdzenia
- Wydajność
- widoki odczytowe przeliczane przyrostowo po zdarzeniu; raport historyczny nie przelicza całego dziennika
Technologie
- TypeScript
- Next.js
- PostgreSQL
- Claude
- REST API
Autor
Mariusz PerzyńskiClient Relations & Operations