Skip to content
karim.semaan(open to work)
WorkExperienceAboutSkillsContactResume ↓
← All work
TimeSheet Platform preview
Full-stackProtected2025

TimeSheet Platform

Enterprise time-tracking SaaS

Rolled out to 350+ employees, cutting the firm's reporting time roughly 80% and retiring the legacy Access database after a ~295k-row migration.

Weekly timesheet · approval workflowSynthetic preview · no real data
Maya K.Audit staffPending review
DayCustomer / caseHours
MonCedar Retail Group8.0
TueCedar Retail Group7.5
WedHarbor Foods SAL8.0
ThuInternal: training6.5
FriCedar Retail Group7.0
Total37.0
Mon
Tue
Wed
Thu
Fri

One synthetic week, Mon to Fri. Hours log against customers or internal cases; a manager approval flips the week's status, like the production workflow.

Synthetic preview. Fictional employees, customers, and hours; no real client data. The production platform is private client work for a regional accounting and audit firm.

Synthetic preview. Fictional employees, customers, and hours. No real client data.

Protected work

Built in-house as AI Solutions Lead at BDO (a regional accounting & audit firm), so source, branding, and data are confidential. Happy to walk through the architecture.

Request access

A production in-house platform that replaced a regional accounting and audit firm's legacy Access (MDB) database with a secure, audited web system for time tracking, customer and employee management, and reporting. The Flask 3 + SQLAlchemy 2 + PostgreSQL backend spans 16 route modules: JWT auth with Argon2id hashing and refresh tokens, role-based access control enforced at both the API and UI layers, an append-only audit log stored in UTC with timezone-converted views, automated email reminders, and an analytics service that runs SQL aggregations, year-over-year comparisons, and productivity heatmaps into ReportLab PDF and CSV exports. The React + TypeScript frontend uses TanStack Query and Router with Chart.js dashboards; employees log hours against customers or internal cases (leave, holidays, training) through an employee hierarchy with manager task views and a customer approval workflow. A staged import pipeline moved ~295k task rows and ~1,670 customer records off Access into Postgres. Ships as Docker Compose behind Caddy TLS, with 41 test files across pytest and Vitest.

  • React
  • TypeScript
  • Flask 3
  • SQLAlchemy 2
  • PostgreSQL
  • Alembic
  • JWT / Argon2
  • ReportLab
  • Docker
  • Caddy

Architecture · legacy Access → audited time-tracking SaaS

  1. 01

    Data migration

    ~295k task rows migrated off a legacy MS Access database into PostgreSQL.

  2. 02

    Time capture + approval

    Employees log hours against customers or internal cases through an employee hierarchy with manager task views and a customer approval workflow.

  3. 03

    Auth + audit

    JWT / Argon2id auth with RBAC and a full audit log across 16 route modules.

  4. 04

    Analytics

    A reporting service runs SQL aggregations, YoY comparisons, and productivity heatmaps.

  5. 05

    Reports + delivery

    Generates PDF/CSV reports; self-hosted via Docker Compose + Caddy TLS.

Reporting time
~80% reduction (350+ employees)
Rows migrated
~295,000 (from MS Access)
Records
350+ employees · ~1,670 customers
Tests
41 files

What I'd improve

The Access migration left compromises worth paying down: migrated task rows carry placeholder location values, and the import pipeline needed a follow-up script just to extract rows that failed to load, so a proper migration reconciliation report is the next data task. Operationally it runs as Docker Compose on a single company VM with manual pg_dump backups; scheduled, restore-tested backups and observability beyond container logs are what I would build next.

Private · request access
Want something like this? Get in touch →

Measured:30/30 chatbot evals·20-case Bastion eval·Serving·Calibration Lab

© 2026 Karim SemaanBuilt with Next.js, Tailwind & Supabase.LinkedIn ↗︎GitHub ↗︎