# Project Settings

**Date:** 2026-06-01
**Status:** Draft
**Spec:** 151
**Tier:** All tiers
**Depends on:** `projects-module`, `project-hourly-budget`, `foundation-auth-rbac`
**Referenced by:** `projects-module`

---

## Overview

Spec 10 (`projects-module`) defines project CRUD and `billing_config` JSONB per project. Spec 139 (`project-hourly-budget`) adds `budget_alert_pct` inside that JSONB. No spec defines tenant-level *defaults* for new projects. This spec adds `/settings/projects` — a page where OWNER/ADMIN configure what billing type, rate, and budget alert values are pre-filled when creating a new project.

---

## Route

`/settings/projects` — requires `projects:write`.

---

## Page Layout

```
┌──────────────────────────────────────────────────────────────┐
│  Settings > Projects                                         │
│                                                              │
│  ┌── New Project Defaults ──────────────────────────────┐  │
│  │                                                        │  │
│  │  Default billing type                                  │  │
│  │  ● Fixed price  ○ Hourly  ○ Retainer                  │  │
│  │                                                        │  │
│  │  Default hourly rate (for new hourly projects)         │  │
│  │  [₪ 0.00]   (leave 0 for no pre-fill)                 │  │
│  │                                                        │  │
│  │  Default currency                                      │  │
│  │  [ILS ▾]                                               │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌── Time Tracking ─────────────────────────────────────┐  │
│  │                                                        │  │
│  │  Enable time tracking on new projects by default       │  │
│  │  ● Yes  ○ No                                           │  │
│  │                                                        │  │
│  │  Default time rounding                                 │  │
│  │  [None ▾]   None · 5 min · 15 min · 30 min            │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌── Budget Alerts ──────────────────────────────────────┐  │
│  │                                                        │  │
│  │  Alert when hourly project reaches _% of budget        │  │
│  │  [80___] %  (applies to new hourly projects)           │  │
│  │                                                        │  │
│  │  Alert channel                                         │  │
│  │  ☑ In-app notification (OWNER + ADMIN)                 │  │
│  │  ☑ Email to OWNER                                      │  │
│  │                                                        │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  [Save changes]                                              │
└──────────────────────────────────────────────────────────────┘
```

---

## Schema Delta

```sql
ALTER TABLE tenant_settings
  ADD COLUMN IF NOT EXISTS project_default_billing_type TEXT NOT NULL DEFAULT 'fixed'
    CHECK (project_default_billing_type IN ('fixed', 'hourly', 'retainer')),
  ADD COLUMN IF NOT EXISTS project_default_hourly_rate NUMERIC(10,2) NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS project_default_currency TEXT NOT NULL DEFAULT 'ILS',
  ADD COLUMN IF NOT EXISTS project_default_time_tracking BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS project_default_time_rounding_minutes INTEGER NOT NULL DEFAULT 0
    CHECK (project_default_time_rounding_minutes IN (0, 5, 15, 30)),
  ADD COLUMN IF NOT EXISTS project_default_budget_alert_pct INTEGER NOT NULL DEFAULT 80
    CHECK (project_default_budget_alert_pct BETWEEN 1 AND 100),
  ADD COLUMN IF NOT EXISTS project_budget_alert_email BOOLEAN NOT NULL DEFAULT true,
  ADD COLUMN IF NOT EXISTS project_budget_alert_in_app BOOLEAN NOT NULL DEFAULT true;
```

---

## Pre-fill Behavior

When a user opens `/projects/new`, the form is pre-filled:

| Field | Source |
|-------|--------|
| Billing type selector | `tenant_settings.project_default_billing_type` |
| Hourly rate input | `tenant_settings.project_default_hourly_rate` (if > 0) |
| Currency selector | `tenant_settings.project_default_currency` |
| "Track time" toggle | `tenant_settings.project_default_time_tracking` |
| Budget alert % | `tenant_settings.project_default_budget_alert_pct` (pre-fills `billing_config.budget_alert_pct`) |

User can override any value per-project. Settings only affect the *new project* form defaults — they do not retroactively change existing projects.

---

## API

```
GET  /api/settings/projects
     → get project default settings
       Returns: { project_default_billing_type, project_default_hourly_rate,
                  project_default_currency, project_default_time_tracking,
                  project_default_time_rounding_minutes,
                  project_default_budget_alert_pct,
                  project_budget_alert_email, project_budget_alert_in_app }
       Requires: projects:read

PATCH /api/settings/projects
      → update project default settings
        body: { ...any settable fields above }
        Requires: projects:write
```

---

## Architecture Decisions

| Decision | Choice | Reason |
|----------|--------|--------|
| Extend `tenant_settings` | Not new `project_settings` table | Scalar tenant-wide defaults; same pattern as contractor settings (spec 148) and invoice settings (spec 125) |
| Default rate of 0 = no pre-fill | Not mandatory | Many tenants have variable rates per customer; forcing a default would produce incorrect pre-fills |
| Budget alert columns on `tenant_settings` | Not inside per-project `billing_config` | Alert *channel* preference (email vs in-app) is tenant-wide policy, not per-project; threshold stays in `billing_config` JSONB per spec 139 |
