Skip to content

feat(models): Sequelize associations across the full entity graph#54

Merged
CryptoJones merged 1 commit into
masterfrom
feat/sequelize-associations
May 18, 2026
Merged

feat(models): Sequelize associations across the full entity graph#54
CryptoJones merged 1 commit into
masterfrom
feat/sequelize-associations

Conversation

@CryptoJones
Copy link
Copy Markdown
Owner

Summary

Wires up hasMany/belongsTo across all 18 models, centralized in db.config.js. JS-side only — the DB-level FK constraints in setup/*.sql + migrations remain authoritative. Enables eager loading via include and the auto-generated get<Foo>()/set<Foo>() helpers.

Graph:

  • Company → 8 child entities (tenancy root)
  • Customer → TimeEntry / Job / Invoice / CustomerPayment
  • Job → InvoiceJob / ProductEntry
  • Invoice → InvoiceJob (lines)
  • InventoryItem ← ProductEntry / InventoryTransaction / PurchaseOrderLine
  • PO chain: Vendor → Header → Line

FK column oddities mirrored verbatim: polpoh (lowercase), invtInitId (BACPAC init prefix), penArch (typo).

Test plan

  • vitest: 29 files / 223 passing (was 28 / 199)
  • New tests/unit/associations.test.js walks each model's .associations and verifies the expected edges — catches typos and column-name drift
  • All existing tests still pass (associations are purely additive)
  • Live include query against PG (not run here — see Server: make express.json() body-size limit explicit + env-tunable #45 / docker compose for the live integration path)

Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/

Wires up hasMany / belongsTo for every FK in the schema, centralized
in db.config.js so the relationship graph is visible in one file
rather than scattered across 18 model definitions. JS-side only —
the DB-level FK constraints remain authoritative via setup/*.sql +
the migrations; associations here enable Sequelize \`include\`
(eager loading) and the auto-generated getter/setter methods.

Graph shape:
  - Company is the tenancy root: hasMany Customer, Worker,
    BillingType, InventoryItem, ApiKey, TimeEntry,
    PurchaseOrderVendor, InventoryTransaction
  - Customer fans out: TimeEntry, Job, Invoice, CustomerPayment
  - Job fans out: InvoiceJob, ProductEntry
  - Invoice fans out: InvoiceJob (lines)
  - InventoryItem fans in: ProductEntry, InventoryTransaction,
    PurchaseOrderLine
  - PO chain: Vendor → Header → Line

A handful of FK column names are unusual ("polpoh" lowercase,
"invtInitId" with the BACPAC "init" prefix, "penArch" typo we
match rather than rename) — associations use the actual column
names so eager loads work without aliasing surprises.

Verified by a new unit-test suite (tests/unit/associations.test.js)
that walks Model.associations and asserts each expected edge.
Catches typos and column-name drift early.

Tests: 29 files / 223 (was 28 / 199).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CryptoJones CryptoJones merged commit c2a6e27 into master May 18, 2026
1 check was pending
@CryptoJones CryptoJones deleted the feat/sequelize-associations branch May 18, 2026 00:01
CryptoJones added a commit that referenced this pull request May 18, 2026
Continues the docs-sync pattern from #44 and #53. CHANGELOG
[Unreleased] now reflects:

  Added:
    - Sequelize associations (#54)
    - Integration test harness (#55)
    - Postman collection (#59)
    - TLS reverse-proxy compose (#60)
    - docker-compose.override.yml committed (#56)

  Fixed:
    - setup/TimeTracker.sql idempotency (#57) — removes the
      \`docker compose down -v\` workaround

  Docs:
    - Integration bring-up flow (#56, #58)
    - README sections for Testing and Behind TLS

Co-authored-by: Aaron K. Clark <akclark@thenetwerk.net>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant