Challenge
A 1,200-feddan mixed farm is not one business. Orchards, daily crops, livestock, land rentals, and the lab each earn and spend differently, and the only question that matters is which of them actually makes money.
Answering it normally means a month-end scramble: field activity recorded in one place, costs in another, and an accountant reconciling the two well after any decision could have been changed. Worse, farm accounting is full of quantities that do not divide cleanly — feed splits, fuel apportioned across sectors, water. Money handled in floating point drifts, and a ledger that drifts is a ledger nobody trusts.
Solution
Our team built the general ledger first, on .NET 10 with the ABP Framework as a DDD-layered modular monolith. The ledger is the spine every later module posts into, so Stores, Equipment, Livestock, Lab, HR, and Sales become siblings that depend only on its published contracts and never reach into its tables.
Three rules were treated as non-negotiable and enforced in the domain rather
than in a review checklist. Money is stored as exact decimal at
numeric(28,8) and never rounded — a derived whole-unit value is shown
alongside it for people who need a round number, without the stored figure
ever losing precision. Double-entry postings must balance on those exact
decimals or they are rejected. And a posted entry can never be edited; a
correction is a new, linked reversing entry, so the audit trail records what
was believed and when it changed.
The piece that produces the headline answer is a constraint: every posting line must carry an active cost center. That single invariant is what makes per-sector profit and loss fall out of the ledger for free instead of being assembled by hand each month.
Multi-tenancy, role-based access, and audit come from ABP rather than being reimplemented — the farm is the first tenant, not the only intended one.
Results
Phase one ships the financial spine: a general ledger with cost centers that produces profit and loss per sector directly from posted entries. Because every field action lands on the ledger with a cost center attached, the question "which sector made money this month" is a query rather than a project.
The domain invariants are covered by their own test project, separate from the application-service and EF Core integration suites, so the rules that protect the books are verified independently of the plumbing that stores them.



