Bed categories, the beds in them, and admission through to discharge. The ward board tells you what is free right now, and it is worked out rather than typed.

Bed categories and what is free, derived from the admissions rather than from a status column.
A bed is free when no admission points at it
That is the whole design. There is a status column on the bed record and the system keeps it in step, but the admission is the truth. In the CodeIgniter system this replaced, a clerk set the bed status and the admission separately, and within weeks the board said one thing and the records said another.
Now there is one source. If the ward board says a bed is taken, there is an open admission behind it that you can click into.

Current admissions by default, discharged ones on request.
Two rules the old system never enforced
- One patient per bed. A bed with an open admission cannot take another.
- One bed per patient. Somebody already admitted cannot be admitted again without being discharged first.
Both checks take a database lock, so two clerks admitting at the same moment get one success and one refusal rather than two successes and a bed with two people in it.
Occupancy over time
The occupancy report counts admissions per day across a date range, with the busiest day, the number of discharges and the average length of stay. It reads the admission rows, not the bed status, so it agrees with the ward board by construction.

Occupancy per day, with length of stay worked out from completed admissions.
See it rather than read about it. The ward board and the admission screens are in the user guide.
The user guide walks the whole system in the order you would meet it, and the screenshots page has every screen. The source is on GitHub under the GPL v3.