Universal Object Model — czyli jedna karta pojazdu na wszystko
Polimorficzna architektura obiektów w MoreCRM: vehicle, motorcycle, boat, truck, farm equipment. Cross-vertical timeline jako killer feature dla multi-vertical service businesses.
Klasyczny CRM dla warsztatu ma tabelę vehicles. Pole make, model, vin, plate, year. Działa. Aż klient przyjeżdża z motocyklem — nie ma plate, ma frame number i engine_cc. Albo z łodzią — ma HIN zamiast VIN. Albo z maszyną rolną — ma serial number. Twój CRM trzeba forkać per typ obiektu. Albo wszystko upchnąć w vehicles z null-able polami i if (type === 'motorcycle') w kodzie.
Tak nie skaluje się.
Universal Object Model
W MoreCRM mamy polimorficzną tabelę objects z object_types discriminator + JSONB specs:
CREATE TABLE objects (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
customer_id UUID NOT NULL,
object_type_id UUID NOT NULL,
identifier TEXT, -- VIN, IMEI, S/N, HIN, chip
display_name TEXT,
primary_image TEXT,
specs JSONB NOT NULL, -- vertical-specific JSON
metadata JSONB,
public_card_token TEXT,
-- ...
);
CREATE TABLE object_types (
id UUID PRIMARY KEY,
tenant_id UUID NULL, -- NULL = system-wide
key TEXT NOT NULL, -- 'vehicle', 'motorcycle', 'boat', 'pet', 'device'
label TEXT NOT NULL,
identifier_label TEXT, -- 'VIN', 'IMEI', 'Chip', 'Hull Number'
spec_schema JSONB NOT NULL -- JSON Schema for specs validation
);
Day-one seed: vehicle, motorcycle, boat, truck, farm_equipment, bicycle. Otwarte na adjacent: pet (weterynaria), device (IT serwis), client_only (salon).
Cross-vertical timeline jako killer feature
Tu leży prawdziwa wartość. Klient ma jedno auto. To auto trafia do Twojego studio detailingu na PPF w marcu. Wraca do Twojej mechaniki na pasek rozrządu w wrześniu. Idzie do Twojej wulkanizacji na opony zima w październiku. Wraca do lakierni na odprysk w lutym. Idzie do auto-szkła w kwietniu.
W single-vertical narzędziu masz 5 osobnych baz, każda widzi tylko swoją zaszłość. W MoreCRM: jedna karta pojazdu, timeline cross-vertical, pełna historia.
To daje Ci moc której nie ma żaden konkurent w Polsce. Klient wraca na przegląd techniczny — Twoja mechanika widzi że ostatni PPF był 14 miesięcy temu, upsell na polerkę przed sezonem. Klient wraca na opony letnie — Twoja wulkanizacja widzi że szyby ma odprysk, upsell na naprawę resin.
Otwarte na adjacent
Universal Object Model otwiera Ci drogę do ekspansji bez refaktoru kodu. Otwierasz salon fryzjerski — object_type: client_only. Otwierasz weterynarię — object_type: pet z polami chip, breed, weight. Otwierasz IT serwis — object_type: device z polami serial, manufacturer, warranty_until.
Architektura jest gotowa już dzisiaj. Marketing nie day-one — robimy go gdy widzimy że biznes się broni w adjacent.
Performance + indexing
JSONB specs jest indexable z GIN:
CREATE INDEX idx_objects_specs ON objects USING GIN (specs);
CREATE INDEX idx_objects_year ON objects (((specs->>'year')::int));
Query “wszystkie auta po 2018 roku” jest szybkie:
SELECT * FROM objects
WHERE object_type_id = (SELECT id FROM object_types WHERE key = 'vehicle')
AND (specs->>'year')::int >= 2018;
Public client portal
Każdy objects ma public_card_token UUID. Klient dostaje link morecrm.pl/portal/<token> i widzi swoją kartę pojazdu 24/7 — bez logowania. Timeline, gwarancje, faktury, kontakt do Twojego warsztatu.
Public portal w Premium tier ma custom domain — Twój klient widzi klient.twojaservice.pl/avensis zamiast generic morecrm.pl URL. Whitelabel multi-brand: 10 brands w Premium, kolejne sloty jako add-on.
Kiedy to ma sens?
Universal Object Model jest overkill jeśli serwisujesz tylko jeden typ obiektu (np. tylko opony). Ale jest must-have jeśli planujesz:
- multi-vertical (detailing + mechanika + wulkanizacja)
- multi-object (auta + motocykle + łódź)
- adjacent ekspansję (weterynaria, IT, salon)
Wypróbuj 14 dni bez karty i zobacz jak Universal Object Card wygląda w produkcji.