← Back
RO EN

Flagship project

Planova

Web and mobile platform for shift scheduling and time tracking, built for organizations that run on shifts. Behind it sits an optimization engine on Google OR-Tools CP-SAT, carrying the rules of Romanian labour law: public holidays, monthly quotas, 12- and 24-hour shifts, balanced hours and weekends. I validated it on real data from a cardiology ward.

Designed and written entirely by me

planova.ro
100%
designed and written by me
2
platforms: web and Android
CP-SAT
Google OR-Tools optimization engine
seconds
from one click to the full monthly schedule

About the project

From the notice board to an optimization engine

In hospitals, clinics and cleaning companies, the month is planned by hand. Whole days are spent matching quotas, rules and preferences, and complaints still turn up at the end: nights shared out unevenly, weekends sacrificed, timesheets redone from scratch.

Planova treats scheduling as what it is, a constrained optimization problem. The mathematical model is solved by Google OR-Tools CP-SAT, which looks for the solution that honours Romanian labour law and spreads hours and weekends fairly across the team.

I validated the platform on real data from a cardiology ward. The manager works in the browser, while employees enter their preferences and check their schedule from the phone app, on Android.

Video demo

Full walkthrough of the web app (in Romanian)

Through the app

01

Generating the schedule

The whole month on one grid for the whole team, built by the CP-SAT engine with every condition honoured. Live per-day counters, a start from employee preferences, import and export, plus cell-by-cell manual editing over the generated solution.

Planova: schedule generation screen with per-day counters and live time tracking
02

Monthly timesheet

The timesheet comes straight out of the schedule: monthly hours, weekend hours and the count of every shift type for every employee, ready to export.

Planova: monthly timesheet with monthly hours, weekend hours and shift counts
03

The employee's own schedule

Every employee sees their own month: colour-coded shifts, total hours, weekend hours and days worked. The same colours on the web and on the phone, so a symbol means the same thing everywhere.

Planova: one employee's own month, with colour-coded shifts

Under the hood

How the engine thinks

Every day of every employee becomes a decision variable. Hard constraints, meaning the law, shift dependencies and approved requests, always hold. Position coverage enters as a penalty with a very large weight, and the balance of hours and weekends gets optimized as far as the rest allows. CP-SAT walks through millions of combinations and returns in seconds a solution a person would chase for days. For the cardiology ward, with 25 nurses and 12 orderlies, each position takes a few seconds. In scaling tests the engine reaches the optimal solution up to 120 people on a single position. At 200 it finds a valid solution, but not always the optimal one, and that is where the algorithm still has room to improve.

The architecture: an ASP.NET Core API with SQL Server, an Angular web interface for managers, a .NET MAUI phone app for employees. One backend, web and phone.

Technical decisions

What I chose and why

01

Hard vs. soft constraints: how I kept the law apart from balance and preferences

The solver works in two phases. Rules that are not up for negotiation are hard constraints: one shift per day, allowed days, bans, consecutive-day limits, shift dependencies and approved requests. Position coverage and weekly overtime enter the first phase as penalties with very large weights. Fairness of hours and weekends is optimized separately, in the second phase, with the first phase's result frozen. Mixed together, the large penalties would have stopped the solver before it ever reached fairness.

02

Validating on real cardiology data: what broke on the first runs and what I changed

I loaded the ward's 510 real requests for October 2026, transcribed from handwritten notes, and the generated schedule honours every one of them. Along the way two bugs surfaced at the boundary between months: the day off after a night shift landed one day late, and an approved request on the 1st made the model impossible to solve. I fixed both and covered them with regression tests. I also found conditions that asked for the impossible, such as staff on the morning shift at weekends, which threw off the solver's stopping rule.

03

One backend, web and phone: why ASP.NET Core + Angular + .NET MAUI

The backend is C#, on ASP.NET Core with ABP Framework and SQL Server. The CP-SAT engine lives in the domain layer and never touches the database, so it can run inside regression tests. Managers work in an Angular web interface. The phone app is .NET MAUI, C# as well, and is only a client: it uses the same API and holds no logic of its own. The rules live in one place, so the web and the phone cannot end up calculating differently.

See Planova in action