|
|
|
# Group Relations
|
|
|
|
|
|
|
|
Work packages may be related to each other in different ways.
|
|
|
|
|
|
|
|
```
|
|
|
|
+--------------+ +--------------+
|
|
|
|
| | 1 1 | |
|
|
|
|
| Work package +-------------+--------------+ Work package |
|
|
|
|
| | from | to | |
|
|
|
|
+--------------+ | +--------------+
|
|
|
|
+------+-------+
|
|
|
|
| Relation |
|
|
|
|
+--------------+
|
|
|
|
| type |
|
|
|
|
| reverseType |
|
|
|
|
| description |
|
|
|
|
| delay |
|
|
|
|
+--------------+
|
|
|
|
```
|
|
|
|
|
|
|
|
## Actions
|
|
|
|
|
|
|
|
| Link | Description | Condition |
|
|
|
|
|:-------------------:| -------------------------------------------------------------------- | --------------------------------------------- |
|
|
|
|
| update | Updates the relation between two work packages via a form | **Permission**: manage work package relations |
|
|
|
|
| updateImmediately | Updates the relation between two work packages | **Permission**: manage work package relations |
|
|
|
|
| delete | Destroys the relation between the two work packages | **Permission**: manage work package relations |
|
|
|
|
|
|
|
|
## Linked Properties
|
|
|
|
| Link | Description | Type | Constraints | Supported operations | Condition |
|
|
|
|
|:-------------:|-------------------------------------- | ------------- | ----------- | -------------------- | --------------------------------------------- |
|
|
|
|
| self | This relation | Relation | not null | READ | **Permission**: view work packages |
|
|
|
|
| schema | The schema of this relation | Schema | not null | READ | |
|
|
|
|
| from | The emanating work package | WorkPackage | not null | READ | **Permission**: view work packages |
|
|
|
|
| to | The work package the relation ends in | WorkPackage | not null | READ | **Permission**: view work packages |
|
|
|
|
|
|
|
|
## Local Properties
|
|
|
|
| Property | Description | Type | Constraints | Supported operations |
|
|
|
|
| :---------------:| ------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
|
|
| id | Relation ID | Integer | x > 0 | READ |
|
|
|
|
| name | The internationalized name of this kind of relation | String | | READ
|
|
|
|
| type | Which kind of relation (blocks, precedes, etc.) | String | in: relates, duplicates, duplicated, blocks, blocked, precedes, follows, includes, partof, requires, required | READ / WRITE |
|
|
|
|
| reverseType | The kind of relation from the other WP's perspective | String | in: relates, duplicates, duplicated, blocks, blocked, precedes, follows, includes, partof, requires, required | READ |
|
|
|
|
| description | Short text further describing the relation | String | | READ / WRITE |
|
|
|
|
| delay* | The delay in days between closing of `from` and start of `to` | Integer | x >= 0 | READ / WRITE |
|
|
|
|
|
|
|
|
\* Only applicable for some relation types such as "follows". You can check using the relation by schema
|
|
|
|
endpoint at `/api/v3/relations/schema/{type}`.
|
|
|
|
|
|
|
|
## Relation [/api/v3/relations/{id}]
|
|
|
|
|
|
|
|
+ Model
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_links":
|
|
|
|
{
|
|
|
|
"self":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1"
|
|
|
|
},
|
|
|
|
"update":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1/form",
|
|
|
|
"method": "POST"
|
|
|
|
},
|
|
|
|
"updateImmediately":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1",
|
|
|
|
"method": "PATCH"
|
|
|
|
},
|
|
|
|
"delete":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1",
|
|
|
|
"method": "DELETE"
|
|
|
|
},
|
|
|
|
"from":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/work_packages/42",
|
|
|
|
"title": "Steel Delivery"
|
|
|
|
},
|
|
|
|
"to":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/work_packages/84",
|
|
|
|
"title": "Bending the steel"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"_type": "Relation",
|
|
|
|
"id": 1,
|
|
|
|
"name": "precedes",
|
|
|
|
"type": "precedes",
|
|
|
|
"reverseType": "follows",
|
|
|
|
"description": "We can't bend the steel before it's been delivered!",
|
|
|
|
"delay": 0
|
|
|
|
}
|
|
|
|
|
|
|
|
## View Relation [GET]
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
|
|
|
|
+ id (required, integer, `1`) ... Relation id
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relation][]
|
|
|
|
|
|
|
|
+ Response 404 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation does not exist or the client does not have sufficient permissions to see it.
|
|
|
|
|
|
|
|
**Required permission:** view work packages for the involved work packages
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
|
|
|
|
"message": "The specified relation does not exist."
|
|
|
|
}
|
|
|
|
|
|
|
|
## Edit Relation [PATCH]
|
|
|
|
|
|
|
|
When calling this endpoint the client provides a single object, containing the properties and links that it wants to change, in the body.
|
|
|
|
It is only allowed to provide properties or links supporting the **write** operation.
|
|
|
|
|
|
|
|
Note that changing the `type` of a relation invariably also changes the respective `reverseType` as well as the "name" of it.
|
|
|
|
The returned Relation object will reflect that change. For instance if you change a Relation's
|
|
|
|
`type` to "follows" then the `reverseType` will be changed to `precedes`.
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
|
|
|
|
+ id (required, integer, `1`) ... Relation ID
|
|
|
|
|
|
|
|
+ Request Update Relation (application/json)
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"type": "blocks",
|
|
|
|
"description": "Actually the supplier has to bend the steel before they can deliver it."
|
|
|
|
"delay": 3
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relation][]
|
|
|
|
|
|
|
|
+ Response 400 (application/hal+json)
|
|
|
|
|
|
|
|
Occurs when the client did not send a valid JSON object in the request body.
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidRequestBody",
|
|
|
|
"message": "The request body was not a single JSON object."
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Response 404 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation does not exist or the client does not have sufficient permissions to see it.
|
|
|
|
|
|
|
|
**Required permission:** manage work package relations
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
|
|
|
|
"message": "The specified relation does not exist."
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Response 422 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if:
|
|
|
|
|
|
|
|
* the client tries to modify a read-only property (`PropertyIsReadOnly`)
|
|
|
|
* a constraint for a property was violated (`PropertyConstraintViolation`)
|
|
|
|
* the client provides a link to an invalid resource (`ResourceTypeMismatch`) or a
|
|
|
|
work package that does not exist or for which the client does not have sufficient permissions
|
|
|
|
to see it (**required permissions**: `view work packages` for the involved work packages).
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
|
|
|
|
"message": "Delay must be a number greater than or equal to 0",
|
|
|
|
"_embedded": {
|
|
|
|
"details": {
|
|
|
|
"attribute": "delay"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## Delete Relation [DELETE]
|
|
|
|
|
|
|
|
Deletes the relation.
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
|
|
|
|
+ id (required, integer, `1`) ... Relation ID
|
|
|
|
|
|
|
|
+ Response 204 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation was deleted successfully.
|
|
|
|
The response body is empty.
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
+ Response 403 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the client does not have sufficient permissions.
|
|
|
|
|
|
|
|
**Required permission:** manage work package relations
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
|
|
|
|
"message": "You are not allowed to delete this relation."
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Response 404 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation does not exist or the client does not have sufficient permissions to see it.
|
|
|
|
|
|
|
|
**Required permission:** manage work package relations
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
|
|
|
|
"message": "The specified relation does not exist."
|
|
|
|
}
|
|
|
|
|
|
|
|
## Relation schema [/api/v3/relations/schema]
|
|
|
|
|
|
|
|
+ Model
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Schema",
|
|
|
|
"_links": {
|
|
|
|
"self": { "href": "/api/v3/relations/schema" }
|
|
|
|
},
|
|
|
|
|
|
|
|
"id": {
|
|
|
|
"name": "ID",
|
|
|
|
"type": "Integer",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"type": {
|
|
|
|
"name": "Type",
|
|
|
|
"type": "String",
|
|
|
|
"writable": true
|
|
|
|
},
|
|
|
|
"reverseType": {
|
|
|
|
"name": "Reverse Type",
|
|
|
|
"type": "String",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"description": {
|
|
|
|
"name": "Description",
|
|
|
|
"type": "String",
|
|
|
|
"writable": true
|
|
|
|
},
|
|
|
|
"from": {
|
|
|
|
"name": "From work package",
|
|
|
|
"type": "WorkPackage",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"to": {
|
|
|
|
"name": "To work package",
|
|
|
|
"type": "WorkPackage",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"delay": {
|
|
|
|
"name": "Delay",
|
|
|
|
"type": "Integer",
|
|
|
|
"writable": true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## View relation schema [GET]
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relation schema][]
|
|
|
|
|
|
|
|
## Relation schema for type [/api/v3/relations/schema/{type}]
|
|
|
|
|
|
|
|
The exact schema for a relation may depend on it's type.
|
|
|
|
For instance the "follows" relation has an additional "delay" field which is not
|
|
|
|
applicable for the other relations.
|
|
|
|
|
|
|
|
## View relation schema for type [GET]
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
|
|
|
|
+ type (required, string, `follows`) ... Type of the schema
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relation schema][]
|
|
|
|
|
|
|
|
+ Response 404 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation type does not exist or the client does not have sufficient permissions to see it.
|
|
|
|
|
|
|
|
**Required permission:** manage work package relations
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
|
|
|
|
"message": "The specified relation type does not exist."
|
|
|
|
}
|
|
|
|
|
|
|
|
## Relations [/api/v3/relations{?filters,sortBy}]
|
|
|
|
|
|
|
|
+ Model
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_links":
|
|
|
|
{
|
|
|
|
"self":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"total": 3,
|
|
|
|
"count": 1,
|
|
|
|
"_type": "Collection",
|
|
|
|
"_embedded":
|
|
|
|
{
|
|
|
|
"elements": [
|
|
|
|
{
|
|
|
|
"_links":
|
|
|
|
{
|
|
|
|
"self":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1"
|
|
|
|
},
|
|
|
|
"update":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1/form",
|
|
|
|
"method": "POST"
|
|
|
|
},
|
|
|
|
"updateImmediately":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1",
|
|
|
|
"method": "PATCH"
|
|
|
|
},
|
|
|
|
"delete":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/relations/1",
|
|
|
|
"method": "DELETE"
|
|
|
|
},
|
|
|
|
"from":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/work_packages/42",
|
|
|
|
"title": "Steel Delivery"
|
|
|
|
},
|
|
|
|
"to":
|
|
|
|
{
|
|
|
|
"href": "/api/v3/work_packages/84",
|
|
|
|
"title": "Bending the steel"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"_type": "Relation",
|
|
|
|
"id": 1,
|
|
|
|
"name": "precedes",
|
|
|
|
"type": "precedes",
|
|
|
|
"reverseType": "follows",
|
|
|
|
"description": "We can't bend the steel before it's been delivered!",
|
|
|
|
"delay": 0
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## List Relations [GET]
|
|
|
|
|
|
|
|
Lists all relations according to the given (optional, logically conjunctive) filters and ordered by ID.
|
|
|
|
The response only includes relations between work packages which the user is allowed to see.
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
+ filters (optional, string, `[{ "from": { "operator": "=", "values": 42 }" }]`) ... JSON specifying filter conditions.
|
|
|
|
Accepts the same format as returned by the [queries](#queries) endpoint. Valid fields to filter by are:
|
|
|
|
+ id - ID of relation
|
|
|
|
+ from - ID of work package from which the filtered relations emanates.
|
|
|
|
+ to - ID of work package to which this related points.
|
|
|
|
+ involved - ID of either the `from` or the `to` work package.
|
|
|
|
+ type - The type of relation to filter by, e.g. "follows".
|
|
|
|
|
|
|
|
+ sortBy (optional, string, `[["type", "asc"]]`) ... JSON specifying sort criteria.
|
|
|
|
Accepts the same format as returned by the [queries](#queries) endpoint.
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relations][]
|
|
|
|
|
|
|
|
## Relation edit form [/api/v3/relations/{id}/form]
|
|
|
|
|
|
|
|
This endpoint returns a form to allow a guided creation of a new work package relation.
|
|
|
|
The returned form will be pre-filled with default values for every property, if available.
|
|
|
|
|
|
|
|
For more details and all possible responses see the general specification of [Forms](#forms).
|
|
|
|
|
|
|
|
+ Model
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_links": {
|
|
|
|
"self": { "href": "/api/v3/relations/form" },
|
|
|
|
"validate": {
|
|
|
|
"href": "/api/v3/relations/form",
|
|
|
|
"method": "POST"
|
|
|
|
},
|
|
|
|
"commit": {
|
|
|
|
"href": "/api/v3/relations",
|
|
|
|
"method": "PATCH"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
"_type": "Form",
|
|
|
|
|
|
|
|
"_embedded": {
|
|
|
|
"payload": {
|
|
|
|
"_links": {
|
|
|
|
"from": { "href": "/api/v3/work_packages/4534" },
|
|
|
|
"to": { "href": "/api/v3/work_packages/3857" }
|
|
|
|
},
|
|
|
|
"_type": "WorkPackage",
|
|
|
|
"type": "follows",
|
|
|
|
"delay": 3,
|
|
|
|
"description": "let it rest for 3 days"
|
|
|
|
},
|
|
|
|
"schema": {
|
|
|
|
"_type": "Schema",
|
|
|
|
"_links": {
|
|
|
|
"self": { "href": "/api/v3/relations/schema" }
|
|
|
|
},
|
|
|
|
|
|
|
|
"id": {
|
|
|
|
"name": "ID",
|
|
|
|
"type": "Integer",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"type": {
|
|
|
|
"name": "Type",
|
|
|
|
"type": "String",
|
|
|
|
"writable": true,
|
|
|
|
"allowedValues": [
|
|
|
|
"relates", "duplicates", "duplicated", "blocks", "blocked",
|
|
|
|
"precedes", "follows", "includes", "partof", "requires", "required"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"reverseType": {
|
|
|
|
"name": "Reverse Type",
|
|
|
|
"type": "String",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"description": {
|
|
|
|
"name": "Description",
|
|
|
|
"type": "String",
|
|
|
|
"writable": true
|
|
|
|
},
|
|
|
|
"from": {
|
|
|
|
"name": "From work package",
|
|
|
|
"type": "WorkPackage",
|
|
|
|
"writeable": false
|
|
|
|
},
|
|
|
|
"to": {
|
|
|
|
"name": "To work package",
|
|
|
|
"type": "WorkPackage",
|
|
|
|
"writable": false
|
|
|
|
},
|
|
|
|
"delay": {
|
|
|
|
"name": "Delay",
|
|
|
|
"type": "Integer",
|
|
|
|
"writable": true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"validationErrors": {
|
|
|
|
"from": {
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:BadExampleError",
|
|
|
|
"message": "For the purpose of this example we need a validation error. The remainder of the response pretends there were no errors."
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## Relation edit form [POST]
|
|
|
|
|
|
|
|
+ Request
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Relation",
|
|
|
|
"type": "follows",
|
|
|
|
"description": "let it rest for 3 days",
|
|
|
|
"delay": 3
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Parameters
|
|
|
|
+ id (required, integer, `1`) ... ID of the relation being modified
|
|
|
|
|
|
|
|
+ Response 200 (application/hal+json)
|
|
|
|
|
|
|
|
[Relation edit form][]
|
|
|
|
|
|
|
|
+ Response 403 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the client does not have sufficient permissions.
|
|
|
|
|
|
|
|
**Required permission:** manage work package relations
|
|
|
|
|
|
|
|
*Note that you will only receive this error, if you are at least allowed to see the involved work packages.*
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
|
|
|
|
"message": "You are not allowed to edit the specified relation."
|
|
|
|
}
|
|
|
|
|
|
|
|
+ Response 404 (application/hal+json)
|
|
|
|
|
|
|
|
Returned if the relation does not exist or the client does not have sufficient permissions to see it.
|
|
|
|
|
|
|
|
**Required permission:** view (involved) work package(s), manage work package relations
|
|
|
|
|
|
|
|
+ Body
|
|
|
|
|
|
|
|
{
|
|
|
|
"_type": "Error",
|
|
|
|
"errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
|
|
|
|
"message": "The specified relation does not exist."
|
|
|
|
}
|