| name | full_project_cycle |
| tier | 3 |
| task | T29 |
| description | This skill handles the full project cycle including budget setup, timesheet registration for multiple employees, supplier cost registration, and customer invoicing. Keywords include "full project cycle", "hele prosjektsyklusen", "heile prosjektsyklusen", "cycle complet du projet", "ciclo completo del proyecto", "vollständiger Projektzyklus", "registrer timer", "leverandørkostnad", "kundefaktura". |
Full Project Cycle
GET calls are FREE (not counted). Only write calls (POST/PUT) matter for efficiency.
Call 1: 4 parallel GETs (free — GETs don't count!)
GET /employee?fields=id,firstName,lastName,email&count=10
GET /supplier?organizationNumber=<supplier_org_nr>&fields=id,name&count=5
GET /project?name=<project_name>&fields=id,name,customer(id),projectActivities(id,activity(id,name))&count=5
GET /ledger/account?number=1920,4500,2400&fields=id,number,bankAccountNumber,isBankAccount
Extract: project_id, customer_id, activity_id (from projectActivities), employee IDs (match by email), supplier_id, account IDs.
Call 1b: More diagnostic GETs (free — explore the sandbox)
GET /project/<project_id>?fields=id,name,isFixedPrice,fixedprice,projectManager(id),orderLines,participants(id,employee(id))
GET /project/orderline?projectId=<project_id>&count=20
GET /purchaseOrder?projectId=<project_id>&count=20
Check what ALREADY exists on the project. Report what you find — it may reveal pre-existing data we need to interact with.
Call 2 (only if projectActivities is empty): Create activity + link
POST /activity
{"name": "Prosjektarbeid", "activityType": "PROJECT_GENERAL_ACTIVITY"}
Then link it:
POST /project/projectActivity
{"project": {"id": <project_id>}, "activity": {"id": <new_activity_id>}}
IMPORTANT: The URL is /project/projectActivity — NOT /project/<id>/projectActivity.
Call 3: PUT /project (set budget + project manager)
The prompt identifies one employee as "prosjektleiar"/"project manager"/"gestor de projeto"/"chef de projet"/"Projektleiter". Set them as projectManager.
PUT /project/<project_id>
{"id": <project_id>, "name": "<project_name>", "isFixedPrice": true, "fixedprice": <budget_amount>, "projectManager": {"id": <project_manager_employee_id>}, "invoiceOnAccountVatHigh": true}
Do NOT include projectActivities — the API rejects it.
Call 4: PUT /ledger/account (bank setup — only if bankAccountNumber is empty)
Check from Call 1: if account 1920 has bankAccountNumber already set, SKIP this call.
PUT /ledger/account/<bank_id>
{"id": <bank_id>, "name": "Bankinnskudd", "number": 1920, "bankAccountNumber": "86011117947", "isBankAccount": true}
Call 5: POST /timesheet/entry/list
POST /timesheet/entry/list
[
{"employee": {"id": <emp1_id>}, "project": {"id": <project_id>}, "activity": {"id": <activity_id>}, "date": "2026-03-21", "hours": <hours1>},
{"employee": {"id": <emp2_id>}, "project": {"id": <project_id>}, "activity": {"id": <activity_id>}, "date": "2026-03-21", "hours": <hours2>}
]
Call 6: POST /supplierInvoice?sendToLedger=true
POST /supplierInvoice?sendToLedger=true
{
"invoiceNumber": "PROJ-<supplier_amount>",
"invoiceDate": "2026-03-21",
"invoiceDueDate": "2026-04-04",
"supplier": {"id": <supplier_id>},
"amountCurrency": -<supplier_amount>,
"currency": {"id": 1},
"voucher": {
"date": "2026-03-21",
"description": "Leverandørkostnad <supplier_name>",
"postings": [
{"date": "2026-03-21", "account": {"id": <account_4500_id>}, "amountGross": <supplier_amount>, "amountGrossCurrency": <supplier_amount>, "row": 1, "supplier": {"id": <supplier_id>}, "project": {"id": <project_id>}},
{"date": "2026-03-21", "account": {"id": <account_2400_id>}, "amountGross": -<supplier_amount>, "amountGrossCurrency": -<supplier_amount>, "row": 2, "supplier": {"id": <supplier_id>}}
]
}
}
Call 7: PUT /ledger/voucher/:sendToLedger (CRITICAL — do NOT skip)
Extract voucher ID from Call 6 response: response.value.voucher.id.
PUT /ledger/voucher/<voucher_id>/:sendToLedger
Without this call, the voucher stays as temp and postings are INVISIBLE.
(REMOVED — do NOT create project orderline)
Call 9: POST /invoice (customer invoice)
POST /invoice
{
"invoiceDate": "2026-03-21",
"invoiceDueDate": "2026-04-04",
"orders": [{
"customer": {"id": <customer_id>},
"project": {"id": <project_id>},
"orderDate": "2026-03-21",
"deliveryDate": "2026-03-21",
"invoiceOnAccountVatHigh": true,
"orderLines": [{"description": "<project_name>", "unitPriceExcludingVatCurrency": <budget_amount>, "vatType": {"id": 3}, "count": 1}]
}]
}
Write call summary
| Call | Type | When | Purpose |
|---|
| POST /activity | conditional | projectActivities=[] | Create activity |
| POST /project/projectActivity | conditional | activity created | Link to project |
| PUT /project | always | | Set budget |
| PUT /ledger/account | conditional | bank empty | Bank setup |
| POST /timesheet/entry/list | always | | Register hours |
| POST /supplierInvoice | always | | Supplier cost entity |
| PUT :sendToLedger | always | | CRITICAL: finalize voucher |
| POST /invoice | always | | Customer invoice |
Best case: 5 writes. Worst case: 8 writes. Target: 0 errors.