Mohle Realty Handbook

The Admin & Staff Handbook

A working reference for the Admin Control Center — members, properties, tenancies, money movement, repairs, and leads.

Where everything lives

The Control Center

Everything in this guide happens inside the Admin Control Center, reached by signing in with an account that has the admin role. The sidebar and the quick-action buttons across the top of the dashboard are your fastest way to any of the sections below.

Every admin screen follows the same rhythm: a filterable list, a View or Manage link into detail, and clearly-labelled action buttons for whatever you're allowed to do from there. Forms that create or change something always show a green confirmation or a red error message right above the form once submitted.

Signing in lands you on a bank-reconciliation banner, then the overview cards below it -- a snapshot of the whole platform:

CardWhat it means
Total Funds HeldEvery bucket of real money the system knows about, netted against what Mohle has already spent -- this is the one figure to compare against your actual bank balance.
Bank BalanceYou type this in yourself whenever you check your real balance -- it's saved with a timestamp so it doesn't reset between visits, but it only stays accurate if you keep updating it.
VarianceBank Balance minus Total Funds Held. Colored amber when it drifts beyond a small tolerance -- that's your cue to check for an unlogged expense or something else unaccounted for.
Total Members / PropertiesStraight counts.
Active / Expired Tenancies, Vacant PropertiesOccupancy at a glance.
Mohle Realty EarningsEverything the business itself has earned — commission, admin recovery fees, OPC handling fees, service charges.
Mohle Operating ExpensesEverything logged via ➕ Log Mohle Expense -- salaries, rent, bank charges, etc. See Mohle expenses, external income & tax reports.
External IncomeMoney the business receives from outside its own service fees -- a stakeholder contribution, an external service payment, bank interest, a grant, etc. Logged via ➕ Log External Income, kept separate from Mohle Realty Earnings since it isn't earned the platform's usual way, but still counted in Total Funds Held since it's just as real in the bank. See Mohle expenses, external income & tax reports.
Tenant Spendable Wallets / Property WalletsTotal money currently held in trust in each of those two wallet systems.
Security Deposits Held / OPC Advances HeldMoney tenants have paid in as security deposits or OPC advances -- held separately from their spendable wallet balance, and refundable at move-out.
Reserve PoolsTotal money set aside across all repair reserve pools.
Pending RemittancesTotal value of remittance/tenant-wallet-transfer requests still awaiting co-owner approval or your batch payout. Not counted again in Total Funds Held -- that money is still sitting inside Property Wallets until you actually confirm the bank transfer.
Awaiting Co-Owner ApprovalHow many of those requests still need another co-owner to sign off before they can move forward at all.
Open RepairsTotal cost of repairs still outstanding -- anything short of the final Vendor Paid stage (see Repairs). This is also counted back into Total Funds Held above: a repair's reserve pool is debited the moment it's logged, well before the vendor is actually paid, so that cash hasn't left the real bank account yet -- it's still sitting there, just earmarked. Reaching Vendor Paid is what finally drops it out of both figures.
Untriaged Repair ReportsTenant-submitted repair reports still waiting for you to log as a real repair or dismiss.
Pending WithdrawalsTotal value tenants have asked to withdraw from their wallets, not yet paid out.
Pending CommissionsAgent commission owed on leads, not yet approved and paid.

2026-08-27: the old "Pending Payments" and "Pending Remittances" cards read from rental_payments, a table nothing in the app ever finishes updating — "Pending Payments" could only ever show ₦0, and "Pending Remittances" only ever grew. Both were replaced: "Pending Payments" was removed outright, and "Pending Remittances" now reads live from the real remittance request pipeline instead.

Keeping the reconciliation honest

Mohle expenses, external income & tax reports

Mohle Realty's own running costs — salaries, rent, bank charges, and the like — come out of the same bank account revenue sits in, so they need logging here for the dashboard's Total Funds Held figure to mean anything. This is separate from ➕ Add Expenses, which is a property's operating costs billed back to its tenants' OPC advances — a different thing entirely.

  1. Use ➕ Log Mohle Expense: description, category, amount, date, and an optional receipt (image or PDF) for your records.
  2. 📜 Expense History lists everything logged, filterable by category and date range, with a running total for whatever filter you've set and a link to view each receipt.

The category dropdown is grouped into four areas — pick whichever row below best matches:

GroupCategoryCovers
🏦 Financial & Compliance CostsBank ChargesTransfer fees, account maintenance fees, and unrecoverable VAT/EMTL on bank services.
Taxes & LicensesLocal government levies, CAC annual filing fees, non-recoverable permits.
Professional FeesLegal fees, audit fees, accounting software subscriptions.
🏢 Operations & Administrative ExpensesRent & UtilitiesOffice rent, waste management fees, electricity/DisCo bills.
Power & FuelDiesel or petrol for generators and company delivery vehicles — kept separate from Rent & Utilities when this is a heavy spend.
Office Supplies & PrintingStationery, printing cartridges, small office consumables.
Repairs & MaintenanceServicing Mohle's own office electronics, generators, or office building — not a property repair (see Repairs), which is a completely separate feature funded from a reserve pool, not this expense log.
👥 Human Resources & Personnel CostsSalaries & WagesGross monthly pay to full-time staff.
Staff Benefits & WelfareHMO premiums, staff lunches, training costs.
PensionsThe employer's portion of mandatory pension contributions.
📣 Marketing & Business DevelopmentAdvertising & PromotionSocial media ad spend, billboard placements, flyer printing.
Entertainment & TravelTransport fares, flights, hotel stays for business trips, client entertainment — keep strict receipts here for FIRS audits.

External income is the reverse case: money coming into the bank account that isn't one of the platform's own service fees — a stakeholder contribution, payment for an external service, bank interest, a grant, and so on. Left untracked, this money would make Total Funds Held drift below your real bank balance every time it arrives.

  1. Use ➕ Log External Income: description, category (stakeholder contribution, external service income, interest income, grant or donation, or other), amount, date, and an optional supporting document (image or PDF) — a bank credit advice, contribution agreement, or invoice, for instance.
  2. 📜 External Income History lists everything logged, filterable the same way as Expense History.

For tax filing or bookkeeping, 📊 Revenue & Expense Report summarizes revenue, external income, and expenses over any date range (defaults to the current calendar year) — totals, net income, and a breakdown by type/category on screen, plus a ⬇️ Download CSV button for the full line-by-line detail to hand to your accountant. External income is kept as its own line rather than folded into revenue, since some categories (a stakeholder contribution, for instance) may not be taxable the same way a service fee is — that's a judgment call the report leaves to whoever's filing.

People on the platform

Members & roles

Nobody signs themselves up — every account starts with you. Use ➕ Add Member on the dashboard to create one: name, contact details, government ID (optional), bank details, and one or more roles — Tenant, Landlord, Lead Agent, or Admin. A single person can hold more than one role at once (e.g. a staff member who's also a tenant) and switches between their views with the role selector on their own dashboard.

Preferred contact: each member has an email address and, optionally, a WhatsApp number plus a Preferred Contact setting (Email, WhatsApp, or Physical). Whenever the system notifies that member — a renewal offer, a repair update, a receipt — it honours this: an Email member gets the email as now; a WhatsApp member gets the message queued on the WhatsApp Dispatch desk, with their email as the automatic fallback if the send fails; a Physical member gets it queued as a printable PDF on the Physical Dispatch desk, for someone to print and hand-deliver. (Legal documents always send the email too, as the record of service, regardless of preferred channel.) Choosing WhatsApp requires a WhatsApp number on the account; Physical is for a member with no working digital contact at all.

ActionWhereWhat it does
Edit detailsMember details → EditUpdate contact info and bank details. Name/sex/government ID lock once the member has a government ID reference on file.
Reset passwordMember details → Reset PasswordThe only way a member regains access if they're locked out — there's no self-service reset yet. The member is emailed a new system password and is forced to set their own the next time they sign in. (New onboarding accounts work the same way.)
Log in as memberMember details → Login As This MemberSee exactly what they see, useful for troubleshooting a reported issue.
Fund tenant walletMember details (tenants only) → Fund Tenant WalletRecord a rent payment received outside the app (bank transfer, cash, POS) against their wallet.
Withdraw tenant walletMember details (tenants only) → Withdraw Tenant WalletQueue a payout of wallet funds back to the tenant — see Tenant withdrawals.
Deactivate / ReactivateMember detailsMark someone as no longer relevant once they've moved out. Only allowed while they have no active, upcoming, extended, or expired tenancy — the button is refused otherwise. Deactivating a primary member also deactivates their linked secondary occupants, but only the ones who don't have a tenancy of their own elsewhere. Inactive members are hidden from the Members list and Send Message by default (a Show inactive too link brings them back). Reactivating has no such guard.

Writing to a member

Send Message

Use this when you need to tell one or more members something that isn't already covered by a system notice (a correction, an announcement, a heads-up). Search for recipients the same way as the Members page (name, email or phone), tick as many as you need, and type only the message itself — the greeting, sign-off, logo and footer are added automatically, the same as every other email the app sends.

Each recipient is sent by their own Preferred Contact setting: an Email member's message goes out immediately; a WhatsApp member's message is queued on the WhatsApp Dispatch desk for a staffer to send, exactly like any other WhatsApp notice; a Physical member's message is turned into a one-page PDF and queued on the Physical Dispatch desk for a staffer to print and hand-deliver. The list shows which channel each person will get before you send, and a member with none of the above on file is skipped and reported rather than blocking the rest of the batch.

The message box supports basic formatting — bold, italic, underline, links, numbered and bulleted lists. Formatting carries through to the email and, for a Physical member, the printed PDF; WhatsApp always receives plain text (with line breaks preserved), since WhatsApp itself can't render formatted text.

The physical inventory

Buildings & properties

A building is the physical structure and address; each property is a rentable unit inside one. Add a building first (➕ Add Building), optionally linking it to a converted lead — see Leads — then add each unit under it with ➕ Add Property.

On the Add / Edit Building form, pick the State from the dropdown and the Local Government Area fills from that choice. The public Listings page shows the street with its house/plot number masked (e.g. XX Olaiya Street) plus the Location, LGA and State, so the Location (neighbourhood/area), the LGA and the Street are all worth filling in — the exact house number stays private until a viewing is confirmed (long-term) or the booking is fully paid (short-let).

When a property has more than one owner, use the owners table on the Add Property form to record each co-owner's ownership percentage and whether they can initiate a payout request, approve one, or both. For a single-owner property these settings are overridden automatically — the sole owner can do everything.

Property Reference is now generated automatically when you save a new property — a plain MR-NNNN code with no address in it (an older hand-typed style like LA-OKE-ALI-33-U1 put the house number in the ref, which undoes the address masking on the public pages). Older references are left untouched while a tenancy is running, then upgrade themselves to the MR-NNNN form the next time the unit falls vacant — on move-out, or when it's re-published to the Listings page — so an in-progress tenancy's paperwork is never disturbed mid-term. Documents already issued keep whatever reference they were generated with. On Edit you can still adjust a reference until the property has been rented, after which it locks.

A property's detail page is your hub for everything about it: rent, commission, remittance mode, reserve fund standing, and its landlord(s). From there you can edit its settings, add a manual remittance, log a repair, jump into repair history, or manage its public listing.

The public shop window

Publishing a vacancy

A property being Active only means it can hold a tenancy — it is not shown to the public until you say so. The public Listings page (in the main website menu) lists only units you have deliberately published.

Open a property's detail page and choose Public Listing & Photos. On that screen:

  • Listing details — an optional headline, a short description (up to 300 characters, shown on the listing card), a full description (shown on the property's own page), an optional brochure PDF, and the photos. It all saves together with one Save listing button, so text you've typed is never lost when you add pictures. Tick List this unit on the public Listings page to publish; untick and save to take it back down. The date it first went live is recorded and kept even if you unpublish later.
  • Photos — attach up to 15 JPG, PNG or WEBP images in the same form. The first becomes the card image (shown in the grid); use Make card image on any other photo to change that. The ↑/↓ buttons set the gallery order, and Delete removes one — if you delete the card image, the next photo in order takes over.
  • Photo size & shape — the listing card and the property-page gallery both show each photo in a landscape 3:2 frame. Upload landscape photos with a 3:2 ratio — ideally 1500 × 1000 px (minimum 1200 × 800), JPEG, under about 2 MB each — and they fill the frame edge to edge. A photo that isn't 3:2 still shows in full (nothing is cropped), but with thin blank margins on the two short sides; a portrait phone photo will have wide margins left and right. Crop tall or square shots to 3:2 landscape before uploading.

The public page lists a unit only while it has a move-out date (or is genuinely empty). If you publish a unit that still has a sitting tenant, the form makes you set that tenant's move-out date — it defaults to the tenancy's end date, and you can change it. On save, the date is written to the tenancy and the tenant is emailed that their move-out has been recorded (with a line telling them to contact us if they mean to renew). The unit then lists as Available from the day after that date. A unit also drops off when its status leaves Active. If a listed tenant decides to renew, unpublish the unit. Note this only schedules the move-out — the tenancy stays Active and the deposit stays held until someone runs Process Move-Out & Refund on it (see Move-out & refunds).

The exact house number is never on the public pages. Both the Listings grid and each property page show the street with its house/plot number masked (e.g. XX Olaiya Street, Shomolu, Lagos) plus the Location, LGA and State. The full, unmasked address is revealed later: to a long-term prospect in the inspection invite and on the confirmation page once they confirm; to a short-let guest on the receipt once the booking is fully paid (stay total + Caution Deposit). The masking is a best-effort match against the free-text street field (it can't safely mask a street with no leading number, or a numbered street name like “3rd Avenue”) — a proper house-number column is a separate future change. Because the auto-generated MR-NNNN reference carries no address, it can't reintroduce the number; a few older references still contain one but are replaced automatically the next time the unit falls vacant (see Buildings & properties).

Short-let units appear on the same page with a SHORT-LET badge and a from ₦X / night rate (the off-peak floor; seasonal surcharges are added per night). Instead of “Apply for residency” / “Book an inspection” a short-let listing shows Book a short stay — a live calendar + instant priced hold (see Short-let bookings). An Ask a question link still routes to the contact form.

Prospective-tenant viewings

Inspection desk

A visitor who selects Book an inspection on a long-term listing fills in their name and one contact channel (email or WhatsApp). That creates a request in Inspection Desk (sidebar). The desk has four tabs — New requests, Awaiting confirmation, Confirmed, History — and within each tab the requests are grouped by property, so you can see everyone waiting on the same unit together.

  1. New requests — review the request and either propose a date (pick a day and a time from the AM/PM list) or Decline it with an optional reason.
  2. Proposing a date moves the request to Awaiting confirmation and starts a confirmation clock (default 48 hours, set by INSPECTION_CONFIRM_WINDOW_HOURS). For an email contact the invite with a confirm link is emailed automatically. For a WhatsApp contact the desk gives you an “Open WhatsApp” link (click it — WhatsApp opens on the visitor's number with the full message, including the confirm link, pre-typed; you just hit send) plus the same text to copy manually. The same click-to-chat link is offered whenever you decline or cancel a WhatsApp contact's request, and it stays on the card while a WhatsApp viewing is awaiting confirmation.
  3. When a property has more than one open request, the property's header carries a Propose to all N picker — one date/time offered to every open request for that unit at once (open-house style), each visitor getting their own confirm link.
  4. The visitor confirms by clicking the link in time — the request moves to Confirmed. You can also Mark confirmed yourself if they confirm by phone, or Reschedule from either Awaiting confirmation or Confirmed (proposing a new date sends a fresh invite and clears any earlier confirmation). If the confirm window lapses, the slot is released automatically the next time that link is opened.
  5. After the viewing, use Attended or No-show on the Confirmed tab. Everything finished (attended, no-show, cancelled, declined) lands in History.

The requester is not a member — no account is created at this stage. One open request per property + contact is allowed; a repeat submission is bounced with a message.

Every outcome the visitor is waiting on — a proposed or rescheduled date, a decline, or a cancellation — sends them a note (emailed for an email contact; for a WhatsApp contact the desk gives you the wording to send). The optional Reason you type on a decline or cancel is included in that note, so leave it blank if it's an internal-only reason. Only the after-the-fact records — Attended / No-show — are silent. The exact house number is never on the public pages (they show the street with its number masked, plus the location, LGA and state); the full address reaches the visitor only in the viewing invite and on the confirmation page after they confirm.

Guest bookings

Short-let bookings

Short-let is a live booking flow, separate from the tenant pipeline. A guest never becomes a member and no application is taken.

How a guest books

On a short-let listing the guest selects Book a short stay, picks their nights on a calendar that greys out dates already taken, and sees the bottom-line price (stay total, any discount, the reservation deposit, the Caution Deposit, and the combined total if paying everything upfront) — the seasonal surcharge and length-of-stay mechanics behind that number stay internal. They enter their full name exactly as on their ID — this is the primary guest member, whose ID and invoice must match at check-in — the guest count, a required email address (their priced offer is emailed here — WhatsApp isn't offered as a contact preference for short-let), a phone number for the team to reach them if needed, and their refund account (account name, bank, account number) — the same account they pay from, which is also where the Caution Deposit or any cancellation refund is paid back to. If someone is booking on behalf of the person who'll actually stay, they tick “booking on behalf of someone else” and give both their own name (the booking contact) and the primary guest's name separately. Whatever the guest count, the form collects every occupant's name, not just a headcount. Submitting holds the dates and auto-issues a priced offer (PDF + email, citing the governing short-term occupancy agreement version) listing the primary guest, who booked on their behalf (if applicable), and the full guest list. Stays over 90 nights are sent to the contact form instead.

Per the signed short-term occupancy agreement, the guest pays in two parts: a reservation deposit (20% of the stay total, configurable) is due now to hold the dates, and the remaining 80% balance plus a separate, refundable Caution Deposit (against damage/violations/late check-out) are both due 7 days before arrival (configurable). The offer asks the guest to pay at least the reservation deposit by bank transfer (guidance: within 24 hours; the hold actually releases after 48). There is no online payment — a staffer records each transfer on the desk. If nothing is recorded before the hold expires, cron_shortlet_holds.php frees the dates.

Short-let Desk

Short-let Desk (sidebar) has three tabs — Held, Confirmed & staying, History. Each row shows the stay, the guest, and the money line (total · reservation deposit · Caution Deposit · paid · balance, with an overdue balance flagged).

  1. Assign to me — takes ownership.
  2. Record payment — enter the amount, method, bank reference, and the sender's name, bank, and the last few digits of the account exactly as they appear on the bank statement (e.g. the ...45 in 0234****45). Every payment writes a numbered receipt (INV-YYYY-NNNNNN) and emails the guest: when the recorded total reaches the reservation deposit, a held booking flips to confirmed (with the balance + Caution Deposit still owing); once the total reaches the full amount (stay + Caution Deposit), the guest is emailed a full receipt PDF instead, citing the governing agreement version and the Caution Deposit refund terms; any payment in between just gets a plain acknowledgement of what's paid and what's still outstanding. A refund can only ever go back to the account that actually paid in (an AML safeguard), so if the sender details don't match the refund account on file, the payment is still recorded but the booking is flagged Refund blocked until Update refund account is used to correct it.
  3. +24h hold (held only) — a goodwill extension for a guest who needs a little longer to pay.
  4. Check in — moves a confirmed stay through arrival. Check-in still works with a balance (including the Caution Deposit) outstanding, but the desk warns you.
  5. No-show — the guest never arrived; whatever they'd paid is forfeited. The stay portion of that forfeited cash is split with the property owner (owner's net to the property's pooled ledger for the next remittance run, Mohle's management commission booked as revenue) — the same split a completed stay gets, just on the smaller amount.
  6. Check out — marks departure and recognises the stay revenue: by now the booking is unquestionably valid, so the desk books Mohle's management commission (from the property's commission rate, VAT shown separately) as revenue and credits the owner's net to the property's pooled ledger, which the next remittance cycle pays out to owners exactly like long-term rent. It still doesn't touch the Caution Deposit or ask about damage — an inspection often happens a day or two later.
  7. Cancel — frees the dates and works out the refund from the agreement's policy: free (full refund) up to 7 days before check-in; inside that window a fee of 90% of the nightly rate plus the Administrative Charge is withheld (not the Caution Deposit) and the rest of whatever was paid is refunded. The withheld fee is Mohle's alone — a cancellation isn't shared with the owner (unlike a completed stay or a no-show). Tick waive fee to refund in full regardless. The guest is notified.
  8. Queue refund (the "Process refund" form) — appears on any checked-out or cancelled booking with money owed back (the full Caution Deposit for a checked-out stay, or the cancellation refund for a cancelled one; the refund account given at booking is shown alongside it). This is where damage is actually assessed: enter an optional damage deduction with a required note. A damage deduction is the property owner's compensation — it's credited to the property's pooled ledger (no Mohle commission on it), not kept by Mohle. It doesn't send any money itself — it approves the net amount, emails the guest a Caution Deposit / Cancellation Refund Settlement Statement (PDF attached, citing it's queued for payout), and queues it for the actual bank transfer. Until you queue it, the desk keeps showing the amount owed; once queued, it shows "approved & queued for payout" instead.
  9. Update refund account — only appears when a booking is flagged Refund blocked (a recorded payment's sender didn't match the refund account on file). Enter the correct account name, bank, and full account number as the guest gives them to you; it's only accepted if it now matches the sender captured at payment time, and clearing the block is what lets a refund be queued.

💵 Process Payouts (the single payout screen on the dashboard) is where a queued refund is actually paid: it lists every pending payout — owner remittances, tenant withdrawals and short-let refunds together — with its payee account; you tick the ones you've transferred, enter one shared batch reference, and mark them paid. Short-let guests aren't members and have no wallet, so a refund row carries a snapshot of the payee account taken when it was queued. No second email goes out at this step; the guest was already told when the refund was queued.

The guest can view and cancel their own booking from the manage link in the offer (shortlet_manage.php) — same 7-day cancellation policy. A guest cancellation shows on the desk and emails the office. Their own page also shows whether an owed refund has been paid yet.

All guest notifications (offer, confirmation, cancellation) are emailed — short-let doesn't use the WhatsApp Dispatch desk. The guest's phone number is shown on the card for the team to call if needed.

Taking a unit off the calendar — Short-let Availability Blocks

Short-let Availability Blocks (sidebar) lets you close a unit to guest bookings for a date range — scheduled painting, the owner using it privately, anything that makes it unavailable without an actual booking. Pick the unit, a from/to range (the unit is free again on the to date, same as a checkout), and an optional internal-only reason. It's rejected if it would overlap an existing confirmed stay or live hold — cancel or reschedule that first. Once added, those dates show as unavailable on the public calendar and quote exactly like a real booking, but guests never see why. Remove reopens the dates immediately (kept in the log, not deleted).

Seasonal pricing — Short-let Seasons

Short-let Seasons (sidebar) is where the per-night surcharge comes from. Create a region (a micro-market such as “Ota” or “Yaba”) — it starts with Low (+0%), Shoulder (+15%) and High (+30%) seasons, which you can adjust. Map each of the region's twelve months to a season, then assign every short-let building to a region on the same screen. A building with no region, or a month left unmapped, prices at the plain nightly floor. Pricing resolves per night from the stay dates, so a stay that straddles two seasons is split night-by-night. This seasonal breakdown is internal — the public booking page only ever shows the guest the bottom-line total, never the per-night surcharge mechanics.

A unit is made a short-let, given its per-night floor rate and its guest maximum, on the Add / Edit Property form. Discount codes (percent or fixed, optionally scoped to one unit or region, with a use limit and dates) are managed in Short-let Vouchers.

Long-stay discount: every booking also gets an automatic discount off the seasonal subtotal based on length of stay: 1–2 nights 0%, 3n 5%, 4n 7%, 5n 9%, 6n 11%, 7n 13%, 10n 20%, 14n 30%, 21n 42%, 29n+ 55% (a night count between two listed tiers bands down to the lower one). A voucher code and the long-stay discount are never combined — whichever is larger for that stay applies, and an out-competed voucher isn't consumed.

Prospective-tenant applications

Application review desk

A prospect who selects Apply for residency on a long-term listing fills in a full application in one sitting — identity, 5-year residence history, employment & income, an optional guarantor, referees, a conduct questionnaire, and document uploads (ID, passport photo, 6-month bank statement, employment/CAC evidence, guarantor ID). They are not a member and get no account. Everything the vetting team needs is captured now, so vetting only has to verify it and take the fee — it never has to go back to the applicant for more detail.

Applications land in Application Desk (sidebar), grouped by property, across four tabs — Open, Selected, Vetting, Closed. Each card shows a summary without expanding: income and employment type, household size, the key conduct figures (smoker, eviction count, conviction count — with the applicant's explanation when either is non-zero), and badges (viewed the unit / says inspected / not inspected, guarantor, income-below-threshold, eviction or conviction history, document count). Expand Full application for everything else — the residence-history table, occupant list, clickable document links, the applicant's document-delivery choice (digital or physical — physical adds a per-term fee to their tenancy) and whether they opted into the deposit Growth Arrangement, and the History log, which names every staff member who has acted on the application (more than one person often works a case). Documents open through an admin-only viewer (doc_application.php) — never reachable by a public URL.

  1. Select — marks this applicant as the one being progressed for that unit. If another application for the same unit was already selected, it drops back to Open automatically (you can swap freely) and any unpaid vetting offer on it is cancelled. The other applicants are not touched and not notified — they simply stay in Open as your backups. If the selected applicant falls through, just select the next one. Nobody is told “you weren't selected” until the unit is actually let — converting the successful applicant to a tenancy (see Vetting desk) closes and notifies the rest in one batch. Selecting also works out the vetting tier (see the box below) and shows it as a badge.
  2. Waive vetting (Selected tab, only for a no vetting tier) — a returning member in good standing needs no checks and no fee. This jumps the application straight to vetting_passed, ready to convert.
  3. Bill vetting fee (Selected tab) — issues the offer. For a full tier: PRIMARY_MEMBERSHIP_FEE for the applicant; for a partial tier: PARTIAL_VETTING_FEE instead. Either way plus SECONDARY_MEMBERSHIP_FEE for each adult occupant who isn't already a member, plus VAT. A pro-forma letter with the bank details is emailed (or queued for the WhatsApp desk, per the applicant's preference). Only one applicant per unit can hold an offer at a time — billing one cancels any unpaid offer elsewhere on that unit. The fee is non-refundable.
  4. Record payment — once the applicant has paid, pick the payment method from the dropdown (the same list used everywhere else in the app) and enter the bank reference. This issues a numbered receipt (INV-YYYY-NNNNNN, the same sequence as rent receipts), books the income, sends the receipt, and moves the application to Vetting.
  5. Request info — type what's missing or unclear; the applicant is emailed and can reply (with an optional file) from their own status page, which moves the application back to Open for you.
  6. Decline — for an applicant who genuinely doesn't qualify. They get a courteous email; the optional Reason you type is included, so leave it blank if it's internal-only.
  7. Withdrawn — record it here if an applicant pulls out by phone. (They can also withdraw themselves from their status page.)
  8. Return to pool — clears a selection without picking anyone else (and cancels its unpaid offer).

The public pages only ever show the area, LGA and state — never the street. An applicant's email is auto-matched against the inspection desk: if they had a confirmed or attended viewing for that unit, the card shows a green viewed the unit badge. The income-below-threshold badge fires when declared monthly income is under APPLICATION_INCOME_RENT_MULTIPLE × (rent + service charge) — the same point at which the public form advises the applicant to add a guarantor.

Vetting tiers — returning members

Every member passed vetting once to join the Mohle ecosystem; after that we watch their standing. When you select an applicant, the desk matches them (by email, WhatsApp number or government ID) to an existing member and their tenancy history, and sets a tier:

Tier badgeWhoWhat happens
no vettingA member with a live tenancy, or whose last tenancy ended within the last 3 months, and no bad record.No checks, no fee. Use Waive vetting → straight to vetting_passed. Prioritise a good returning member over a new applicant.
partial vettingA member who has been without an active tenancy for more than 3 months, or an existing occupant taking up their own tenancy.Financial capability only. Bill financial vetting fee (PARTIAL_VETTING_FEE). On the Vetting Desk only the employment / guarantor section shows — identity, residence-history and reference checks are skipped.
full vettingNot known to us.The full process, as before.

A member with a bad record (their member record shows rental_standing = blocked) cannot be selected at all — the desk refuses it. Real bad-record scoring arrives with the move-out / credit-score phase; for now it's a manual flag on the member. Each occupant already in our system (matched by government ID) is likewise not re-vetted and not charged the ₦5k — the card shows how many of the occupants that covers.

Background checks

Vetting desk

Once an applicant has paid the vetting fee they appear in Vetting Desk (sidebar), In progress tab, grouped by property. This is where the team records what each check turned up and then releases an overall decision.

  1. Adult occupants — a Pass / Fail (with a note) for each adult named on the application, from the identity and background check.
  2. Employment / business, Guarantor (only shown if one was provided) and References — each set to Verified, Concern or Unreachable with a note.
  3. Residence history — the same three-way result per address, from phoning each landlord/agent. Their number is shown next to the row.
  4. Documents open through the same admin-only viewer as the review desk.
  5. Set as many rows as you like — occupants, sections and residences together — then press Save all checks once. Rows left on keep are untouched; every row you did set still records its own history entry.
  6. Release PASS / FAIL — enabled once every occupant check is decided (the other checks may still be pending, with a warning). Releasing writes a consolidated vetting report PDF and notifies the applicant over their preferred channel: a pass attaches the report and moves the application to vetting_passed (ready to convert to a tenancy, below); a fail sends a courteous note (your final note is included) and closes the application.

A partial-vetting card (a returning member — see Vetting tiers) shows a banner and only the financial section: employment / business and guarantor. Occupant, residence-history and reference checks don't appear, and releasing is gated only on the employment / business check. A no-vetting applicant never reaches this desk — it was waived at selection.

Released applications move to the Released tab (read-only) and also show under Closed on the Application Desk. The report PDF is reachable any time from the card via an admin-only link.

Convert & issue tenancy offer

A vetting_passed card carries a Convert & issue tenancy offer form — just a start date, pre-filled from the applicant's preferred move-in. Submitting it, in one step:

  1. Creates the primary member from the applicant (or links to their existing member account if the email / WhatsApp number / government ID already matches one — a returning tenant keeps their history), opens a tenant wallet, and sends a welcome message with login details over their preferred channel. Each adult occupant becomes a member (member type occupant, no login).
  2. Issues the tenancy offer: a 3, 6 and 12-month plan menu. Each plan is basic rent × the months + OPC / service charge × the months + the full security deposit (LONG_TERM_DEPOSIT_MONTHS × monthly rent + charge) + the unit's one-time fee if it has one (e.g. an estate levy, also shown on the public listing) + the physical document delivery fee (PHYSICAL_DELIVERY_SERVICE_FEE + VAT) if the applicant chose physical delivery. The letter also carries the governing lease-agreement version and link, and any wallet credit already on hand. It asks for payment within 48 hours — informational only; give more time at your discretion.
  3. The card moves to the Tenancy offered tab. The other applicants for the unit are not touched yet.

The Tenancy offered card shows the plan menu, the member and their current wallet balance (each plan the balance already covers is ticked), a link to Fund this wallet, and a Re-send offer button. Re-send offer e-mails the same letter that was already issued (same reference, same PDF) — it does not draw up a new one. The Re-send offer button on a billed vetting-fee card works the same way.

Payment & automatic activation

The applicant pays into their Mohle wallet — staff record the transfer on Fund Tenant Wallet (from the member's page or the Tenancy offered card). The moment the balance covers a plan, the system automatically, exactly like a lease renewal:

  1. creates the tenancy from the largest plan the balance covers (status active, or upcoming if the start date is in the future), with all members attached;
  2. debits the wallet, writes the rent / deposit / OPC ledger entries, and issues a numbered rent receipt (INV-YYYY-NNNNNN, the one shared sequence);
  3. books Mohle's commission on the basic rent as income, and the physical delivery fee (when charged) as a service charge — rent, OPC, deposit and the one-time fee are pass-through. If the applicant opted into the deposit Growth Arrangement it is recorded on the tenancy (security_deposit_invest_consent);
  4. closes every other still-open application for that unit — they move to not_selected and each applicant is notified. This is the one batch “you weren't selected” message.

The card moves to the Converted tab showing the tenancy number and status, the members, the dates and the rent-receipt number. A nightly job also sweeps up any funded offer the wallet step missed.

Outgoing WhatsApp messages

WhatsApp dispatch

Whenever the system needs to send someone a WhatsApp message — an inspection invite, an application decline, an application confirmation for someone who chose WhatsApp — it does not send it directly (there is no WhatsApp API). It queues the message in WhatsApp Dispatch (sidebar). A dedicated staffer works this list.

  1. Messages are grouped by recipient, and within each recipient they run oldest first, top to bottom. Open the person's chat once (Open this chat on the group header, or Open WhatsApp on any card) and work straight down the list — so, for example, a member's welcome goes out before their tenancy offer, never the other way round.
  2. Each card in To send shows the full message text (already written) and where it came from. Hit Open WhatsApp — WhatsApp opens on that number with the message pre-filled. Review it, send it, come back and hit Mark sent.
  3. If the number turns out not to be on WhatsApp (or anything else goes wrong), type a short reason and hit Failed → email. When the message has a fallback email address on file, it is emailed automatically instead (with the attachment, if any); otherwise it is flagged for someone to chase another way.
  4. Cancel drops a message that is no longer needed (e.g. a viewing was rescheduled, superseding the old invite). Put back in the queue revives a failed or cancelled one.

Attachments (offer letters, receipts): a wa.me link can only carry text, so the file is delivered as a secure link inside the message, served by wa_file.php. That link only works after you mark the message sent, and it expires 30 days from when the message was queued. If you would rather attach the file yourself in WhatsApp Web, each card has a download link.

The originating screen shows the send status — e.g. on the Inspection Desk's Awaiting confirmation tab a card reads WhatsApp: queued until the dispatcher sends it, then WhatsApp: sent 3 Sep. Origin staff no longer copy numbers or links themselves.

Members with no working digital contact

Physical dispatch

A member whose Preferred Contact is Physical has no working email or WhatsApp number — everything meant for them is queued in Physical Dispatch (sidebar) as a printable PDF instead. A dedicated staffer works this list the same way WhatsApp Dispatch works: download the PDF, print it, hand-deliver it, then mark it sent.

  1. Each card in To print shows who it's for and where it came from. Hit Download PDF, print it, and deliver it. Come back and hit Mark sent.
  2. If delivery doesn't go through (wrong address, member unreachable), type a short reason and hit Mark failed — there's no automatic fallback from here, since Physical is already the last-resort channel; someone will need to follow up another way.
  3. Cancel drops a message that's no longer needed. Put back in the queue revives a failed or cancelled one.

For a formal notice (a renewal offer, a statutory notice) that already has its own PDF, Physical Dispatch reuses that exact document — nothing is re-generated. For a plain message (e.g. from Send Message) with no document of its own, a simple one-page PDF is generated from the typed text automatically.

Funding repairs

Reserve pools

Every property draws repair money from a reserve pool — a fund with a target amount and a running balance. Manage pools from 🏦 Reserve Pools on the dashboard, or jump to a specific property's pool via the manage link on its details page.

A pool isn't tied to one property. This is the tool for two real situations:

  • One landlord, many units — instead of capping each of a portfolio's units separately (which idles a lot of cash across dozens of units), assign several of that landlord's properties to one pool with a single shared target.
  • A shared building fund — give a pool more than one member (with the Can approve box checked for whoever should sign off spending), and assign it as the repair pool for the co-owned units, or even single-owned units whose repairs the group has agreed to fund jointly.

The Add Member dropdown only ever lists actual owners of a property already linked to this pool -- being a pool member grants a real say over its money (approving spending, being notified of decisions), so it can never be opened to just anyone in the system. Link the property first if the person you want to add doesn't appear yet.

Member count is what changes the behavior: a pool with one member behaves like a simple property reserve — minor repairs debit it instantly. A pool with more than one member requires everyone who can approve to sign off before any repair debits it (see Repairs). A single-owner pool can opt into the same sign-off step too — check Require approval before releasing repair funds on the pool's Manage page for clients who'd rather approve their own repairs before funds move, instead of the default auto-release.

Every pool has an overdraft limit: the LOWER of (a) one month's basic rent across only the properties whose rent actually pays into that pool as their income pool — a property merely linked as a repair candidate contributes no cash flow to front against, so it doesn't widen the limit — and (b) the pool's own Target. (b) exists because whoever set a pool's target already chose how big a buffer they want held against it: a pool with a ₦15k target never overdraws past ₦15k even if its funders' rent totals ₦20k. A repair is allowed to push the pool's balance negative — it self-heals from the next rent payment — but never past that limit, so a single ₦15k/month unit funding its own ₦100k-target pool can be overdrawn by at most ₦15k, while five such units sharing one income pool can be overdrawn by ₦75k between them (unless that pool's own target is lower still). A repair that would breach the limit is refused outright (or, for a shared pool, marked blocked after all approvers have already signed off, with the requester notified to resubmit smaller or wait for the pool to recover).

While a pool is in overdraft (balance below zero), you can't reassign or remove whichever property currently pays its income into it — pulling that rent away right when the pool is relying on it to recover is blocked until the balance reaches zero or above. Moving a property's income into an overdrawn pool is unaffected, since that only adds funding. This never blocks repair-candidate changes, adding new income properties, or anything on a pool that isn't overdrawn.

Every property has exactly one income pool — the pool its rent tops up, since rent can only fund one pool at a time — but any number of repair-candidate pools it can draw repair funds from. Its own income pool always counts as a repair candidate too (a unit's own personal reserve can always fund its own repairs); on top of that, link it to as many additional pools as make sense — typically its own personal pool plus a shared building-wide fund, so a private in-unit repair and a common-area issue for the same unit can be booked from different pools without ever reassigning anything.

On a pool's Manage page, the "Assign Property to This Pool" section has two separate actions: Set as Income Pool always replaces whichever pool the property's rent currently tops up (single-valued, so this can undo a previous income assignment). Add as Repair Candidate is purely additive — it links this pool as one more repair option for the property without ever touching its income pool or any other repair-candidate pool already linked. Each property listed there also has a Remove button that fully detaches it from that one pool (clearing it as the income pool if it is one, and dropping it as a repair candidate if it's that too) without touching any of its other pool relationships.

When a pool's balance falls short of its target and more than one property pays its rent into it, the remittance cycle never lets any single property's rent cover the whole shortfall alone — each funding property is only ever asked for its own fair slice, tracked as a running Owed amount shown per property on the pool's Manage page. The Contribution method setting there decides how a new slice is worked out whenever one opens up: Equal split (the default) gives every funding property the same share regardless of size; Proportional to rent weights each property's share by its own rent, so a bigger unit shoulders more. With only one property funding a pool, both behave identically.

A property's Owed amount is real, tracked debt, not just a live recalculation — once it's paid down to zero, that property isn't asked for more toward the SAME shortfall, even if its rent keeps arriving while its co-funders' hasn't yet (it can take several cycles for everyone to catch up). A new Owed amount is only opened for everyone again when the pool's shortfall genuinely grows, most commonly because a repair drew the balance down further -- at which point every current funder, including one that already paid off its earlier debt, gets a fresh slice of that new shortfall specifically. Leaving a pool (Remove, or reassigning its income elsewhere) forgives whatever it still owed there -- that debt was for funding that specific pool, not something to carry forward.

A pool's Target can be edited any time from its Manage page, not just set at creation. While the pool is in overdraft, though, it can only be raised, never lowered, until the balance recovers to zero or above — the Target directly caps the Overdraft Limit above it, so lowering it while already drawn down past the new, smaller number would retroactively shrink a credit line the pool has already been drawn against.

Lowering a Target below the pool's actual balance doesn't move any money by itself — it just means the pool is now holding more than it needs. When that happens, a Release Excess to Owners section appears on the pool's Manage page, showing exactly how much is above target and releasable. This is a staff decision, not something owners request or approve (it's their money either way, not a discretionary spend like a repair) — enter an amount up to the shown maximum and release it; asking for more than that is refused outright. Released money is split across the pool's funding properties (by Contribution method, same as a shortfall), then across each property's own owners by ownership percentage, exactly the way rent is: an auto-mode owner's share is queued on 💵 Process Payouts immediately; an on_demand owner's share is credited to their balance but waits for them to submit a remittance request, same as rent.

Pool names must be unique — creating one with a name already in use is refused. Retiring a pool always needs no outstanding debt first (balance at zero or above); a positive balance is never a blocker on its own — it's released to the pool's owners first, exactly like Release Excess to Owners above but for the full balance rather than just the amount over target. From there, two options on the pool's Manage page:

  • Delete removes the pool outright, but only if it's never had a repair logged against it — that history must always be preserved, so a pool that's actually been used this way can never be deleted this way.
  • Archive is the option for a pool WITH real history: it detaches every property and member link (so it stops being offered as an income or repair-candidate pool for anything new) and hides it from the active Reserve Pools list, but keeps its row and every past repair pointing at it exactly as-is. Find it again via 🗄 View Archived Pools at the bottom of the screen, where Unarchive restores it to the active list (its properties/members aren't automatically re-linked, since detaching them was deliberate, not accidental).

Putting a tenant in a unit

Creating & managing tenancies

Use ➕ Create Tenancy to start one: pick the property and tenant, a rent cycle (monthly through annual), a start date, and whether the tenant will occupy the unit themselves. You can add other occupants (existing tenant-role members only) as primary or secondary at the same time, and record whether the tenant consents to their security deposit being invested.

From a tenancy's detail page you can edit its status, dates, investment consent, and occupant list at any time via Save Changes.

A member can hold any number of tenancies at once — a company renting several units for its staff, for example, or someone renting more than one unit for themselves. Create each one the same way; on their own dashboard the tenant sees every tenancy they hold in one searchable, filterable, paginated list, with their transaction history spanning all of them (filterable down to one property). Their wallet balance stays a single shared figure across every tenancy, since it's one wallet per member, not one per tenancy.

An active, extended, or expired tenancy's details page also has a Force Renewal Offer button — use it when a tenant needs a fresh renewal offer (current prices and agreement version) regardless of how far out their end date is, instead of waiting for the normal 45-day-before-end trigger. It doesn't generate anything immediately: it queues the tenancy for the next daily cron run, which then builds and sends the offer the same way it always does.

Ending a tenancy

Move-out & refunds

When a tenant is leaving, use the Move-Out & Refund section on their tenancy's edit page (it disappears once already processed, so this only happens once per tenancy):

  1. Choose the final status — Closed for a normal end, Terminated otherwise.
  2. Set the move-out date.
  3. If damages are being deducted from the security deposit, enter the amount and a note explaining it — the note is required whenever you deduct damages.
  4. Select Process Move-Out & Refund.

This settles the tenant's ledger (deposit minus any damages, plus their OPC advance and any spare wallet balance), automatically queues the refund for payout, emails the tenant a settlement statement (with a numbered NR- reference), and sets the tenancy's status. You still confirm the actual bank transfer yourself — see Tenant withdrawals.

Any outstanding tenant fee charge or Administrative Recovery Charge — across every tenancy the tenant has ever held, not just this one — is cleared from what's left of the deposit next, after damages and before any refund. This never blocks the move-out: a single charge bigger than what's left simply stays outstanding and the deposit is refunded in full.

A move-out date on its own does not end the tenancy. Setting a move-out date — whether here, or automatically when you publish a still-tenanted unit — only schedules it: the public page starts listing the unit as available from the day after, the tenant is emailed, and the returning-tenant vetting grace clock starts. The tenancy stays Active and the deposit stays held until you actually run Process Move-Out & Refund. The nightly cron never closes a tenancy on its move-out date — it only moves tenancies past their lease end date to Expired. So a tenant who has physically left still shows as Active until you process the move-out; do it promptly so their refund isn't left sitting.

Getting owners paid

Rent & remittances

Rent collected against a property is held, net of management commission, until it's remitted to the owner(s). Two automatic pieces run this on a schedule (see Automated processes): a remittance cycle that tops up each property's reserve pool and splits the remainder by ownership percentage, and an auto-queue step for any property set to Auto remittance mode.

Properties set to On Demand instead wait for the owner to request their own payout (and, if jointly owned, for every approving co-owner to sign off) before anything is queued.

ScreenUse it to
💵 Process PayoutsOne list of every queued bank transfer — owner remittances, tenant withdrawals and short-let refunds. Tick what you have transferred, enter one shared batch reference, mark them paid. A row whose payee has no complete bank details on file (account name, number and bank) is shown but its checkbox is disabled — you can't record a payout against an account we don't hold; use the row's Add now link to fill them in, then reload. The row is also left out of the CSV export until then.
📜 Rental Payout HistoryLook up anything already paid.
Property details → Add RemittanceRecord a one-off manual payout directly to an owner — for legacy entries or off-cycle corrections, bypassing the normal queue.
Member details → Fund Property WalletRecord rent received for a property outside the app.

There's no payment gateway — "marking paid" is you confirming a real transfer already happened. A missing bank detail is flagged in red on the batch screen with a direct link to add it before you can pay that item.

Getting tenants paid

Tenant withdrawals

The same pattern as owner remittances, mirrored for tenants: a move-out automatically queues a withdrawal for the refund amount, or you can queue one manually from a tenant's member details page. Confirm real transfers via 💵 Process Payouts, and look up past ones in 📜 Tenant Withdrawal History.

Fixing a mistake after the fact

Receipts & credit notes

Every rent receipt is listed on its tenancy's details page, each with a View PDF link and an Issue Credit Note action. A receipt is never edited or deleted once issued -- it's a sequentially-numbered tax invoice, and quietly rewriting one would break that trail. To correct one, issue a credit note instead: its own separately-numbered document (CN-YYYY-NNNNNN) that references the original receipt, reverses whichever line item(s) you choose, and is emailed/WhatsApped to the tenant with its own PDF attached -- the original stays on file exactly as first issued.

Open Issue Credit Note on the receipt in question. Every line item that was actually printed on it is listed, alongside how much of it (if any) has already been reversed by an earlier credit note -- you can never refund more than an item's original amount, whether in one go or across several corrections over time. Enter how much to reverse for whichever item(s) apply (a full or partial amount), give a reason, and submit.

Only Administrative Recovery Charge, Physical Service Delivery Fee, Caution Fee Adjustment, and Security Deposit can be reversed this way. Basic Rent and OPC are shown for context but can't be -- that money flows on into the property's own ledger and, once a remittance cycle has run, a real payout to the landlord, so clawing it back needs a human to work out the landlord side directly rather than a generic reversal.

What happens when you issue one:

  • The reversed total is credited straight to the tenant's Mohle wallet, available toward any future bill.
  • An Administrative Recovery Charge or Physical Service Delivery Fee reversal also books an equal-and-opposite entry against the Mohle revenue that charge had originally generated -- your revenue reports net out correctly, without the original entry ever being deleted.
  • A Caution Fee Adjustment or Security Deposit reversal reduces the tenancy's recorded security deposit by the same amount -- that money was never Mohle's income, so nothing changes on the revenue side.

Issuing a credit note only ever returns money to the tenant's wallet -- it does not automatically apply that balance toward anything else outstanding (an unpaid caution top-up, for instance). If freed-up funds should now cover something that couldn't be collected before, that's a separate, deliberate follow-up action.

Tenants can view and download all of this themselves from their own 📁 My Documents page -- receipts, credit notes, pending fee-charge pro-formas, and notices -- without needing to ask staff.

One-off, tenant-specific costs

Tenant fee charges

For a charge that's specific to one tenant and doesn't fit rent, OPC, or an existing billing path — an access-refusal fee an inspector charged, compensation owed another tenant for a joint-electricity fault, and similar cases — raise a fee charge from the tenancy's details page (Raise a New Fee Charge). Pick a catalogued fee type or choose Other and give it your own label, then split the amount into two parts:

  • Real Charge Amount — the underlying cost itself (the inspector's fine, the other tenant's compensation). This is collected into Mohle's general funds and is never booked as Mohle revenue.
  • Mohle Service Fee — Mohle's own handling fee for administering the charge, entered before VAT. VAT is added automatically at the current rate (shown next to the field) before the pro-forma is raised. This fee is booked as revenue, same treatment as the Physical Service Delivery Fee.

Add a reason and submit. This raises a pro-forma only — nothing is charged yet. The tenant is notified (with the pro-forma document attached) and has a 2-week objection window to contact support if they dispute it (there's no in-app dispute button; objections are always handled by a staff member).

During the objection window you can Edit the charge (this never changes the original row — it's marked superseded and a fresh pro-forma is issued with a brand-new 2-week window) or Cancel it outright if the objection is accepted.

Left untouched, the charge auto-confirms after 2 weeks and an immediate collection attempt is made against the tenant's wallet. If the wallet covers it, it's collected right away and a receipt issued. If not, it stays confirmed and outstanding — a daily sweep re-checks the tenant's wallet and collects it the moment funds allow, rather than waiting for anything else to trigger it, and at the latest it's folded into the tenant's next renewal as a hard requirement: the fee must be paid before that tenancy can renew. You can also trigger collection yourself early with Collect Now once a charge is confirmed. A receipt is generated for the charge itself either way — including when it's settled as part of a renewal, alongside that renewal's own combined rent receipt. If it's still outstanding when the tenant moves out, it's deducted from their security deposit before any refund — see Move-out & refunds.

The Documents column on the tenancy's details page links to whichever of the charge's own documents exist — the pro-forma once issued, and the receipt once collected.

Disbursing the real-charge portion is a manual step you must remember. Once a charge is collected, if its Real Charge Amount needs to go somewhere — paying an inspector, compensating another tenant — do that yourself using the existing 💰 Fund Tenant Wallet or 🧾 Log Mohle Expense screens, quoting Fee Charge #<id> in the note so it's traceable back to this charge. Then return to the tenancy's details page and click Mark as Disbursed. Any confirmed-or-collected charge with a real-charge amount still not marked disbursed shows up on the dashboard's Outstanding Fee Disbursements card so it's never silently forgotten.

Late-renewal fee

Administrative Recovery Charge

When a renewal finally settles 11 or more days after the previous tenancy's end date, an Administrative Recovery Charge applies — but it never blocks or delays that renewal. A tenant who funded their wallet with exactly what their renewal letter quoted is renewed immediately on that amount; the renewal letter is issued before the overdue period and can't have known a late fee might apply, so it's never held against them at the point of settlement.

Instead, once the renewal goes through, a separate 14-day payment notice is issued against the new tenancy. Nothing is actively chased beyond that one notice — it's settled by whichever happens first:

  • The daily sweep notices the tenant's wallet now covers it (from a later top-up, for example) and collects it quietly.
  • It's folded into the tenant's next renewal as a hard requirement, the same tier a tenant fee charge sits in.
  • It's deducted from the security deposit at move-out, before any refund — see Move-out & refunds.

A charge this size (bigger than what's left of the deposit after any damages) at move-out is left untouched rather than partially collected — the move-out still proceeds and the full deposit is refunded. There's no partial-payment bookkeeping for any charge type in this app.

Operating costs

Expenses (OPC)

Use ➕ Add Expenses to log an operating cost against either specific units or an entire building — a description, an amount, and the date it was incurred. These draw down from what tenants have paid in as their OPC advance. A building-wide charge splits evenly across every unit whose tenancy covered the expense date — active, extended, or expired (lease term lapsed but not yet moved out) all count, whether or not the unit is still occupied today.

Each affected tenancy gets its own receipt for its share (real cost + Mohle's handling fee + VAT), with a proper sequential invoice number — visible on the tenancy's Receipts list and the tenant's own My Documents page. Deliberately no email/WhatsApp is sent for this one; the tenant downloads it if and when they need it.

Separately, a weekly background job (cron_opc_summary.php) sends every currently-occupied tenant (active, extended, or expired — lease term lapsed but not yet moved out) a summary of their OPC activity roughly every six months, by email/WhatsApp — no admin action needed. Each summary carries its own Notice Reference, printed on the document.

Keeping units livable

Repairs

Log a repair from a property's details page (Log Repair): a description, the cost, and an optional vendor name. If the property has more than one repair-candidate pool (see Reserve pools), a dropdown lets you pick which one this specific repair should actually draw from — a private in-unit fix and a common-area issue for the same property might belong in different pools, and that's a judgment call you make each time you review the issue, not something fixed in advance. What happens next depends on the amount and who shares the chosen pool:

SituationWhat happens
Minor (at or under the pool's target) — single-member pool Debited immediately. The pool's owner is notified; no approval needed. The balance is allowed to go negative — it self-heals from the next rent cycle's top-up.
Minor — shared (multi-member) pool Logged as a fund request instead of executing right away. Every approving member is notified and must sign off (via Review Repair Approvals on their own dashboard) before the amount is actually debited. An amount that would already breach the pool's overdraft limit is refused right here at logging, before anyone is asked to vote — catching it only after every approver signs off would waste everyone's time on a repair that could never actually be released.
Major (above the pool's target) No money moves, regardless of pool size. Every pool member is notified with the description, estimated cost, and a fix-by deadline — funding and arranging the fix is the owner's responsibility.

Track everything from 🔧 Repair History, filterable by property and date. A repair's status tracks the real work, separately from whether funding has been secured (a minor repair debits its pool immediately, but that alone doesn't mean anyone's actually fixed anything yet): Open → In Progress → Completed → Vendor Paid, advanced one stage at a time from this screen as the job actually moves along. There's no automatic enforcement (blocking the unit or withholding payouts) if a major repair's deadline is missed, so following up is a manual, human judgment call.

Every property owner, every member of the repair's pool, and the tenant who originally reported it (if it started life as a repair report) are emailed automatically whenever a repair moves to In Progress or Completed -- they see it on their own dashboard's 🔧 Repair Status too. Vendor Paid is the one stage nobody outside Mohle staff ever sees or is notified about — it's when Mohle has settled up with the contractor, distinct from the pool being debited (which already happened at logging time) and from the physical repair being Completed; a member-facing view always shows it as "Completed" instead (repairStatusLabel($status, true) in includes/functions.php).

2026-08-30: Vendor Paid only applies to a minor repair — a major one never moves any money through Mohle, so there's no vendor payment to ever mark, and Completed is its terminal state (no button appears there; it shows "not funded through Mohle" instead). This also means a major repair's amount is never added back into the dashboard's Total Funds Held reconciliation, since nothing was ever debited from a pool for it in the first place.

Tenants can flag an issue themselves without knowing what it costs to fix, from their own dashboard's Report a Repair. These land in 📋 Repair Reports, filterable by status, with any photos, video, or audio they attached. From there:

  • Log Repair carries the tenant's description straight into the normal Log Repair form above — you just add the cost and vendor. Submitting it marks the report acknowledged and lets the tenant know.
  • Dismiss (with an optional reason) closes it out without creating a repair — for duplicates, non-issues, or anything that's the tenant's own responsibility. They're notified either way.

Not every issue comes in through the tenant's own form — a property inspector's finding, a tenant who phoned it in, or something you noticed yourself on a visit. Use ➕ Log Repair Report for these: pick any property, optionally link it to a specific tenancy if it's on a tenant's behalf, and note the source (tenant phoned in, property inspector, admin observation, or other) plus the reporter's name if it's not you personally. It lands in the same 📋 Repair Reports list, triaged exactly the same way.

Growing the portfolio

Leads & agent commission

Agents submit prospective landlords as leads from their own dashboard. Review and progress them from Lead Agents in the sidebar:

  1. Move the lead's status along as it progresses — New → Contacted → Inspection Scheduled → Converted (or Rejected).
  2. Once converted, set a commission amount (typically ₦20,000–₦70,000 depending on property size) and save it.
  3. Select Approve Commission — only available once the lead is converted and has an amount set.
  4. When you've actually paid the agent, record the payment method and reference and select Mark Paid.

When you create the building for a converted lead, link it from the Add Building form's Source Lead field — this link is permanent once set.

What runs without you

Automated processes

A few scheduled jobs keep the numbers current without anyone clicking anything:

  • Remittance cycle — runs continuously (it just queues, so it's safe to run often): tops up reserve pools, splits remaining rent by ownership percentage, and auto-queues payouts for Auto-mode properties. The actual bank transfers — owner remittances, tenant withdrawals and short-let deposit refunds alike — go out on the platform's configured weekly payout day (the REMITTANCE_DATE setting; a public holiday pushes it to the next business day), confirmed by an admin on the batch screens.
  • Tenancy lifecycle — handles renewals and related notices as tenancies approach their end dates, confirms/collects due tenant fee charges, retries any outstanding tenant fee charge or Administrative Recovery Charge against the tenant's current wallet balance daily, and generates rent receipts.
  • OPC spending summary — weekly, sends each active tenant a summary of their OPC activity roughly every six months.

You don't need to trigger these — they're for awareness. If a property or tenant's numbers look like they haven't updated when you'd expect, that's the first thing worth checking with whoever manages the server.

If any of these jobs hits a real error, an email goes out automatically to the audit inbox — nobody has to remember to go looking through a log file. A routine run that simply finds nothing to do stays silent (it doesn't write anything to that job's own log), so only genuine failures or real activity ever show up.

Escalation

Getting help

This handbook covers the day-to-day. For anything structural — a new feature, a schema question, or something behaving unexpectedly — that's a conversation with whoever maintains the Mohle Realty codebase, not something to work around inside the admin panel.