RealEstateAI
Delavnica

CRM smo prenovili s Claudom, tabelo za tabelo

Od sistema brez programiranja (no-code) na Airtablu do lastne aplikacije na Postgresu, ne da bi starega kdaj ugasnili. Kaj je delovalo, kaj se je pokvarilo in katera pravila so nastala iz tega.

2. oktober 2026 · 7 min

Delovna miza ponoči s prenosnikom in tlorisom (slika, ustvarjena z umetno inteligenco)AI · immagine generata

Naš CRM je bil leta sistem, zgrajen na Airtablu: osem baz, približno sto štirideset tabel, kakih sedemdeset pogledov. Deloval je, in prav zato se ga je bilo težko lotiti. To poletje smo ga začeli graditi znova, kot lastno aplikacijo na Postgresu, ki smo jo večinoma napisali v sodelovanju s Claudom. Ni dokončana, in to povemo takoj: nekatere tabele še vedno prihajajo kopirane iz starega sistema. A danes vsi delamo v njem in je dovolj napredoval, da lahko povemo, kaj smo se naučili.

Zakaj starega nismo preprosto ugasnili in prižgali novega

Agencija se ne more za konec tedna ustaviti, da bi izvedla migracijo. Stranke pišejo, ogledi se dogovarjajo, portali pošiljajo povpraševanja ob vsaki uri. Zato smo izbrali počasnejšo pot: novi sistem nastaja ob starem, tabele pa se selijo ena za drugo.

Na začetku enosmerna kopija prenaša podatke iz Airtabla v Postgres: vsakih pol ure žive tabele (kontakti, ogledi, klici, nepremičnine), ponoči vse ostalo. Vsaka tabela ima svoj urnik »odklopa«. Odklop pomeni eno samo, natančno določeno stvar: tabelo izločiti iz kopije. Preden to storimo, mora v novem sistemu obstajati mesto, kjer jo je mogoče urejati. Tabela, ki za popravke še potrebuje stari sistem, ni odklopljena, ne glede na to, kaj piše v načrtu.

To povemo, ker se nam je zgodilo: odklop najpomembnejše tabele, tiste s kontakti, je bil določen za točen datum konec avgusta. Isti dan smo ga prestavili, ker smo se odločili, da del dela, ki smo ga nameravali pustiti staremu sistemu, v celoti prenesemo v novega. Urnik se je podaljšal, pravilo ne.

Kopija, ki briše

Prva resna okvara je prišla z najbolj nedolžne strani: od kopije. Da bi ostala zvesta izvirniku, kopija ob vsakem krogu iz nove baze izbriše vrstice, ki jih na Airtablu ni več. Prav, dokler nihče ne piše v novo bazo. Takoj ko smo začeli pisati tukaj, je vrstica, shranjena zvečer, ob treh ponoči izginila, brez napak in brez dnevnika, ker je na drugi strani »ni bilo več«.

Rešitev je bila dvojna: vrstice, nastale v novem sistemu, nosijo oznako, ki jo kopija upošteva, vsaka sprememba, narejena tukaj, pa se zapiše v register, ki jo po vsaki kopiji znova uveljavi. Vrstica in register se zapišeta v isti transakciji: ali oboje ali nič.

Pravila, ki smo jih drago plačali

En sam kanal za objavo: git push. Na začetku smo objavljali ročno, iz lokalne mape. Ko je vzporedno teklo več delovnih sej, je tisti, ki je objavil drugi, na splet vrnil stanje svojega diska, delo drugega pa je izginilo iz produkcije, čeprav je ostalo v zgodovini kode. Zgodilo se je dvakrat, na starem in na novem sistemu. Danes je projekt povezan z repozitorijem: push na glavno vejo zgradi in objavi, nihče pa ne objavlja s svojega računalnika. Pred vsakim pushem se preveri, ali se oddaljena veja ni premaknila naprej; če se je, se združi in ponovno preveri. Stranska past: če ponudnik gostovanja ne prepozna avtorja commitov, build tiho obtiči. Push uspe in videti je le, kot da se »ni posodobilo«.

Prazna potrditvena polja niso false, ampak NULL. V Airtablu je neoznačeno potrditveno polje preprosto prazno. Ko ga kopiramo v Postgres, postane NULL. In v SQL »ni opravljeno« za NULL ni resnično: je neznano. Prva poizvedba, ki je iskala neopravljene naloge, je vrnila nič vrstic namesto sedemintridesetih. Težava zadeva desetine stolpcev, zato je pravilo mehanično: piše se is not true, nikoli not. Bližnji sorodnik: primerjava z NULL ni neresnična, ampak NULL, in pri štetju »neprebrano / neopravljeno« je število videti verjetno, a je napačno prav v primeru, ki nas zanima.

Datumi se oblikujejo v bazi. Ko smo jih prenesli ven kot datumske objekte, so zaradi časovnega pasu zdrsnili na prejšnji dan. Zdaj jih oblikujemo v SQL in to je to.

Imen stolpcev se ne ugiba. Preden napišemo poizvedbo, vprašamo bazo. Štiri »očitna« imena od štirih so bila napačna.

Vsako pisanje v stari sistem se prijavi in ponovno prebere. Nekaj časa mora novi sistem pisati tudi v Airtable, ker nekateri procesi starega sistema še berejo od tam. Naučili smo se dvoje. Prvič: ta pisanja je treba navesti na vrhu modula, ki jih izvaja, s tabelo, razlogom in tem, kdo jih bere. Drugič: odgovor 200 ni dokaz. Zgodilo se nam je, da je API odgovoril »ok«, ob ponovnem branju pa je bila vrednost še vedno prejšnja. Od takrat vsako tako pisanje polje ponovno prebere in, če se ne ujema, to jasno pove, z razloženo zavrnitvijo in ne s splošnim »poskusite znova«.

Nevidnost, ki ni izguba

Obstaja napaka, ki je subtilnejša od izgube podatkov: podatek je tam, a kdor še dela na drugi strani, ga ne vidi. Nova funkcija je dosje za nadaljnji stik (follow-up) ustvarjala samo v novi bazi. Stranka je bila označena kot prednostna, a mehanizem opomnikov, ki je še tekel na starem sistemu, je ni videl. Rezultat: prižgana zvezdica in nobenega nadaljnjega stika, nikoli. Zdaj mora vsak modul, ki piše, navesti, kaj stari sistem vidi in česa ne. Kjer nevidnost škodi, se piše tudi tja.

Dokument, ki je lagal

Najbolj nenavadna lekcija se ne tiče kode, ampak navodil. Avgusta smo v navodila projekta zapisali, da novi sistem nikoli ne bo pisal v starega. Mesec pozneje smo prešteli in ugotovili, da koda to počne v sedemindvajsetih različnih modulih, v vseh iz dobrih razlogov. »Nikoli«, kršen sedemindvajsetkrat, ne varuje ničesar. Uči, da dokument laže, in vodi v napake v dveh smereh: kdor mu verjame, podvoji pisanje, ki je že obstajalo, kdor mu ne verjame, uvede novo, ne da bi ga prijavil. Pravilo smo prepisali tako, kot je dejansko bilo, z datumom stare odločitve prečrtanim, a čitljivim, ker pojasnjuje, kakšna je bila koda takrat.

Najprej šteti, potem graditi

Preden prenovimo razdelek, pogledamo, kakšen je bil v starem sistemu, in preštejemo vrstice. Razdelek, ki je bil videti kot cel projekt, je obsegal sedemnajst kartic. Drug, ki se je zdel obroben, je vseboval na stotine prepisov telefonskih pogovorov, ki jih nihče ni pregledoval. Ime stvari ne pove, koliko tehta. Staro kodo pa beremo iz objavljene različice, ne iz lokalne kopije: naša je zaostajala za več sto commitov in število je raslo.

Kako je tako delati s Claudom

Skoraj vsa nova koda je nastala v sejah s Claudom. Pri obsegu dela se je dobro obneslo: celi razdelki, prepisani v nekaj dneh. A zgornjih pravil ni izumil model. Prišla so iz okvar in vsako je postalo vrstica v navodilih, ki jih vsaka seja prebere, preden se česar koli dotakne. Vrednost ni v tem, da kodo piše stroj. Je v tem, da vodimo pošten zvezek o tem, kaj se je pokvarilo, in ga damo v branje vsakomur, ki dela za nami, človeku ali modelu.

Prevedeno iz italijanščine z umetno inteligenco.

#crm#migracija#postgres#airtable#claude

Berite naprej