ckb/.agents/skills/timesheet-checker/README.md
Michał Kopeć c9336941ac Add timesheet and invoice skills
Add four skills for Tempo/KSeF timesheet and invoice workflows:
- check-my-timesheet: show/log the current user's Tempo time entries
- timesheet-checker: audit timesheet completion across all reporters
- invoice-checker: pull KSeF invoices, check contractors + MF white list
- invoice-prep: summarize Tempo hours per Jira project for invoicing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:14:52 +02:00

209 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Timesheet Checker
Checks whether employees have completed their timesheets for a given period by pulling Tempo worklogs. Compares against each employee's country calendar (public holidays fetched from date.nager.at) and a configurable minimum of hours per day. Produces a completion report ranked by missing hours.
---
## Prerequisites
The skill needs four credentials. The easiest setup is a `.env` file — copy the template and fill it in once:
macOS / Linux:
```bash
cp .claude/skills/timesheet-checker/.env.example .claude/skills/timesheet-checker/.env
```
Windows (PowerShell):
```powershell
Copy-Item .claude\skills\timesheet-checker\.env.example .claude\skills\timesheet-checker\.env
```
Or copy the file manually in Explorer / Finder — rename `.env.example` to `.env` in the skill folder.
Then open `.env` and fill in your values:
```
TEMPO_API_TOKEN=your_tempo_token
JIRA_BASE_URL=https://your-company.atlassian.net
JIRA_EMAIL=your.email@company.com
JIRA_API_TOKEN=your_jira_token
```
The script looks for `.env` in the **working directory first**, then the skill folder as a fallback. This means you can also place a `.env` in your project root if you prefer one file for all skills.
Environment variables set via `export` always take priority over `.env` values, so both approaches work side-by-side.
The `.env` file is gitignored — credentials are never committed.
| Variable | What it is | Where to get it |
|---|---|---|
| `TEMPO_API_TOKEN` | Tempo read token | Tempo → Settings → API Integration |
| `JIRA_BASE_URL` | Your Atlassian URL | The URL you use to open Jira |
| `JIRA_EMAIL` | Your Jira login email | Your Atlassian account email |
| `JIRA_API_TOKEN` | Jira personal API token | [id.atlassian.com](https://id.atlassian.com) → Security → API tokens |
If any credential is missing from both `.env` and the environment, the script stops with a clear error listing exactly what is needed.
---
## How to use in Claude Code
Claude Code runs as a CLI, desktop app, web app (claude.ai/code), or IDE extension. **Claude Code runs the full pipeline automatically — no manual script steps.**
**Install** — copy the skill folder into your project's Claude skills directory:
macOS / Linux:
```bash
cp -r src/timesheet-checker .claude/skills/
```
Windows (PowerShell):
```powershell
Copy-Item -Recurse -Path src\timesheet-checker -Destination .claude\skills\
```
**Use:**
Just describe what you want — Claude will pick up the skill automatically:
```
Check if timesheets are complete for last week
```
```
Timesheet completion for last month
```
```
Check logged hours for 2026-06-01 to 2026-06-30
```
Claude fetches Polish public holidays, pulls Tempo worklogs, computes completion per employee, generates the report, and shows you the results. Output files land in `./timesheet-output/`.
---
## How to use in the Claude.ai app
> Full automation (no manual script running) requires Claude Code. In the Claude.ai app, the Python steps must be run locally.
**Set up once (Project approach):**
1. Create a new Project in Claude.ai.
2. In **Project Instructions**, paste the full contents of `SKILL.md`.
3. Upload `references/employees.md` and `references/output-format.md` to the Project knowledge.
**Each time you run:**
1. Set all four credentials in your shell, then run the pre-processor locally:
```bash
python3 $SKILL_DIR/scripts/preprocess.py \
--period last-week \
--output-dir ./timesheet-output
```
The script will use `./employees.md` if it exists, otherwise `$SKILL_DIR/references/employees.md`.
2. Upload `timesheet_data.json` to the Project conversation.
3. Ask Claude to summarise and present the results.
4. Run the post-processor locally to generate the formatted report:
```bash
python3 $SKILL_DIR/scripts/postprocess.py \
--data ./timesheet-output/timesheet_data.json \
--output-dir ./timesheet-output
```
**Without Projects:** Paste the contents of `SKILL.md` at the start of a new conversation, attach the two reference files, then follow the same steps.
---
## What is included
| File | Description |
|---|---|
| `SKILL.md` | Orchestrating skill — instructions for Claude |
| `references/employees.md` | Editable list of employees and their Tempo account IDs |
| `references/output-format.md` | Structure of `timesheet_data.json` and the final report |
| `scripts/preprocess.py` | Fetches Tempo worklogs + Polish holidays, computes completion |
| `scripts/postprocess.py` | Formats `timesheet_data.json` into the markdown report |
| `sample/employees_sample.md` | Sample employees file with placeholder account IDs |
## Outputs (in `./timesheet-output/`)
| File | Description |
|---|---|
| `timesheet_data.json` | Computed stats per employee + period + summary |
| `timesheet_report.md` | Manager-readable report ranked by missing hours |
---
## Configuring employees
The script looks for the employees file in this order:
1. `employees.md` in the **current working directory** — place it here for a project-specific list
2. `references/employees.md` in the **skill folder** — the default shipped with the skill
To use a project-specific list, copy the sample and edit it:
```bash
cp .claude/skills/timesheet-checker/sample/employees_sample.md ./employees.md
```
The file has two tables:
**Defaults** — applies to every employee unless overridden:
| setting | value |
|---|---|
| `country` | ISO 3166-1 alpha-2 country code (e.g. `PL`, `GB`, `DE`). Used for public holiday lookup. |
| `expected_hours_per_day` | Minimum hours per working day |
**Employees** — one row per person. Leave any column blank to inherit the default.
| Column | What it controls |
|---|---|
| `name` | Display name in the report |
| `email` | Work email address (used to look up the Jira account ID automatically) |
| `country` | Override the default country for this employee |
| `expected_hours_per_day` | Override the default hours for this employee |
| `start_date` | First working day — leave blank if employed for the full period |
---
## Period formats
| Input | Meaning | End date |
|---|---|---|
| `last-week` | Previous MondayFriday | Last Friday |
| `last-month` | Previous calendar month | Last day of that month |
| `last-year` | Previous calendar year | 31 December |
| `yesterday` | Yesterday only | Yesterday |
| `current-week` | Monday of this week to yesterday | Yesterday |
| `current-month` | 1st of this month to yesterday | Yesterday |
| `current-year` | 1st January of this year to yesterday | Yesterday |
| `YYYY-MM-DD:YYYY-MM-DD` | Explicit date range | As specified |
For `current-*` periods the current in-progress day is always excluded — end date is yesterday. If today is the first day of the period (e.g. `current-week` on a Monday), the period contains no past working days and the report will show 0 expected hours.
In Claude Code, you can also use natural language ("last week", "this month", "yesterday", "June 2026") and Claude converts it automatically.
---
## How working days are calculated
The script fetches Polish public holidays from the [date.nager.at](https://date.nager.at) public API (no authentication needed). It then excludes weekends and those holidays from the period. This runs live each time — holiday data is never hardcoded.
---
## Integration
This skill connects to **Tempo Cloud** (`api.tempo.io/4`) by default. For self-hosted Tempo (Jira Data Center), pass the correct base URL:
```bash
python3 $SKILL_DIR/scripts/preprocess.py \
--tempo-base-url https://your-jira.company.com/rest/tempo-timesheets/4 \
...
```
Or in Claude Code:
```
Check timesheets for last week, Tempo is at https://jira.company.com/rest/tempo-timesheets/4
```
---
## Limits
- Requires `TEMPO_API_TOKEN` — the script stops immediately with a clear error if it is missing.
- Employees with 0 hours may be on leave; the tool does not distinguish between missing logs and approved absence. Review these manually.
- If the period end date is today or in the future, the period is still open and data will be partial.
- Polish holidays only. If your team uses a different country calendar, the `get_polish_holidays` function in `preprocess.py` needs updating.
- Tempo Cloud API v4 only. Tempo Server / Data Center may require a different base URL and authentication method.