● 1.0.0-beta.1 · Python 3.12 · FastAPI · MIT
Keep the books
where the business already talks.¶
Type فروش ۲۵۰ک and it is recorded. One account across Telegram,
Bale and Rubika, and an HTTP API over the same rules. Money is exact, the
calendar is Jalali, and every transaction has a balanced double-entry journal
behind it.
Install¶
curl -fsSL https://raw.githubusercontent.com/Emadhabibnia1385/KasbBook/main/scripts/install.sh | sudo bash
Debian or Ubuntu, Python 3.11+, Docker for the datastores. It asks for one thing — a bot token — and generates everything else, because a signing key somebody types is a signing key somebody can guess. Running it twice is safe.
This is a beta
It runs in production for its author and its tests are thorough, but it has
not been run by many people on many books yet. Take backups —
scripts/backup.sh does it for you and verifies what it wrote — and read
the roadmap for what is deliberately not built.
What it does¶
-
Books and a real ledger
Personal, business, team and organization books under one account. Every transaction writes a balanced journal entry, so the books can be proved, not just read. See double-entry.
-
Money that stays exact
Decimaleverywhere,NUMERIC(28,4)in PostgreSQL, and a string over HTTP — because JSON's only numeric type is a float and12500000.15does not survive that round trip. -
Jalali, properly
A period like
1403-05becomes a Gregorian range before any query runs. The database never sees a Jalali value and the reader never sees a Gregorian one. -
One account, many messengers
A messenger id is never the account — it points at one. Lose a Telegram account and the books stay. See the data model.
-
Payroll for teams
Periods, member shares, recorded work, bonuses and deductions, payslips that freeze every input, staged payment, and a treasury taken before profit is shared. See payroll.
-
An API over the same rules
Not a second implementation. Both the bot and the API call the same services, so a rule cannot be enforced in one and forgotten in the other. See the API.
How it is put together¶
Telegram Bale Rubika
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────┐
│ adapters/ translate payloads │ no database, no rules
└───────────────────┬─────────────────────┘
▼
┌─────────────────────────────────────────┐
│ bot/ screens + routing │ no provider names
└───────────────────┬─────────────────────┘
│
┌───────────────────┼─────────────────────┐
│ api/ ───────────┤ │ parse, call, translate errors
└───────────────────┼─────────────────────┘
▼
┌─────────────────────────────────────────┐
│ modules/*/service.py │ every rule, exactly once
└───────────────────┬─────────────────────┘
▼
PostgreSQL · Redis · Alembic
Two clients, one set of rules. Why the seams are where they are.
If something looks wrong¶
Troubleshooting is the page to read first. Every entry in it is a failure that actually happened in this project, written as symptom → cause → fix — because in almost every one of them, the symptom pointed somewhere else.
Where to go next¶
| Install it and record something | Getting started |
| Understand the shape | Architecture |
| Call it from a script | The API |
| Run it for other people | Operations · Security |
| Change it | Development |
Persian readers: the project's README is also in Persian.