Add unit tests for invoicing, orders normalization, gateway commands, and department complaints. Update schema bootstraps and improve agent command execution logic.

This commit is contained in:
Jeppe Bundgaard
2026-04-09 12:24:22 +02:00
parent 9e9372db05
commit 22f856c62a
35 changed files with 2346 additions and 167 deletions
+516 -11
View File
@@ -901,14 +901,16 @@ paths:
summary: Process inbound Bird voice call lifecycle
operationId: birdInboundVoiceCallWebhook
description: >
Stateful inbound-call webhook that answers the call immediately, tracks DTMF input, and enforces a timeout hangup flow.
During the first 300 seconds from call start, DTMF input is extracted from fixed payload fields
(`dtmf`, `digit`, `digits`, `keys`, and known nested variants). A Slack message is sent whenever any DTMF
value is captured, the call acknowledges input, and gather is re-issued with retry-loop semantics
checking for input every 2 seconds until a digit is entered. At or after 300 seconds, the webhook
says `timeout reached`, waits 10
seconds, sends a hangup command once, and polls Bird call status until terminal. Call lifecycle
state is only finalized and cleared after terminal status is observed.
Stateful inbound-call webhook that answers the call immediately, runs a DTMF-driven IVR for
phone-controlled entrance and exit gates, and enforces a timeout hangup flow. During the
first 300 seconds from call start, DTMF input is extracted from payload fields such as
`dtmf`, `digit`, `digits`, `keys`, `result.keys`, and nested `conditions[].value`. Values
like `1#` are normalized to a single menu digit before the route resolves the department
selection and then the gate type selection (`1=entrance`, `2=exit`). When a valid gate is
resolved, the webhook triggers the corresponding `department_gates` phone-call gate, announces
the result, sends a hangup command, and keeps the completed state cached until Bird reports a
terminal call status. At or after 300 seconds, the webhook says `timeout reached`, waits 10
seconds, sends a hangup command once, and polls Bird call status until terminal.
parameters:
- in: query
name: workspaceId
@@ -9878,6 +9880,33 @@ paths:
'403':
$ref: '#/components/responses/Forbidden'
/superuser/system/status:
get:
tags:
- Superuser
summary: Aggregated system status snapshot
description: Returns a read-only snapshot of runtime health, dependency connectivity, module configuration/probe status, and active user session activity for the superuser dashboard.
operationId: getSuperuserSystemStatus
parameters:
- in: query
name: force
required: false
schema:
type: boolean
default: false
description: Bypass cached external module probes for this request.
responses:
'200':
description: System status snapshot returned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SuperuserSystemStatusResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
# Configuration Endpoints
/economic/config:
get:
@@ -10938,6 +10967,127 @@ paths:
application/json:
schema: {}
/departments/daily-reports/complaints:
get:
tags:
- Departments
summary: List or fetch daily report customer complaints
operationId: listDailyReportComplaints
parameters:
- name: id
in: query
required: false
schema: {type: integer}
- name: page
in: query
required: false
schema: {type: integer}
- name: limit
in: query
required: false
schema: {type: integer}
- name: search
in: query
required: false
schema: {type: string}
- name: filters
in: query
required: false
schema: {type: string}
- name: order
in: query
required: false
schema: {type: string}
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintCollectionResponse'
post:
tags:
- Departments
summary: Create daily report customer complaint
operationId: createDailyReportComplaint
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintCreateRequest'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintResponse'
put:
tags:
- Departments
summary: Update daily report customer complaint
operationId: updateDailyReportComplaint
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintUpdateRequest'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintResponse'
delete:
tags:
- Departments
summary: Delete daily report customer complaint
operationId: deleteDailyReportComplaint
parameters:
- name: id
in: query
required: true
schema: {type: integer}
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintDeleteResponse'
/departments/daily-reports/complaints/customers:
get:
tags:
- Departments
summary: Search selectable customers for daily report complaints
operationId: searchDailyReportComplaintCustomers
parameters:
- name: search
in: query
required: true
schema:
type: string
minLength: 2
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 20
default: 10
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/DepartmentDailyReportComplaintCustomerSearchResponse'
/departments/daily-reports/product-count:
get:
tags:
@@ -11262,6 +11412,245 @@ components:
type: integer
description: HTTP status code
SuperuserSystemStatusResponse:
type: object
properties:
success:
type: boolean
data:
$ref: '#/components/schemas/SuperuserSystemStatusPayload'
meta:
type: object
additionalProperties: true
includes:
type: object
additionalProperties: true
required:
- success
- data
- meta
- includes
SuperuserSystemStatusPayload:
type: object
properties:
overall_status:
$ref: '#/components/schemas/SuperuserSystemStatusEnum'
generated_at:
type: string
format: date-time
refresh_after_seconds:
type: integer
runtime:
type: object
properties:
cpu:
$ref: '#/components/schemas/SuperuserRuntimeMetric'
memory:
$ref: '#/components/schemas/SuperuserRuntimeMetric'
disk:
$ref: '#/components/schemas/SuperuserRuntimeMetric'
dependencies:
type: object
properties:
database:
$ref: '#/components/schemas/SuperuserDependencyStatus'
redis:
$ref: '#/components/schemas/SuperuserDependencyStatus'
minio:
$ref: '#/components/schemas/SuperuserMinioDependencyStatus'
modules:
type: array
items:
$ref: '#/components/schemas/SuperuserModuleStatus'
sessions:
$ref: '#/components/schemas/SuperuserSessionStatus'
warnings:
type: array
items:
type: string
required:
- overall_status
- generated_at
- refresh_after_seconds
- runtime
- dependencies
- modules
- sessions
- warnings
SuperuserSystemStatusEnum:
type: string
enum: [ok, degraded, down]
SuperuserModuleStatusEnum:
type: string
enum: [disabled, not_configured, configured, ok, degraded, down]
SuperuserRuntimeMetric:
type: object
properties:
status:
$ref: '#/components/schemas/SuperuserSystemStatusEnum'
usage_percent:
type: number
format: float
nullable: true
used_bytes:
type: integer
nullable: true
free_bytes:
type: integer
nullable: true
total_bytes:
type: integer
nullable: true
path:
type: string
nullable: true
source:
type: string
nullable: true
checked_at:
type: string
format: date-time
SuperuserDependencyStatus:
type: object
properties:
status:
$ref: '#/components/schemas/SuperuserSystemStatusEnum'
latency_ms:
type: number
format: float
nullable: true
database:
oneOf:
- type: integer
- type: string
nullable: true
server_version:
type: string
nullable: true
http_status:
type: integer
nullable: true
checked_at:
type: string
format: date-time
error:
type: string
nullable: true
SuperuserMinioDependencyStatus:
type: object
properties:
status:
$ref: '#/components/schemas/SuperuserSystemStatusEnum'
latency_ms:
type: number
format: float
nullable: true
endpoint:
type: string
nullable: true
http_status:
type: integer
nullable: true
buckets:
type: array
items:
type: object
properties:
name:
type: string
status:
type: string
error:
type: string
nullable: true
checked_at:
type: string
format: date-time
error:
type: string
nullable: true
SuperuserModuleStatus:
type: object
properties:
key:
type: string
enabled:
type: boolean
configured:
type: boolean
probe_supported:
type: boolean
status:
$ref: '#/components/schemas/SuperuserModuleStatusEnum'
status_reason:
type: string
nullable: true
checked_at:
type: string
format: date-time
required:
- key
- enabled
- configured
- probe_supported
- status
- checked_at
SuperuserSessionStatus:
type: object
properties:
active_window_minutes:
type: integer
active_users:
type: integer
active_sessions:
type: integer
recent_sessions:
type: array
items:
type: object
properties:
session_kind:
type: string
principal_id:
type: integer
display_name:
type: string
context_label:
type: string
nullable: true
customer_number_context:
type: integer
nullable: true
device_type:
type: string
user_agent:
type: string
last_route:
type: string
first_seen_at:
type: string
format: date-time
nullable: true
last_seen_at:
type: string
format: date-time
nullable: true
active:
type: boolean
required:
- active_window_minutes
- active_users
- active_sessions
- recent_sessions
SystemSearchEntityType:
type: string
enum:
@@ -16077,16 +16466,20 @@ components:
example: ongoing
dtmf:
type: string
description: DTMF value when present
description: DTMF value when present, for example `1` or `1#`
example: "5"
digit:
type: string
description: Alternate DTMF field
description: Alternate DTMF field, also accepts values such as `1#`
example: "5"
digits:
type: string
description: Alternate DTMF field
example: "5"
keys:
type: string
description: Alternate DTMF field returned by gather results
example: "1#"
call:
type: object
additionalProperties: true
@@ -16110,7 +16503,11 @@ components:
properties:
phase:
type: string
enum: [lock_not_acquired, input_window, timeout_window, terminal_completion]
enum: [lock_not_acquired, input_window, timeout_window, completed, terminal_completion]
stage:
type: string
nullable: true
enum: [department_select, gate_type_select, completed]
call_id:
type: string
example: "4015cf84-8028-46a1-a0d9-9213e5bf4f09"
@@ -16131,6 +16528,19 @@ components:
last_input:
type: string
nullable: true
selected_department_id:
type: integer
nullable: true
selected_gate_type:
type: string
nullable: true
enum: [entrance, exit]
gate_id:
type: integer
nullable: true
gate_opened:
type: boolean
nullable: true
answered_at:
type: integer
nullable: true
@@ -16616,6 +17026,101 @@ components:
type: array
items: { type: integer }
DepartmentDailyReportComplaintCreateRequest:
type: object
required: [department_id, description]
properties:
department_id: { type: integer }
customer_number:
type: integer
nullable: true
description:
type: string
minLength: 1
maxLength: 4000
DepartmentDailyReportComplaintUpdateRequest:
type: object
required: [id]
properties:
id: { type: integer }
department_id: { type: integer }
customer_number:
type: integer
nullable: true
description:
type: string
minLength: 1
maxLength: 4000
DepartmentDailyReportComplaintCustomerSearchResult:
type: object
properties:
customer_number:
type: integer
customer_name:
type: string
nullable: true
DepartmentDailyReportComplaint:
type: object
properties:
id: { type: integer }
department_id: { type: integer }
department_name:
type: string
nullable: true
customer_number:
type: integer
nullable: true
customer_name:
type: string
nullable: true
description: { type: string }
created_by: { type: integer }
created_by_name:
type: string
nullable: true
created_at:
type: string
format: date-time
DepartmentDailyReportComplaintResponse:
type: object
properties:
success: { type: boolean, example: true }
data:
$ref: '#/components/schemas/DepartmentDailyReportComplaint'
DepartmentDailyReportComplaintCollectionResponse:
type: object
properties:
success: { type: boolean, example: true }
data:
oneOf:
- $ref: '#/components/schemas/DepartmentDailyReportComplaint'
- type: array
items:
$ref: '#/components/schemas/DepartmentDailyReportComplaint'
DepartmentDailyReportComplaintCustomerSearchResponse:
type: object
properties:
success: { type: boolean, example: true }
data:
type: array
items:
$ref: '#/components/schemas/DepartmentDailyReportComplaintCustomerSearchResult'
DepartmentDailyReportComplaintDeleteResponse:
type: object
properties:
success: { type: boolean, example: true }
data:
type: object
properties:
message: { type: string }
DepartmentDailyReportProductTile:
type: object
properties: