{"id":839,"slug":"client-bjf-data-model-tanks-first-class","title":"B&J data model — first-class entities, including TANKS (the most quotable architecture decision)","kind":"decision-record","scope":"client-case-studies","status":"current","audiences":["kevin","candid-team","client-prospect"],"topics":["tank-services","crm-systems","client-boucher-jones","case-study-source","architectural-decisions","data-model-design"],"reference_body":"**This is the single most interesting story for the case study.**\n\nGeneric CRMs treat fuel customers as accounts with an address. Reality is more structured than that — and we modeled it that way.\n\n## First-class entities in the B&J CRM schema\n\n| Entity | Why it is first-class (and why a generic CRM gets it wrong) |\n|---|---|\n| **Accounts** | Tagged by segment (residential / agricultural / fleet / construction). Carries payment terms, credit limit, rep, acquisition source. A generic CRM has accounts — but does not enforce segmentation in the data model, so segmentation degrades to a free-text field. |\n| **Locations / Sites** | One account ↔ many locations. A farm customer has a farmhouse, a barn, a shop, and a remote field tank — each with its own delivery access notes and degree-day zone. Generic CRMs do not model multi-site accounts as a first-class relation; they treat addresses as a property of a contact. |\n| **Tanks** | Each location has one or more tanks. Each tank carries fuel type, capacity, ownership (customer-owned vs B&J-owned), inspection date, and reorder point. **The reorder point is what drives automatic delivery scheduling.** No generic CRM models tanks at all. |\n| **Contacts** | Multiple contacts per account, each tagged with role and communication preferences. The bookkeeper gets invoices; the operations manager gets delivery notifications; the owner is the decision-maker on contract renewals. |\n| **Price contracts** | Per-account, per-product, with type (fixed / capped / market rate / budget billing), rate, and effective/expiry dates. Fuel pricing is contract-driven and contract types are nontrivial. Generic CRMs do not model price contracts. |\n| **Products** | Unified catalog of fuels, lubricants, additives, and services. |\n| **Delivery orders** | The operational heart. Date, product, quantity, price-at-delivery, driver, truck, status, classification (automatic / will-call / emergency). |\n| **Invoices** | Line items, HST, due date, payment status. Linked to one or more delivery orders. |\n| **Payments** | Amount, method, date, reference. Drives AR reporting. |\n| **Interactions** | Calls, emails, complaints, site visits. The relationship layer. |\n\n**[Verified — `crm_project_plan.docx` §2.1]**\n\n## The two most quotable lines\n\n> **\"We treat tanks as first-class objects, not free-text fields.\"**\n\nThat one decision is the architectural difference between a fuel CRM and a CRM with fuel pasted onto it.\n\n> **\"Multi-site accounts, fuel-type-specific contracts, degree-day zones, and delivery type are all data, not notes.\"**\n\nSee [[client-bjf-custom-vs-industry-erp]] for why this needed to be built rather than bought, and [[client-bjf-arch-decisions-ranked]] for how this fits among other case-study-worthy decisions.","rationale_body":"Tagged as `decision-record` rather than `reference` because the entity is the architectural decision itself — modeling tanks as first-class objects — not just a description of the data model.","metadata":null,"links":{"outgoing":[{"slug":"client-bjf-custom-vs-industry-erp","title":"B&J architectural decision: custom platform vs Manage Petro / PDI / Cargas — why custom won","kind":"decision-record","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-arch-decisions-ranked","title":"B&J architectural decisions worth surfacing in case-study narrative — eight, ranked","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-crm-stack-planned","title":"B&J CRM platform — PLANNED stack (not yet built)","kind":"reference","scope":"client-case-studies","link_type":"relates-to"}],"incoming":[{"slug":"client-bjf-case-study-source-v1","title":"Boucher & Jones Fuels — case-study source material, v1 (parent index)","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-custom-vs-industry-erp","title":"B&J architectural decision: custom platform vs Manage Petro / PDI / Cargas — why custom won","kind":"decision-record","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-narrative-angles-ranked","title":"B&J case study — suggested narrative angles, ranked, with a recommended hybrid lead","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-arch-decisions-ranked","title":"B&J architectural decisions worth surfacing in case-study narrative — eight, ranked","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-database-state-v2","title":"B&J — database state (v2, verified 2026-05-24) — marketing site is materially read-only","kind":"reference","scope":"client-case-studies","link_type":"relates-to"}]},"created_at":"2026-05-24T00:26:55.449Z","updated_at":"2026-05-24T00:26:55.449Z"}