Project Schema
Felder
Project Schema
Schema for validating project entities
title
Project title
description
Project description
status
Project status. Tenant-configurable via the workflow editor — the base workflow defines PLANNED, ACTIVE, IN_REVIEW, ON_HOLD, COMPLETED, CANCELLED.
startDate
Project start date (YYYY-MM-DD)
endDate
Project end date (YYYY-MM-DD)
budget
Project budget as decimal string
managerId
Project manager user UUID
previousManagerId
ADR 0895 — who was project manager before the tech-review handover moved `managerId` to the team lead. Written only by project-review-manager-handover.service.ts. Makes undoing the handover a single click and answers "who had it before?" without reading the history. Absent on every project that never went through the (opt-in) handover — runtime fallback, no backfill.
orgUnitId
Organisational unit (department / team) the project is organisationally located in.
teamUserIds
Internal users that make up the project team (independent of orgUnitId). Used for team_member data scope, task filters and notifications.
partyId
Associated party UUID
partyAddressId
Specific site/address of the associated party
contractId
Associated contract UUID
standaloneBilling
ADR 0274 — STANDALONE billing for this project. When enabled, all billable time of this project (direct PROJECT bookings + its tickets + its tasks) is carved out of the customer collective Leistungsnachweis and billed as its own project LN via POST /projects/:id/generate-performance-record. NEW projects default to enabled=true (materialised at create). EXISTING projects with this object ABSENT are treated as collective (resolveBillingUnit: absent → not standalone) — production-safe, no backfill. `performanceRecord*`/`invoicedAt` back-references are server-set only.
enabled
performanceRecordId
performanceRecordNumber
invoicedAt
budgetMinutes
Time budget in minutes
budgetUsedMinutes
Used time budget in minutes (auto-computed)
methodology
Project methodology
KANBANSCRUMWATERFALLHYBRIDdefaultBoardId
Default board UUID
tags
Project tags
salesOrderId
Linked sales_order UUID (works for both native and weclapp-sourced orders). Phase 1 of ADR 0139.
salesOrderSource
Origin of the linked sales-order (ADR 0139)
internalweclappnullcontrolling
Aggregated controlling data for the project (ADR 0139). Recomputed by reconcile-order-tasks job and on task/time-record mutations.
totalPlannedMinutes
totalPlannedAmount
totalLoggedMinutes
totalNonBillableLoggedMinutes
totalLoggedRealMinutes
totalLoggedAmount
totalBillableMinutes
totalBillableAmount
lastRecalculatedAt
materialReadiness
Materialbereitschaft des Projekts (Wareneingang). Servergeführt: nur POST/DELETE /projects/:id/material-readiness und die Order-Reconcile-Jobs schreiben hier.
status
not_tracked = keine Lieferpositionen am Auftrag (reines DL-Projekt, darf NICHT rot sein). awaiting/partial/complete = Wareneingang offen / teilweise / vollständig.
not_trackedawaitingpartialcompletesetBy
User, der den aktuellen Stand gesetzt hat (null bei Ableitung).
setAt
note
Freitext, z. B. „2 von 3 Paketen da, Switch fehlt".
source
manual = von Hand gesetzt (gewinnt immer gegen die Ableitung). internal/weclapp = aus Bestellung bzw. weclapp-Wareneingang abgeleitet.
manualinternalweclappcompletedAt
Wann es `complete` wurde; beim Zurücksetzen wieder null.
weclappSalesOrderId
weclapp sales order ID
weclappOrderUrl
URL to the weclapp sales order detail page
weclappSalesOrderNumber
weclapp sales order number (e.g. AB-2026-00042)
orderIntake
ADR 0765 — set when the order intake found this project by order number (TANSS-imported, order number only in title/description) and linked it instead of creating a duplicate. `mode: linked-existing` tells every later intake run to keep its hands off positions, tasks and checklists — without the marker the next weclapp UPDATE would materialise them into a running project. Written by the worker and the dedupe script only.
weclappPerformanceRecordId
weclapp performance record created from the sales order at project billing completion (ADR 0412). Set once — the completion endpoint is idempotent on it.
weclappPerformanceRecordNumber
Number of the weclapp performance record (display/deep-link).
weclappBillingCompletedAt
When the weclapp billing completion ran for this project.
weclappBillingItemIds
ADR 0634 — weclapp salesOrderItem-Ids der beim Abrechnungsabschluss gesammelt angehängten Buchungspositionen. Adresse für den Wiederholungslauf: ein erneuter Abschluss entfernt exakt diese Positionen und schreibt das Bild neu, statt zu duplizieren.
weclappBillingItemsTransferredAt
ADR 0634 — wann die gesammelten Buchungspositionen zuletzt in den weclapp-Auftrag geschrieben wurden.
weclappBillingReplacedItemIds
ADR 0634 — weclapp salesOrderItem-Ids der Platzhalterpositionen, die beim Abschluss aus dem Auftrag ENTFERNT wurden. Reine Nachvollziehbarkeit: weclapp kennt die gelöschte Position danach nicht mehr, ohne diese Spur wäre im Nachhinein nicht erkennbar, was ersetzt wurde.
weclappSalesInvoiceId
weclapp sales invoice created from the performance record (ADR 0412). Set once — the create-invoice endpoint is idempotent on it.
weclappSalesInvoiceNumber
Number of the weclapp sales invoice (display).
weclappSalesInvoiceUrl
URL to the weclapp sales invoice detail page.
weclappInvoiceCreatedAt
When the weclapp sales invoice was created from the billing dialog.
weclappSalesOrderData
Cached weclapp sales order data
limits
Project cap configuration (budget, hours, deadlines). Used by /projects/:id/limits and warning logic.
budgetWarningPercent
Percent of budget at which a warning is raised
hoursWarningPercent
Percent of project-total hours at which a warning is raised
hoursPerTaskWarningPercent
Percent of task.maxMinutes at which a warning is raised
deadlineWarningDays
Days before the project deadline at which a warning is raised
hardBlockOnExceed
If true, new time records are rejected once project-level budget or hours are exceeded
thresholdsNotified
Threshold keys that have already triggered a notification (first-time only).
budgetCapPercent
Per-project HARD CAP (Obergrenze) as % of the € budget (controlling.totalLoggedAmount / budget). Once logged spend reaches this percent, further time bookings on the project or its tasks are rejected (422 project-cap-exceeded). null/absent ⇒ inherit the tenant default (settings.projects.defaultLimits.budgetCapPercent); 0 ⇒ explicitly no €-cap for this project (overrides a tenant default). Values > 100 allow a controlled overrun. Tolerated missing on existing projects — runtime fallback, no backfill.
hoursCapPercent
Per-project HARD CAP (Obergrenze) as % of the hours budget (usedMinutes / budgetMinutes). Once the projected usage reaches this percent, further time bookings are rejected (422). null/absent ⇒ inherit the tenant default (settings.projects.defaultLimits.hoursCapPercent), else the legacy limits.hardBlockOnExceed flag (= 100%); 0 ⇒ explicitly no hours-cap. Values > 100 allow a controlled overrun. Runtime fallback, no backfill.
lockThresholdPercent
Per-project override (%) for the task-progress review lock. When task completion (done/total) first reaches this, the project auto-locks for team-lead review. Null ⇒ use tenant default (settings.projectLock.thresholdPercent, default 70).
budgetLockThresholdPercent
Per-project override (%) for the BUDGET-progress review lock (ADR 0191). When budget usage (controlling.totalLoggedAmount / budget €) first reaches this, the project auto-locks for team-lead review — independent of, and OR-combined with, the task-progress lock. Setting a value enables budget-locking for this project even if the tenant default is off. Null ⇒ use tenant default (settings.projectLock.lockOnBudget + budgetThresholdPercent).
planLockThresholdPercent
Per-project override (%) for the POSITION-PLAN review lock (ADR 0422). When plan usage (controlling.totalLoggedMinutes / totalPlannedMinutes, else the amount equivalent) first reaches this, the project auto-locks for team-lead review — independent of, and OR-combined with, the task and budget locks. Exists because order-materialised projects usually carry no project-level €/hours budget: their planned effort lives in the position limits, so neither of the other two triggers can ever fire there. Setting a value enables plan-locking for this project even if the tenant switch is off. Null ⇒ use tenant default (settings.projectLock.lockOnPlan + planThresholdPercent).
reviewLock
Progress-based review lock state (ADR 0191). One-time checkpoint: once released it does not re-lock at the same threshold. Set/cleared ONLY by the project-lock service and the /projects/:id/review endpoints — listed in protectedFields so generic CRUD PATCH cannot write it.
status
none = never locked; locked = awaiting team-lead release (blocks technician time bookings); released = reviewed & freed (no re-lock at this threshold).
nonelockedreleasedthresholdPercent
Effective threshold (%) that triggered the lock.
lockedAt
lockedProgressPercent
Progress percent of the triggering metric (see lockedMetric) at the moment the lock fired.
lockedMetric
Which metric crossed its threshold and triggered the lock: "tasks" (completion done/total), "budget" (controlling.totalLoggedAmount / budget €) or "plan" (controlling.totalLoggedMinutes / totalPlannedMinutes — the position plan, ADR 0422). Drives the banner + review-task wording.
tasksbudgetplanconsumedMetrics
Per-metric one-time checkpoints already consumed (ADR 0191, extended by ADR 0422). A metric in this list does not re-lock — but the task, budget and plan checkpoints are independent, so releasing one never disables the others. Absent on locks written before this field existed; the service then derives it from lockedMetric (no backfill).
reviewTaskId
The auto-created review task assigned to the reviewer(s).
reviewerIds
Internal user IDs allowed to release (team leads of orgUnit, else the project manager). Mirrored onto the review task assignees.
releasedAt
releasedBy
Internal user ID who released the lock.
customerAccess
Customer access configuration for project visibility
mode
Access mode for customer project view
DISABLEDAUTHENTICATEDSECURE_LINKLINK_PLUS_LOGINvisibilityProfile
Predefined visibility profile or CUSTOM for manual feature selection
MINIMALSTANDARDEXTENDEDCOLLABORATIVECUSTOMaccessToken
Random token for public access URL
accessTokenCreatedAt
When the access token was generated
allowedPartyIds
Party UUIDs that are allowed to access the project
sourceTemplateId
task_template this project was instantiated from.
sourceTemplateVersion
Pinned template version at instantiation time.
inboundReplyAckedAt
Timestamp at which the latest inbound customer email was acknowledged as "handled, no reply needed". Clears the awaiting-reply badge when >= the last inbound email time; a newer inbound email re-arms it. Mirrors opportunity.inboundReplyAckedAt.
inboundReplyAckedBy
User who acknowledged the latest inbound customer email (see inboundReplyAckedAt).
Keine Felder passen zum Filter.
Standard-Endpoints
Diese Resource folgt dem generischen CRUD-Vertrag der Plattform. Lesen Sie die Konventionen für Pagination, Idempotenz, Optimistic Locking und Audit. Die wichtigsten Endpoints:
GET /api/v1/projects— Liste, paginiert + filterbarGET /api/v1/projects/<id>— Einzelne EntityPOST /api/v1/projects— AnlegenPATCH /api/v1/projects/<id>— Teil-UpdateDELETE /api/v1/projects/<id>— Soft-DeleteGET /api/v1/projects/<id>/timeline— Audit + Aktivitäten