myFenyx
myFenyx is the internal application of Fenyx Group's consultants, in which each of them declares the actions that earn them points, follows their wallet and the ranking, then exchanges their points for gifts.
- Role
- Author of the mobile application and main author of the API
- Period
- From January 2023 to today
- Status
- In service. In service, published on Google Play and on the App Store
- Technologies
- Django 3.2, Django REST Framework, Celery, PostgreSQL, Redis, Flutter, flutter_bloc
- Repositories
- Two
This study complements the article myFenyx: turning a manual HR process into a real application, which sets out the intent of the project. It keeps to the architecture and to a few technical choices, since the rules specific to the company have no place here.
Context
The rewards scheme of Fenyx Group was kept by hand by human resources, and a consultant had to phone to find out their balance. From January 2023, myFenyx replaced it with a mobile application and an administration interface, from which human resources read the declarations, credit the points and process the exchange requests. The application then extended to the group’s news and events, with their notifications.
Problem
An internal economy requires exact balances and a ranking that can be read without delay, whereas points are awarded by year and spent long after they were earned. An exchange request also had to take nothing from a consultant until it had been validated, and the sign-in had to suit agencies that do not all have the same directory.
Answer
A wallet per year, a precomputed ranking
Credits and debits are two separate tables, each row of which carries its year, and the balance is obtained by difference. A third table keeps, for each consultant and each year, their points, their spending, their balance and their rank; it is rebuilt when the administration changes the data, and the ranking endpoint reads nothing else. The application thus displays the ranking without the server having to compute it on demand.
A two-step exchange
A consultant’s request checks that their balance covers their basket, but debits nothing, and it can still be cancelled. The debit takes place only when an administrator processes the request, inside a transaction, drawing first on the oldest year and writing one spending row per year drawn on. This order, first in, first out, is the one the article describes.
A sign-in decided by the server
Each agency declares the sign-in methods it accepts, namely the company’s Microsoft directory or a one-time code sent by email, and the application chains its screens accordingly. The code path was rewritten in July 2026: the code is drawn at random, only its hash is kept, it is used only once, attempts are counted, and the response is identical whether the account exists or not. Rate limiting relies on Redis, so that it holds whichever process receives the request.
Notifications that are kept
A notification is first a row in the database, created for each consultant concerned by an event or a news item, and it is the saving of that row that triggers the sending to the phone. It carries a type code and an identifier, which the application translates into a destination. Lastly, the build number of the application is derived from the number of commits, then recorded in a git tag, so that a version in the store can always be tied to a state of the repository.
Limits and outlook
The tests cover only the sign-in by code, six cases in all, and nothing yet verifies the wallet, the debit order or the ranking, which are nonetheless the heart of the application. The ranking is moreover rebuilt in full and synchronously on every change, which suits the current headcount and will have to move to a background task if it grows.
A WebSocket channel was prepared on the server side without being put into service, the application refreshing itself when it receives a notification. The integration pipelines are not wired up and releases still leave from my machine. Lastly, the API remains on Django 3.2, whose upgrade has to be planned, and the history of the schema is not under version control, which will have to be corrected first.




