Le Bistroy
A franchise operations platform: from partner applications through contracting and quality assurance to partner ordering, invoicing and warehousing.
About the project
A platform that runs the whole Le Bistroy franchise operation: from partner applications through contracting and quality assurance to partner ordering, invoicing and warehousing. Developed by Milcomp.
The challenge
A franchise network is not one company, it is many small ones under a shared brand. Head office has to handle applicants, contracting, the quality of the outlets it hands over, the equipment, partner orders, invoices and stock - all at once, and in a way that lets each partner see only their own data.
This kind of system fails when a step is silently skipped: an invoice that never went out, a status change that never ran, a notification that never sent. The problem in those cases is not that something went wrong. It is that nobody knows.
The solution
A Laravel system with three surfaces: a public site with the menu and the franchise application, a partner portal where outlets order their own stock, and an admin that runs the whole franchise lifecycle.
A partner orders for their own outlets, picks a delivery date and time slot from a calendar, pays by card or bank transfer, and follows the order's state. Behind it the order becomes an invoice, the invoice becomes stock movements, and the stock movements become handover documents for the logistics partner.
The most important design rule
The system is built around a single convention: if a status transition has a domain-significant side effect, that side effect gets its own status. The recognition test is one question: if this step failed silently, could you tell from a query?
If not, a status is missing. Not a log line, not an error report, not a nullable timestamp - a status. The difference is that a log tells you something about the record you are already looking at, while a status lets you list every record where the step did not run. In a franchise system that is the difference between spotting the partner invoices that never went out yourself, and hearing about them from the partners.
Working days you cannot calculate
Delivery and payment deadlines are counted in working days, but the Hungarian working calendar has two layers. One is computable: fixed holidays and the Easter-linked ones. The other is not - each year's decree relocates working days onto Saturdays and inserts bridge days, and no formula produces that.
So the calendar has two layers: the system generates the computable part itself and synchronises the relocations. The Easter calculation is deliberately our own code, because PHP's built-in function lives in an extension that is not available on every host - and by then every date calculation in the system depended on this component.
Technology
Laravel on PHP 8.4, a Filament admin, Livewire and Tailwind CSS 4, TypeScript, MariaDB and Redis. Card payments through OTP SimplePay, invoicing over the Billingo API, PDF generation for contracts and documents, and spreadsheet export for the logistics partner. Every significant model is audited and access is role-based.
What to take from this
Two things carry over to any system like this. The first is the status rule above: a silent failure costs more than a loud one.
The second is about authorisation. In a multi-tenant system it is not enough to protect individual records - the list queries have to be scoped too, and scoped fail-closed. If a user has no partner attached, they should see nothing, not everything. That is the difference between a permissions bug and a data breach.