Skip to content

vladimirwashere/workshop-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Workshop Tracker

Workshop project planning, daily work logging, cost tracking, and reporting application. Manages production operations in Romania for a UK construction company, with dual-currency support (RON/GBP). Logo (logo.png, icon.png) and company name placeholders for legal purposes.

Stack

Layer Technology
Core Ruby 3.3.6, Rails 8.1.2, PostgreSQL 16
Frontend Tailwind CSS 4, Hotwire (Turbo + Stimulus), D3.js
Auth Pundit (deny-by-default), bcrypt, Active Record Encryption
Background Solid Queue
Libraries Discard (soft deletes), Pagy (pagination), Prawn (PDF), caxlsx (XLSX)
Ops Honeybadger (error tracking), Rack::Attack (rate limiting)
Testing Minitest + FactoryBot
Infrastructure Docker Compose, Kamal, GitHub Actions CI/CD

Architecture

Models

  • User — Role-based access (admin:0, owner:1, manager:2) with encrypted email, password history
  • Project — Core entity with optional Phases
  • Phase — Optional grouping within Projects
  • Task — Belongs to Project, optionally to Phase
  • Worker — Employee management with salary history
  • WorkerSalary — Gross/net salary with derived daily rate
  • DailyLog — Time tracking with scope field for work descriptions
  • MaterialEntry — Material costs with VAT support (0% or 21%)
  • CurrencyRate — RON/GBP exchange rate tracking
  • Attachment — Polymorphic file attachments via Active Storage (25MB limit)
  • AuditLog — Immutable mutation log with user attribution and IP
  • PasswordHistory — Password reuse prevention (last 5 passwords)
  • Config — Key-value application configuration
  • Session — Time-bounded user sessions with IP tracking
  • UserSetting — Per-user preferences (currency, Gantt zoom, dashboard filters)

Concerns

Model: Auditable (audit logging on create/update/discard), DateRangeValidatable (date range validations), Attachable (polymorphic attachments), Statusable (status enum with transitions), CreatedByUser (creator tracking)

Policy: StandardCrudPolicy (DRY CRUD authorization rules)

Controller: Authentication (session management), CreatesAttachmentsFromParams (file upload handling)

Services

Service Purpose
FXFetcher ExchangeRate-API integration with retry/backoff
ReportGenerator Unified report data (labour, materials, combined)
XlsxExporter Excel export for all report types
PdfExporter PDF generation with Prawn
CurrencyConverter RON/GBP conversion using stored rates

Authorization

Role-based access control via Pundit:

  • Admin & Manager: Identical permissions, full CRUD across all resources
  • Owner: Read-only access to all data including reports, costs, and salary information
  • All policies inherit ApplicationPolicy with deny-by-default security model

Background Jobs

Job Schedule Purpose
FetchFXRatesJob Daily 8:00 UTC Fetch RON/GBP exchange rate
CleanupExpiredSessionsJob Daily 3:00 UTC Remove expired sessions

Processed via Solid Queue (config/recurring.yml).

Root Directory Structure

workshop-tracker/ ├── .github/ # GitHub Actions CI/CD workflows ├── .kamal/ # Kamal deployment configuration ├── app/ # Main application code ├── bin/ # Executable scripts ├── config/ # Application configuration ├── db/ # Database schema and migrations ├── lib/ # Custom libraries and extensions ├── log/ # Application logs ├── public/ # Static assets ├── script/ # Utility scripts ├── test/ # Test suite (Minitest + FactoryBot) ├── vendor/ # Data visualization library └── [Configuration Files]

Quick Start

Prerequisites

  • Docker Desktop installed
  • Git installed

Setup

# Clone the repository
git clone https://github.com/your-org/bah-workshop-tracker.git
cd bah-workshop-tracker

# Create environment file
cp .env.example .env
# Edit .env — set ADMIN_EMAIL, ADMIN_PASSWORD, and AR_ENCRYPTION_* keys
# Generate encryption keys: bin/rails db:encryption:init

# Build and initialize
docker compose build
docker compose run --rm web bin/rails db:schema:load db:seed

# Start services
docker compose up

Visit http://localhost:3000 and log in with ADMIN_EMAIL / ADMIN_PASSWORD from .env.

See admin_instructions.md for detailed setup and configuration guide.

Development

Running Tests

docker compose run --rm web bin/rails test

Background Jobs

The worker service handles Solid Queue jobs (FX rate fetching). It starts automatically with docker compose up.

Schema Changes

Schema changes use Rails migrations:

docker compose run --rm web bin/rails generate migration AddColumnToTable column:type
docker compose run --rm web bin/rails db:migrate

CI/CD Pipeline

Automated via .github/workflows/ci.yml:

  1. Security — Gitleaks secret scanning
  2. Lint — RuboCop, Brakeman, bundler-audit, importmap audit
  3. Test — Full test suite with PostgreSQL
  4. Build — Docker image verification

Environment Variables

See .env.example for detailed inline comments. Key variables:

Database (Required)

Variable Description
DATABASE_HOST PostgreSQL host (default: db for Docker)
DATABASE_USERNAME Database username (default: postgres)
DATABASE_PASSWORD Database password
DATABASE_PORT Host port for DB container (default: 5432)

Rails (Required in Production)

Variable Description
SECRET_KEY_BASE Rails secret key for sessions/cookies. Generate with bin/rails secret
RAILS_ENV Environment (development/production)

Email (Optional)

Variable Description
SENDGRID_API_KEY SendGrid API key for transactional emails. Optional; dev mode opens emails in browser
MAILER_FROM From address for emails
MAILER_DOMAIN Domain for email delivery

FX Rates (Optional)

Variable Description
EXCHANGERATE_API_KEY API key from exchangerate-api.com. Optional; FX features work without it but won't fetch rates

Active Record Encryption (Required)

Variable Description
AR_ENCRYPTION_PRIMARY_KEY Primary encryption key. Generate with bin/rails db:encryption:init
AR_ENCRYPTION_DETERMINISTIC_KEY Deterministic encryption key
AR_ENCRYPTION_KEY_DERIVATION_SALT Key derivation salt

| HONEYBADGER_API_KEY | No | Error tracking (reports in production only) |

Application (Required)

Variable Description
APP_HOST App hostname for email links and absolute URLs (e.g., localhost:3000 or app.example.com)

Admin Seed Account (Required on First Setup)

Variable Description
ADMIN_EMAIL Email for the initial admin account
ADMIN_PASSWORD Password for the initial admin account
ADMIN_DISPLAY_NAME Display name for the initial admin account (defaults to "Admin")

Key Features

Project & Task Planning

  • Hierarchical project structure with optional phases
  • Task assignment with planned hours
  • Interactive Gantt chart visualization (D3.js) with drag-and-drop date editing
  • Full project tree view (always expandable, never paginated)

Daily Work Logging

  • Line-by-line time tracking with worker assignment
  • Duplicate shortcut for repetitive entries
  • Scope field for work descriptions
  • Date range filtering with period shortcuts

Worker Management

  • Employee profiles with trade/specialty
  • Salary history tracking with automatic hourly rate calculation
  • Worker timeline visualization showing assignments and actual hours
  • Romanian tax calculations (CAS 25%, CASS 10%, income tax 10%)

Cost Tracking

  • Labour Costs: Auto-calculated from worker salary history
  • Material Costs: Entry-level tracking with VAT support (0% or 21%)
  • Currency Support: Dual-currency display (RON/GBP) with automatic conversion
  • FX Integration: Daily exchange rate fetching with missing rate indicators

Unified Reporting System

  • Labour Reports: By project, by worker, or summary view
  • Materials Report: Project-level breakdown with VAT details
  • Combined Cost Report: Labour + materials per project
  • Export Options: Excel (XLSX) and PDF for all report types
  • Date range and project/worker filtering

Dashboard & Analytics

  • KPI cards: Total labour, materials, combined costs, hours logged
  • Top 5 active projects summary
  • Date range filtering with persistence

File Attachments

  • Polymorphic attachment support for tasks, daily logs, and material entries
  • 25MB file size limit
  • Lightbox image viewer
  • Active Storage integration

Security & Audit

  • Active Record Encryption for PII (email addresses)
  • Password complexity requirements and reuse prevention (last 5)
  • Time-bounded sessions with concurrent session limits
  • Audit logging on all data mutations with user attribution
  • Content Security Policy, SSL enforcement, CSRF protection
  • HTTP-only cookies with SameSite=Lax
  • See SECURITY.md for full security policy

Deployment

Deployable to any Docker-capable PaaS (Render, Fly.io, Railway) or self-hosted with Kamal.

  • Dockerfile — Multi-stage production build with jemalloc, Thruster (port 80)
  • Kamal — Config included (config/deploy.yml)
  • All environment variables must be set (see .env.example)
  • Solid Queue worker must be running for background jobs

Documentation

File Description
README.md Project overview and quick start
admin_instructions.md Setup, configuration, and operations guide
DATABASE_SCHEMA.md Database schema reference
SECURITY.md Security policy and vulnerability reporting

License

Licensed under the MIT License.

About

No description, website, or topics provided.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •