Initial commit
This commit is contained in:
557
templates/odata-resource-template.md
Normal file
557
templates/odata-resource-template.md
Normal file
@@ -0,0 +1,557 @@
|
||||
# OData Resource Template
|
||||
|
||||
## How to Use This Template
|
||||
|
||||
**Purpose**: Document individual OData resources (entity sets) within a service with all available operations.
|
||||
|
||||
**When to Use**:
|
||||
- Creating detailed documentation for a specific OData entity set/resource
|
||||
- Documenting all CRUD operations on a resource
|
||||
- Listing navigation properties and custom functions/actions
|
||||
- Linking from Service Overview to specific resource documentation
|
||||
|
||||
**Instructions**:
|
||||
1. Replace all [bracketed text] with your actual resource information
|
||||
2. Verify all operations against service metadata
|
||||
3. Document navigation properties with cardinality (1:1, 1:N)
|
||||
4. Include permission requirements for each operation type
|
||||
5. List custom functions and actions with brief descriptions
|
||||
6. Remove optional sections if not applicable
|
||||
|
||||
**Cross-Reference**: Use with [OData Service Overview Template](#odata-service-overview-template) for service context and [OData Operation Template](#odata-operation-template) for detailed operation docs.
|
||||
|
||||
**Template Structure**:
|
||||
- Title & Introduction
|
||||
- Resource Information (path, key, permissions)
|
||||
- Operations (CRUD, navigation, custom)
|
||||
- Common Headers
|
||||
- Status and Error Codes
|
||||
- Examples
|
||||
|
||||
---
|
||||
|
||||
## [Resource Name] Resource
|
||||
|
||||
[Provide clear description of what this resource represents and contains. Include:
|
||||
- What business entity or data domain it covers
|
||||
- Primary use cases
|
||||
- Relationship to other resources
|
||||
- Scope or limitations]
|
||||
|
||||
**Example**:
|
||||
"Collection of all employees in the system. Provides access to employee master
|
||||
data including personal information, organizational assignments, employment
|
||||
status, and related compensation information. Navigation properties allow
|
||||
access to related departments, managers, and compensation details."
|
||||
|
||||
### Additional Context
|
||||
|
||||
[Any important information about this resource]
|
||||
|
||||
This resource represents [explain domain/purpose]. Use for [primary use cases].
|
||||
Navigation properties allow [explain relationships].
|
||||
|
||||
---
|
||||
|
||||
## Resource Information
|
||||
|
||||
### Resource Path
|
||||
|
||||
**Path**: `[Relative path to entity set, e.g., /Employees]`
|
||||
|
||||
[Explanation of resource path]
|
||||
|
||||
### Absolute URI
|
||||
|
||||
**Absolute URI**: `[Root URI]/[Resource Path]`
|
||||
|
||||
**Example**: `[https://api.example.com/odata/v4/Employees`](https://api.example.com/odata/v4/Employees`)
|
||||
|
||||
### Key Property
|
||||
|
||||
**Key Property**: [Property name that uniquely identifies each resource]
|
||||
|
||||
[Description of key property and format/pattern]
|
||||
|
||||
**Example**:
|
||||
```
|
||||
Key Property: EmployeeID
|
||||
Type: String
|
||||
Format: E followed by 5 digits
|
||||
Pattern: E[0-9]{5}
|
||||
Example: E12345
|
||||
```
|
||||
|
||||
### Individual Resource Addressing
|
||||
|
||||
[How to address/access a single resource by key]
|
||||
|
||||
**URI Pattern**: `[Resource Path]('{[Key Value]}')`
|
||||
|
||||
**Examples**:
|
||||
- `/Employees('E12345')` - Address by string key
|
||||
- `/Employees(EmployeeID='E12345')` - Explicit property name
|
||||
- `[https://api.example.com/odata/v4/Employees('E12345](https://api.example.com/odata/v4/Employees('E12345)')` - Absolute URI
|
||||
|
||||
### Required Permissions
|
||||
|
||||
[Document permissions for different operation types on this resource]
|
||||
|
||||
| Operation Type | Required Permission | Description |
|
||||
|---|---|---|
|
||||
| Read/Query | [Role] | [What permission is needed and what it allows] |
|
||||
| Create (POST) | [Role] | [Permission required] |
|
||||
| Update (PUT/PATCH) | [Role] | [Permission required] |
|
||||
| Delete | [Role] | [Permission required] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Operation Type | Required Permission | Description |
|
||||
|---|---|---|
|
||||
| Read/Query | ROLE_HR_USER | Read-only access to all employee data |
|
||||
| Create (POST) | ROLE_HR_MANAGER | Create new employee records |
|
||||
| Update (PUT/PATCH) | ROLE_HR_MANAGER | Modify existing employee data |
|
||||
| Delete | ROLE_ADMIN | Delete employee records (limited to admins) |
|
||||
```
|
||||
|
||||
### Resource Properties
|
||||
|
||||
[Complete list of all properties available on this resource]
|
||||
|
||||
| Property Name | Data Type | Description | Example | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [Property] | [Type] | [Description] | [Example value] | [Nullable, constraints, etc.] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Property Name | Data Type | Description | Example | Notes |
|
||||
|---|---|---|---|---|
|
||||
| EmployeeID | String | Unique employee identifier | E12345 | Key property, not null |
|
||||
| FirstName | String | Employee's first name | John | 1-50 characters, required |
|
||||
| LastName | String | Employee's last name | Doe | 1-50 characters, required |
|
||||
| Email | String | Corporate email address | john.doe@company.com | Must be unique, required |
|
||||
| HireDate | Date | Employment start date | 2024-01-15 | ISO 8601 format, optional |
|
||||
| Status | String | Employment status | ACTIVE | Values: ACTIVE, INACTIVE, ON_LEAVE, TERMINATED |
|
||||
| Salary | Decimal | Annual salary | 95000.00 | Nullable, 2 decimal places |
|
||||
| CreatedAt | DateTime | Record creation timestamp | 2024-01-15T10:30:00Z | UTC, auto-set |
|
||||
| LastModified | DateTime | Last modification timestamp | 2024-01-15T14:30:00Z | UTC, auto-updated |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Operations
|
||||
|
||||
### CRUD Operations
|
||||
|
||||
Standard Create, Read, Update, Delete operations available on this resource:
|
||||
|
||||
| HTTP Method | Operation | URI | Description |
|
||||
|---|---|---|---|
|
||||
| GET | [Read Collection](#operation-read-collection) | `[Resource]` | Retrieve all resources |
|
||||
| GET | [Read Single](#operation-read-single) | `[Resource]('{Key}')` | Retrieve specific resource |
|
||||
| POST | [Create](#operation-create) | `[Resource]` | Create new resource |
|
||||
| PUT | [Replace](#operation-replace) | `[Resource]('{Key}')` | Replace entire resource |
|
||||
| PATCH | [Update](#operation-update) | `[Resource]('{Key}')` | Partial update resource |
|
||||
| DELETE | [Delete](#operation-delete) | `[Resource]('{Key}')` | Delete resource |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| HTTP Method | Operation | URI | Description |
|
||||
|---|---|---|---|
|
||||
| GET | [Query all employees](#operation-read-collection) | `/Employees` | Retrieve all employees with optional filtering and paging |
|
||||
| GET | [Get single employee](#operation-read-single) | `/Employees('{EmployeeID}')` | Retrieve specific employee by ID |
|
||||
| POST | [Create employee](#operation-create) | `/Employees` | Create new employee record |
|
||||
| PUT | [Replace employee](#operation-replace) | `/Employees('{EmployeeID}')` | Replace entire employee record |
|
||||
| PATCH | [Update employee](#operation-update) | `/Employees('{EmployeeID}')` | Partial update of employee fields |
|
||||
| DELETE | [Delete employee](#operation-delete) | `/Employees('{EmployeeID}')` | Delete/deactivate employee |
|
||||
```
|
||||
|
||||
### Navigation Properties
|
||||
|
||||
[If resource has relationships to other entities, document navigation properties]
|
||||
|
||||
**Navigation Properties**:
|
||||
|
||||
| Navigation Name | Target Entity | Cardinality | Description |
|
||||
|---|---|---|---|
|
||||
| [Property] | [Entity] | [1:1 / 1:N] | [Description of relationship] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Navigation Name | Target Entity | Cardinality | Description |
|
||||
|---|---|---|---|
|
||||
| Department | Department | 1:1 | Navigate to employee's department |
|
||||
| Manager | Employee | 1:1 | Navigate to employee's manager (another employee) |
|
||||
| DirectReports | Employee | 1:N | Navigate to employees reporting to this employee |
|
||||
| Compensation | Compensation | 1:1 | Navigate to compensation details |
|
||||
```
|
||||
|
||||
**How to Use Navigation Properties**:
|
||||
|
||||
Using `$expand` to include related data:
|
||||
```
|
||||
GET /Employees?$expand=Department HTTP/1.1
|
||||
|
||||
Returns employee(s) with embedded Department entity data.
|
||||
```
|
||||
|
||||
Using `$expand` with `$select` to limit properties:
|
||||
```
|
||||
GET /Employees?$expand=Department($select=DepartmentID,Name) HTTP/1.1
|
||||
|
||||
Returns employee(s) with only specific Department properties included.
|
||||
```
|
||||
|
||||
Multi-level expansion:
|
||||
```
|
||||
GET /Employees?$expand=Department,Manager($expand=Department) HTTP/1.1
|
||||
|
||||
Includes Department for the employee and Department for the manager.
|
||||
Maximum expansion depth: [specify limit, e.g., 3 levels]
|
||||
```
|
||||
|
||||
### Custom Functions and Actions
|
||||
|
||||
[If resource supports custom functions or actions, document them]
|
||||
|
||||
| Operation Type | Name | URI | Description |
|
||||
|---|---|---|---|
|
||||
| [Function/Action] | [Name] | [URI Pattern] | [Description] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Operation Type | Name | URI | Description |
|
||||
|---|---|---|---|
|
||||
| Function | GetManager | `/Employees('{EmployeeID}')/GetManager()` | Get the direct manager of an employee |
|
||||
| Function | GetDirectReports | `/Employees('{EmployeeID}')/GetDirectReports()` | Get all direct reports of an employee |
|
||||
| Action | Promote | `/Employees('{EmployeeID}')/Promote` | Promote employee to next level (requires payload with details) |
|
||||
| Action | Deactivate | `/Employees('{EmployeeID}')/Deactivate` | Mark employee as inactive |
|
||||
```
|
||||
|
||||
**Detailed Function/Action Information**:
|
||||
|
||||
For each custom operation, provide:
|
||||
- Purpose and use case
|
||||
- Request parameters (if any)
|
||||
- Return type
|
||||
- Permission requirements
|
||||
- Example request/response
|
||||
|
||||
---
|
||||
|
||||
## Common Headers
|
||||
|
||||
### Request Headers
|
||||
|
||||
| Header Name | Required | Possible Values | Description |
|
||||
|---|---|---|---|
|
||||
| [Header] | [Yes/No] | [Values] | [Description with format/examples] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Header Name | Required | Possible Values | Description |
|
||||
|---|---|---|---|
|
||||
| Authorization | Yes | Bearer {token} | OAuth2 authentication token in format: Authorization: Bearer {token} |
|
||||
| Content-Type | Yes (POST/PUT/PATCH) | application/json | Media type of request body for create/update operations |
|
||||
| Accept | No | application/json | Preferred response format. Default: application/json. Value: application/json |
|
||||
| Prefer | No | return=representation, return=minimal | OData preference. return=representation: include created/updated resource. return=minimal: response without body. |
|
||||
| If-Match | No | {ETag} | ETag value for optimistic concurrency control on PUT/PATCH. Example: "abc123def456". Prevents lost-update problem. |
|
||||
| X-Request-ID | No | UUID | Request tracking ID for logging and debugging. Any valid UUID format. Optional but recommended. |
|
||||
```
|
||||
|
||||
### Response Headers
|
||||
|
||||
| Header Name | Description | Example Value |
|
||||
|---|---|---|
|
||||
| [Header] | [What this header contains] | [Example] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
| Header Name | Description | Example Value |
|
||||
|---|---|---|
|
||||
| Content-Type | Response body media type | application/json |
|
||||
| ETag | Entity tag for caching and optimistic concurrency | "abc123def456" |
|
||||
| Location | URL of newly created resource (201 responses) | [https://api.example.com/odata/v4/Employees('E12346](https://api.example.com/odata/v4/Employees('E12346)') |
|
||||
| OData-Version | OData protocol version | 4.0 |
|
||||
| Preference-Applied | Which Prefer header preference was applied | return=representation |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Status and Error Codes
|
||||
|
||||
### Common Status Codes
|
||||
|
||||
| Status Code | Description | Typical Scenarios |
|
||||
|---|---|---|
|
||||
| [Code] | [Description] | [When this occurs] |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
Success Codes:
|
||||
|
||||
| Status Code | Description | Typical Scenarios |
|
||||
|---|---|---|
|
||||
| 200 OK | Request successful. Response body contains requested data. | GET operations, POST with Prefer: return=representation |
|
||||
| 201 Created | Resource successfully created. Location header contains new resource URL. | POST operations creating new entity |
|
||||
| 204 No Content | Request successful. No response body returned. | DELETE operations, PUT/PATCH with Prefer: return=minimal |
|
||||
|
||||
Error Codes:
|
||||
|
||||
| Status Code | Description | Typical Scenarios |
|
||||
|---|---|---|
|
||||
| 400 Bad Request | Invalid request format, syntax, or OData query error. Response includes error details. | Malformed filter syntax, missing required fields, invalid data types |
|
||||
| 401 Unauthorized | Authentication token missing, invalid, or expired. | Missing Authorization header, invalid token, expired token |
|
||||
| 403 Forbidden | Authenticated but insufficient permissions for operation. | User lacks required role, permission denied for operation |
|
||||
| 404 Not Found | Requested resource doesn't exist. | Invalid resource ID/key, deleted resource |
|
||||
| 409 Conflict | Request conflicts with current state (duplicate, constraint violation). | Duplicate key/email, unique constraint violation, data conflict |
|
||||
| 500 Internal Server Error | Server encountered unexpected error. | Unhandled server exception, database error |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Query All Resources
|
||||
|
||||
Retrieve all resources with optional filtering, selection, ordering, and pagination:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
GET /[ResourceName]?$filter=[filter]&$select=[properties]&$orderby=[property]&$top=[limit]&$skip=[offset] HTTP/1.1
|
||||
Host: [host]
|
||||
Authorization: Bearer {token}
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**Example - Get all active employees, sorted by name, limit 20**:
|
||||
```http
|
||||
GET /Employees?$filter=Status eq 'ACTIVE'&$select=EmployeeID,FirstName,LastName,Email&$orderby=LastName asc&$top=20&$skip=0 HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
OData-Version: 4.0
|
||||
|
||||
{
|
||||
"value": [
|
||||
{
|
||||
"EmployeeID": "E12345",
|
||||
"FirstName": "John",
|
||||
"LastName": "Doe",
|
||||
"Email": "john.doe@company.com"
|
||||
},
|
||||
{
|
||||
"EmployeeID": "E12346",
|
||||
"FirstName": "Jane",
|
||||
"LastName": "Smith",
|
||||
"Email": "jane.smith@company.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Query Single Resource
|
||||
|
||||
Retrieve a single resource by key:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
GET /[ResourceName]('{Key}') HTTP/1.1
|
||||
Host: [host]
|
||||
Authorization: Bearer {token}
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```http
|
||||
GET /Employees('E12345') HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
ETag: "abc123def456"
|
||||
|
||||
{
|
||||
"EmployeeID": "E12345",
|
||||
"FirstName": "John",
|
||||
"LastName": "Doe",
|
||||
"Email": "john.doe@company.com",
|
||||
"Department": "ENGINEERING",
|
||||
"HireDate": "2020-06-01",
|
||||
"Salary": 120000.00,
|
||||
"Status": "ACTIVE"
|
||||
}
|
||||
```
|
||||
|
||||
### Query with Navigation Expansion
|
||||
|
||||
Include related entity data:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
GET /Employees('E12345')?$expand=Department,Manager($select=FirstName,LastName) HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer {token}
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"EmployeeID": "E12345",
|
||||
"FirstName": "John",
|
||||
"LastName": "Doe",
|
||||
"Email": "john.doe@company.com",
|
||||
"Department": {
|
||||
"DepartmentID": "ENG",
|
||||
"Name": "Engineering",
|
||||
"Location": "San Francisco"
|
||||
},
|
||||
"Manager": {
|
||||
"FirstName": "Jane",
|
||||
"LastName": "Smith"
|
||||
},
|
||||
"Status": "ACTIVE"
|
||||
}
|
||||
```
|
||||
|
||||
### Create Resource
|
||||
|
||||
Create a new resource:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
POST /[ResourceName] HTTP/1.1
|
||||
Host: [host]
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
|
||||
[Request body with resource properties]
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```http
|
||||
POST /Employees HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
|
||||
{
|
||||
"FirstName": "Michael",
|
||||
"LastName": "Johnson",
|
||||
"Email": "michael.johnson@company.com",
|
||||
"Department": "SALES",
|
||||
"HireDate": "2024-01-15",
|
||||
"Salary": 85000.00
|
||||
}
|
||||
```
|
||||
|
||||
**Response** (201 Created):
|
||||
```http
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
Location: [https://api.example.com/odata/v4/Employees('E12347](https://api.example.com/odata/v4/Employees('E12347)')
|
||||
|
||||
{
|
||||
"EmployeeID": "E12347",
|
||||
"FirstName": "Michael",
|
||||
"LastName": "Johnson",
|
||||
"Email": "michael.johnson@company.com",
|
||||
"Department": "SALES",
|
||||
"HireDate": "2024-01-15",
|
||||
"Salary": 85000.00,
|
||||
"Status": "ACTIVE",
|
||||
"CreatedAt": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Update Resource
|
||||
|
||||
Partially update a resource using PATCH:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
PATCH /[ResourceName]('{Key}') HTTP/1.1
|
||||
Host: [host]
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
If-Match: "{ETag}"
|
||||
|
||||
[Request body with properties to update]
|
||||
```
|
||||
|
||||
**Example - Update salary and department**:
|
||||
```http
|
||||
PATCH /Employees('E12345') HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
Content-Type: application/json
|
||||
If-Match: "abc123def456"
|
||||
|
||||
{
|
||||
"Department": "ENGINEERING",
|
||||
"Salary": 125000.00
|
||||
}
|
||||
```
|
||||
|
||||
**Response** (204 No Content):
|
||||
```http
|
||||
HTTP/1.1 204 No Content
|
||||
```
|
||||
|
||||
### Delete Resource
|
||||
|
||||
Delete a resource:
|
||||
|
||||
**Request**:
|
||||
```http
|
||||
DELETE /[ResourceName]('{Key}') HTTP/1.1
|
||||
Host: [host]
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```http
|
||||
DELETE /Employees('E12345') HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
**Response** (204 No Content):
|
||||
```http
|
||||
HTTP/1.1 204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **Parent Service**: [Service Name](#[service-anchor])
|
||||
- **Detailed Operations**:
|
||||
- [Create](#odata-operation-create)
|
||||
- [Read](#odata-operation-read)
|
||||
- [Update](#odata-operation-update)
|
||||
- [Delete](#odata-operation-delete)
|
||||
- **Related Resources**: [Other Resource Name](#)
|
||||
|
||||
---
|
||||
|
||||
**Template Version**: 1.0
|
||||
**Last Updated**: 2025-11-21
|
||||
**Compliance**: SAP API Style Guide Section 50
|
||||
Reference in New Issue
Block a user