System produkcyjny, CRM i QuickBooks połączone przez Apache Camel
Każdy nowy klient, który zakłada konto na platformie, sam pojawia się w CRM, a jego płatności trafiają do QuickBooks. Usługa integracyjna na Apache Camel łączy na bieżąco system produkcyjny z CRM i księgowością — i działa bez przerwy od ponad 7 lat.
- lat ciągłej pracy integracji, bez przerwy
- 7+
- cykl synchronizacji nowych klientów, sald i pakietów do CRM
- 1 h
- typów obiektów w ciągłej migracji ze starego CRM do nowego
- 6
- systemy połączone jedną usługą integracyjną
- 4
Wyzwanie
Platforma SaaS dostarczająca dane motoryzacyjne klientom biznesowym na rynku amerykańskim ma własny system produkcyjny, który obsługuje cały cykl życia klienta: rejestrację konta, pakiety, saldo, faktury i płatności. Dział sprzedaży i obsługi pracował jednak w CRM, a rozliczenia prowadziła księgowość w QuickBooks. Te trzy światy nie wiedziały o sobie nawzajem — nowy klient istniał w systemie produkcyjnym, ale trzeba go było ręcznie przepisać do CRM, a płatność osobno zaksięgować.
Do tego firma przechodziła ze starej wersji CRM na nową — CRM open source wywodzący się z SugarCRM. Stara instalacja przez lata zgromadziła konta, kontakty, notatki, dokumenty, produkty i licencje klientów. Zespół nie mógł zatrzymać pracy na czas jednorazowej migracji, więc stary i nowy CRM musiały przez pewien czas działać równolegle.
Rozwiązanie
Zbudowaliśmy jedną usługę integracyjną na Apache Camel i Spring Boot. Każdy przepływ danych to osobna trasa z własnym harmonogramem, obsługą błędów i zapisem tego, co już zostało przetworzone.

System produkcyjny → CRM. Dane płyną na bieżąco: co godzinę — tak często, żeby CRM był aktualny, i na tyle rzadko, żeby nie obciążać bazy systemu produkcyjnego. Przy każdym przebiegu usługa pobiera klientów, którzy pojawili się od poprzedniego, i zakłada w CRM organizację oraz powiązany z nią kontakt. Znacznik ostatnio przetworzonego rekordu jest zapisywany trwale, więc restart usługi nie oznacza ani pominięcia, ani ponownego importu. Osobne trasy co godzinę przenoszą do CRM saldo konta klienta i listę jego aktywnych pakietów — do CRM trafia tylko to, co się faktycznie zmieniło.
System produkcyjny → QuickBooks. Usługa udostępnia API z kolejnymi opłaconymi fakturami i danymi klienta. Po stronie księgowości działa napisany przez nas konektor — usługa Windows obok QuickBooks Desktop, komunikująca się z nim przez QuickBooks SDK (QBXML). Co kilka godzin pobiera nowe faktury partiami, zakłada klienta, jeśli jeszcze go nie ma, i rejestruje płatność jako paragon sprzedaży. Przed zapisem sprawdza, czy dokument o tym numerze już istnieje, a numer ostatnio przetworzonej faktury zapamiętuje — ponowienie nie tworzy więc duplikatów w księgach.
Stary CRM → nowy CRM. Ciągła migracja co kilka godzin przenosi konta, kontakty, notatki, załączniki, produkty oraz licencje klientów, które w nowym CRM stały się umowami serwisowymi. Rekordy zmienione w starym systemie po migracji można zsynchronizować ponownie — usługa porównuje daty modyfikacji i nie nadpisuje nowszych danych.
Technologia — co sprawia, że to działa w złe dni
- Idempotentny konsument. Każdy przepływ ma trwały rejestr rekordów już przetworzonych. Powtórzenie przebiegu — po awarii, restarcie czy ręcznym wywołaniu — nie tworzy duplikatów. Przy saldach i pakietach kluczem jest para „klient + wartość”, więc rekord wraca do CRM tylko wtedy, gdy wartość się zmieniła.
- Mapowanie identyfikatorów. Ten sam klient ma inny identyfikator w każdym systemie. Usługa prowadzi tabelę odwzorowań „stary → nowy” i na niej odtwarza relacje — kontakt trafia do właściwej organizacji, notatka do właściwego kontaktu, załącznik do właściwego dokumentu.
- Ponowienia i błędy biznesowe. Chwilowe błędy połączenia z CRM są ponawiane. Odpowiedź „duplikat” jest traktowana jako osobny, przewidziany przypadek (rekord jest pomijany), a pozostałe błędy — jako awaria z pełnym zapisem żądania i odpowiedzi.
- Ostrożność wobec systemu produkcyjnego. Import ze źródła idzie małymi partiami, posortowanymi po indeksowanej kolumnie, żeby nie obciążać systemu, który w tym czasie obsługuje klientów.
- CI/CD. Budowa i wdrożenie obrazu Dockera z pipeline'u GitLab CI.
Efekt
- Nowy klient, który założy konto na platformie, pojawia się w CRM automatycznie — jako organizacja z kontaktem, z saldem i aktywnymi pakietami.
- Płatności klientów trafiają do QuickBooks bez ręcznego przepisywania.
- Przejście ze starego CRM na nowy odbyło się bez przerwy w pracy zespołu: migracja działała w tle, a pierwsza pełna migracja produkcyjna ruszyła niecałe dwa miesiące po pierwszym commicie.
- Integracja działa bez przerwy od ponad 7 lat. Przez ten czas dochodziły nowe przepływy (saldo konta, pakiety, powiązania notatek z kontaktami) bez przebudowy tego, co już działało.
Czego się nauczyliśmy
- Ponowienie całości to nie to samo co ponowienie kroku. Gdy założenie kontaktu się nie udawało (np. przez brak nazwiska w danych źródłowych), ponawiany był cały przebieg — a organizacja, utworzona w pierwszym kroku, już istniała. Efektem były zdublowane organizacje. Poprawka objęła normalizację danych przed wysłaniem do CRM i jawne traktowanie duplikatu jako przypadku do pominięcia. Wniosek ogólny: każdy krok przepływu wieloetapowego musi być idempotentny sam w sobie, nie tylko przepływ jako całość.
- Znacznik czasu nie jest unikalny. Wiele rekordów źródłowych miało ten sam znacznik czasu, więc samo „pobierz nowsze niż ostatni” gubiło albo powtarzało dane. Rozwiązaniem było połączenie znacznika (od którego zaczynamy) z idempotentnym konsumentem (który odrzuca to, co już było).
- Nie przekazuj wszystkiego dalej. Camel domyślnie przenosi nagłówki wiadomości do wywołań HTTP. Część z nich przekraczała dopuszczalne długości i psuła żądania do CRM. Od tej pory do zewnętrznych API trafia tylko jawnie dozwolona lista nagłówków.
- Produkcja różni się od testów. Instancja produkcyjna CRM miała inną konfigurację pól niestandardowych niż testowa — mapowanie pól stało się konfiguracją, a nie kodem.
Szerzej o pracy dla tej platformy piszemy w opisie modernizacji platformy SaaS.