caloohpay
v2.1.0
Published
A CLI tool and library to calculate out-of-hours on-call compensation. Works in Node.js and browsers (Next.js, React, etc.)
Downloads
205
Maintainers
Readme
CalOohPay - Calculate Out-of-Hours Pay
A command-line tool that automates the calculation of out-of-hours (OOH) on-call compensation for engineering teams using PagerDuty schedules.
🚀 What It Does
CalOohPay eliminates the manual work of calculating on-call payments by:
- Fetching schedule data directly from PagerDuty API
- Calculating compensation based on weekday vs weekend rates
- Supporting multiple teams and schedules simultaneously
- Providing auditable records for payroll processing
- Handling timezone conversions automatically
The Problem It Solves
In many organizations, engineers get compensated for going on-call outside of working hours. Managers typically spend 5-10 minutes per team each month reconciling on-call rotas for payroll. With multiple teams and distributed locations, this manual process quickly becomes time-consuming and error-prone.
CalOohPay automates this entire process, turning hours of manual work into a single command.
📋 Prerequisites
- Node.js (v14 or higher)
- npm or yarn
- PagerDuty API User Token (How to get one)
🚀 Quick Start
1. Installation
Via npm (Recommended)
npm install -g caloohpayvia npx
No installation required, run directly with npx:
npx caloohpay -r "SCHEDULE_ID"From Source
git clone https://github.com/lonelydev/caloohpay.git
cd caloohpay
npm install
npm run build
npm link2. Configuration
Create a .env file in the project root:
# .env
API_TOKEN=your_pagerduty_api_token_here3. Basic Usage
CLI Usage
# Get help
caloohpay --help
# Calculate payments for a single schedule (previous month)
caloohpay -r "PQRSTUV"
# Calculate for multiple schedules with custom date range
caloohpay -r "PQRSTUV,PSTUVQR" -s "2024-01-01" -u "2024-01-31"Programmatic Usage
CalOohPay can be used as a library in both Node.js and browser environments.
Node.js (with file system access and PagerDuty API):
import { ConfigLoader, OnCallPaymentsCalculator } from 'caloohpay';
const loader = new ConfigLoader();
const rates = loader.loadRates();
const calculator = new OnCallPaymentsCalculator(rates.weekdayRate, rates.weekendRate);Browser/Web Applications (Next.js, React, Vue, etc.):
import { OnCallUser, OnCallPeriod, OnCallPaymentsCalculator } from 'caloohpay/core';
// Create on-call periods from your data
const user = new OnCallUser('user-id', 'John Doe', [
new OnCallPeriod(
new Date('2024-08-01T18:00:00Z'),
new Date('2024-08-05T09:00:00Z'),
'Europe/London'
)
]);
// Calculate with custom rates
const calculator = new OnCallPaymentsCalculator(60, 90);
const amount = calculator.calculateOnCallPayment(user);
console.log(`Compensation: $${amount}`);📚 View Full API Documentation →
🌐 Browser Compatibility (New in v2.1.0)
CalOohPay now works in web browsers! The core calculation engine is completely independent of Node.js.
Package Structure
// 🌐 Browser-compatible core (zero Node.js dependencies)
import { OnCallPaymentsCalculator, OnCallUser, OnCallPeriod, DEFAULT_RATES } from 'caloohpay/core';
// 🖥️ Node.js-specific features (ConfigLoader, CsvWriter, PagerDuty API)
import { ConfigLoader, CsvWriter, calOohPay } from 'caloohpay/node';
// 📦 Everything (backward compatible, Node.js only)
import { ConfigLoader, OnCallPaymentsCalculator } from 'caloohpay';Next.js / React Example
'use client'; // Next.js 13+ App Router
import { useState } from 'react';
import { OnCallPaymentsCalculator, DEFAULT_RATES } from 'caloohpay/core';
export default function CompensationCalculator() {
const [weekdayRate, setWeekdayRate] = useState(DEFAULT_RATES.weekdayRate);
const [weekendRate, setWeekendRate] = useState(DEFAULT_RATES.weekendRate);
const calculator = new OnCallPaymentsCalculator(weekdayRate, weekendRate);
// Use calculator.calculateOnCallPayment(user) with your data
return (
<div>
<input value={weekdayRate} onChange={(e) => setWeekdayRate(Number(e.target.value))} />
<input value={weekendRate} onChange={(e) => setWeekendRate(Number(e.target.value))} />
{/* Your UI here */}
</div>
);
}What works in browsers:
- ✅ Core calculation engine (
OnCallPaymentsCalculator) - ✅ Models (
OnCallUser,OnCallPeriod) - ✅ All constants and types
- ✅ Date utilities and validation
Node.js only:
- ❌ ConfigLoader (uses
fsmodule) - ❌ CsvWriter (uses
fsmodule) - ❌ calOohPay function (uses PagerDuty API)
- ❌ CLI tools
💰 Compensation Rates
Default Rates
| Period | Rate | |--------|------| | Weekdays (Mon-Thu) | £50 per day | | Weekends (Fri-Sun) | £75 per day |
Customizing Rates
You can customize compensation rates by creating a .caloohpay.json file:
{
"rates": {
"weekdayRate": 60,
"weekendRate": 90,
"currency": "USD"
}
}The tool searches for this file in:
- Current working directory (project-specific rates)
- Home directory
~/.caloohpay.json(user-wide defaults) - Built-in defaults if no config found
Example config file: .caloohpay.json.example
Development and contributing
Development, testing, contributor workflow and git-hook guidance has moved to CONTRIBUTING.md. Please read that document for detailed setup and contribution instructions, including how to run tests, lint, generate docs, and prepare a pull request.
Note on ESLint configuration: this project uses ESLint v9 with a flat config file located at eslint.config.cjs (instead of legacy .eslintrc.json). If you need to adjust lint rules or add new shareable configs, update eslint.config.cjs and run npm run lint to validate your changes.
🔧 Troubleshooting
Common Issues
"Command not found: caloohpay"
- Run
npm linkafter building - Restart your terminal
- Check if
dist/src/CalOohPay.jsexists
"Invalid API Token"
- Verify your
.envfile contains the correct token - Ensure no extra spaces or quotes around the token
- Check token permissions in PagerDuty
"No schedule entries found"
- Verify the schedule ID is correct
- Check the date range includes on-call periods
- Ensure you have permissions to view the schedule
📝 Finding Schedule IDs
Schedule IDs can be found in PagerDuty:
- Navigate to People → On-Call Schedules
- Click on your schedule
- The ID is in the URL:
https://yourcompany.pagerduty.com/schedules/PQRSTUV
📟 PagerDuty API Setup
To fetch schedule data from PagerDuty, you need an API User Token that provides the same permissions as your user account.
Getting Your API Token
- Login to PagerDuty
- Navigate to Profile: Hover over your profile icon → My Profile
- Access Settings: Go to User Settings
- Create Token: Click Create API User Token
- Secure Storage: Store the token securely (e.g., 1Password, environment variable)
⚠️ Security Warning: Never commit your API token to version control!
📖 CLI Reference
Quick Reference
caloohpay -r "SCHEDULE_ID" [options]Common Options:
-r, --rota-ids- Schedule ID(s) (required)-s, --since- Start date (YYYY-MM-DD)-u, --until- End date (YYYY-MM-DD)-o, --output-file- Save to CSV file-t, --timeZoneId- Override timezone-k, --key- API token override
Examples:
# Basic usage
caloohpay -r "PQRSTUV"
# Multiple schedules to CSV
caloohpay -r "TEAM_A,TEAM_B" -o "./monthly-report.csv"
# Custom date range
caloohpay -r "PQRSTUV" -s "2024-01-01" -u "2024-01-31"✅ Current Features
- ✅ PagerDuty Integration: Fetches schedules with automatic timezone detection
- ✅ Multi-Schedule Support: Process multiple schedules simultaneously
- ✅ Configurable Rates: Custom weekday/weekend rates via
.caloohpay.json - ✅ Timezone Support: Accurate OOH calculations for distributed teams
- ✅ CSV Export: Google Sheets compatible payroll files
- ✅ Comprehensive Testing: 328+ unit tests with full coverage
Quick Timezone Example
# Automatic timezone detection (recommended)
caloohpay -r "SCHEDULE_ID"
# Override timezone if needed
caloohpay -r "SCHEDULE_ID" -t "America/New_York"🚧 Development Roadmap
Recently Completed:
- ✅ Configurable rates via config file
- ✅ Full timezone support with automatic detection
- ✅ CSV export for payroll systems
Coming Soon:
- Enhanced console output with colors
- NPM package distribution
- Automated monthly reporting
📚 Technical References
- API Documentation - Auto-generated API docs (GitHub Pages)
- PagerDuty API Documentation
- PagerDuty Time Zones
- Luxon.js Documentation
- Jest Testing Framework
- TypeScript with Node.js
- Yargs Command Line Parser
📄 License
This project is licensed under the ISC License - see the LICENSE file for details.
🤝 Support
If you encounter any issues or have questions:
- Check the troubleshooting section
- Search existing issues
- Create a new issue with detailed information
☕ Sponsor This Project
If CalOohPay has saved you time and made your life easier, consider supporting its development!
Your support helps me:
- 🚀 Continue developing new features
- 🐛 Fix bugs and improve stability
- 📚 Maintain documentation
- 💡 Explore new ideas and integrations
Every coffee counts and is greatly appreciated! ☕
Made with ❤️ for engineering teams who deserve fair compensation for their on-call dedication.
