Proinet
← Realizacje
Platforma SaaS, dane motoryzacyjne B2B (USA)

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.

Schemat przepływu danych między systemem produkcyjnym, CRM i QuickBooks
01 Schemat przepływu danych między systemem produkcyjnym, CRM i QuickBooks
Przepływ danych — usługa integracyjna na Apache Camel łączy system produkcyjny, stary i nowy CRM oraz QuickBooks.

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.