What it is
A small system for recording daily meat sales. An operator picks a product, enters a value, and the system computes the weight and logs the sale against whoever entered it. At the end of the period there are statistics, and a CSV export.
That is the whole product. It is the smallest thing on this list, and it taught me something I have used on every project since.
The requirement behind the requirement
The client asked for “a system to record sales, with statistics”.
What he actually wanted was to know which operator was selling what. He did not say that, because saying it out loud sounds like accusing your staff of something. But every follow-up question he asked was some version of it, and once I noticed, the design became obvious: per-operator tracking is not a reporting filter bolted on at the end, it is the primary axis of the data model.
NOTEThe stated requirement was “statistics”. The real requirement was one specific question he wanted answered without having to ask anyone. Since then I try to find the question before building the feature.
The other lesson: he trusted a spreadsheet more than my database
I built a CSV export because he asked for a backup. Then I watched him use it constantly, not as a backup but as the primary way he looked at his own data.
That was humbling and correct. He had years of experience with spreadsheets and about a week with my system. Exporting was not a lack of trust in me, it was a rational preference for a tool he could already use. I stopped treating export as a checkbox feature after that.
What is in it
- Daily sales registration with automatic weight and value calculation, because manual arithmetic at a counter produces errors.
- Per-operator tracking, the real requirement.
- Statistics and a dashboard for the period.
- CSV export as both backup and primary reporting tool.
- User activity monitoring.
How it is built
Django on the backend, Vue 3 with Quasar on the frontend, SQLite for storage, hosted on PythonAnywhere.
SQLite was the right call for a single-location shop with a handful of operators, and I would make the same choice again. There was a plan to migrate to MySQL that never became necessary, which is the best outcome for a migration plan.
Status
Live and barely maintained, which is honest. It does what it was built to do and has not needed to do more. I list it because small projects with clear lessons are worth more than large projects with vague ones.




