Portrait of Patrice GADEGBEPatrice GADEGBE

Encheria

Encheria is a mobile application devoted to judicial real-estate auctions in France: it gathers the listings, gives each one a score, simulates the acquisition costs and the rental yield, and alerts the user when a property matches their criteria.

Role
Author of the mobile application; on the server, written by a business partner, I contributed the subscriptions, the sign-in, the links and the deployment
Period
From May 2026 to today
Status
In development. In development, distributed in staging only
Technologies
Flutter, flutter_bloc, Spring Boot 4, PostgreSQL and PostGIS, Redis
Repositories
Two, as well as a back office
Architecture of EncheriaThe Flutter application calls a Spring Boot API through nginx, which also serves the files of the universal links. The API relies on PostgreSQL and PostGIS. Subscriptions are bought in the app stores.ApplicationFlutter, flutter_bloc33 pagesnginxuniversal linksand proxyAPISpring Boot 4, Java 2173 endpointsHTTPS, JWT tokenApp storesin-app purchasesPostgreSQL 16PostGIS43 migrations
Figure 1. Architecture of Encheria. The app stores hold the subscriptions, which the server verifies on its side.

Context

Encheria is aimed at private individuals who invest in property by way of judicial sales. The server, whose core was written by my business partner, collects public listings every day, cross-references them with the State’s open data on transactions and on rents, then computes a score and the costs of an acquisition. The mobile application, which I wrote, presents these properties on a map and in a radar, carries the simulators and manages the alerts as well as the subscription.

This study keeps to what I built, namely the application and, on the server, the subscriptions, the sign-in with Google and with Apple, the universal links and the deployment.

Problem

Three difficulties of the application are retained here. The choice of a search area, whether a region, a department or a municipality, had to work without a network while resulting in a single request. A link to a property, shared by a user, had to open the application for its recipient, which the application server refused to serve. Lastly, a subscription paid for in a store was not to be lost when a notification from that store failed to arrive.

Answer

An embedded geography

The application embeds the geography of France, that is 18 regions, 101 departments and 34,875 municipalities, in a file of 2.6 megabytes produced by a script from the public data, in which the coordinates are kept as integers. The selection is therefore made without a call to the server. The API, for its part, accepts up to twenty circles, which it combines; when a circle would exceed two hundred kilometres in radius, or when more than twenty would be needed, the application gives up on circles and sends the whole selection as exact codes.

List<LocationCircle>? searchCirclesFor(
  Iterable<LocationRef> refs,
  GeoIndex index,
) {
  final circles = <LocationCircle>[];
  for (final ref in refs) {
    final circle = locationCircleFor(ref, index);
    if (circle == null || circle.radiusKm > maxCircleRadiusKm) return null;
    if (circles.contains(circle)) continue;
    circles.add(circle);
  }
  if (circles.isEmpty || circles.length > maxSearchZones) return null;
  return circles;
}
Listing 1. All the places as circles, or none: the function returns a null value as soon as a single place does not lend itself to it.

The association files that iOS and Android require, as well as the fallback page of a shared property, are served by the nginx container and not by the Spring application, with one set of files per environment. In the application, a guard rejects any link whose host is not that of the installed variant, and sets the destination aside until the user is signed in.

Subscriptions reconciled on read

Purchases are verified by the server with the stores. A lost notification, however, froze the end date of the period and would have brought a paying subscriber back to the free plan. The reconciliation is therefore done on read: the server queries the store only for a subscription that appears to have lapsed, at most once every quarter of an hour, and a store outage never prevents the read from completing. No scheduled sweep is needed.

Limits and outlook

The application is not published: some fifty staging versions have been sent to the stores, and the production domain is not yet served. No pipeline runs the tests, which are launched from the development machine; the application has about seven hundred of them, but the latest local measurement gives only 38.6% of lines covered, with no threshold enforced.

A known bias of the yield simulator also remains to be corrected, as the application sends a price that already includes costs which the server computes again. Two screens are not finished, namely the market analysis, which is not linked to the navigation, and the export of personal data. Lastly, the back office is not yet under version control.

Back to the work