---
title: "Timesheets"
description: "Time and billing. Record time spent on project tasks in minutes, mark it billable and run it through an approval step."
canonical: "https://obop.dev/apps/timesheets/"
lang: "en"
---

# Timesheets

## What it is for

Record time spent on project tasks in minutes, mark it billable and run it through an approval step. Needs the Projects package.

## What the package does and does not do

Time spent on project tasks, entered in minutes, with a billable flag and an approval step. Needs the Projects package. A worker sees and edits only their own entries; timesheets.manager sees all.

## Module details

- **Version:** `0.3.0`
- **Author:** SpaceCorps
- **Licence:** [AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later.html)
- **Needs core:** `^0.2` (core 0.2.0 is current)
- **Maturity:** Beta
- **Categories:** Services

## Models

### `timesheets_entry`

Time one person spent on one task on one day

Read group: `timesheets.user`. Write group: `timesheets.user`.

| Field | Kind | Data class | Personal data | Group | Agents see | Description |
|---|---|---|---|---|---|---|
| `task_id` | ref → projects_task | `none` | no | `timesheets.user` | in clear | The task worked on |
| `worker` | text | `internal` | yes | `timesheets.user` | masked | User name of the person who did the work; the person who creates the entry unless set otherwise |
| `worked_on` | date | `none` | no | `timesheets.user` | in clear | Day the work was done (YYYY-MM-DD) |
| `minutes` | number | `none` | no | `timesheets.user` | in clear | Time spent, in minutes |
| `billable` | bool | `none` | no | `timesheets.user` | in clear | Whether the time can be charged to the customer |
| `description` | text | `none` | no | `timesheets.user` | in clear | What was done |
| `cost_rate` | money | `financial` | yes | `timesheets.cost_viewer` | withheld | Internal hourly cost of the worker at the time of entry (minor currency units, e.g. cents) |
| `state` | select (draft, submitted, approved) | `none` | no | `timesheets.user` | in clear | Entry status: draft, submitted, approved |

## Workflows

### `timesheets_entry`

| Action | Moves | Who may run it | Approval |
|---|---|---|---|
| `timesheets_entry.submit` | state: draft → submitted | `timesheets.user` | no |
| `timesheets_entry.approve` | state: submitted → approved | `timesheets.manager` | no |
| `timesheets_entry.reject` | state: submitted → draft | `timesheets.manager` | no |

## Permission groups

Groups used by this app:

- `timesheets.cost_viewer`
- `timesheets.manager`
- `timesheets.user`

## Approval steps

No step in this app needs an approval, apart from deleting records.

## What agents can and cannot do

An agent can read, search, create and update records of this app, and run the actions that need no approval, within the permission groups of its token.

It can only propose these steps, and a person must approve them: `timesheets_entry.delete`.

Personal data is masked as placeholder tokens: `timesheets_entry.worker`.

These fields are withheld from agents entirely: `timesheets_entry.cost_rate`.

## Dependencies

Each dependency states the versions it accepts. Built-in apps version with the core, so a requirement on one is checked against the core version.

- [Project](/apps/projects/): `>=0.3, <1`

Installing this app from the marketplace also installs the dependencies it is missing, in one plan that you confirm once.

## Install

Install it from the Customize app (Marketplace), or from the command line:

```bash
obop modules install-from timesheets
```

Needs a database and administrator rights.

## Build your own

[The module guide shows how apps like this one are written](/docs/reference/module-manifest/)
