Short answer: HOA and apartment management software is not a dues list, it is a charges-and-payments system. The first question to ask a vendor is not about the dashboard but this: is the record opened against the person or against the unit, is each month’s charge created as its own record before any payment arrives, and does the system import the bank statement and match it to payments? Those three questions eliminate most off-the-shelf packages in the first meeting; the monthly report residents actually see eliminates the rest.
The record belongs to the unit, not the person
A building’s real asset is not the resident list but the history of each apartment and shop. The same unit sees three tenants in five years, changes owners twice and sits empty for a while. If the record is opened against a person, every move breaks the history: the old tenant’s arrears float free and the new owner cannot see how last year’s costs were split. If the record belongs to the unit, the unit has one ledger and people attach to it with a date range.
The data-model consequence is clear: the unit is the master record, and owner and tenant are two separate relationships with start and end dates. A unit can have one owner and one tenant at the same time, and an ownership change must not disturb the tenancy. Who a charge is billed to depends on the community’s bylaws and board resolutions; the software should not hard-code that decision but carry the responsible party as a field per charge type. The unit’s ownership share is also a unit attribute, because shared costs are split by it.
If units are recorded by person, an ownership change wipes the history. The answer to who paid for the roof repair three years ago lives in the previous manager’s binder, not in the system.
Charges and payments are separate records
The most common mistake in dues tracking is creating the debt when the payment arrives. The correct order is the reverse: at the start of each month the charges are generated from the annual budget, and incoming payments are then applied against them. A system without charges has no arrears report, only a payment list, and who is behind by how much gets worked out by hand. The same separation applies to recurring billing in gym membership software, but communities add one more twist: there are several charge types. Monthly dues, reserve-fund contributions, special assessments and heating shares are distinct types, each with its own split rule (equal, by ownership share, per building) and possibly a different responsible party.
The second critical point is partial payment. When a resident pays part of three months’ arrears, which month does the money count towards? The rule is written once and applied by the machine; in most communities it is oldest debt first. Late-fee calculation depends on it too: the number of days late is computed per charge, from its due date to the payment date. The late-fee rate is set by the board and is usually capped by local law; keep it as a period-based setting rather than a constant in code, and have your legal adviser confirm the current cap.
type Charge = {
id: string;
period: string; // '2026-03'
dueDate: Date;
amount: number;
outstanding: number;
};
type Allocation = { chargeId: string; amount: number; daysLate: number };
/** Applies a partial payment to open charges, oldest due date first. */
export function allocatePayment(
paidOn: Date,
paidAmount: number,
openCharges: Charge[],
): { allocations: Allocation[]; credit: number } {
const sorted = [...openCharges]
.filter((c) => c.outstanding > 0)
.sort((a, b) => a.dueDate.getTime() - b.dueDate.getTime());
const allocations: Allocation[] = [];
let remaining = paidAmount;
for (const c of sorted) {
if (remaining <= 0) break;
const applied = Math.min(remaining, c.outstanding);
// Days late = whole days from due date to payment date;
// zero for a charge paid before it fell due.
const days = Math.floor(
(paidOn.getTime() - c.dueDate.getTime()) / 86400000,
);
allocations.push({
chargeId: c.id,
amount: applied,
daysLate: Math.max(0, days),
});
remaining -= applied;
}
// Leftover money is not booked as "prepaid" against a month that
// has no charge yet; it sits as credit and clears the next charge.
return { allocations, credit: remaining };
}Two decisions here are deliberate. Leftover money is not booked as prepayment for next month but held as credit, because next month’s charge does not exist yet and its amount may change. And days late are computed per charge closed, not once for the total balance; a single late count on the total treats a three-month-old debt the same as a one-month-old one.
Bank reconciliation: the statement, not the receipt
Most dues arrive by bank transfer, and what goes in the reference field is up to the resident. The software’s job is to import the bank statement and match each line to a unit. Matching tries three routes in order: a sender IBAN already on file, a unit number or name in the reference, and finally amount plus date proximity. Unmatched lines are not deleted; they wait in a separate queue for the manager to link by hand, and an IBAN linked once is recognised automatically the following month.
Online payment reduces this load at the source: when a resident sees their own balance and pays by card, the payment arrives already attached to the right unit. For setup and fees see payment integration for websites and virtual POS commission rates; in communities the amounts are small and frequent, so the fixed per-transaction fee decides the total.
The real product is the report residents see
The measure of management software is not the manager’s screen but the report residents see every month: income and expense lines, cash and bank balances, change against last month and their own unit’s balance. That report cannot be produced without tying every statement line to an expense category, which means bank reconciliation is done for the expense side as well, not just for collections. A report whose cash and bank balances do not agree with the statement is one nobody opens in month two.
On personal data, one rule is enough: everyone sees their own balance and nobody sees their neighbour’s. Instead of posting a debtor list in the lobby or sending it in a group message, use individual notifications. Residents’ names, phone numbers, ID numbers and IBANs are personal data; the purpose of collection, retention period and access rights are written down up front. The principles are the same as in our privacy-compliant website article, and this article is not legal advice.
Staff, maintenance requests and scheduled servicing
Dues are the core but not the only module. Attendance and timesheets for caretakers, security and cleaning staff follow the logic of a time and attendance system; community software should not reinvent that, it either pulls from an existing system or keeps a simple shift log. Residents’ fault reports and complaints live in a queue like a helpdesk ticket system: who opened it, who it was assigned to, when it closed. Lifts, generators and fire systems are asset records with a computed next-service date, and the list of assets past their service date should be the first screen a manager looks at.
Off-the-shelf or custom?
For a single community, a ready-made cloud package is usually enough. The decision changes if at least two of the three tests below come back yes; for the general framework see custom software vs off-the-shelf.
- You manage several communities and need cross-site consolidated reporting, shared suppliers and a single treasury view (professional management companies).
- Your split rules are non-standard: some costs go per building, some by ownership share, some equally, and commercial units follow a separate rule.
- Automatic data exchange with your accounting package or bank is mandatory; manual file uploads do not work at your scale. How that is built is covered in accounting software integration.
- A fourth question applies in every case: can you export the data with full charge, payment and reconciliation detail? If not, the history is locked in when the manager changes.
Five mistakes that sink the project
- Opening the record against a person: the unit’s history breaks when the owner or tenant changes.
- Creating the debt when the payment arrives: without charges there is no arrears report.
- Hard-coding the late-fee rate: when the board changes it, past periods cannot be recalculated.
- Leaving the bank statement outside the system: payments are keyed in from receipts and reconciliation never balances.
- Publishing the debtor list to everyone: a privacy breach and needless friction; each resident should see only their own balance.
Conclusion
When choosing community management software, ignore the feature count and look at three things: is the record opened against the unit, are charges kept separate from payments, and is the bank statement imported into the system. Get those right and the resident report and late-fee calculation become meaningful on their own. If you manage several communities or your split rules do not fit a package, talk to our corporate solutions team; we will map your current process and work out which parts a ready tool can cover and which need custom development. Get in touch for a quote.