backend phase 8
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
# Contract — Booking requests (backend phase b8)
|
||||
|
||||
> The **pre-payment intent** layer of the engagement lifecycle: a customer requests a nurse; the nurse
|
||||
> accepts/rejects before a config-driven response deadline; on accept a config-driven **30-minute payment
|
||||
> window** opens. **No money and no `bookings` row exist here** — accept only opens the window (conversion is
|
||||
> b9/b10). Assumes [`../conventions/api-conventions.md`](../conventions/api-conventions.md) +
|
||||
> [`../conventions/money-and-types.md`](../conventions/money-and-types.md). Machine schema:
|
||||
> [`../openapi/swagger.v1.json`](../openapi/README.md) (refreshed for b8).
|
||||
|
||||
**Status:** live as of backend-phase-b8 · **Frontend consumer:** frontend-phase-f7-b8
|
||||
|
||||
> **Routing note.** Routes are **action-style** (`[controller]/[action]`, snake_cased). All responses use the
|
||||
> standard `{ succeeded, statusCode, data }` envelope; `data` shapes are below. Request bodies are camelCase.
|
||||
|
||||
## Key semantics (read first)
|
||||
|
||||
- **Two-table split, no money on a request.** A `booking_requests` row never carries a price/total and never
|
||||
creates a booking. Accept moves it to `accepted_awaiting_payment` and opens the payment window; b9 later
|
||||
consumes that and creates the `bookings` row (+ money), setting the request to `converted`.
|
||||
- **Two-stage clinical disclosure (stage 1).** The nurse sees **only** the unencrypted, limited
|
||||
`customer_notes` — never a full clinical/care instruction (those are b9's encrypted, post-confirmation
|
||||
`booking_care_instructions`). The **nurse view of a request masks the full address** (address line / postal
|
||||
code / recipient) and shows only a coarse city/district location; the **customer/admin view** returns the
|
||||
full address.
|
||||
- **Tenancy invariant (enforced at create).** The `patient` and `customer_address` must belong to the caller's
|
||||
customer; the `variant` must belong to the requested `nurse_id`. A mismatch is a clean `404` — never a leak.
|
||||
- **Same-gender match is first-class.** `required_caregiver_gender` (`male`/`female`/`any`) is matched against
|
||||
the nurse's gender at request time. `male`/`female` must equal the nurse's gender; `any` matches either. A
|
||||
mismatch is a `400`. It is required on create and never silently defaulted.
|
||||
- **Deadlines are frozen from config.** `nurse_response_deadline_at` = create-time `now +
|
||||
nurse_response_deadline_hours` (default 24h); `payment_deadline_at` = accept-time `now +
|
||||
booking_payment_deadline_minutes` (**30**). Both are absolute UTC timestamps stored on the row — a later
|
||||
config change never moves an existing request's deadlines.
|
||||
- **Forward-only status machine.** Illegal transitions return `409`. Terminal states
|
||||
(`converted`/`rejected_by_nurse`/`expired_no_response`/`payment_deadline_expired`/`cancelled_by_customer`)
|
||||
have no outgoing edges. An accept after the response deadline, or on a non-pending request, is `409`.
|
||||
- **Auto-expiry.** A background sweep (also an admin manual trigger) moves `pending_nurse_response →
|
||||
expired_no_response` past the response deadline and `accepted_awaiting_payment → payment_deadline_expired`
|
||||
past the payment window, and notifies the customer.
|
||||
- **Timestamps** are UTC ISO-8601. **Ids** are `BIGINT`. **There is no money field anywhere in this domain.**
|
||||
|
||||
## Enums used
|
||||
- `booking_request_status`: `pending_nurse_response` | `accepted_awaiting_payment` | `converted` |
|
||||
`rejected_by_nurse` | `expired_no_response` | `payment_deadline_expired` | `cancelled_by_customer`.
|
||||
- `required_caregiver_gender`: `male` | `female` | `any`.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### `POST api/v1/booking_requests/create`
|
||||
- **Purpose:** a customer requests a nurse for a patient/variant/address/date.
|
||||
- **Auth:** authenticated **customer (owner)** · **Rate-limited:** no · **Idempotency key:** no
|
||||
- **Request body:**
|
||||
```json
|
||||
{
|
||||
"nurseId": 42,
|
||||
"variantId": 8,
|
||||
"patientId": 5,
|
||||
"customerAddressId": 6,
|
||||
"requestedDate": "2026-08-01",
|
||||
"requestedTimeStart": "09:00:00",
|
||||
"requestedTimeEnd": "13:00:00",
|
||||
"requiredCaregiverGender": "female",
|
||||
"customerNotes": "Careful with the IV line."
|
||||
}
|
||||
```
|
||||
- **Success `200` payload (`data`):** a `BookingRequestDto` (customer view — full address), status
|
||||
`pending_nurse_response`, `nurseResponseDeadlineAt` set, `paymentDeadlineAt` null.
|
||||
- **Failure cases:** `400` validation (missing/invalid gender, `requestedTimeEnd ≤ requestedTimeStart`,
|
||||
past date, notes > 1000, inactive variant, nurse not verified/accepting, **same-gender mismatch**);
|
||||
`401` unauthenticated; `403` not a customer / no customer profile; `404` patient/address not owned or
|
||||
variant not the nurse's or nurse absent.
|
||||
- **Side effects:** in-app `booking_request_received` notification to the nurse (`data_json`:
|
||||
`booking_request_id`, `patient_display_name`, `requested_date`).
|
||||
|
||||
### `POST api/v1/booking_requests/accept/{id}`
|
||||
- **Purpose:** the assigned nurse accepts a pending request, opening the 30-minute payment window.
|
||||
- **Auth:** authenticated **nurse (assigned)** · path param `id` (BIGINT).
|
||||
- **Request body:** none.
|
||||
- **Success `200` payload (`data`):** `BookingRequestDto` (nurse view — masked address), status
|
||||
`accepted_awaiting_payment`, `paymentDeadlineAt = now + booking_payment_deadline_minutes` (30 min).
|
||||
- **Failure cases:** `401`; `403` not a nurse; `404` not the caller's request; `409` not pending / already
|
||||
past the response deadline.
|
||||
- **Side effects:** in-app `booking_request_accepted` notification to the customer (`data_json`:
|
||||
`booking_request_id`, `payment_deadline_at`). **No `bookings` row and no money are created.**
|
||||
|
||||
### `POST api/v1/booking_requests/reject/{id}`
|
||||
- **Purpose:** the assigned nurse declines a pending request with a reason.
|
||||
- **Auth:** authenticated **nurse (assigned)** · path param `id`.
|
||||
- **Request body:** `{ "reason": "Fully booked that week." }` (required, ≤ 500 chars).
|
||||
- **Success `200` payload (`data`):** `BookingRequestDto`, status `rejected_by_nurse`, `nurseRejectionReason` set.
|
||||
- **Failure cases:** `400` empty/too-long reason; `401`; `403`; `404`; `409` not pending.
|
||||
- **Side effects:** in-app `booking_request_rejected` notification to the customer.
|
||||
|
||||
### `POST api/v1/booking_requests/cancel/{id}`
|
||||
- **Purpose:** the customer withdraws a request that is still `pending_nurse_response` or
|
||||
`accepted_awaiting_payment` (before paying).
|
||||
- **Auth:** authenticated **customer (owner)** · path param `id`.
|
||||
- **Request body:** none.
|
||||
- **Success `200` payload (`data`):** `BookingRequestDto` (customer view), status `cancelled_by_customer`.
|
||||
- **Failure cases:** `401`; `403`; `404` not owned; `409` request is terminal (converted/rejected/expired).
|
||||
|
||||
### `GET api/v1/booking_requests/list`
|
||||
- **Purpose:** the role-scoped inbox (paginated).
|
||||
- **Auth:** authenticated (customer **or** nurse).
|
||||
- **Query params:** `status` (optional enum filter); `role` (`customer`|`nurse`, optional — disambiguates a
|
||||
user who holds both roles; inferred from the caller's profile when omitted); `page`/`pageSize` (default
|
||||
1 / 50, max 100).
|
||||
- **Success `200` payload (`data`):** `PagedResult<BookingRequestListItemDto>` (`items`, `total`, `page`,
|
||||
`pageSize`). Actionable rows sort first. The **customer** inbox sets `counterpartyName` = nurse name +
|
||||
`nurseRating`; the **nurse** inbox sets `counterpartyName` = patient name + `customerNotes` (stage-1 only).
|
||||
- **Failure cases:** `400` holds both roles and no `role` given; `401`. A caller with neither profile gets an
|
||||
empty page.
|
||||
|
||||
### `GET api/v1/booking_requests/get/{id}`
|
||||
- **Purpose:** a single request.
|
||||
- **Auth:** its **customer** (full address), its **nurse** (masked address), or an **admin** (full).
|
||||
- **Success `200` payload (`data`):** `BookingRequestDto`.
|
||||
- **Failure cases:** `401`; `404` absent **or** caller is neither party nor admin (existence not leaked).
|
||||
|
||||
### `POST api/v1/admin_booking_requests/expire`
|
||||
- **Purpose:** admin/test manual trigger of the expiry sweep (the same command the recurring job runs).
|
||||
- **Auth:** **admin** (`DynamicPermission`) · **Rate-limited:** no.
|
||||
- **Request body:** none.
|
||||
- **Success `200` payload (`data`):** `{ "expiredNoResponse": 0, "paymentDeadlineExpired": 0 }` — counts moved
|
||||
this run (idempotent; re-running on a drained set returns zeros).
|
||||
- **Failure cases:** `401`; `403` non-admin.
|
||||
|
||||
## Shared shapes
|
||||
|
||||
- `BookingRequestDto` (full single-request view):
|
||||
`id` (long), `status` (enum), `nurseId` (long), `nurseName` (string), `nurseRating` (decimal),
|
||||
`nurseTotalReviews` (int), `patientId` (long), `patientName` (string), `variantId` (long),
|
||||
`variantLabel` (string), `variantPriceUnit` (string), `customerAddressId` (long), `addressTitle` (string),
|
||||
`cityId` (long), `cityNameFa`/`cityNameEn` (string), `districtId` (long?, null = whole city),
|
||||
`districtNameFa`/`districtNameEn` (string?), `addressLine`/`postalCode`/`recipientName`/`recipientPhone`
|
||||
(string?, **null in the nurse view** — masked), `requiredCaregiverGender` (enum?), `requestedDate` (date),
|
||||
`requestedTimeStart`/`requestedTimeEnd` (time), `customerNotes` (string?, stage-1 plaintext),
|
||||
`nurseResponseDeadlineAt` (UTC datetime), `paymentDeadlineAt` (UTC datetime?, null until accept),
|
||||
`nurseRejectionReason` (string?), `createdAt` (UTC datetime).
|
||||
- `BookingRequestListItemDto` (inbox row):
|
||||
`id`, `status`, `counterpartyName` (nurse name for customer view / patient name for nurse view),
|
||||
`nurseRating` (decimal?, customer view only), `requiredCaregiverGender` (enum?), `requestedDate`,
|
||||
`requestedTimeStart`, `requestedTimeEnd`, `nurseResponseDeadlineAt`, `paymentDeadlineAt`,
|
||||
`customerNotes` (string?, **nurse view only**).
|
||||
- `ExpireBookingRequestsResult`: `expiredNoResponse` (int), `paymentDeadlineExpired` (int).
|
||||
|
||||
## Changelog
|
||||
- b8 — initial contract (create/accept/reject/cancel + role-scoped list + single get + admin expire).
|
||||
@@ -7,10 +7,75 @@
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://localhost"
|
||||
"url": "https://localhost:5002"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/api/v1/admin_booking_requests/expire": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"AdminBookingRequests"
|
||||
],
|
||||
"operationId": "AdminBookingRequests_Expire",
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfExpireBookingRequestsResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/admin_catalog/create_category": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -2484,6 +2549,510 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/create": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"summary": "Creates a BookingRequest",
|
||||
"operationId": "BookingRequests_Create",
|
||||
"requestBody": {
|
||||
"x-name": "command",
|
||||
"description": "A BookingRequest representation",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateBookingRequestCommand"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"x-position": 1
|
||||
},
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfBookingRequestDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/cancel/{id}": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"operationId": "BookingRequests_Cancel",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"x-position": 1
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfBookingRequestDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/accept/{id}": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"operationId": "BookingRequests_Accept",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"x-position": 1
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfBookingRequestDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/reject/{id}": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"operationId": "BookingRequests_Reject",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"x-position": 1
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"x-name": "command",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RejectBookingRequestCommand"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"x-position": 2
|
||||
},
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfBookingRequestDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/list": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"operationId": "BookingRequests_List",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Status",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"x-position": 1
|
||||
},
|
||||
{
|
||||
"name": "Role",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"x-position": 2
|
||||
},
|
||||
{
|
||||
"name": "Page",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"x-position": 3
|
||||
},
|
||||
{
|
||||
"name": "PageSize",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"x-position": 4
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfPagedResultOfBookingRequestListItemDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/booking_requests/get/{id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"BookingRequests"
|
||||
],
|
||||
"summary": "Retrieves a BookingRequest by unique id",
|
||||
"operationId": "BookingRequests_Get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "A unique id for the BookingRequest",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"x-position": 1
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfDictionaryOfStringAndListOfString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResultOfBookingRequestDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/catalog/categories": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3786,7 +4355,7 @@
|
||||
"tags": [
|
||||
"Me"
|
||||
],
|
||||
"description": "Role claims live inside the access token \u2014 after selecting a role the client should\n refresh its tokens to pick the new role up.",
|
||||
"description": "Role claims live inside the access token — after selecting a role the client should\n refresh its tokens to pick the new role up.",
|
||||
"operationId": "Me_SelectRole",
|
||||
"requestBody": {
|
||||
"x-name": "command",
|
||||
@@ -7200,6 +7769,41 @@
|
||||
500
|
||||
]
|
||||
},
|
||||
"ApiResultOfExpireBookingRequestsResult": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"data": {
|
||||
"nullable": true,
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ExpireBookingRequestsResult"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ExpireBookingRequestsResult": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"expiredNoResponse": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"paymentDeadlineExpired": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApiResultOfServiceCategoryDto": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -8578,6 +9182,306 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApiResultOfBookingRequestDto": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"data": {
|
||||
"nullable": true,
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingRequestDto"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"BookingRequestDto": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"nurseId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"nurseName": {
|
||||
"type": "string"
|
||||
},
|
||||
"nurseRating": {
|
||||
"type": "number",
|
||||
"format": "decimal"
|
||||
},
|
||||
"nurseTotalReviews": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"patientId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"patientName": {
|
||||
"type": "string"
|
||||
},
|
||||
"variantId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"variantLabel": {
|
||||
"type": "string"
|
||||
},
|
||||
"variantPriceUnit": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAddressId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"addressTitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"cityId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"cityNameFa": {
|
||||
"type": "string"
|
||||
},
|
||||
"cityNameEn": {
|
||||
"type": "string"
|
||||
},
|
||||
"districtId": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"nullable": true
|
||||
},
|
||||
"districtNameFa": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"districtNameEn": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"addressLine": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"postalCode": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"recipientName": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"recipientPhone": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"requiredCaregiverGender": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"requestedDate": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"requestedTimeStart": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"requestedTimeEnd": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"customerNotes": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"nurseResponseDeadlineAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"paymentDeadlineAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"nurseRejectionReason": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateBookingRequestCommand": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"nurseId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"variantId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"patientId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"customerAddressId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"requestedDate": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"requestedTimeStart": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"requestedTimeEnd": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"requiredCaregiverGender": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerNotes": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"RejectBookingRequestCommand": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApiResultOfPagedResultOfBookingRequestListItemDto": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ApiResult"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"data": {
|
||||
"nullable": true,
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/PagedResultOfBookingRequestListItemDto"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"PagedResultOfBookingRequestListItemDto": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"nullable": true,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/BookingRequestListItemDto"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"page": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"BookingRequestListItemDto": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"counterpartyName": {
|
||||
"type": "string"
|
||||
},
|
||||
"nurseRating": {
|
||||
"type": "number",
|
||||
"format": "decimal",
|
||||
"nullable": true
|
||||
},
|
||||
"requiredCaregiverGender": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"requestedDate": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"requestedTimeStart": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"requestedTimeEnd": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"nurseResponseDeadlineAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"paymentDeadlineAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"customerNotes": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApiResultOfPagedResultOfServiceCategoryDto": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user