Add comprehensive documentation for Self-Serve Module.

- Describe architecture, domain models, eligibility rules, API endpoints, runtime status, and lane control.
- Include end-to-end examples for happy paths and failure scenarios.
- Provide PHP and Bash usage samples for integration.
- Add detailed flow diagrams and entity definitions for clarity.
This commit is contained in:
Jeppe Bundgaard
2026-03-16 13:08:12 +01:00
parent 16eb2730b8
commit b7b19d1ad9
2 changed files with 1568 additions and 24 deletions
+531 -22
View File
@@ -3257,6 +3257,113 @@ paths:
items:
$ref: '#/components/schemas/DepartmentGuest'
/department/selfserve/machine-types:
get:
tags:
- Self-Serve
summary: List reusable self-serve machine types
operationId: listSelfserveMachineTypes
parameters:
- name: id
in: query
required: false
schema:
type: integer
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PerPageParam'
- $ref: '#/components/parameters/SearchParam'
responses:
'200':
description: Successfully retrieved machine types
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SelfserveMachineType'
- type: array
items:
$ref: '#/components/schemas/SelfserveMachineType'
'404':
$ref: '#/components/responses/NotFound'
post:
tags:
- Self-Serve
summary: Add reusable self-serve machine type
operationId: addSelfserveMachineType
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
description:
type: string
nullable: true
responses:
'200':
description: Successfully added machine type
content:
application/json:
schema:
$ref: '#/components/schemas/SelfserveMachineType'
put:
tags:
- Self-Serve
summary: Update reusable self-serve machine type
operationId: updateSelfserveMachineType
parameters:
- name: id
in: query
required: true
schema:
type: integer
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
description:
type: string
nullable: true
responses:
'200':
description: Successfully updated machine type
content:
application/json:
schema:
$ref: '#/components/schemas/SelfserveMachineType'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags:
- Self-Serve
summary: Delete reusable self-serve machine type
operationId: deleteSelfserveMachineType
parameters:
- name: id
in: query
required: true
schema:
type: integer
responses:
'200':
description: Successfully deleted machine type
content:
application/json:
schema:
type: string
example: Machine type deleted
'404':
$ref: '#/components/responses/NotFound'
/department/selfserve/questions:
get:
tags:
@@ -3307,7 +3414,7 @@ paths:
tags:
- Self-Serve
summary: Add self-serve question
description: Add a new self-serve question.
description: Add a new self-serve question. Questions are typically shared across departments and lanes by omitting department, lane, and product, which default to 0.
operationId: addSelfserveQuestion
requestBody:
required: true
@@ -3316,18 +3423,18 @@ paths:
schema:
type: object
required:
- department
- lane
- product
- question
- description
properties:
department:
type: integer
default: 0
lane:
type: integer
default: 0
product:
type: integer
default: 0
question:
type: string
description:
@@ -3455,6 +3562,16 @@ paths:
description: Filter by condition ID
schema:
type: integer
- name: machine_type_id
in: query
description: Filter by reusable machine type ID
schema:
type: integer
- name: machine_type_id
in: query
description: Filter by reusable machine type ID
schema:
type: integer
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PerPageParam'
- $ref: '#/components/parameters/SearchParam'
@@ -3477,7 +3594,7 @@ paths:
tags:
- Self-Serve
summary: Add self-serve condition
description: Add a new self-serve condition.
description: Add a new self-serve condition. Either provide a reusable machine_type_id or a legacy department/lane/product scope.
operationId: addSelfserveCondition
requestBody:
required: true
@@ -3486,18 +3603,21 @@ paths:
schema:
type: object
required:
- department
- lane
- product
- name
- description
properties:
department:
type: integer
default: 0
lane:
type: integer
default: 0
product:
type: integer
default: 0
machine_type_id:
type: integer
nullable: true
condition_id:
type: integer
nullable: true
@@ -3542,6 +3662,9 @@ paths:
type: integer
product:
type: integer
machine_type_id:
type: integer
nullable: true
condition_id:
type: integer
nullable: true
@@ -3848,7 +3971,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentSelfserveVehicleCondition'
$ref: '#/components/schemas/DepartmentSelfserveVehicleConditionMutationResponse'
'400':
$ref: '#/components/responses/BadRequest'
'500':
@@ -3892,7 +4015,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentSelfserveVehicleCondition'
$ref: '#/components/schemas/DepartmentSelfserveVehicleConditionMutationResponse'
'400':
$ref: '#/components/responses/BadRequest'
'404':
@@ -3919,13 +4042,83 @@ paths:
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Condition deleted
selfserve:
allOf:
- $ref: '#/components/schemas/SelfserveWashSummary'
nullable: true
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
/department/selfserve/vehicle/allowed:
get:
tags:
- Self-Serve
summary: Check whether self-serve is allowed for a vehicle on a lane
operationId: getSelfserveVehicleAllowed
parameters:
- name: lane_id
in: query
required: true
schema:
type: integer
- name: reg
in: query
required: true
schema:
type: string
responses:
'200':
description: Successfully evaluated self-serve eligibility
content:
application/json:
schema:
$ref: '#/components/schemas/SelfserveVehicleAllowedResponse'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/department/selfserve/washes/summary:
get:
tags:
- Self-Serve
summary: Get self-serve wash summary
operationId: getSelfserveWashSummary
parameters:
- name: session_id
in: query
required: false
schema:
type: integer
- name: lane_id
in: query
required: false
schema:
type: integer
- name: reg
in: query
required: false
schema:
type: string
responses:
'200':
description: Successfully retrieved self-serve wash summary
content:
application/json:
schema:
$ref: '#/components/schemas/SelfserveWashSummary'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/department/selfserve/tasks:
get:
tags:
@@ -3981,7 +4174,7 @@ paths:
tags:
- Self-Serve
summary: Add self-serve task
description: Add a new self-serve task.
description: Add a new self-serve task. Either provide a reusable machine_type_id or a legacy department/lane/product scope.
operationId: addSelfserveTask
requestBody:
required: true
@@ -3990,18 +4183,21 @@ paths:
schema:
type: object
required:
- department
- lane
- product
- task
- description
properties:
department:
type: integer
default: 0
lane:
type: integer
default: 0
product:
type: integer
default: 0
machine_type_id:
type: integer
nullable: true
condition_id:
type: integer
nullable: true
@@ -4064,6 +4260,9 @@ paths:
type: integer
product:
type: integer
machine_type_id:
type: integer
nullable: true
condition_id:
type: integer
nullable: true
@@ -6578,19 +6777,59 @@ paths:
get:
tags:
- Plate Scans
summary: Add button press
summary: Record machine start button press webhook
operationId: addButtonPress
parameters:
- name: token
in: query
required: true
required: false
schema: {type: string}
- name: lane_id
in: query
required: false
schema:
type: integer
- name: reg
in: query
required: false
schema:
type: string
responses:
'201':
description: Button press recorded
description: Button press recorded and linked to a self-serve wash session
content:
application/json:
schema: {}
schema:
$ref: '#/components/schemas/MachineButtonPressWebhookResponse'
'404':
$ref: '#/components/responses/NotFound'
post:
tags:
- Plate Scans
summary: Record machine start button press webhook
operationId: addButtonPressPost
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
token:
type: string
lane_id:
type: integer
reg:
type: string
responses:
'201':
description: Button press recorded and linked to a self-serve wash session
content:
application/json:
schema:
$ref: '#/components/schemas/MachineButtonPressWebhookResponse'
'404':
$ref: '#/components/responses/NotFound'
# Module - e-conomic Endpoints
/economic/customers/import:
@@ -7751,7 +7990,7 @@ paths:
tags:
- Search
summary: System-wide search
description: Search across all supported entities with permission-aware filtering and optional intent parsing debug metadata.
description: Search across all supported entities with permission-aware filtering and optional intent parsing debug metadata. Customer records and customer-related entities are matched against a local e-conomic customer index (name/address/email/CVR) that is refreshed by cron. Intent parsing is invoked adaptively when lexical confidence is low or when the query looks intent-driven. Results are ordered by relevance, with recent records preferred when relevance is comparable.
operationId: systemWideSearchGet
parameters:
- in: query
@@ -7759,7 +7998,7 @@ paths:
required: true
schema:
type: string
description: Free-text query to search for.
description: Free-text query to search for. Supports natural-language intent fallback and domain synonyms such as `rabat` -> `discount`.
- in: query
name: include_types
required: false
@@ -7826,7 +8065,7 @@ paths:
tags:
- Search
summary: System-wide search
description: Search across all supported entities using JSON request payload.
description: Search across all supported entities using JSON request payload. Customer-related matches include local e-conomic customer index fields. Intent parsing may run adaptively for intent-driven natural-language queries. Results are ordered by relevance, with recent records preferred when relevance is comparable.
operationId: systemWideSearchPost
requestBody:
required: true
@@ -9224,7 +9463,7 @@ components:
properties:
query:
type: string
description: Free-text query to search for.
description: Free-text query to search for. Customer lookups include local e-conomic index fields and lexical synonym expansion (for example `rabat` -> `discount`).
include_types:
type: array
items:
@@ -11322,6 +11561,257 @@ components:
enum:
- MACHINE
SelfserveMachineType:
type: object
properties:
id:
type: integer
name:
type: string
description:
type: string
nullable: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
nullable: true
SelfserveVisibleQuestion:
type: object
properties:
id:
type: integer
question:
type: string
description:
type: string
condition_id:
type: integer
nullable: true
order_priority:
type: integer
answer:
type: boolean
nullable: true
SelfserveTaskDecision:
type: object
properties:
id:
type: integer
task:
type: string
description:
type: string
condition_id:
type: integer
nullable: true
order_priority:
type: integer
services:
type: array
items:
$ref: '#/components/schemas/SelfserveLaneService'
buttons:
type: array
items:
type: integer
SelfserveWashSession:
type: object
properties:
id:
type: integer
lane_id:
type: integer
department_id:
type: integer
machine_type_id:
type: integer
nullable: true
customer_number:
type: integer
nullable: true
vehicle_id:
type: integer
nullable: true
vehicle_type_id:
type: integer
nullable: true
reg:
type: string
status:
type: string
allowed:
type: boolean
machine_relay_enabled:
type: boolean
machine_relay_enabled_at:
type: string
format: date-time
nullable: true
machine_start_triggered:
type: boolean
machine_start_triggered_at:
type: string
format: date-time
nullable: true
order_id:
type: integer
nullable: true
completed_at:
type: string
format: date-time
nullable: true
metadata:
type: object
additionalProperties: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
nullable: true
SelfserveWashQuestionAnswer:
type: object
properties:
question_id:
type: integer
question:
type: string
answer:
type: boolean
answered_at:
type: string
format: date-time
SelfserveWashTaskSnapshot:
type: object
properties:
task_id:
type: integer
nullable: true
task:
type: string
description:
type: string
nullable: true
services:
type: array
items:
$ref: '#/components/schemas/SelfserveLaneService'
buttons:
type: array
items:
type: integer
SelfserveWashEvent:
type: object
properties:
id:
type: integer
type:
type: string
payload:
type: object
additionalProperties: true
nullable: true
created_at:
type: string
format: date-time
SelfserveVehicleAllowedResponse:
type: object
properties:
lane:
$ref: '#/components/schemas/DepartmentLane'
machine_type:
allOf:
- $ref: '#/components/schemas/SelfserveMachineType'
nullable: true
vehicle:
type: object
additionalProperties: true
nullable: true
reg:
type: string
customer_number:
type: integer
nullable: true
questions:
type: array
items:
$ref: '#/components/schemas/SelfserveVisibleQuestion'
tasks:
type: array
items:
$ref: '#/components/schemas/SelfserveTaskDecision'
allowed_services:
type: array
items:
$ref: '#/components/schemas/SelfserveLaneService'
machine_available:
type: boolean
all_visible_questions_answered:
type: boolean
allowed:
type: boolean
session:
allOf:
- $ref: '#/components/schemas/SelfserveWashSession'
nullable: true
SelfserveWashSummary:
type: object
properties:
session:
$ref: '#/components/schemas/SelfserveWashSession'
lane:
allOf:
- $ref: '#/components/schemas/DepartmentLane'
nullable: true
machine_type:
allOf:
- $ref: '#/components/schemas/SelfserveMachineType'
nullable: true
questions:
type: array
items:
$ref: '#/components/schemas/SelfserveWashQuestionAnswer'
tasks:
type: array
items:
$ref: '#/components/schemas/SelfserveWashTaskSnapshot'
events:
type: array
items:
$ref: '#/components/schemas/SelfserveWashEvent'
DepartmentSelfserveVehicleConditionMutationResponse:
type: object
properties:
condition:
$ref: '#/components/schemas/DepartmentSelfserveVehicleCondition'
selfserve:
$ref: '#/components/schemas/SelfserveWashSummary'
MachineButtonPressWebhookResponse:
type: object
properties:
message:
type: string
scanner:
type: string
lane_id:
type: integer
selfserve:
$ref: '#/components/schemas/SelfserveWashSummary'
DepartmentSelfserveQuestion:
type: object
properties:
@@ -11372,6 +11862,10 @@ components:
product:
type: integer
description: Product ID
machine_type_id:
type: integer
description: Reusable machine type ID
nullable: true
condition_id:
type: integer
description: Condition ID (if conditional task)
@@ -11423,6 +11917,10 @@ components:
product:
type: integer
description: Product ID
machine_type_id:
type: integer
description: Reusable machine type ID
nullable: true
condition_id:
type: integer
description: Optional condition ID
@@ -11722,6 +12220,11 @@ components:
type: integer
nullable: true
minimum: 1
machine_type_id:
type: integer
nullable: true
status:
type: string
created_at:
type: string
format: date-time
@@ -11749,6 +12252,9 @@ components:
type: integer
nullable: true
minimum: 1
machine_type_id:
type: integer
nullable: true
DepartmentLaneUpdate:
type: object
@@ -11771,6 +12277,9 @@ components:
type: integer
nullable: true
minimum: 1
machine_type_id:
type: integer
nullable: true
DepartmentGate:
type: object
+1035
View File
File diff suppressed because it is too large Load Diff