Block Settings & Management Fee Configuration
Block Settings & Management Fee Configuration
Each block has a dedicated settings page for configuring management fees, RMC/RTM company details, and service charge apportionment.
Accessing Block Settings
From the Blocks list, open any block's detail view and click the Settings button. This navigates to:
/dashboard/blocks/[blockId]/settings
The settings page is divided into three tabs.
Tab 1: Management Fee
Configures how your management fee is calculated and invoiced for the block.
Compliance note: Management fees are always kept separate from client money. This configuration is the block-level record of your fee arrangement and does not commingle with service charge funds.
Fee Structure
| Setting | Options | Notes |
|---|---|---|
| Fee Type | Fixed Annual Fee, Percentage of Service Charge Budget | Select the basis on which the fee is charged |
| Annual Fee (£) | Numeric, e.g. 2500.00 | Shown when fee type is Fixed Annual |
| Fee Percentage (%) | Numeric, e.g. 15.00 | Shown when fee type is Percentage of Budget |
Billing Schedule
| Setting | Options | Notes |
|---|---|---|
| Invoice Frequency | Monthly, Quarterly, Annual | How often management fee invoices are raised |
| Financial Year Start | Any month | Defaults to April (UK financial year) |
| Auto-generate Invoices | Toggle | When enabled, invoices are generated automatically on schedule |
Click Save Fee Settings to apply changes.
Tab 2: RMC / RTM Details
If the block has a Resident Management Company (RMC) or Right to Manage (RTM) company, record its details here. This information can be used on notices, accounts, and correspondence.
Company Details
- Company Name — e.g.
Maple Court (RMC) Ltd - Company Number — Companies House registration number
Registered Address
- Address Line 1, Address Line 2, City, Postcode
Directors
Add and remove directors as needed. Each director record holds:
| Field | Required | Notes |
|---|---|---|
| Name | Yes | Full name |
| No | Contact email | |
| Role | No | e.g. Director, Secretary |
Click Add Director to append a new row, or Remove to delete one. Click Save RMC/RTM Details to apply changes.
Tab 3: Apportionment
Configures how service charges are divided between the units in the block.
Apportionment Status
A status banner at the top of the tab indicates whether the current apportionment is complete (sums to exactly 100%) or incomplete.
Methods
| Method | Behaviour |
|---|---|
| Equal Split | Each unit receives the same percentage. Basis points are distributed automatically, with any remainder allocated to the first unit. |
| By Floor Area | Apportionment is calculated proportionally based on each unit's floor area as recorded on the unit record. |
| Custom Percentages | You manually set basis points for each unit. The total must equal exactly 10,000 (= 100%) before saving is permitted. |
Basis Points
Apportionment is stored and edited in basis points where 10,000 = 100%. The editor shows both the raw basis point value and the equivalent percentage (e.g. 2500 = 25.00%).
The running total is shown in the table footer. If the custom total does not equal 10,000, saving is blocked and an error message indicates the discrepancy.
The Distribute Equally button recalculates all units to an even split at any time.
Saving an Apportionment Change
When you save apportionment changes:
- A new immutable version snapshot is created, recording the method, all unit basis points, and the effective date.
- The unit records in the block are updated with the new basis point values.
- All changes are audit-logged.
You may optionally enter a Reason for Change (e.g. Updated following lease extension on Flat 3). This reason is stored with the version record.
Version History
The Version History panel (collapsed by default) lists every past apportionment schedule. Each version shows:
- Version number
- Method used
- Created date/time
- Effective date
- Reason (if provided)
- Expandable snapshot of all unit percentages at that point in time
Version records are immutable and cannot be edited or deleted, providing a complete audit trail.
Access Control
- Read: Available to all authenticated users with access to the block's organisation
- Write (upsert / update apportionment): Restricted to admin role users only
All write operations are audit-logged.
API Reference
All block settings operations are exposed via the blockSettings tRPC router.
blockSettings.get
Returns the current settings for a block, or null if not yet configured.
trpc.blockSettings.get.useQuery({ blockId: string })
blockSettings.upsert
Creates or updates block settings.
trpc.blockSettings.upsert.useMutation()
// Input:
{
blockId: string
managementFeeType?: "fixed_annual" | "percentage_of_budget" | null
managementFeeAmountPence?: number | null // e.g. 250000 = £2,500.00
managementFeePercentageBasisPoints?: number | null // e.g. 1500 = 15.00%
billingSchedule?: "monthly" | "quarterly" | "annual" | null
autoGenerateInvoices?: boolean
financialYearStartMonth?: number // 1–12
rmcCompanyName?: string | null
rmcCompanyNumber?: string | null
rmcAddressLine1?: string | null
rmcAddressLine2?: string | null
rmcCity?: string | null
rmcPostcode?: string | null
rmcDirectors?: { name: string; email?: string; role?: string }[]
}
blockSettings.updateApportionment
Updates the apportionment schedule and creates a versioned snapshot.
trpc.blockSettings.updateApportionment.useMutation()
// Input:
{
blockId: string
method: "equal" | "floor_area" | "custom"
unitApportionments?: { unitId: string; basisPoints: number }[] // required for "custom"
reason?: string
}
For custom method, unitApportionments must be provided and the sum of all basisPoints values must equal exactly 10000.
blockSettings.listApportionmentVersions
Returns the full version history for a block, newest first.
trpc.blockSettings.listApportionmentVersions.useQuery({ blockId: string })
// Returns: version[], each with id, version, method, snapshot, reason, createdBy, effectiveDate, createdAt
blockSettings.getCurrentApportionment
Returns the current apportionment values read from unit records.
trpc.blockSettings.getCurrentApportionment.useQuery({ blockId: string })
// Returns: { units[], totalBasisPoints, isComplete, unitCount }