Add unit tests and routes for department weather targets, including GET/PUT endpoints, thresholds validation, and aggregate status handling. Extend OpenAPI spec with schema mappings for department weather targets and machine relay endpoints.

This commit is contained in:
Jeppe Bundgaard
2026-03-25 11:14:25 +01:00
parent 6fdc8d466e
commit 7fc70184df
16 changed files with 1765 additions and 88 deletions
+244 -2
View File
@@ -7366,6 +7366,80 @@ paths:
'403':
$ref: '#/components/responses/Forbidden'
/modules/self-serve/lane/relay/machine/status:
get:
tags:
- Modules
summary: Get MACHINE relay status for a lane
description: |
Reads the current Shelly MACHINE relay status (`on`/`off`) for the given lane.
operationId: getSelfServeLaneMachineRelayStatus
parameters:
- name: lane_id
in: query
required: true
schema:
type: integer
responses:
'200':
description: MACHINE relay status retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/SelfServeLaneMachineRelayStatus'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/modules/self-serve/lane/relay/machine/set:
post:
tags:
- Modules
summary: Set MACHINE relay status for a lane
description: |
Sets the Shelly MACHINE relay state for the lane to on or off and returns the latest status.
operationId: setSelfServeLaneMachineRelayStatus
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- lane_id
- on
properties:
lane_id:
type: integer
on:
type: boolean
responses:
'200':
description: MACHINE relay status updated
content:
application/json:
schema:
type: object
properties:
lane_id:
type: integer
relay:
type: string
enum: [MACHINE]
requested_on:
type: boolean
relay_id:
type: string
online:
type: boolean
on:
type: boolean
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/modules/self-serve/lane/relay/machine/enable:
post:
tags:
@@ -7798,7 +7872,7 @@ paths:
tags:
- Departments
summary: Get department weather timeline
description: Returns hourly weather, washes, Workfeed employee-hours, and productivity status aggregated across selected departments (server local time). Default range is start of yesterday (`00:00`) to end of today (`23:00`). Use `date_from` and `date_to` (`YYYY-MM-DD`) together to override the range. If department coordinates are missing/invalid or WeatherAPI cannot resolve the location, weather data falls back silently and timeline slots default to `mostly_clear`.
description: Returns hourly weather, washes, Workfeed employee-hours, and productivity status aggregated across selected departments (server local time). Default range is start of yesterday (`00:00`) to end of today (`23:00`). Use `date_from` and `date_to` (`YYYY-MM-DD`) together to override the range. If department coordinates are missing/invalid or WeatherAPI cannot resolve the location, weather data falls back silently and timeline slots default to `mostly_clear`. Slots return `unknown` status when they have no evaluable employee-hours or when one or more selected departments are missing department weather targets.
operationId: getDepartmentWeatherTimeline
parameters:
- name: id
@@ -7863,6 +7937,100 @@ paths:
washes: 0
hours: 2.5
status: unhealthy
- date: '2026-03-24'
time: '14:00'
current: false
weather: mostly_clear
washes: 0
hours: 1.0
status: unknown
/departments/weather/targets:
get:
tags:
- Departments
summary: Get department weather status targets
description: Returns department-specific weather productivity thresholds used by `/departments/weather` to classify `healthy`, `degraded`, and `unhealthy` statuses.
operationId: getDepartmentWeatherTargets
parameters:
- name: id
in: query
required: false
schema:
type: array
items:
type: integer
minimum: 1
minItems: 1
uniqueItems: true
style: form
explode: true
description: Department ID list. Repeat `id` to select multiple departments (`?id=1&id=2`).
- name: ids
in: query
required: false
schema:
type: string
example: '1,2,3'
description: Optional CSV alternative for department IDs. Merged with `id` if both are provided. At least one of `id` or `ids` must be provided.
responses:
'200':
description: Department weather targets retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentWeatherTargetsResponse'
example:
success: true
meta: []
includes: []
data:
- department_id: 1
degraded_threshold: 1.0
healthy_threshold: 1.3
configured: true
- department_id: 2
degraded_threshold: null
healthy_threshold: null
configured: false
put:
tags:
- Departments
summary: Upsert department weather status targets
description: Creates or updates the weather productivity thresholds for one department. `healthy_threshold` must be greater than or equal to `degraded_threshold`.
operationId: upsertDepartmentWeatherTarget
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentWeatherTargetUpsertRequest'
example:
department_id: 1
degraded_threshold: 1.0
healthy_threshold: 1.3
responses:
'200':
description: Department weather targets updated successfully
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ModuleConfigEnvelopeBase'
- type: object
properties:
data:
$ref: '#/components/schemas/DepartmentWeatherTarget'
required: [data]
example:
success: true
meta: []
includes: []
data:
department_id: 1
degraded_threshold: 1.0
healthy_threshold: 1.3
configured: true
/modules/entra/users:
get:
@@ -10455,13 +10623,49 @@ components:
DepartmentWeatherStatus:
type: string
description: Productivity health for the slot. `unknown` is returned when the slot has not started yet or has no employee-hours.
description: Productivity health for the slot. `unknown` is returned when the slot has not started yet, has no employee-hours, or one or more selected departments are missing department weather targets.
enum: [unknown, healthy, degraded, unhealthy]
DepartmentWeatherCondition:
type: string
enum: [clear, mostly_clear, partly_cloudy, mostly_cloudy, overcast, rain, showers, thunderstorm, snow, fog]
DepartmentWeatherTarget:
type: object
properties:
department_id:
type: integer
minimum: 1
degraded_threshold:
type: number
nullable: true
minimum: 0
description: Minimum washes per hour ratio required for `degraded`. `null` when target is not configured.
healthy_threshold:
type: number
nullable: true
minimum: 0
description: Minimum washes per hour ratio required for `healthy`. `null` when target is not configured.
configured:
type: boolean
description: Whether both weather status thresholds are configured and valid for the department.
required: [department_id, degraded_threshold, healthy_threshold, configured]
DepartmentWeatherTargetUpsertRequest:
type: object
required: [department_id, degraded_threshold, healthy_threshold]
properties:
department_id:
type: integer
minimum: 1
degraded_threshold:
type: number
minimum: 0
healthy_threshold:
type: number
minimum: 0
description: Must be greater than or equal to `degraded_threshold`.
DepartmentWeatherTimelineEntry:
type: object
properties:
@@ -10665,6 +10869,17 @@ components:
$ref: '#/components/schemas/DepartmentWeatherTimelineEntry'
required: [data]
DepartmentWeatherTargetsResponse:
allOf:
- $ref: '#/components/schemas/ModuleConfigEnvelopeBase'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DepartmentWeatherTarget'
required: [data]
ModuleConfigEntry:
type: object
properties:
@@ -12126,6 +12341,21 @@ components:
description: Customer number associated with the current lane use
nullable: true
SelfServeLaneMachineRelayStatus:
type: object
properties:
lane_id:
type: integer
relay:
type: string
enum: [MACHINE]
relay_id:
type: string
online:
type: boolean
on:
type: boolean
SelfServeConfig:
type: object
properties:
@@ -12799,6 +13029,10 @@ components:
type: string
relay_machine_id:
type: string
relay_machine_program_picker_id:
type: string
relay_machine_cleaner_id:
type: string
dynamic_image_id:
type: integer
nullable: true
@@ -12831,6 +13065,10 @@ components:
type: string
relay_machine_id:
type: string
relay_machine_program_picker_id:
type: string
relay_machine_cleaner_id:
type: string
dynamic_image_id:
type: integer
nullable: true
@@ -12856,6 +13094,10 @@ components:
type: string
relay_machine_id:
type: string
relay_machine_program_picker_id:
type: string
relay_machine_cleaner_id:
type: string
dynamic_image_id:
type: integer
nullable: true