BIKELEASE is a FastAPI-based bike rental operations platform for small and medium lease shops. It combines:
- a server-rendered web app (Jinja2 + vanilla JS),
- API endpoints for auth, fleet, customers, sessions, checkout, and reports,
- PostgreSQL persistence through SQLAlchemy,
- M-Pesa STK Push integration for digital checkout.
The app is designed around minute-based bike leasing: start a session, track duration, stop it, and settle with cash or M-Pesa.
This codebase includes both production-use code and scaffold placeholders generated from init.sh / init.cmd.
- Implemented and active modules:
apps/api/main.py,apps/web/main.py, API routers (auth,shop,bikes,customers,payments,queries), ORM models, auth/security, utility helpers, templates, and static assets. - Placeholder/empty files exist for some planned layers (
domain/services/*,apps/api/schemas/*,apps/api/routers/health.py,reports.py, etc.).
This README reflects the code as it exists now.
- A shop owner creates an account and shops.
- Owner creates employees and bikes.
- Staff creates/fetches a customer.
- Staff starts a bike session.
- Session runs until stopped.
- Checkout is processed as:
CASH, orMPESA(STK Push + callback webhook).
- Sessions are visible in shop views and query endpoints.
- Python
- FastAPI for routing and web server integration
- Uvicorn/Gunicorn runtime dependencies
- SQLAlchemy 2.x style ORM (
DeclarativeBase, typedMapped[]) - PostgreSQL-specific types (
JSONB,UUID) in models - Pydantic Settings for environment configuration
- Passlib + JOSE JWT for PIN hashing and cookie token auth
- Jinja2 templates (server-rendered pages)
- Vanilla JavaScript for UX/workflow interactions
- Custom CSS theme system (dark/light in landing page)
- SweetAlert2 used on workflow screens for toasts/dialogs
- Safaricom M-Pesa STK Push via async
httpxcalls
- Alembic is present (config + env), but migrations are not fully built out in this repo state.
- Docker files exist but are currently empty placeholders.
- Pytest tests exist, focused on auth flow and utility functions.
apps/
api/
main.py # FastAPI app factory, router mounting, static mount, DB init
routers/
auth.py # owner/employee auth + cookies
shop.py # shop creation
bikes.py # bike creation/update
customers.py # customer, start/stop session, checkout
payments.py # M-Pesa callback webhook
queries.py # session listing query
health.py # placeholder
rentals.py # placeholder
reports.py # placeholder
web/
main.py # page routes + template rendering
templates/ # Jinja HTML pages
static/ # CSS, JS, images
core/
config.py # env settings contract
security.py # JWT + cookie auth + user resolution
errors.py # custom exceptions
data/
db.py # SQLAlchemy engine + session dependency
models/__init__.py # ORM entities + enums
repositories/ # placeholders
integrations/
mpesa/
client.py # token + STK push initiation
scripts/
create_admin.py # bootstrap owner account
seed.py # local/dev seed data
simulate_btoc.py # callback simulation helper
simulate_ctob.py # callback simulation helper
tests/
test_auth_v1.py
test_utils.py
The homepage template is apps/web/templates/lander.html and presents BIKELEASE as a leasing + tracking + payments product with:
- hero messaging,
- “How it works” flow,
- USSD positioning,
- payment capability highlights,
- login CTA to
/login.
Additional pages include dashboard, shop overview, bikes list/create, session list, session details, start/stop and checkout interfaces.
Base prefixes are mounted in apps/api/main.py.
POST /create-shop-ownerPOST /create-employeePOST /loginPOST /logout
POST /create-shop
POST /create-bikePATCH /update
POST /create-customerPOST /start-sessionPATCH /stop-sessionPOST /checkout-session
POST /hook(M-Pesa callback receiver)
GET /sessions/{shop_id}/all
Primary SQLAlchemy entities are defined in data/models/__init__.py:
ShopOwnerShopEmployeeCustomerBikeSessionSessionCheckoutMpesaCheckout
Enums:
PaymentMethod:CASH,MPESAMpesaTransactionStatus:PENDING,SUCCESS,FAILED,CANCELLED
Notable model behavior:
- Session checkout is one-to-one with session.
- M-Pesa checkout is one-to-one with session checkout.
- Flexible metadata is stored with
JSONBfields (metadata_e) across entities.
- Login is PIN-based and category-based (
owneroremployee). - Access and refresh JWTs are issued as HTTP-only cookies.
- CSRF token cookie is also set; helper exists for header-vs-cookie comparison.
- Protected endpoints resolve current user through cookie token payload and DB lookup.
Authorization logic is route-level and role-aware:
- owners can act within owned shops,
- employees are scoped to their assigned shop.
Environment variables are declared in core/config.py via GlobalSettings.
Required values:
DATABASE_URLTEST_DATABASE_URLJWT_SECRET_KEYAPP_NAMEC2B_CONSUMER_KEYC2B_CONSUMER_SECRETC2B_SHORTCODEC2B_ONLINE_PASSKEYB2C_CONSUMER_KEYB2C_CONSUMER_SECRETB2C_SHORTCODEB2C_INITIATOR_NAMEB2C_SECURITY_CREDENTIAL
Create a local .env file at repository root with these keys.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtSet all keys listed above.
uvicorn apps.api.main:app --reloadThe web UI is served from the same app (template routes under /).
Run tests with:
pytest -qCurrent tests include:
- auth endpoint behavior (
tests/test_auth_v1.py) - phone number normalization/validation helpers (
tests/test_utils.py)
Note: tests require a valid environment and reachable database because app settings and DB engine are initialized from environment-backed config.
- Several files are scaffolds/placeholders and should either be implemented or removed to reduce confusion.
pyproject.toml, Dockerfile, and compose file are empty in this snapshot.- Some route logic and naming can be hardened/refactored (validation consistency, error detail handling, function naming cleanup, stricter typing).
- API docs are disabled in FastAPI app config (
docs_url=None,redoc_url=None,openapi_url=None); enable in non-production contexts if needed. - Add migration scripts and stronger CI checks to align with the data model lifecycle.
- Add complete Alembic revision history.
- Fill domain/services and schema layers, then wire routers to typed DTOs.
- Restore containerization assets (
infra/docker/*) and document a one-command local stack. - Add integration tests for full rental flow (create customer → start → stop → checkout).
- Add structured logging and request-id middleware wiring in app startup.
No explicit license file is present in this repository snapshot.