crisphive 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +183 -16
- data/crisphive.gemspec +5 -5
- data/lib/crisphive/api/business_skill_api.rb +502 -8
- data/lib/crisphive/api/customer_api.rb +20 -14
- data/lib/crisphive/api/job_request_business_api.rb +1273 -167
- data/lib/crisphive/api/job_types_api.rb +214 -2
- data/lib/crisphive/api/permission_api.rb +79 -0
- data/lib/crisphive/api/service_area_api.rb +214 -6
- data/lib/crisphive/api/technician_api.rb +510 -6
- data/lib/crisphive/api/technician_time_off_api.rb +240 -0
- data/lib/crisphive/api/vehicle_api.rb +214 -6
- data/lib/crisphive/api/webhooks_api.rb +213 -0
- data/lib/crisphive/api_client.rb +2 -2
- data/lib/crisphive/api_error.rb +2 -2
- data/lib/crisphive/configuration.rb +3 -3
- data/lib/crisphive/models/api_internal_techtimeoff_actions.rb +232 -0
- data/lib/crisphive/models/api_internal_techtimeoff_status.rb +42 -0
- data/lib/crisphive/models/assignable_group.rb +289 -0
- data/lib/crisphive/models/book_and_confirm_job_request200_response.rb +253 -0
- data/lib/crisphive/models/commit_absence_resolve200_response.rb +253 -0
- data/lib/crisphive/models/commit_emergency_reschedule200_response.rb +253 -0
- data/lib/crisphive/models/commit_job_request_move200_response.rb +253 -0
- data/lib/crisphive/models/create_customer200_response.rb +5 -2
- data/lib/crisphive/models/create_job_request200_response.rb +5 -2
- data/lib/crisphive/models/create_job_type200_response.rb +253 -0
- data/lib/crisphive/models/create_service_area200_response.rb +253 -0
- data/lib/crisphive/models/create_skill200_response.rb +253 -0
- data/lib/crisphive/models/create_skill_category200_response.rb +253 -0
- data/lib/crisphive/models/create_technician200_response.rb +253 -0
- data/lib/crisphive/models/create_technician_time_off200_response.rb +253 -0
- data/lib/crisphive/models/create_vehicle200_response.rb +253 -0
- data/lib/crisphive/models/create_webhook_endpoint200_response.rb +253 -0
- data/lib/crisphive/models/customer.rb +13 -3
- data/lib/crisphive/models/customer_address.rb +2 -2
- data/lib/crisphive/models/customer_address_request.rb +11 -2
- data/lib/crisphive/models/customer_contact.rb +27 -7
- data/lib/crisphive/models/customer_create_request.rb +14 -4
- data/lib/crisphive/models/customer_create_response.rb +2 -2
- data/lib/crisphive/models/customer_list.rb +3 -3
- data/lib/crisphive/models/customer_list_item.rb +13 -3
- data/lib/crisphive/models/customer_profile.rb +2 -2
- data/lib/crisphive/models/customer_quick_books_link.rb +235 -0
- data/lib/crisphive/models/customer_service_area_ref.rb +225 -0
- data/lib/crisphive/models/customer_spending.rb +2 -2
- data/lib/crisphive/models/customer_technician_ref.rb +225 -0
- data/lib/crisphive/models/customer_tier_progress.rb +2 -2
- data/lib/crisphive/models/customer_update_request.rb +25 -22
- data/lib/crisphive/models/get_customer200_response.rb +5 -2
- data/lib/crisphive/models/get_job_request200_response.rb +5 -2
- data/lib/crisphive/models/get_job_request_timeline200_response.rb +5 -2
- data/lib/crisphive/models/get_job_type200_response.rb +5 -2
- data/lib/crisphive/models/get_service_area200_response.rb +5 -2
- data/lib/crisphive/models/get_technician200_response.rb +5 -2
- data/lib/crisphive/models/get_technician_schedule200_response.rb +253 -0
- data/lib/crisphive/models/get_vehicle200_response.rb +5 -2
- data/lib/crisphive/models/internal_jobrequest_http_address_req.rb +475 -0
- data/lib/crisphive/models/job_date.rb +5 -3
- data/lib/crisphive/models/job_date_business_range.rb +7 -3
- data/lib/crisphive/models/job_date_period.rb +2 -2
- data/lib/crisphive/models/job_date_period_entry.rb +4 -2
- data/lib/crisphive/models/job_request.rb +56 -6
- data/lib/crisphive/models/job_request_absence_alternative.rb +356 -0
- data/lib/crisphive/models/job_request_absence_alternative_cost.rb +275 -0
- data/lib/crisphive/models/job_request_absence_assignment.rb +319 -0
- data/lib/crisphive/models/job_request_absence_commit_request.rb +296 -0
- data/lib/crisphive/models/job_request_absence_notification.rb +283 -0
- data/lib/crisphive/models/job_request_absence_plan.rb +322 -0
- data/lib/crisphive/models/job_request_absence_preview_request.rb +280 -0
- data/lib/crisphive/models/job_request_absence_resolved_job.rb +499 -0
- data/lib/crisphive/models/job_request_absence_solver.rb +289 -0
- data/lib/crisphive/models/job_request_absence_time_off.rb +281 -0
- data/lib/crisphive/models/job_request_absence_unresolved_job.rb +364 -0
- data/lib/crisphive/models/job_request_action_audit_by.rb +2 -2
- data/lib/crisphive/models/job_request_action_audit_entry.rb +3 -3
- data/lib/crisphive/models/job_request_action_summary.rb +3 -3
- data/lib/crisphive/models/job_request_address_summary.rb +2 -2
- data/lib/crisphive/models/job_request_archive_summary.rb +2 -2
- data/lib/crisphive/models/job_request_arrival_window.rb +4 -4
- data/lib/crisphive/models/job_request_assigned_vehicle.rb +2 -2
- data/lib/crisphive/models/job_request_assignment_summary.rb +2 -2
- data/lib/crisphive/models/job_request_attention_summary.rb +259 -0
- data/lib/crisphive/models/job_request_available_vehicle.rb +235 -0
- data/lib/crisphive/models/job_request_blocker.rb +363 -0
- data/lib/crisphive/models/job_request_blocker_ref.rb +223 -0
- data/lib/crisphive/models/job_request_book_and_confirm_customer.rb +302 -0
- data/lib/crisphive/models/job_request_book_and_confirm_emergency.rb +315 -0
- data/lib/crisphive/models/job_request_book_and_confirm_emergency_result.rb +279 -0
- data/lib/crisphive/models/job_request_book_and_confirm_refusal.rb +280 -0
- data/lib/crisphive/models/job_request_book_and_confirm_request.rb +466 -0
- data/lib/crisphive/models/job_request_book_and_confirm_response.rb +295 -0
- data/lib/crisphive/models/job_request_booking_windows.rb +2 -2
- data/lib/crisphive/models/job_request_buddy_slot_candidates.rb +239 -0
- data/lib/crisphive/models/job_request_business_time_range.rb +3 -3
- data/lib/crisphive/models/job_request_changes.rb +2 -2
- data/lib/crisphive/models/job_request_confirm_request.rb +255 -0
- data/lib/crisphive/models/job_request_create_request.rb +61 -7
- data/lib/crisphive/models/job_request_create_response.rb +2 -2
- data/lib/crisphive/models/job_request_crew_candidates.rb +227 -0
- data/lib/crisphive/models/job_request_crew_change.rb +299 -0
- data/lib/crisphive/models/job_request_crew_member.rb +7 -4
- data/lib/crisphive/models/job_request_crew_member_input.rb +284 -0
- data/lib/crisphive/models/job_request_crew_recommendation.rb +255 -0
- data/lib/crisphive/models/job_request_customer_summary.rb +2 -2
- data/lib/crisphive/models/job_request_day_windows.rb +3 -3
- data/lib/crisphive/models/job_request_emergency_candidate.rb +319 -0
- data/lib/crisphive/models/job_request_emergency_candidates.rb +311 -0
- data/lib/crisphive/models/job_request_emergency_candidates_request.rb +341 -0
- data/lib/crisphive/models/job_request_emergency_commit_request.rb +361 -0
- data/lib/crisphive/models/job_request_emergency_inline_job.rb +353 -0
- data/lib/crisphive/models/job_request_emergency_plan.rb +367 -0
- data/lib/crisphive/models/job_request_emergency_preview_request.rb +342 -0
- data/lib/crisphive/models/job_request_job_date_business_range_request.rb +3 -3
- data/lib/crisphive/models/job_request_job_date_period_request.rb +2 -2
- data/lib/crisphive/models/job_request_job_date_request.rb +3 -3
- data/lib/crisphive/models/job_request_lead_candidate.rb +311 -0
- data/lib/crisphive/models/job_request_list.rb +2 -2
- data/lib/crisphive/models/job_request_move_commit_req.rb +353 -0
- data/lib/crisphive/models/job_request_move_member.rb +299 -0
- data/lib/crisphive/models/job_request_move_plan.rb +387 -0
- data/lib/crisphive/models/job_request_move_preview_req.rb +300 -0
- data/lib/crisphive/models/job_request_move_warning.rb +335 -0
- data/lib/crisphive/models/job_request_period.rb +2 -2
- data/lib/crisphive/models/job_request_priority_update_result.rb +217 -0
- data/lib/crisphive/models/job_request_quote_request.rb +343 -0
- data/lib/crisphive/models/job_request_quote_summary.rb +2 -2
- data/lib/crisphive/models/job_request_rating_summary.rb +2 -2
- data/lib/crisphive/models/job_request_reassign_fallback.rb +287 -0
- data/lib/crisphive/models/job_request_reschedule_day.rb +227 -0
- data/lib/crisphive/models/job_request_reschedule_move.rb +319 -0
- data/lib/crisphive/models/job_request_reschedule_reassignment.rb +339 -0
- data/lib/crisphive/models/job_request_schedule.rb +2 -2
- data/lib/crisphive/models/job_request_session.rb +8 -7
- data/lib/crisphive/models/job_request_skill_summary.rb +3 -3
- data/lib/crisphive/models/job_request_status_summary.rb +3 -3
- data/lib/crisphive/models/job_request_tech_candidate.rb +287 -0
- data/lib/crisphive/models/job_request_technician_info.rb +2 -2
- data/lib/crisphive/models/job_request_time_segments.rb +287 -0
- data/lib/crisphive/models/job_request_time_segments_business_time.rb +321 -0
- data/lib/crisphive/models/job_request_time_segments_day.rb +247 -0
- data/lib/crisphive/models/job_request_time_segments_slot.rb +375 -0
- data/lib/crisphive/models/job_request_time_segments_worker.rb +295 -0
- data/lib/crisphive/models/job_request_timeline.rb +2 -2
- data/lib/crisphive/models/job_request_timeline_action.rb +2 -2
- data/lib/crisphive/models/job_request_timeline_event.rb +2 -2
- data/lib/crisphive/models/job_request_update_priority_request.rb +295 -0
- data/lib/crisphive/models/job_type.rb +44 -4
- data/lib/crisphive/models/job_type_create_request.rb +399 -0
- data/lib/crisphive/models/job_type_create_response.rb +215 -0
- data/lib/crisphive/models/job_type_update_request.rb +400 -0
- data/lib/crisphive/models/list_assignable_groups200_response.rb +255 -0
- data/lib/crisphive/models/list_crew_candidates200_response.rb +253 -0
- data/lib/crisphive/models/list_customers200_response.rb +5 -2
- data/lib/crisphive/models/list_emergency_candidates200_response.rb +253 -0
- data/lib/crisphive/models/list_job_request_booking_windows200_response.rb +5 -2
- data/lib/crisphive/models/list_job_request_changes200_response.rb +5 -2
- data/lib/crisphive/models/list_job_requests200_response.rb +5 -2
- data/lib/crisphive/models/list_job_types200_response.rb +5 -2
- data/lib/crisphive/models/list_matching_slots200_response.rb +253 -0
- data/lib/crisphive/models/list_nearby_technicians200_response.rb +253 -0
- data/lib/crisphive/models/list_service_areas200_response.rb +5 -2
- data/lib/crisphive/models/list_skill_categories200_response.rb +5 -2
- data/lib/crisphive/models/list_skills200_response.rb +5 -2
- data/lib/crisphive/models/list_skills_by_category200_response.rb +5 -2
- data/lib/crisphive/models/list_technician_skills200_response.rb +253 -0
- data/lib/crisphive/models/list_technician_time_off200_response.rb +253 -0
- data/lib/crisphive/models/list_technicians200_response.rb +5 -2
- data/lib/crisphive/models/list_vehicles200_response.rb +5 -2
- data/lib/crisphive/models/list_webhook_event_types200_response.rb +255 -0
- data/lib/crisphive/models/nearby_technician.rb +319 -0
- data/lib/crisphive/models/nearby_technicians.rb +237 -0
- data/lib/crisphive/models/pagination.rb +7 -2
- data/lib/crisphive/models/quote_job_request200_response.rb +253 -0
- data/lib/crisphive/models/replace_technician_service_areas200_response.rb +253 -0
- data/lib/crisphive/models/response_envelope.rb +6 -2
- data/lib/crisphive/models/service_area.rb +23 -3
- data/lib/crisphive/models/service_area_create_request.rb +455 -0
- data/lib/crisphive/models/service_area_create_response.rb +215 -0
- data/lib/crisphive/models/service_area_list.rb +2 -2
- data/lib/crisphive/models/service_area_update_request.rb +451 -0
- data/lib/crisphive/models/skill.rb +9 -2
- data/lib/crisphive/models/skill_by_category_list.rb +4 -2
- data/lib/crisphive/models/skill_category.rb +7 -2
- data/lib/crisphive/models/skill_category_create_request.rb +270 -0
- data/lib/crisphive/models/skill_category_create_response.rb +215 -0
- data/lib/crisphive/models/skill_category_list.rb +4 -2
- data/lib/crisphive/models/skill_create_request.rb +270 -0
- data/lib/crisphive/models/skill_create_response.rb +215 -0
- data/lib/crisphive/models/skill_list.rb +2 -2
- data/lib/crisphive/models/skill_summary.rb +2 -2
- data/lib/crisphive/models/skill_update_request.rb +281 -0
- data/lib/crisphive/models/technician.rb +66 -4
- data/lib/crisphive/models/technician_address.rb +2 -2
- data/lib/crisphive/models/technician_address_input.rb +408 -0
- data/lib/crisphive/models/technician_buddies_request.rb +236 -0
- data/lib/crisphive/models/technician_create_request.rb +603 -0
- data/lib/crisphive/models/technician_create_response.rb +215 -0
- data/lib/crisphive/models/technician_lead_ref.rb +2 -2
- data/lib/crisphive/models/technician_leads_request.rb +236 -0
- data/lib/crisphive/models/technician_list.rb +3 -3
- data/lib/crisphive/models/technician_schedule.rb +279 -0
- data/lib/crisphive/models/technician_schedule_block.rb +225 -0
- data/lib/crisphive/models/technician_schedule_session.rb +311 -0
- data/lib/crisphive/models/technician_service_area_ref.rb +2 -2
- data/lib/crisphive/models/technician_service_areas_request.rb +236 -0
- data/lib/crisphive/models/technician_service_areas_response.rb +217 -0
- data/lib/crisphive/models/technician_skill.rb +265 -0
- data/lib/crisphive/models/technician_skill_list.rb +227 -0
- data/lib/crisphive/models/technician_skills_request.rb +236 -0
- data/lib/crisphive/models/technician_status.rb +2 -2
- data/lib/crisphive/models/technician_time_off.rb +334 -0
- data/lib/crisphive/models/technician_time_off_create_request.rb +285 -0
- data/lib/crisphive/models/technician_time_off_create_response.rb +215 -0
- data/lib/crisphive/models/technician_time_off_list.rb +246 -0
- data/lib/crisphive/models/technician_update_request.rb +507 -0
- data/lib/crisphive/models/technician_vehicles_request.rb +236 -0
- data/lib/crisphive/models/vehicle.rb +26 -4
- data/lib/crisphive/models/vehicle_create_request.rb +420 -0
- data/lib/crisphive/models/vehicle_create_response.rb +215 -0
- data/lib/crisphive/models/vehicle_list.rb +2 -2
- data/lib/crisphive/models/vehicle_owner.rb +2 -2
- data/lib/crisphive/models/vehicle_update_request.rb +440 -0
- data/lib/crisphive/models/webhook_create_request.rb +320 -0
- data/lib/crisphive/models/webhook_create_response.rb +391 -0
- data/lib/crisphive/models/webhook_verification.rb +235 -0
- data/lib/crisphive/version.rb +3 -3
- data/lib/crisphive.rb +126 -2
- data/spec/spec_helper.rb +2 -2
- metadata +129 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
=begin
|
|
2
|
-
#
|
|
2
|
+
#Crisphive Developer API
|
|
3
3
|
|
|
4
|
-
#Public REST API for integrating
|
|
4
|
+
#Public REST API for integrating Crisphive from your own backend. Authenticate every request with a secret API key as a Bearer token (`Authorization: Bearer chsk_live_…`). The key prefix selects the data environment: `chsk_live_…` → production (live), `chsk_test_…` → sandbox (isolated test). **Key scopes (restricted keys).** A key is either *full-access* (can call every endpoint below) or *restricted* to a set of permission codes chosen at creation — the same codes as the dashboard permission grid (e.g. `customers_view`, `job_create`, `team_manage`). A restricted key calling an endpoint outside its scope gets `403`. The full code list is the permission catalog (`GET /permission/modules` on the dashboard API). Create, scope, and revoke keys from the business dashboard. Every response is wrapped in the envelope `{ \"error_code\": 0, \"message\": \"Success\", \"data\": <payload> }`.
|
|
5
5
|
|
|
6
6
|
The version of the OpenAPI document: 1.0
|
|
7
7
|
|
|
@@ -19,31 +19,33 @@ module Crisphive
|
|
|
19
19
|
def initialize(api_client = ApiClient.default)
|
|
20
20
|
@api_client = api_client
|
|
21
21
|
end
|
|
22
|
-
#
|
|
23
|
-
#
|
|
22
|
+
# Book, schedule and confirm a job in one call
|
|
23
|
+
# Creates the job, quotes it (job_duration_minutes, or the job type's default_duration_minutes) and confirms it at scheduled_at on the customer's behalf — the dashboard's \"book for a caller\" in a single request, built for voice agents and automation platforms that cannot run create → quote → slots → confirm. Customer: send `customer_id`, or `customer` (+ `address`) to match-or-create by phone/email — a caller who already exists is matched, never duplicated. Find a caller first with listCustomers?phone=. Every input is validated BEFORE anything is written (time and business timezone, future start, a duration or a job-type default, non-negative mobilization/demobilization minutes, active job type, phone format); those failures are ordinary 4xx and create nothing. ⚠️ A `technician_id` the engine cannot honour at that time is refused BEFORE anything is written: `409 JOB_REQUEST_TECH_INFEASIBLE`, no job, no customer, no webhook. Change the technician or the time and send again with a NEW Idempotency-Key: like every 4xx here the 409 is cached against its key for 24h, so the same key replays it (same body) or answers 422 IDEMPOTENCY_KEY_REUSE (changed body). This check is BEST-EFFORT — if the scheduling engine cannot be reached it is skipped and the call proceeds, so a pinned request can still come back as the 200 + `refusal` below. Handle both. ⚠️ ONE carve-out: a `p0` whose pinned technician is merely BUSY is NOT refused here. The job is created and the call answers 200 + `refusal` carrying JOB_REQUEST_P0_REQUIRES_DISPLACEMENT, because the remedy for that code is the emergency flow and listEmergencyCandidates / previewEmergencyReschedule / commitEmergencyReschedule all require `emergency_job_id` — a 409 carries no job id. Read `job_id` off the 200 and run the emergency flow; do not re-book. Every other doomed pin on a `p0` (out of area, missing skills, not a lead) still answers 409. ⚠️ A SECOND carve-out, narrower: for a `p0`, a PERSONAL-CALENDAR overlap on the pinned technician is not refused here either — naming them is treated as having already phoned them — and the call answers 200 + `confirmed: true`. Nothing on this response discloses it; the only record is the business's activity feed (`job_calendar_override`). `calendar_busy`/`calendar_conflict` therefore never appear in the 409 reason vocabulary below when the pin is a `p0` naming a technician explicitly (this endpoint never books a crew, so the exclusion is unconditional here). ⚠️ Otherwise, once the job is created it is never discarded, and the call answers 200 even if scheduling then fails: `confirmed: false` with `refusal` (stage + the exact error_code/data the quote or confirm endpoint would have returned, e.g. JOB_REQUEST_NO_TECHNICIAN_AVAILABLE with blockers). The job is then quoted and waiting in the coordinator's queue — tell the caller the office will confirm a time. Retry with the SAME Idempotency-Key to replay the result; a new key books a second job. P0 dispatch: send `emergency` with `priority: \"p0\"`. `dispatch: \"now\"` plans the displacement cascade BEFORE anything is written — a refusal is a 409 creating nothing — then books, quotes and commits it. `dispatch: \"later\"` parks a quoted P0 in the tray and ignores the other fields. ⚠️ `emergency.expected_move_ids` is REQUIRED with `dispatch: \"now\"` and has three meanings: omitted is refused, `[]` means \"my preview showed no displacement\" and commits a free lane, and a named set is the fence. Get the ids from previewEmergencyReschedule. ⚠️ A refusal AFTER the job is created answers 200 with `confirmed: false` and `refusal.stage: \"dispatch\"`. Read `job_id`, re-preview with previewEmergencyReschedule and commit with commitEmergencyReschedule. Never re-book.
|
|
24
|
+
# @param job_request_book_and_confirm_request [JobRequestBookAndConfirmRequest] Book and confirm in one call
|
|
24
25
|
# @param [Hash] opts the optional parameters
|
|
25
|
-
# @option opts [String] :
|
|
26
|
-
# @return [
|
|
27
|
-
def
|
|
28
|
-
data, _status_code, _headers =
|
|
26
|
+
# @option opts [String] :idempotency_key Makes retries safe: a repeat send with the same key returns the original result instead of booking again
|
|
27
|
+
# @return [BookAndConfirmJobRequest200Response]
|
|
28
|
+
def book_and_confirm_job_request(job_request_book_and_confirm_request, opts = {})
|
|
29
|
+
data, _status_code, _headers = book_and_confirm_job_request_with_http_info(job_request_book_and_confirm_request, opts)
|
|
29
30
|
data
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
#
|
|
33
|
-
#
|
|
33
|
+
# Book, schedule and confirm a job in one call
|
|
34
|
+
# Creates the job, quotes it (job_duration_minutes, or the job type's default_duration_minutes) and confirms it at scheduled_at on the customer's behalf — the dashboard's \"book for a caller\" in a single request, built for voice agents and automation platforms that cannot run create → quote → slots → confirm. Customer: send `customer_id`, or `customer` (+ `address`) to match-or-create by phone/email — a caller who already exists is matched, never duplicated. Find a caller first with listCustomers?phone=. Every input is validated BEFORE anything is written (time and business timezone, future start, a duration or a job-type default, non-negative mobilization/demobilization minutes, active job type, phone format); those failures are ordinary 4xx and create nothing. ⚠️ A `technician_id` the engine cannot honour at that time is refused BEFORE anything is written: `409 JOB_REQUEST_TECH_INFEASIBLE`, no job, no customer, no webhook. Change the technician or the time and send again with a NEW Idempotency-Key: like every 4xx here the 409 is cached against its key for 24h, so the same key replays it (same body) or answers 422 IDEMPOTENCY_KEY_REUSE (changed body). This check is BEST-EFFORT — if the scheduling engine cannot be reached it is skipped and the call proceeds, so a pinned request can still come back as the 200 + `refusal` below. Handle both. ⚠️ ONE carve-out: a `p0` whose pinned technician is merely BUSY is NOT refused here. The job is created and the call answers 200 + `refusal` carrying JOB_REQUEST_P0_REQUIRES_DISPLACEMENT, because the remedy for that code is the emergency flow and listEmergencyCandidates / previewEmergencyReschedule / commitEmergencyReschedule all require `emergency_job_id` — a 409 carries no job id. Read `job_id` off the 200 and run the emergency flow; do not re-book. Every other doomed pin on a `p0` (out of area, missing skills, not a lead) still answers 409. ⚠️ A SECOND carve-out, narrower: for a `p0`, a PERSONAL-CALENDAR overlap on the pinned technician is not refused here either — naming them is treated as having already phoned them — and the call answers 200 + `confirmed: true`. Nothing on this response discloses it; the only record is the business's activity feed (`job_calendar_override`). `calendar_busy`/`calendar_conflict` therefore never appear in the 409 reason vocabulary below when the pin is a `p0` naming a technician explicitly (this endpoint never books a crew, so the exclusion is unconditional here). ⚠️ Otherwise, once the job is created it is never discarded, and the call answers 200 even if scheduling then fails: `confirmed: false` with `refusal` (stage + the exact error_code/data the quote or confirm endpoint would have returned, e.g. JOB_REQUEST_NO_TECHNICIAN_AVAILABLE with blockers). The job is then quoted and waiting in the coordinator's queue — tell the caller the office will confirm a time. Retry with the SAME Idempotency-Key to replay the result; a new key books a second job. P0 dispatch: send `emergency` with `priority: \"p0\"`. `dispatch: \"now\"` plans the displacement cascade BEFORE anything is written — a refusal is a 409 creating nothing — then books, quotes and commits it. `dispatch: \"later\"` parks a quoted P0 in the tray and ignores the other fields. ⚠️ `emergency.expected_move_ids` is REQUIRED with `dispatch: \"now\"` and has three meanings: omitted is refused, `[]` means \"my preview showed no displacement\" and commits a free lane, and a named set is the fence. Get the ids from previewEmergencyReschedule. ⚠️ A refusal AFTER the job is created answers 200 with `confirmed: false` and `refusal.stage: \"dispatch\"`. Read `job_id`, re-preview with previewEmergencyReschedule and commit with commitEmergencyReschedule. Never re-book.
|
|
35
|
+
# @param job_request_book_and_confirm_request [JobRequestBookAndConfirmRequest] Book and confirm in one call
|
|
34
36
|
# @param [Hash] opts the optional parameters
|
|
35
|
-
# @option opts [String] :
|
|
36
|
-
# @return [Array<(
|
|
37
|
-
def
|
|
37
|
+
# @option opts [String] :idempotency_key Makes retries safe: a repeat send with the same key returns the original result instead of booking again
|
|
38
|
+
# @return [Array<(BookAndConfirmJobRequest200Response, Integer, Hash)>] BookAndConfirmJobRequest200Response data, response status code and response headers
|
|
39
|
+
def book_and_confirm_job_request_with_http_info(job_request_book_and_confirm_request, opts = {})
|
|
38
40
|
if @api_client.config.debugging
|
|
39
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
41
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.book_and_confirm_job_request ...'
|
|
40
42
|
end
|
|
41
|
-
# verify the required parameter '
|
|
42
|
-
if @api_client.config.client_side_validation &&
|
|
43
|
-
fail ArgumentError, "Missing the required parameter '
|
|
43
|
+
# verify the required parameter 'job_request_book_and_confirm_request' is set
|
|
44
|
+
if @api_client.config.client_side_validation && job_request_book_and_confirm_request.nil?
|
|
45
|
+
fail ArgumentError, "Missing the required parameter 'job_request_book_and_confirm_request' when calling JobRequestBusinessApi.book_and_confirm_job_request"
|
|
44
46
|
end
|
|
45
47
|
# resource path
|
|
46
|
-
local_var_path = '/job-requests'
|
|
48
|
+
local_var_path = '/job-requests/book-and-confirm'
|
|
47
49
|
|
|
48
50
|
# query parameters
|
|
49
51
|
query_params = opts[:query_params] || {}
|
|
@@ -57,22 +59,22 @@ module Crisphive
|
|
|
57
59
|
if !content_type.nil?
|
|
58
60
|
header_params['Content-Type'] = content_type
|
|
59
61
|
end
|
|
60
|
-
header_params[:'
|
|
62
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
61
63
|
|
|
62
64
|
# form parameters
|
|
63
65
|
form_params = opts[:form_params] || {}
|
|
64
66
|
|
|
65
67
|
# http body (model)
|
|
66
|
-
post_body = opts[:debug_body] || @api_client.object_to_http_body(
|
|
68
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_book_and_confirm_request)
|
|
67
69
|
|
|
68
70
|
# return_type
|
|
69
|
-
return_type = opts[:debug_return_type] || '
|
|
71
|
+
return_type = opts[:debug_return_type] || 'BookAndConfirmJobRequest200Response'
|
|
70
72
|
|
|
71
73
|
# auth_names
|
|
72
74
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
73
75
|
|
|
74
76
|
new_options = opts.merge(
|
|
75
|
-
:operation => :"JobRequestBusinessApi.
|
|
77
|
+
:operation => :"JobRequestBusinessApi.book_and_confirm_job_request",
|
|
76
78
|
:header_params => header_params,
|
|
77
79
|
:query_params => query_params,
|
|
78
80
|
:form_params => form_params,
|
|
@@ -83,34 +85,38 @@ module Crisphive
|
|
|
83
85
|
|
|
84
86
|
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
85
87
|
if @api_client.config.debugging
|
|
86
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
88
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#book_and_confirm_job_request\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
87
89
|
end
|
|
88
90
|
return data, status_code, headers
|
|
89
91
|
end
|
|
90
92
|
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
+
# Commit the previewed re-staffing of a technician's day
|
|
94
|
+
# Applies the plan returned by /absence/preview, ATOMICALLY: every assignment in one transaction (all or nothing), each job re-staffed onto its alternate at its unchanged window, its \"needs attention\" flag cleared, its status_version bumped. Commit VERIFIES and never re-solves — send `assignments[]` copied from `preview.resolved[]` (you may drop rows, never add or re-point them) and, to ACCEPT a priced alternative from `preview.unresolved[].alternatives[]`, the same row plus its `alternative_kind` and (for a reschedule kind) its `start_at`/`end_at`; the engine re-checks that technician at that window under exactly that relaxation. A reschedule kind rewrites `scheduled_at`, notifies the customer of the NEW TIME (`job_rescheduled`, never `tech_reassigned` on top) and fires `job_request.rescheduled`; the response row then carries `alternative_kind`, `cost`, `original_start_at`/`original_end_at` and `window_preserved: false`. Requires a time-off record covering EVERY day of the range for the technician (pending or approved); a pending one is APPROVED by the commit, because the engine's feasibility filter reads approved time-off only and without it the absent technician stays bookable everywhere else. The response mirrors the preview plus per-job `notification` evidence (dispatched | skipped + reason — what the routing WILL do, never proof of delivery), `attention_cleared`, and `time_off`. Supports Idempotency-Key. Requires job_manage AND schedule_manage (the approval is a scheduling action). See ABSENCE_RESOLVE_DESIGN.md. 409 NEXT STEPS: ABSENCE_RESOLVE_TIME_OFF_REQUIRED — the absence is not recorded well enough to commit against: `data.uncovered_dates[]` (days no eligible record touches) and `data.uncovered_jobs[]` (jobs no single eligible record spans); eligible = approved records, plus PENDING records whose span lies INSIDE the range — a pending record WIDER than the range (somebody's leave request) is never approved by this commit and is listed in `data.pending_wider_time_off_ids[]` for a human to decide. Record a sick-day time-off via `data.create_via` (POST /business/technician-time-off, pending is enough), then commit again. ABSENCE_RESOLVE_PLAN_DRIFTED — the world moved since the preview; `data.drifted[]` names the job (job_id/short_code/expected_version) and `reason` says how: `version` (the row changed or left the technician's lane), `infeasible` (the alternate can no longer take it), `occupied` (the alternate's lane overlapped after the write). No job was written; `data.time_offs[]` lists any pending record the commit had already approved — re-preview, show the new plan, commit again. ABSENCE_RESOLVE_NO_ORPHANED_JOBS — the board is empty for the range.
|
|
95
|
+
# @param job_request_absence_commit_request [JobRequestAbsenceCommitRequest] preview scope + the previewed assignments to apply
|
|
93
96
|
# @param [Hash] opts the optional parameters
|
|
94
|
-
# @
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
98
|
+
# @return [CommitAbsenceResolve200Response]
|
|
99
|
+
def commit_absence_resolve(job_request_absence_commit_request, opts = {})
|
|
100
|
+
data, _status_code, _headers = commit_absence_resolve_with_http_info(job_request_absence_commit_request, opts)
|
|
97
101
|
data
|
|
98
102
|
end
|
|
99
103
|
|
|
100
|
-
#
|
|
101
|
-
#
|
|
104
|
+
# Commit the previewed re-staffing of a technician's day
|
|
105
|
+
# Applies the plan returned by /absence/preview, ATOMICALLY: every assignment in one transaction (all or nothing), each job re-staffed onto its alternate at its unchanged window, its \"needs attention\" flag cleared, its status_version bumped. Commit VERIFIES and never re-solves — send `assignments[]` copied from `preview.resolved[]` (you may drop rows, never add or re-point them) and, to ACCEPT a priced alternative from `preview.unresolved[].alternatives[]`, the same row plus its `alternative_kind` and (for a reschedule kind) its `start_at`/`end_at`; the engine re-checks that technician at that window under exactly that relaxation. A reschedule kind rewrites `scheduled_at`, notifies the customer of the NEW TIME (`job_rescheduled`, never `tech_reassigned` on top) and fires `job_request.rescheduled`; the response row then carries `alternative_kind`, `cost`, `original_start_at`/`original_end_at` and `window_preserved: false`. Requires a time-off record covering EVERY day of the range for the technician (pending or approved); a pending one is APPROVED by the commit, because the engine's feasibility filter reads approved time-off only and without it the absent technician stays bookable everywhere else. The response mirrors the preview plus per-job `notification` evidence (dispatched | skipped + reason — what the routing WILL do, never proof of delivery), `attention_cleared`, and `time_off`. Supports Idempotency-Key. Requires job_manage AND schedule_manage (the approval is a scheduling action). See ABSENCE_RESOLVE_DESIGN.md. 409 NEXT STEPS: ABSENCE_RESOLVE_TIME_OFF_REQUIRED — the absence is not recorded well enough to commit against: `data.uncovered_dates[]` (days no eligible record touches) and `data.uncovered_jobs[]` (jobs no single eligible record spans); eligible = approved records, plus PENDING records whose span lies INSIDE the range — a pending record WIDER than the range (somebody's leave request) is never approved by this commit and is listed in `data.pending_wider_time_off_ids[]` for a human to decide. Record a sick-day time-off via `data.create_via` (POST /business/technician-time-off, pending is enough), then commit again. ABSENCE_RESOLVE_PLAN_DRIFTED — the world moved since the preview; `data.drifted[]` names the job (job_id/short_code/expected_version) and `reason` says how: `version` (the row changed or left the technician's lane), `infeasible` (the alternate can no longer take it), `occupied` (the alternate's lane overlapped after the write). No job was written; `data.time_offs[]` lists any pending record the commit had already approved — re-preview, show the new plan, commit again. ABSENCE_RESOLVE_NO_ORPHANED_JOBS — the board is empty for the range.
|
|
106
|
+
# @param job_request_absence_commit_request [JobRequestAbsenceCommitRequest] preview scope + the previewed assignments to apply
|
|
102
107
|
# @param [Hash] opts the optional parameters
|
|
103
|
-
# @
|
|
104
|
-
|
|
108
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
109
|
+
# @return [Array<(CommitAbsenceResolve200Response, Integer, Hash)>] CommitAbsenceResolve200Response data, response status code and response headers
|
|
110
|
+
def commit_absence_resolve_with_http_info(job_request_absence_commit_request, opts = {})
|
|
105
111
|
if @api_client.config.debugging
|
|
106
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
112
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.commit_absence_resolve ...'
|
|
107
113
|
end
|
|
108
|
-
# verify the required parameter '
|
|
109
|
-
if @api_client.config.client_side_validation &&
|
|
110
|
-
fail ArgumentError, "Missing the required parameter '
|
|
114
|
+
# verify the required parameter 'job_request_absence_commit_request' is set
|
|
115
|
+
if @api_client.config.client_side_validation && job_request_absence_commit_request.nil?
|
|
116
|
+
fail ArgumentError, "Missing the required parameter 'job_request_absence_commit_request' when calling JobRequestBusinessApi.commit_absence_resolve"
|
|
111
117
|
end
|
|
112
118
|
# resource path
|
|
113
|
-
local_var_path = '/job-requests/
|
|
119
|
+
local_var_path = '/job-requests/absence/commit'
|
|
114
120
|
|
|
115
121
|
# query parameters
|
|
116
122
|
query_params = opts[:query_params] || {}
|
|
@@ -119,21 +125,27 @@ module Crisphive
|
|
|
119
125
|
header_params = opts[:header_params] || {}
|
|
120
126
|
# HTTP header 'Accept' (if needed)
|
|
121
127
|
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
128
|
+
# HTTP header 'Content-Type'
|
|
129
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
130
|
+
if !content_type.nil?
|
|
131
|
+
header_params['Content-Type'] = content_type
|
|
132
|
+
end
|
|
133
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
122
134
|
|
|
123
135
|
# form parameters
|
|
124
136
|
form_params = opts[:form_params] || {}
|
|
125
137
|
|
|
126
138
|
# http body (model)
|
|
127
|
-
post_body = opts[:debug_body]
|
|
139
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_absence_commit_request)
|
|
128
140
|
|
|
129
141
|
# return_type
|
|
130
|
-
return_type = opts[:debug_return_type] || '
|
|
142
|
+
return_type = opts[:debug_return_type] || 'CommitAbsenceResolve200Response'
|
|
131
143
|
|
|
132
144
|
# auth_names
|
|
133
145
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
134
146
|
|
|
135
147
|
new_options = opts.merge(
|
|
136
|
-
:operation => :"JobRequestBusinessApi.
|
|
148
|
+
:operation => :"JobRequestBusinessApi.commit_absence_resolve",
|
|
137
149
|
:header_params => header_params,
|
|
138
150
|
:query_params => query_params,
|
|
139
151
|
:form_params => form_params,
|
|
@@ -142,38 +154,117 @@ module Crisphive
|
|
|
142
154
|
:return_type => return_type
|
|
143
155
|
)
|
|
144
156
|
|
|
145
|
-
data, status_code, headers = @api_client.call_api(:
|
|
157
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
146
158
|
if @api_client.config.debugging
|
|
147
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
159
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#commit_absence_resolve\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
160
|
+
end
|
|
161
|
+
return data, status_code, headers
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Commit emergency insert + cascade reschedule
|
|
165
|
+
# Applies the cascade previewed by /emergency/preview: assigns the emergency job to the technician and pushes the displaced jobs back (or, with `displacement_mode=reassign`, re-staffs them onto their previewed alternates first), atomically. Supports Idempotency-Key. The server recomputes the plan under a lock and fences each job on its status_version — if anything changed since the preview it returns 409 EMERGENCY_RESCHEDULE_PLAN_DRIFTED (re-preview). Same body as preview + optional `emergency_expected_version`. `after_hours_override=true` must match the preview it followed — it drops the non-working-day rejection (this endpoint never runs the technician's working-hours/time-off feasibility check; that only happens on /candidates), and the response carries an AFTER_HOURS warning; the committed job's activity feed also records who authorized the after-hours placement. Isolated feature (see EMERGENCY_RESCHEDULE_DESIGN.md). 409 NEXT STEPS: EMERGENCY_RESCHEDULE_PLAN_DRIFTED — the schedule changed between your preview and this commit (another booking/move won a lane); `data.drifted[]` names the job(s) whose status_version moved when the fence can attribute it (absent, never empty, when only a length mismatch is known): call /preview again, show the fresh plan, then commit. EMERGENCY_RESCHEDULE_SLOT_OCCUPIED — landing window blocked by an immovable anchor (P0/crew/multi-day); `data.conflicts[]` names it: another tech or time. Other codes — same remedies and `data` shapes as /candidates. EMERGENCY_RESCHEDULE_NO_WORKING_DAY fires on a closed day without after_hours_override and carries `data.override_available: true` — confirm with the coordinator, then retry with the flag.
|
|
166
|
+
# @param job_request_emergency_commit_request [JobRequestEmergencyCommitRequest] emergency insert spec
|
|
167
|
+
# @param [Hash] opts the optional parameters
|
|
168
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
169
|
+
# @return [CommitEmergencyReschedule200Response]
|
|
170
|
+
def commit_emergency_reschedule(job_request_emergency_commit_request, opts = {})
|
|
171
|
+
data, _status_code, _headers = commit_emergency_reschedule_with_http_info(job_request_emergency_commit_request, opts)
|
|
172
|
+
data
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Commit emergency insert + cascade reschedule
|
|
176
|
+
# Applies the cascade previewed by /emergency/preview: assigns the emergency job to the technician and pushes the displaced jobs back (or, with `displacement_mode=reassign`, re-staffs them onto their previewed alternates first), atomically. Supports Idempotency-Key. The server recomputes the plan under a lock and fences each job on its status_version — if anything changed since the preview it returns 409 EMERGENCY_RESCHEDULE_PLAN_DRIFTED (re-preview). Same body as preview + optional `emergency_expected_version`. `after_hours_override=true` must match the preview it followed — it drops the non-working-day rejection (this endpoint never runs the technician's working-hours/time-off feasibility check; that only happens on /candidates), and the response carries an AFTER_HOURS warning; the committed job's activity feed also records who authorized the after-hours placement. Isolated feature (see EMERGENCY_RESCHEDULE_DESIGN.md). 409 NEXT STEPS: EMERGENCY_RESCHEDULE_PLAN_DRIFTED — the schedule changed between your preview and this commit (another booking/move won a lane); `data.drifted[]` names the job(s) whose status_version moved when the fence can attribute it (absent, never empty, when only a length mismatch is known): call /preview again, show the fresh plan, then commit. EMERGENCY_RESCHEDULE_SLOT_OCCUPIED — landing window blocked by an immovable anchor (P0/crew/multi-day); `data.conflicts[]` names it: another tech or time. Other codes — same remedies and `data` shapes as /candidates. EMERGENCY_RESCHEDULE_NO_WORKING_DAY fires on a closed day without after_hours_override and carries `data.override_available: true` — confirm with the coordinator, then retry with the flag.
|
|
177
|
+
# @param job_request_emergency_commit_request [JobRequestEmergencyCommitRequest] emergency insert spec
|
|
178
|
+
# @param [Hash] opts the optional parameters
|
|
179
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
180
|
+
# @return [Array<(CommitEmergencyReschedule200Response, Integer, Hash)>] CommitEmergencyReschedule200Response data, response status code and response headers
|
|
181
|
+
def commit_emergency_reschedule_with_http_info(job_request_emergency_commit_request, opts = {})
|
|
182
|
+
if @api_client.config.debugging
|
|
183
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.commit_emergency_reschedule ...'
|
|
184
|
+
end
|
|
185
|
+
# verify the required parameter 'job_request_emergency_commit_request' is set
|
|
186
|
+
if @api_client.config.client_side_validation && job_request_emergency_commit_request.nil?
|
|
187
|
+
fail ArgumentError, "Missing the required parameter 'job_request_emergency_commit_request' when calling JobRequestBusinessApi.commit_emergency_reschedule"
|
|
188
|
+
end
|
|
189
|
+
# resource path
|
|
190
|
+
local_var_path = '/job-requests/emergency/commit'
|
|
191
|
+
|
|
192
|
+
# query parameters
|
|
193
|
+
query_params = opts[:query_params] || {}
|
|
194
|
+
|
|
195
|
+
# header parameters
|
|
196
|
+
header_params = opts[:header_params] || {}
|
|
197
|
+
# HTTP header 'Accept' (if needed)
|
|
198
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
199
|
+
# HTTP header 'Content-Type'
|
|
200
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
201
|
+
if !content_type.nil?
|
|
202
|
+
header_params['Content-Type'] = content_type
|
|
203
|
+
end
|
|
204
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
205
|
+
|
|
206
|
+
# form parameters
|
|
207
|
+
form_params = opts[:form_params] || {}
|
|
208
|
+
|
|
209
|
+
# http body (model)
|
|
210
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_emergency_commit_request)
|
|
211
|
+
|
|
212
|
+
# return_type
|
|
213
|
+
return_type = opts[:debug_return_type] || 'CommitEmergencyReschedule200Response'
|
|
214
|
+
|
|
215
|
+
# auth_names
|
|
216
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
217
|
+
|
|
218
|
+
new_options = opts.merge(
|
|
219
|
+
:operation => :"JobRequestBusinessApi.commit_emergency_reschedule",
|
|
220
|
+
:header_params => header_params,
|
|
221
|
+
:query_params => query_params,
|
|
222
|
+
:form_params => form_params,
|
|
223
|
+
:body => post_body,
|
|
224
|
+
:auth_names => auth_names,
|
|
225
|
+
:return_type => return_type
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
229
|
+
if @api_client.config.debugging
|
|
230
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#commit_emergency_reschedule\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
148
231
|
end
|
|
149
232
|
return data, status_code, headers
|
|
150
233
|
end
|
|
151
234
|
|
|
152
|
-
#
|
|
153
|
-
#
|
|
235
|
+
# Commit a schedule-board job move
|
|
236
|
+
# Applies the move previewed by /move/preview: places the job on the technician at the new time and pushes the displaced jobs back, atomically (per-tech advisory lock; the server recomputes the plan and fences each job on its status_version — drift since the preview returns 409 SCHEDULE_MOVE_PLAN_DRIFTED, re-preview). Same body as preview + optional `expected_version`. See SCHEDULE_BOARD_DESIGN.md. 409 NEXT STEPS: SCHEDULE_MOVE_PLAN_DRIFTED — the schedule changed since your preview (or expected_move_ids/expected_member_ids no longer match): re-preview, show the fresh plan, commit again; carries no further `data` (the fence cannot attribute the drift to one specific job). All other codes — same remedies AND `data` shapes as /move/preview.
|
|
154
237
|
# @param id [String] Job request ID (UUID or short_code)
|
|
238
|
+
# @param job_request_move_commit_req [JobRequestMoveCommitReq] move spec
|
|
155
239
|
# @param [Hash] opts the optional parameters
|
|
156
|
-
# @
|
|
157
|
-
|
|
158
|
-
|
|
240
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
241
|
+
# @return [CommitJobRequestMove200Response]
|
|
242
|
+
def commit_job_request_move(id, job_request_move_commit_req, opts = {})
|
|
243
|
+
data, _status_code, _headers = commit_job_request_move_with_http_info(id, job_request_move_commit_req, opts)
|
|
159
244
|
data
|
|
160
245
|
end
|
|
161
246
|
|
|
162
|
-
#
|
|
163
|
-
#
|
|
247
|
+
# Commit a schedule-board job move
|
|
248
|
+
# Applies the move previewed by /move/preview: places the job on the technician at the new time and pushes the displaced jobs back, atomically (per-tech advisory lock; the server recomputes the plan and fences each job on its status_version — drift since the preview returns 409 SCHEDULE_MOVE_PLAN_DRIFTED, re-preview). Same body as preview + optional `expected_version`. See SCHEDULE_BOARD_DESIGN.md. 409 NEXT STEPS: SCHEDULE_MOVE_PLAN_DRIFTED — the schedule changed since your preview (or expected_move_ids/expected_member_ids no longer match): re-preview, show the fresh plan, commit again; carries no further `data` (the fence cannot attribute the drift to one specific job). All other codes — same remedies AND `data` shapes as /move/preview.
|
|
164
249
|
# @param id [String] Job request ID (UUID or short_code)
|
|
250
|
+
# @param job_request_move_commit_req [JobRequestMoveCommitReq] move spec
|
|
165
251
|
# @param [Hash] opts the optional parameters
|
|
166
|
-
# @
|
|
167
|
-
|
|
252
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
253
|
+
# @return [Array<(CommitJobRequestMove200Response, Integer, Hash)>] CommitJobRequestMove200Response data, response status code and response headers
|
|
254
|
+
def commit_job_request_move_with_http_info(id, job_request_move_commit_req, opts = {})
|
|
168
255
|
if @api_client.config.debugging
|
|
169
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
256
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.commit_job_request_move ...'
|
|
170
257
|
end
|
|
171
258
|
# verify the required parameter 'id' is set
|
|
172
259
|
if @api_client.config.client_side_validation && id.nil?
|
|
173
|
-
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.
|
|
260
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.commit_job_request_move"
|
|
261
|
+
end
|
|
262
|
+
# verify the required parameter 'job_request_move_commit_req' is set
|
|
263
|
+
if @api_client.config.client_side_validation && job_request_move_commit_req.nil?
|
|
264
|
+
fail ArgumentError, "Missing the required parameter 'job_request_move_commit_req' when calling JobRequestBusinessApi.commit_job_request_move"
|
|
174
265
|
end
|
|
175
266
|
# resource path
|
|
176
|
-
local_var_path = '/job-requests/{id}/
|
|
267
|
+
local_var_path = '/job-requests/{id}/move/commit'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
177
268
|
|
|
178
269
|
# query parameters
|
|
179
270
|
query_params = opts[:query_params] || {}
|
|
@@ -182,21 +273,27 @@ module Crisphive
|
|
|
182
273
|
header_params = opts[:header_params] || {}
|
|
183
274
|
# HTTP header 'Accept' (if needed)
|
|
184
275
|
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
276
|
+
# HTTP header 'Content-Type'
|
|
277
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
278
|
+
if !content_type.nil?
|
|
279
|
+
header_params['Content-Type'] = content_type
|
|
280
|
+
end
|
|
281
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
185
282
|
|
|
186
283
|
# form parameters
|
|
187
284
|
form_params = opts[:form_params] || {}
|
|
188
285
|
|
|
189
286
|
# http body (model)
|
|
190
|
-
post_body = opts[:debug_body]
|
|
287
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_move_commit_req)
|
|
191
288
|
|
|
192
289
|
# return_type
|
|
193
|
-
return_type = opts[:debug_return_type] || '
|
|
290
|
+
return_type = opts[:debug_return_type] || 'CommitJobRequestMove200Response'
|
|
194
291
|
|
|
195
292
|
# auth_names
|
|
196
293
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
197
294
|
|
|
198
295
|
new_options = opts.merge(
|
|
199
|
-
:operation => :"JobRequestBusinessApi.
|
|
296
|
+
:operation => :"JobRequestBusinessApi.commit_job_request_move",
|
|
200
297
|
:header_params => header_params,
|
|
201
298
|
:query_params => query_params,
|
|
202
299
|
:form_params => form_params,
|
|
@@ -205,66 +302,75 @@ module Crisphive
|
|
|
205
302
|
:return_type => return_type
|
|
206
303
|
)
|
|
207
304
|
|
|
208
|
-
data, status_code, headers = @api_client.call_api(:
|
|
305
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
209
306
|
if @api_client.config.debugging
|
|
210
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
307
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#commit_job_request_move\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
211
308
|
end
|
|
212
309
|
return data, status_code, headers
|
|
213
310
|
end
|
|
214
311
|
|
|
215
|
-
#
|
|
216
|
-
#
|
|
312
|
+
# Confirm a booking on behalf of the customer
|
|
313
|
+
# Fires the customer-actor `confirm_booking` action from the BUSINESS surface (audited as business_on_behalf). Two uses: (1) LIVE — staff confirm a slot for a customer who booked by phone; (2) SANDBOX — the customer magic-token surface is live-only (a sandbox job's link can never reach a real customer), so this is the ONLY way to drive a sandbox test job past booking (book → quote → confirm → assign → complete). Body carries the customer-chosen scheduled_at (business-local naive datetime). DECISION TABLE — every 409 this endpoint returns, and the correct NEXT STEP (branch on error_code, never on the HTTP status): • JOB_REQUEST_STAGE_CONFLICT — the job changed since you read it (NOTE: every FAILED confirm attempt also bumps status_version by design). Next: re-GET the job, retry with the fresh status_version. • JOB_REQUEST_ACTION_NOT_PENDING — the job is no longer at the confirm step (usually: already confirmed). Next: re-GET and show current status; do not retry. • JOB_REQUEST_NO_TECHNICIAN_AVAILABLE — the TIME is infeasible for everyone (outside working hours / the customer window, or nobody qualifies). Best-effort `data` breakdown: `considered` (roster size checked), `blocked_by` (histogram of blockers[0].kind → count, only kinds that actually blocked someone), `truncated` (roster larger than the check covered). Next: pick another time via booking-windows / time-segments. NOT an emergency case — displacement cannot conjure capacity. • JOB_REQUEST_TECH_INFEASIBLE — the FORCED technician cannot take the job then; `data.reason` says why (blockers[0].kind): outside_service_area | missing_required_skills | not_lead_tier | no_working_day | on_time_off | off_shift | calendar_busy | calendar_conflict | visit_too_long | occupied (they are already working then — `data.earliest_feasible_at` is when they are free) | cannot_arrive_in_time (see `data.earliest_feasible_at`, RFC3339 UTC — the first same-day time they CAN be on site → offer it) | not_available_today (diagnosis unavailable). `data.blockers[]` names EVERY cause, most-structural first; `data.technician` carries `{id, name}`, name best-effort (empty only when the lookup itself could not resolve) — EXCEPT on not_lead_tier, which carries a flat `data.technician_id` and no technician object. A UI that reads only `reason` still works. Next: keep the tech and reschedule to earliest_feasible_at+, OR keep the time and drop technician_id (auto-pick) / choose another tech from time-segments. NOT an emergency case. • JOB_REQUEST_P0_REQUIRES_DISPLACEMENT — the ONLY code that routes to the EMERGENCY flow: the job is P0, the tech qualifies, but the lane is genuinely occupied. Next: POST emergency/candidates → preview → commit (the commit auto-confirms). Caveat: if the occupying jobs are themselves P0 the preview will reject with EMERGENCY_RESCHEDULE_SLOT_OCCUPIED (P0 never displaces P0) — then pick another tech/time.
|
|
314
|
+
# @param id [String] Job request ID
|
|
315
|
+
# @param job_request_confirm_request [JobRequestConfirmRequest] Chosen slot (scheduled_at) + optional technician_id force-assign (P0–P3 flow: pins the ranked candidate, feasibility still enforced)
|
|
217
316
|
# @param [Hash] opts the optional parameters
|
|
218
|
-
# @option opts [String] :
|
|
219
|
-
# @
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
data, _status_code, _headers = list_job_request_booking_windows_with_http_info(x_timezone, opts)
|
|
317
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
318
|
+
# @return [ResponseEnvelope]
|
|
319
|
+
def confirm_job_request(id, job_request_confirm_request, opts = {})
|
|
320
|
+
data, _status_code, _headers = confirm_job_request_with_http_info(id, job_request_confirm_request, opts)
|
|
223
321
|
data
|
|
224
322
|
end
|
|
225
323
|
|
|
226
|
-
#
|
|
227
|
-
#
|
|
324
|
+
# Confirm a booking on behalf of the customer
|
|
325
|
+
# Fires the customer-actor `confirm_booking` action from the BUSINESS surface (audited as business_on_behalf). Two uses: (1) LIVE — staff confirm a slot for a customer who booked by phone; (2) SANDBOX — the customer magic-token surface is live-only (a sandbox job's link can never reach a real customer), so this is the ONLY way to drive a sandbox test job past booking (book → quote → confirm → assign → complete). Body carries the customer-chosen scheduled_at (business-local naive datetime). DECISION TABLE — every 409 this endpoint returns, and the correct NEXT STEP (branch on error_code, never on the HTTP status): • JOB_REQUEST_STAGE_CONFLICT — the job changed since you read it (NOTE: every FAILED confirm attempt also bumps status_version by design). Next: re-GET the job, retry with the fresh status_version. • JOB_REQUEST_ACTION_NOT_PENDING — the job is no longer at the confirm step (usually: already confirmed). Next: re-GET and show current status; do not retry. • JOB_REQUEST_NO_TECHNICIAN_AVAILABLE — the TIME is infeasible for everyone (outside working hours / the customer window, or nobody qualifies). Best-effort `data` breakdown: `considered` (roster size checked), `blocked_by` (histogram of blockers[0].kind → count, only kinds that actually blocked someone), `truncated` (roster larger than the check covered). Next: pick another time via booking-windows / time-segments. NOT an emergency case — displacement cannot conjure capacity. • JOB_REQUEST_TECH_INFEASIBLE — the FORCED technician cannot take the job then; `data.reason` says why (blockers[0].kind): outside_service_area | missing_required_skills | not_lead_tier | no_working_day | on_time_off | off_shift | calendar_busy | calendar_conflict | visit_too_long | occupied (they are already working then — `data.earliest_feasible_at` is when they are free) | cannot_arrive_in_time (see `data.earliest_feasible_at`, RFC3339 UTC — the first same-day time they CAN be on site → offer it) | not_available_today (diagnosis unavailable). `data.blockers[]` names EVERY cause, most-structural first; `data.technician` carries `{id, name}`, name best-effort (empty only when the lookup itself could not resolve) — EXCEPT on not_lead_tier, which carries a flat `data.technician_id` and no technician object. A UI that reads only `reason` still works. Next: keep the tech and reschedule to earliest_feasible_at+, OR keep the time and drop technician_id (auto-pick) / choose another tech from time-segments. NOT an emergency case. • JOB_REQUEST_P0_REQUIRES_DISPLACEMENT — the ONLY code that routes to the EMERGENCY flow: the job is P0, the tech qualifies, but the lane is genuinely occupied. Next: POST emergency/candidates → preview → commit (the commit auto-confirms). Caveat: if the occupying jobs are themselves P0 the preview will reject with EMERGENCY_RESCHEDULE_SLOT_OCCUPIED (P0 never displaces P0) — then pick another tech/time.
|
|
326
|
+
# @param id [String] Job request ID
|
|
327
|
+
# @param job_request_confirm_request [JobRequestConfirmRequest] Chosen slot (scheduled_at) + optional technician_id force-assign (P0–P3 flow: pins the ranked candidate, feasibility still enforced)
|
|
228
328
|
# @param [Hash] opts the optional parameters
|
|
229
|
-
# @option opts [String] :
|
|
230
|
-
# @
|
|
231
|
-
|
|
232
|
-
def list_job_request_booking_windows_with_http_info(x_timezone, opts = {})
|
|
329
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
|
|
330
|
+
# @return [Array<(ResponseEnvelope, Integer, Hash)>] ResponseEnvelope data, response status code and response headers
|
|
331
|
+
def confirm_job_request_with_http_info(id, job_request_confirm_request, opts = {})
|
|
233
332
|
if @api_client.config.debugging
|
|
234
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
333
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.confirm_job_request ...'
|
|
235
334
|
end
|
|
236
|
-
# verify the required parameter '
|
|
237
|
-
if @api_client.config.client_side_validation &&
|
|
238
|
-
fail ArgumentError, "Missing the required parameter '
|
|
335
|
+
# verify the required parameter 'id' is set
|
|
336
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
337
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.confirm_job_request"
|
|
338
|
+
end
|
|
339
|
+
# verify the required parameter 'job_request_confirm_request' is set
|
|
340
|
+
if @api_client.config.client_side_validation && job_request_confirm_request.nil?
|
|
341
|
+
fail ArgumentError, "Missing the required parameter 'job_request_confirm_request' when calling JobRequestBusinessApi.confirm_job_request"
|
|
239
342
|
end
|
|
240
343
|
# resource path
|
|
241
|
-
local_var_path = '/job-requests/
|
|
344
|
+
local_var_path = '/job-requests/{id}/confirm'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
242
345
|
|
|
243
346
|
# query parameters
|
|
244
347
|
query_params = opts[:query_params] || {}
|
|
245
|
-
query_params[:'from'] = opts[:'from'] if !opts[:'from'].nil?
|
|
246
|
-
query_params[:'to'] = opts[:'to'] if !opts[:'to'].nil?
|
|
247
348
|
|
|
248
349
|
# header parameters
|
|
249
350
|
header_params = opts[:header_params] || {}
|
|
250
351
|
# HTTP header 'Accept' (if needed)
|
|
251
352
|
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
252
|
-
|
|
353
|
+
# HTTP header 'Content-Type'
|
|
354
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
355
|
+
if !content_type.nil?
|
|
356
|
+
header_params['Content-Type'] = content_type
|
|
357
|
+
end
|
|
358
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
253
359
|
|
|
254
360
|
# form parameters
|
|
255
361
|
form_params = opts[:form_params] || {}
|
|
256
362
|
|
|
257
363
|
# http body (model)
|
|
258
|
-
post_body = opts[:debug_body]
|
|
364
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_confirm_request)
|
|
259
365
|
|
|
260
366
|
# return_type
|
|
261
|
-
return_type = opts[:debug_return_type] || '
|
|
367
|
+
return_type = opts[:debug_return_type] || 'ResponseEnvelope'
|
|
262
368
|
|
|
263
369
|
# auth_names
|
|
264
370
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
265
371
|
|
|
266
372
|
new_options = opts.merge(
|
|
267
|
-
:operation => :"JobRequestBusinessApi.
|
|
373
|
+
:operation => :"JobRequestBusinessApi.confirm_job_request",
|
|
268
374
|
:header_params => header_params,
|
|
269
375
|
:query_params => query_params,
|
|
270
376
|
:form_params => form_params,
|
|
@@ -273,79 +379,72 @@ module Crisphive
|
|
|
273
379
|
:return_type => return_type
|
|
274
380
|
)
|
|
275
381
|
|
|
276
|
-
data, status_code, headers = @api_client.call_api(:
|
|
382
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
277
383
|
if @api_client.config.debugging
|
|
278
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
384
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#confirm_job_request\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
279
385
|
end
|
|
280
386
|
return data, status_code, headers
|
|
281
387
|
end
|
|
282
388
|
|
|
283
|
-
#
|
|
284
|
-
#
|
|
389
|
+
# Create a job request
|
|
390
|
+
# Books a field-operations job — the work order that enters the dispatch & scheduling pipeline. Send the customer's UUID plus requested `job_dates` (date + morning/afternoon/evening periods, ideally offered from GET /job-requests/booking-windows), optional `job_type_id` (service catalog), `skill_ids` (required technician qualifications) and a free-text description. Quoting, technician/crew assignment and completion then advance the work order through the business's workflow.
|
|
391
|
+
# @param job_request_create_request [JobRequestCreateRequest] Booking payload
|
|
285
392
|
# @param [Hash] opts the optional parameters
|
|
286
|
-
# @option opts [String] :
|
|
287
|
-
# @option opts [String] :
|
|
288
|
-
# @
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD or RFC3339), exclusive
|
|
292
|
-
# @option opts [String] :since RFC3339 cursor from the prior response's next_since. OMIT on the first poll to prime the cursor at server-now.
|
|
293
|
-
# @option opts [Integer] :limit Max changes per poll (default 15, max 1000). If the page fills, has_more=true.
|
|
294
|
-
# @return [ListJobRequestChanges200Response]
|
|
295
|
-
def list_job_request_changes(opts = {})
|
|
296
|
-
data, _status_code, _headers = list_job_request_changes_with_http_info(opts)
|
|
393
|
+
# @option opts [String] :x_timezone Customer IANA timezone
|
|
394
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key returns the original booking instead of creating a duplicate
|
|
395
|
+
# @return [CreateJobRequest200Response]
|
|
396
|
+
def create_job_request(job_request_create_request, opts = {})
|
|
397
|
+
data, _status_code, _headers = create_job_request_with_http_info(job_request_create_request, opts)
|
|
297
398
|
data
|
|
298
399
|
end
|
|
299
400
|
|
|
300
|
-
#
|
|
301
|
-
#
|
|
401
|
+
# Create a job request
|
|
402
|
+
# Books a field-operations job — the work order that enters the dispatch & scheduling pipeline. Send the customer's UUID plus requested `job_dates` (date + morning/afternoon/evening periods, ideally offered from GET /job-requests/booking-windows), optional `job_type_id` (service catalog), `skill_ids` (required technician qualifications) and a free-text description. Quoting, technician/crew assignment and completion then advance the work order through the business's workflow.
|
|
403
|
+
# @param job_request_create_request [JobRequestCreateRequest] Booking payload
|
|
302
404
|
# @param [Hash] opts the optional parameters
|
|
303
|
-
# @option opts [String] :
|
|
304
|
-
# @option opts [String] :
|
|
305
|
-
# @
|
|
306
|
-
|
|
307
|
-
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD or RFC3339); range is [from, to)
|
|
308
|
-
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD or RFC3339), exclusive
|
|
309
|
-
# @option opts [String] :since RFC3339 cursor from the prior response's next_since. OMIT on the first poll to prime the cursor at server-now.
|
|
310
|
-
# @option opts [Integer] :limit Max changes per poll (default 15, max 1000). If the page fills, has_more=true.
|
|
311
|
-
# @return [Array<(ListJobRequestChanges200Response, Integer, Hash)>] ListJobRequestChanges200Response data, response status code and response headers
|
|
312
|
-
def list_job_request_changes_with_http_info(opts = {})
|
|
405
|
+
# @option opts [String] :x_timezone Customer IANA timezone
|
|
406
|
+
# @option opts [String] :idempotency_key Unique key making retries safe: a repeat send with the same key returns the original booking instead of creating a duplicate
|
|
407
|
+
# @return [Array<(CreateJobRequest200Response, Integer, Hash)>] CreateJobRequest200Response data, response status code and response headers
|
|
408
|
+
def create_job_request_with_http_info(job_request_create_request, opts = {})
|
|
313
409
|
if @api_client.config.debugging
|
|
314
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
410
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.create_job_request ...'
|
|
411
|
+
end
|
|
412
|
+
# verify the required parameter 'job_request_create_request' is set
|
|
413
|
+
if @api_client.config.client_side_validation && job_request_create_request.nil?
|
|
414
|
+
fail ArgumentError, "Missing the required parameter 'job_request_create_request' when calling JobRequestBusinessApi.create_job_request"
|
|
315
415
|
end
|
|
316
416
|
# resource path
|
|
317
|
-
local_var_path = '/job-requests
|
|
417
|
+
local_var_path = '/job-requests'
|
|
318
418
|
|
|
319
419
|
# query parameters
|
|
320
420
|
query_params = opts[:query_params] || {}
|
|
321
|
-
query_params[:'status_keys'] = opts[:'status_keys'] if !opts[:'status_keys'].nil?
|
|
322
|
-
query_params[:'priority'] = opts[:'priority'] if !opts[:'priority'].nil?
|
|
323
|
-
query_params[:'customer_id'] = opts[:'customer_id'] if !opts[:'customer_id'].nil?
|
|
324
|
-
query_params[:'technician_id'] = opts[:'technician_id'] if !opts[:'technician_id'].nil?
|
|
325
|
-
query_params[:'scheduled_from'] = opts[:'scheduled_from'] if !opts[:'scheduled_from'].nil?
|
|
326
|
-
query_params[:'scheduled_to'] = opts[:'scheduled_to'] if !opts[:'scheduled_to'].nil?
|
|
327
|
-
query_params[:'since'] = opts[:'since'] if !opts[:'since'].nil?
|
|
328
|
-
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
329
421
|
|
|
330
422
|
# header parameters
|
|
331
423
|
header_params = opts[:header_params] || {}
|
|
332
424
|
# HTTP header 'Accept' (if needed)
|
|
333
425
|
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
426
|
+
# HTTP header 'Content-Type'
|
|
427
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
428
|
+
if !content_type.nil?
|
|
429
|
+
header_params['Content-Type'] = content_type
|
|
430
|
+
end
|
|
431
|
+
header_params[:'X-Timezone'] = opts[:'x_timezone'] if !opts[:'x_timezone'].nil?
|
|
432
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
334
433
|
|
|
335
434
|
# form parameters
|
|
336
435
|
form_params = opts[:form_params] || {}
|
|
337
436
|
|
|
338
437
|
# http body (model)
|
|
339
|
-
post_body = opts[:debug_body]
|
|
438
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_create_request)
|
|
340
439
|
|
|
341
440
|
# return_type
|
|
342
|
-
return_type = opts[:debug_return_type] || '
|
|
441
|
+
return_type = opts[:debug_return_type] || 'CreateJobRequest200Response'
|
|
343
442
|
|
|
344
443
|
# auth_names
|
|
345
444
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
346
445
|
|
|
347
446
|
new_options = opts.merge(
|
|
348
|
-
:operation => :"JobRequestBusinessApi.
|
|
447
|
+
:operation => :"JobRequestBusinessApi.create_job_request",
|
|
349
448
|
:header_params => header_params,
|
|
350
449
|
:query_params => query_params,
|
|
351
450
|
:form_params => form_params,
|
|
@@ -354,63 +453,41 @@ module Crisphive
|
|
|
354
453
|
:return_type => return_type
|
|
355
454
|
)
|
|
356
455
|
|
|
357
|
-
data, status_code, headers = @api_client.call_api(:
|
|
456
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
358
457
|
if @api_client.config.debugging
|
|
359
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
458
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#create_job_request\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
360
459
|
end
|
|
361
460
|
return data, status_code, headers
|
|
362
461
|
end
|
|
363
462
|
|
|
364
|
-
#
|
|
463
|
+
# Get a job request
|
|
464
|
+
# Returns the full work order: current workflow status, quoted duration, confirmed schedule, customer contact snapshot and the assigned technician / crew — everything a dispatcher or an external field-operations system needs to track one job.
|
|
465
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
365
466
|
# @param [Hash] opts the optional parameters
|
|
366
|
-
# @
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
# @option opts [String] :technician_id Technician UUID
|
|
370
|
-
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD or RFC3339); range is [from, to)
|
|
371
|
-
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD or RFC3339), exclusive
|
|
372
|
-
# @option opts [String] :q Search short_code or description (case-insensitive, partial match)
|
|
373
|
-
# @option opts [String] :sort Sort key
|
|
374
|
-
# @option opts [Integer] :page Page number
|
|
375
|
-
# @option opts [Integer] :limit Page size
|
|
376
|
-
# @return [ListJobRequests200Response]
|
|
377
|
-
def list_job_requests(opts = {})
|
|
378
|
-
data, _status_code, _headers = list_job_requests_with_http_info(opts)
|
|
467
|
+
# @return [GetJobRequest200Response]
|
|
468
|
+
def get_job_request(id, opts = {})
|
|
469
|
+
data, _status_code, _headers = get_job_request_with_http_info(id, opts)
|
|
379
470
|
data
|
|
380
471
|
end
|
|
381
472
|
|
|
382
|
-
#
|
|
473
|
+
# Get a job request
|
|
474
|
+
# Returns the full work order: current workflow status, quoted duration, confirmed schedule, customer contact snapshot and the assigned technician / crew — everything a dispatcher or an external field-operations system needs to track one job.
|
|
475
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
383
476
|
# @param [Hash] opts the optional parameters
|
|
384
|
-
# @
|
|
385
|
-
|
|
386
|
-
# @option opts [String] :customer_id Customer UUID
|
|
387
|
-
# @option opts [String] :technician_id Technician UUID
|
|
388
|
-
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD or RFC3339); range is [from, to)
|
|
389
|
-
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD or RFC3339), exclusive
|
|
390
|
-
# @option opts [String] :q Search short_code or description (case-insensitive, partial match)
|
|
391
|
-
# @option opts [String] :sort Sort key
|
|
392
|
-
# @option opts [Integer] :page Page number
|
|
393
|
-
# @option opts [Integer] :limit Page size
|
|
394
|
-
# @return [Array<(ListJobRequests200Response, Integer, Hash)>] ListJobRequests200Response data, response status code and response headers
|
|
395
|
-
def list_job_requests_with_http_info(opts = {})
|
|
477
|
+
# @return [Array<(GetJobRequest200Response, Integer, Hash)>] GetJobRequest200Response data, response status code and response headers
|
|
478
|
+
def get_job_request_with_http_info(id, opts = {})
|
|
396
479
|
if @api_client.config.debugging
|
|
397
|
-
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.
|
|
480
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.get_job_request ...'
|
|
481
|
+
end
|
|
482
|
+
# verify the required parameter 'id' is set
|
|
483
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
484
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.get_job_request"
|
|
398
485
|
end
|
|
399
486
|
# resource path
|
|
400
|
-
local_var_path = '/job-requests'
|
|
487
|
+
local_var_path = '/job-requests/{id}'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
401
488
|
|
|
402
489
|
# query parameters
|
|
403
490
|
query_params = opts[:query_params] || {}
|
|
404
|
-
query_params[:'status_keys'] = opts[:'status_keys'] if !opts[:'status_keys'].nil?
|
|
405
|
-
query_params[:'status'] = opts[:'status'] if !opts[:'status'].nil?
|
|
406
|
-
query_params[:'customer_id'] = opts[:'customer_id'] if !opts[:'customer_id'].nil?
|
|
407
|
-
query_params[:'technician_id'] = opts[:'technician_id'] if !opts[:'technician_id'].nil?
|
|
408
|
-
query_params[:'scheduled_from'] = opts[:'scheduled_from'] if !opts[:'scheduled_from'].nil?
|
|
409
|
-
query_params[:'scheduled_to'] = opts[:'scheduled_to'] if !opts[:'scheduled_to'].nil?
|
|
410
|
-
query_params[:'q'] = opts[:'q'] if !opts[:'q'].nil?
|
|
411
|
-
query_params[:'sort'] = opts[:'sort'] if !opts[:'sort'].nil?
|
|
412
|
-
query_params[:'page'] = opts[:'page'] if !opts[:'page'].nil?
|
|
413
|
-
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
414
491
|
|
|
415
492
|
# header parameters
|
|
416
493
|
header_params = opts[:header_params] || {}
|
|
@@ -424,13 +501,13 @@ module Crisphive
|
|
|
424
501
|
post_body = opts[:debug_body]
|
|
425
502
|
|
|
426
503
|
# return_type
|
|
427
|
-
return_type = opts[:debug_return_type] || '
|
|
504
|
+
return_type = opts[:debug_return_type] || 'GetJobRequest200Response'
|
|
428
505
|
|
|
429
506
|
# auth_names
|
|
430
507
|
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
431
508
|
|
|
432
509
|
new_options = opts.merge(
|
|
433
|
-
:operation => :"JobRequestBusinessApi.
|
|
510
|
+
:operation => :"JobRequestBusinessApi.get_job_request",
|
|
434
511
|
:header_params => header_params,
|
|
435
512
|
:query_params => query_params,
|
|
436
513
|
:form_params => form_params,
|
|
@@ -441,7 +518,1036 @@ module Crisphive
|
|
|
441
518
|
|
|
442
519
|
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
443
520
|
if @api_client.config.debugging
|
|
444
|
-
@api_client.config.logger.debug "API called: JobRequestBusinessApi#
|
|
521
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#get_job_request\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
522
|
+
end
|
|
523
|
+
return data, status_code, headers
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# Job timeline
|
|
527
|
+
# Per-status progress of a job's lifecycle (e.g. booked → confirmed → on the way → arrived → completed, following the business's configured workflow) — render it as a job-tracking timeline. Each status carries its state (completed | current | upcoming), when the job entered it, and the actions fired within it. entered_at may be null for upcoming steps and for older jobs predating the backfill.
|
|
528
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
529
|
+
# @param [Hash] opts the optional parameters
|
|
530
|
+
# @return [GetJobRequestTimeline200Response]
|
|
531
|
+
def get_job_request_timeline(id, opts = {})
|
|
532
|
+
data, _status_code, _headers = get_job_request_timeline_with_http_info(id, opts)
|
|
533
|
+
data
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
# Job timeline
|
|
537
|
+
# Per-status progress of a job's lifecycle (e.g. booked → confirmed → on the way → arrived → completed, following the business's configured workflow) — render it as a job-tracking timeline. Each status carries its state (completed | current | upcoming), when the job entered it, and the actions fired within it. entered_at may be null for upcoming steps and for older jobs predating the backfill.
|
|
538
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
539
|
+
# @param [Hash] opts the optional parameters
|
|
540
|
+
# @return [Array<(GetJobRequestTimeline200Response, Integer, Hash)>] GetJobRequestTimeline200Response data, response status code and response headers
|
|
541
|
+
def get_job_request_timeline_with_http_info(id, opts = {})
|
|
542
|
+
if @api_client.config.debugging
|
|
543
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.get_job_request_timeline ...'
|
|
544
|
+
end
|
|
545
|
+
# verify the required parameter 'id' is set
|
|
546
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
547
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.get_job_request_timeline"
|
|
548
|
+
end
|
|
549
|
+
# resource path
|
|
550
|
+
local_var_path = '/job-requests/{id}/timeline'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
551
|
+
|
|
552
|
+
# query parameters
|
|
553
|
+
query_params = opts[:query_params] || {}
|
|
554
|
+
|
|
555
|
+
# header parameters
|
|
556
|
+
header_params = opts[:header_params] || {}
|
|
557
|
+
# HTTP header 'Accept' (if needed)
|
|
558
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
559
|
+
|
|
560
|
+
# form parameters
|
|
561
|
+
form_params = opts[:form_params] || {}
|
|
562
|
+
|
|
563
|
+
# http body (model)
|
|
564
|
+
post_body = opts[:debug_body]
|
|
565
|
+
|
|
566
|
+
# return_type
|
|
567
|
+
return_type = opts[:debug_return_type] || 'GetJobRequestTimeline200Response'
|
|
568
|
+
|
|
569
|
+
# auth_names
|
|
570
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
571
|
+
|
|
572
|
+
new_options = opts.merge(
|
|
573
|
+
:operation => :"JobRequestBusinessApi.get_job_request_timeline",
|
|
574
|
+
:header_params => header_params,
|
|
575
|
+
:query_params => query_params,
|
|
576
|
+
:form_params => form_params,
|
|
577
|
+
:body => post_body,
|
|
578
|
+
:auth_names => auth_names,
|
|
579
|
+
:return_type => return_type
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
583
|
+
if @api_client.config.debugging
|
|
584
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#get_job_request_timeline\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
585
|
+
end
|
|
586
|
+
return data, status_code, headers
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
# One technician's real schedule (sessions + time off)
|
|
590
|
+
# The technician's ACTUAL occupancy over a date range: every job session on their lane (solo/lead and crew) plus approved time-off blocks. Weekly recurring working hours come from the technician-availability endpoints — combine both for the full availability picture (\"get crew availability\"). from/to are business-local dates (YYYY-MM-DD, inclusive); omitted = today .. +7 days; range max 31 days.
|
|
591
|
+
# @param id [String] Technician ID
|
|
592
|
+
# @param [Hash] opts the optional parameters
|
|
593
|
+
# @option opts [String] :from Start date (YYYY-MM-DD, business-local; default today)
|
|
594
|
+
# @option opts [String] :to End date (YYYY-MM-DD, inclusive; default from+7d; max range 31 days)
|
|
595
|
+
# @return [GetTechnicianSchedule200Response]
|
|
596
|
+
def get_technician_schedule(id, opts = {})
|
|
597
|
+
data, _status_code, _headers = get_technician_schedule_with_http_info(id, opts)
|
|
598
|
+
data
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
# One technician's real schedule (sessions + time off)
|
|
602
|
+
# The technician's ACTUAL occupancy over a date range: every job session on their lane (solo/lead and crew) plus approved time-off blocks. Weekly recurring working hours come from the technician-availability endpoints — combine both for the full availability picture (\"get crew availability\"). from/to are business-local dates (YYYY-MM-DD, inclusive); omitted = today .. +7 days; range max 31 days.
|
|
603
|
+
# @param id [String] Technician ID
|
|
604
|
+
# @param [Hash] opts the optional parameters
|
|
605
|
+
# @option opts [String] :from Start date (YYYY-MM-DD, business-local; default today)
|
|
606
|
+
# @option opts [String] :to End date (YYYY-MM-DD, inclusive; default from+7d; max range 31 days)
|
|
607
|
+
# @return [Array<(GetTechnicianSchedule200Response, Integer, Hash)>] GetTechnicianSchedule200Response data, response status code and response headers
|
|
608
|
+
def get_technician_schedule_with_http_info(id, opts = {})
|
|
609
|
+
if @api_client.config.debugging
|
|
610
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.get_technician_schedule ...'
|
|
611
|
+
end
|
|
612
|
+
# verify the required parameter 'id' is set
|
|
613
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
614
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.get_technician_schedule"
|
|
615
|
+
end
|
|
616
|
+
# resource path
|
|
617
|
+
local_var_path = '/technicians/{id}/schedule'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
618
|
+
|
|
619
|
+
# query parameters
|
|
620
|
+
query_params = opts[:query_params] || {}
|
|
621
|
+
query_params[:'from'] = opts[:'from'] if !opts[:'from'].nil?
|
|
622
|
+
query_params[:'to'] = opts[:'to'] if !opts[:'to'].nil?
|
|
623
|
+
|
|
624
|
+
# header parameters
|
|
625
|
+
header_params = opts[:header_params] || {}
|
|
626
|
+
# HTTP header 'Accept' (if needed)
|
|
627
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
628
|
+
|
|
629
|
+
# form parameters
|
|
630
|
+
form_params = opts[:form_params] || {}
|
|
631
|
+
|
|
632
|
+
# http body (model)
|
|
633
|
+
post_body = opts[:debug_body]
|
|
634
|
+
|
|
635
|
+
# return_type
|
|
636
|
+
return_type = opts[:debug_return_type] || 'GetTechnicianSchedule200Response'
|
|
637
|
+
|
|
638
|
+
# auth_names
|
|
639
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
640
|
+
|
|
641
|
+
new_options = opts.merge(
|
|
642
|
+
:operation => :"JobRequestBusinessApi.get_technician_schedule",
|
|
643
|
+
:header_params => header_params,
|
|
644
|
+
:query_params => query_params,
|
|
645
|
+
:form_params => form_params,
|
|
646
|
+
:body => post_body,
|
|
647
|
+
:auth_names => auth_names,
|
|
648
|
+
:return_type => return_type
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
652
|
+
if @api_client.config.debugging
|
|
653
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#get_technician_schedule\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
654
|
+
end
|
|
655
|
+
return data, status_code, headers
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
# Matching crew candidates for a job
|
|
659
|
+
# RE-STAFFING candidates for a CONFIRMED, SCHEDULED job (not yet completed/archived) — any earlier or later stage returns 409 JOB_REQUEST_INVALID_TRANSITION. This is the pool of technicians who could REPLACE the current crew: the currently assigned lead and buddies are deliberately excluded (they are the status quo, not an option), so on a small roster an empty `leads` list is a normal answer, not an error. For pre-booking discovery (\"who could take this job before it is confirmed?\") use listJobRequestBookingWindows / listMatchingSlots / the time-segments grid instead. Candidates are matched and ranked by the smart-assignment engine — skills per crew slot, weekly availability, existing schedule, time off and travel are all checked; each carries a score breakdown (distance, travel, matched skills) plus the exact on-site session plan they would work. NOT a raw roster list (use GET /technicians for that). Returns the ranked feasible LEAD pool by default; pass include_buddies=true to also return per-slot buddy pools, include_vehicle=true to include the available-vehicle list. force_lead_id checks one specific technician: returns only that lead (with their crew combo) if feasible, else 409 JOB_REQUEST_NO_TECHNICIAN_AVAILABLE.
|
|
660
|
+
# @param id [String] Job request ID or short_code
|
|
661
|
+
# @param [Hash] opts the optional parameters
|
|
662
|
+
# @option opts [Boolean] :include_buddies Also return buddy candidate pools
|
|
663
|
+
# @option opts [Boolean] :include_vehicle Also return the available-vehicle list
|
|
664
|
+
# @option opts [String] :force_lead_id Check a specific technician as lead — returns only that lead if feasible, else 409
|
|
665
|
+
# @return [ListCrewCandidates200Response]
|
|
666
|
+
def list_crew_candidates(id, opts = {})
|
|
667
|
+
data, _status_code, _headers = list_crew_candidates_with_http_info(id, opts)
|
|
668
|
+
data
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
# Matching crew candidates for a job
|
|
672
|
+
# RE-STAFFING candidates for a CONFIRMED, SCHEDULED job (not yet completed/archived) — any earlier or later stage returns 409 JOB_REQUEST_INVALID_TRANSITION. This is the pool of technicians who could REPLACE the current crew: the currently assigned lead and buddies are deliberately excluded (they are the status quo, not an option), so on a small roster an empty `leads` list is a normal answer, not an error. For pre-booking discovery (\"who could take this job before it is confirmed?\") use listJobRequestBookingWindows / listMatchingSlots / the time-segments grid instead. Candidates are matched and ranked by the smart-assignment engine — skills per crew slot, weekly availability, existing schedule, time off and travel are all checked; each carries a score breakdown (distance, travel, matched skills) plus the exact on-site session plan they would work. NOT a raw roster list (use GET /technicians for that). Returns the ranked feasible LEAD pool by default; pass include_buddies=true to also return per-slot buddy pools, include_vehicle=true to include the available-vehicle list. force_lead_id checks one specific technician: returns only that lead (with their crew combo) if feasible, else 409 JOB_REQUEST_NO_TECHNICIAN_AVAILABLE.
|
|
673
|
+
# @param id [String] Job request ID or short_code
|
|
674
|
+
# @param [Hash] opts the optional parameters
|
|
675
|
+
# @option opts [Boolean] :include_buddies Also return buddy candidate pools
|
|
676
|
+
# @option opts [Boolean] :include_vehicle Also return the available-vehicle list
|
|
677
|
+
# @option opts [String] :force_lead_id Check a specific technician as lead — returns only that lead if feasible, else 409
|
|
678
|
+
# @return [Array<(ListCrewCandidates200Response, Integer, Hash)>] ListCrewCandidates200Response data, response status code and response headers
|
|
679
|
+
def list_crew_candidates_with_http_info(id, opts = {})
|
|
680
|
+
if @api_client.config.debugging
|
|
681
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_crew_candidates ...'
|
|
682
|
+
end
|
|
683
|
+
# verify the required parameter 'id' is set
|
|
684
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
685
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.list_crew_candidates"
|
|
686
|
+
end
|
|
687
|
+
# resource path
|
|
688
|
+
local_var_path = '/job-requests/{id}/crew-candidates'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
689
|
+
|
|
690
|
+
# query parameters
|
|
691
|
+
query_params = opts[:query_params] || {}
|
|
692
|
+
query_params[:'include_buddies'] = opts[:'include_buddies'] if !opts[:'include_buddies'].nil?
|
|
693
|
+
query_params[:'include_vehicle'] = opts[:'include_vehicle'] if !opts[:'include_vehicle'].nil?
|
|
694
|
+
query_params[:'force_lead_id'] = opts[:'force_lead_id'] if !opts[:'force_lead_id'].nil?
|
|
695
|
+
|
|
696
|
+
# header parameters
|
|
697
|
+
header_params = opts[:header_params] || {}
|
|
698
|
+
# HTTP header 'Accept' (if needed)
|
|
699
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
700
|
+
|
|
701
|
+
# form parameters
|
|
702
|
+
form_params = opts[:form_params] || {}
|
|
703
|
+
|
|
704
|
+
# http body (model)
|
|
705
|
+
post_body = opts[:debug_body]
|
|
706
|
+
|
|
707
|
+
# return_type
|
|
708
|
+
return_type = opts[:debug_return_type] || 'ListCrewCandidates200Response'
|
|
709
|
+
|
|
710
|
+
# auth_names
|
|
711
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
712
|
+
|
|
713
|
+
new_options = opts.merge(
|
|
714
|
+
:operation => :"JobRequestBusinessApi.list_crew_candidates",
|
|
715
|
+
:header_params => header_params,
|
|
716
|
+
:query_params => query_params,
|
|
717
|
+
:form_params => form_params,
|
|
718
|
+
:body => post_body,
|
|
719
|
+
:auth_names => auth_names,
|
|
720
|
+
:return_type => return_type
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
724
|
+
if @api_client.config.debugging
|
|
725
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_crew_candidates\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
726
|
+
end
|
|
727
|
+
return data, status_code, headers
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# Rank technicians for a P0 emergency insert
|
|
731
|
+
# Returns the technicians who could take the emergency job at the requested start, ranked FASTEST-ARRIVAL first (arrival beats route efficiency for a P0). The response also carries a historical `crew_recommendation` (median crew size on comparable completed jobs + mandatory disclaimer — AC-2). Booked technicians are still candidates — each entry carries the displacement preview (which lower-priority jobs would be pushed, per day) that committing to them would cause; total_moves=0 means a free slot. P0 jobs are never displaced; P1 only by a P0. ETA is estimated from the technician's start location (no live GPS). `after_hours_override=true` — the coordinator has phoned the technician — drops the non-working-day rejection AND each candidate's working-hours/time-off feasibility check; an affected candidate carries a per-technician TIME_OFF_OVERLAP warning instead. This is THE phone list for an after-hours insert: it ranks even on a day with no working hours once the flag is set. Feed the chosen technician_id into emergency/preview + emergency/commit. 409 NEXT STEPS: EMERGENCY_RESCHEDULE_NOT_ELIGIBLE — the job cannot be emergency-inserted; `data.failed_precondition` names which (not_quoted | archived | completed | not_p0 | smart_assign_unavailable): fix the job state or use a normal confirm. EMERGENCY_RESCHEDULE_CREW_UNSUPPORTED — crew jobs cannot use the emergency flow (v1, `data.crew_size` = lead + buddies): staff via confirm/reassign instead. EMERGENCY_RESCHEDULE_MULTIDAY_UNSUPPORTED — either a confirmed multi-day job (`data.session_count`/`data.session_dates`; use the normal reassign flow) or a single visit longer than the structural span bound, in which case `data.reason=visit_too_long` + `data.blockers[0]` (visit_minutes/max_minutes) name it — no remedy but a shorter visit. EMERGENCY_RESCHEDULE_NO_WORKING_DAY — the chosen date has no working hours (`data.business_timezone`/`data.requested_weekday`): pick a working day, or set after_hours_override=true (the coordinator has phoned someone) to rank candidates anyway. EMERGENCY_RESCHEDULE_IN_PAST — start time already passed: pick a future time; `data` carries the timezone the naive start_at was read in (`business_timezone`) plus the instant it resolved to, so a start that looks future on the caller's own clock can be diagnosed without guessing.
|
|
732
|
+
# @param job_request_emergency_candidates_request [JobRequestEmergencyCandidatesRequest] Emergency job + desired start
|
|
733
|
+
# @param [Hash] opts the optional parameters
|
|
734
|
+
# @return [ListEmergencyCandidates200Response]
|
|
735
|
+
def list_emergency_candidates(job_request_emergency_candidates_request, opts = {})
|
|
736
|
+
data, _status_code, _headers = list_emergency_candidates_with_http_info(job_request_emergency_candidates_request, opts)
|
|
737
|
+
data
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
# Rank technicians for a P0 emergency insert
|
|
741
|
+
# Returns the technicians who could take the emergency job at the requested start, ranked FASTEST-ARRIVAL first (arrival beats route efficiency for a P0). The response also carries a historical `crew_recommendation` (median crew size on comparable completed jobs + mandatory disclaimer — AC-2). Booked technicians are still candidates — each entry carries the displacement preview (which lower-priority jobs would be pushed, per day) that committing to them would cause; total_moves=0 means a free slot. P0 jobs are never displaced; P1 only by a P0. ETA is estimated from the technician's start location (no live GPS). `after_hours_override=true` — the coordinator has phoned the technician — drops the non-working-day rejection AND each candidate's working-hours/time-off feasibility check; an affected candidate carries a per-technician TIME_OFF_OVERLAP warning instead. This is THE phone list for an after-hours insert: it ranks even on a day with no working hours once the flag is set. Feed the chosen technician_id into emergency/preview + emergency/commit. 409 NEXT STEPS: EMERGENCY_RESCHEDULE_NOT_ELIGIBLE — the job cannot be emergency-inserted; `data.failed_precondition` names which (not_quoted | archived | completed | not_p0 | smart_assign_unavailable): fix the job state or use a normal confirm. EMERGENCY_RESCHEDULE_CREW_UNSUPPORTED — crew jobs cannot use the emergency flow (v1, `data.crew_size` = lead + buddies): staff via confirm/reassign instead. EMERGENCY_RESCHEDULE_MULTIDAY_UNSUPPORTED — either a confirmed multi-day job (`data.session_count`/`data.session_dates`; use the normal reassign flow) or a single visit longer than the structural span bound, in which case `data.reason=visit_too_long` + `data.blockers[0]` (visit_minutes/max_minutes) name it — no remedy but a shorter visit. EMERGENCY_RESCHEDULE_NO_WORKING_DAY — the chosen date has no working hours (`data.business_timezone`/`data.requested_weekday`): pick a working day, or set after_hours_override=true (the coordinator has phoned someone) to rank candidates anyway. EMERGENCY_RESCHEDULE_IN_PAST — start time already passed: pick a future time; `data` carries the timezone the naive start_at was read in (`business_timezone`) plus the instant it resolved to, so a start that looks future on the caller's own clock can be diagnosed without guessing.
|
|
742
|
+
# @param job_request_emergency_candidates_request [JobRequestEmergencyCandidatesRequest] Emergency job + desired start
|
|
743
|
+
# @param [Hash] opts the optional parameters
|
|
744
|
+
# @return [Array<(ListEmergencyCandidates200Response, Integer, Hash)>] ListEmergencyCandidates200Response data, response status code and response headers
|
|
745
|
+
def list_emergency_candidates_with_http_info(job_request_emergency_candidates_request, opts = {})
|
|
746
|
+
if @api_client.config.debugging
|
|
747
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_emergency_candidates ...'
|
|
748
|
+
end
|
|
749
|
+
# verify the required parameter 'job_request_emergency_candidates_request' is set
|
|
750
|
+
if @api_client.config.client_side_validation && job_request_emergency_candidates_request.nil?
|
|
751
|
+
fail ArgumentError, "Missing the required parameter 'job_request_emergency_candidates_request' when calling JobRequestBusinessApi.list_emergency_candidates"
|
|
752
|
+
end
|
|
753
|
+
# resource path
|
|
754
|
+
local_var_path = '/job-requests/emergency/candidates'
|
|
755
|
+
|
|
756
|
+
# query parameters
|
|
757
|
+
query_params = opts[:query_params] || {}
|
|
758
|
+
|
|
759
|
+
# header parameters
|
|
760
|
+
header_params = opts[:header_params] || {}
|
|
761
|
+
# HTTP header 'Accept' (if needed)
|
|
762
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
763
|
+
# HTTP header 'Content-Type'
|
|
764
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
765
|
+
if !content_type.nil?
|
|
766
|
+
header_params['Content-Type'] = content_type
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
# form parameters
|
|
770
|
+
form_params = opts[:form_params] || {}
|
|
771
|
+
|
|
772
|
+
# http body (model)
|
|
773
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_emergency_candidates_request)
|
|
774
|
+
|
|
775
|
+
# return_type
|
|
776
|
+
return_type = opts[:debug_return_type] || 'ListEmergencyCandidates200Response'
|
|
777
|
+
|
|
778
|
+
# auth_names
|
|
779
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
780
|
+
|
|
781
|
+
new_options = opts.merge(
|
|
782
|
+
:operation => :"JobRequestBusinessApi.list_emergency_candidates",
|
|
783
|
+
:header_params => header_params,
|
|
784
|
+
:query_params => query_params,
|
|
785
|
+
:form_params => form_params,
|
|
786
|
+
:body => post_body,
|
|
787
|
+
:auth_names => auth_names,
|
|
788
|
+
:return_type => return_type
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
792
|
+
if @api_client.config.debugging
|
|
793
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_emergency_candidates\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
794
|
+
end
|
|
795
|
+
return data, status_code, headers
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
# Booking availability
|
|
799
|
+
# Real-time appointment availability from the scheduling engine: returns the bookable date + time-period windows given technician capacity, working hours and service-territory coverage. Call this before creating a job request and offer the customer ONLY the returned windows — it prevents unschedulable bookings.
|
|
800
|
+
# @param x_timezone [String] Customer IANA timezone
|
|
801
|
+
# @param [Hash] opts the optional parameters
|
|
802
|
+
# @option opts [String] :from Start YYYY-MM-DD
|
|
803
|
+
# @option opts [String] :to End YYYY-MM-DD
|
|
804
|
+
# @return [ListJobRequestBookingWindows200Response]
|
|
805
|
+
def list_job_request_booking_windows(x_timezone, opts = {})
|
|
806
|
+
data, _status_code, _headers = list_job_request_booking_windows_with_http_info(x_timezone, opts)
|
|
807
|
+
data
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
# Booking availability
|
|
811
|
+
# Real-time appointment availability from the scheduling engine: returns the bookable date + time-period windows given technician capacity, working hours and service-territory coverage. Call this before creating a job request and offer the customer ONLY the returned windows — it prevents unschedulable bookings.
|
|
812
|
+
# @param x_timezone [String] Customer IANA timezone
|
|
813
|
+
# @param [Hash] opts the optional parameters
|
|
814
|
+
# @option opts [String] :from Start YYYY-MM-DD
|
|
815
|
+
# @option opts [String] :to End YYYY-MM-DD
|
|
816
|
+
# @return [Array<(ListJobRequestBookingWindows200Response, Integer, Hash)>] ListJobRequestBookingWindows200Response data, response status code and response headers
|
|
817
|
+
def list_job_request_booking_windows_with_http_info(x_timezone, opts = {})
|
|
818
|
+
if @api_client.config.debugging
|
|
819
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_job_request_booking_windows ...'
|
|
820
|
+
end
|
|
821
|
+
# verify the required parameter 'x_timezone' is set
|
|
822
|
+
if @api_client.config.client_side_validation && x_timezone.nil?
|
|
823
|
+
fail ArgumentError, "Missing the required parameter 'x_timezone' when calling JobRequestBusinessApi.list_job_request_booking_windows"
|
|
824
|
+
end
|
|
825
|
+
# resource path
|
|
826
|
+
local_var_path = '/job-requests/booking-windows'
|
|
827
|
+
|
|
828
|
+
# query parameters
|
|
829
|
+
query_params = opts[:query_params] || {}
|
|
830
|
+
query_params[:'from'] = opts[:'from'] if !opts[:'from'].nil?
|
|
831
|
+
query_params[:'to'] = opts[:'to'] if !opts[:'to'].nil?
|
|
832
|
+
|
|
833
|
+
# header parameters
|
|
834
|
+
header_params = opts[:header_params] || {}
|
|
835
|
+
# HTTP header 'Accept' (if needed)
|
|
836
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
837
|
+
header_params[:'X-Timezone'] = x_timezone
|
|
838
|
+
|
|
839
|
+
# form parameters
|
|
840
|
+
form_params = opts[:form_params] || {}
|
|
841
|
+
|
|
842
|
+
# http body (model)
|
|
843
|
+
post_body = opts[:debug_body]
|
|
844
|
+
|
|
845
|
+
# return_type
|
|
846
|
+
return_type = opts[:debug_return_type] || 'ListJobRequestBookingWindows200Response'
|
|
847
|
+
|
|
848
|
+
# auth_names
|
|
849
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
850
|
+
|
|
851
|
+
new_options = opts.merge(
|
|
852
|
+
:operation => :"JobRequestBusinessApi.list_job_request_booking_windows",
|
|
853
|
+
:header_params => header_params,
|
|
854
|
+
:query_params => query_params,
|
|
855
|
+
:form_params => form_params,
|
|
856
|
+
:body => post_body,
|
|
857
|
+
:auth_names => auth_names,
|
|
858
|
+
:return_type => return_type
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
862
|
+
if @api_client.config.debugging
|
|
863
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_job_request_booking_windows\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
864
|
+
end
|
|
865
|
+
return data, status_code, headers
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
# Poll for new & changed job requests (sync feed)
|
|
869
|
+
# Keep an external system (your CRM, ERP or field-operations tool) in sync with bookings WITHOUT re-listing everything: returns the job requests (work orders) whose state changed (created, status transition, reschedule, soft-delete/archive) at or after the `since` cursor, ordered oldest-change-first (updated_at ASC). How to use it: (1) On your first poll OMIT `since` — the server primes the cursor at \"now\", returns no items and a `next_since`. (2) Store `next_since` and pass it as `since` on the next poll. (3) Apply each returned item to your store by UPSERTING on `id` (the server re-scans a ~5s safety window, so the same job may appear again — never blindly append). (4) If `has_more` is true the page filled to `limit` and more changes are already waiting — poll again immediately; otherwise wait your normal interval (e.g. 5–15s). This is NOT pagination — it is a time-keyed change feed. Use the paginated GET /job-requests for the initial bulk load, then this endpoint to stay live. Filters (status_keys, customer_id, …) narrow the feed to the slice you care about.
|
|
870
|
+
# @param [Hash] opts the optional parameters
|
|
871
|
+
# @option opts [String] :status_keys Comma-separated status slugs — only surface changes to jobs in these statuses
|
|
872
|
+
# @option opts [String] :priority Priority filter (p0|p1|p2|p3)
|
|
873
|
+
# @option opts [String] :customer_id Only changes to this customer's jobs (UUID)
|
|
874
|
+
# @option opts [String] :technician_id Only changes to jobs assigned to this technician (UUID)
|
|
875
|
+
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to)
|
|
876
|
+
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
877
|
+
# @option opts [String] :since RFC3339 cursor from the prior response's next_since. OMIT on the first poll to prime the cursor at server-now.
|
|
878
|
+
# @option opts [Integer] :limit Max changes per poll (default 15, max 1000). If the page fills, has_more=true.
|
|
879
|
+
# @return [ListJobRequestChanges200Response]
|
|
880
|
+
def list_job_request_changes(opts = {})
|
|
881
|
+
data, _status_code, _headers = list_job_request_changes_with_http_info(opts)
|
|
882
|
+
data
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
# Poll for new & changed job requests (sync feed)
|
|
886
|
+
# Keep an external system (your CRM, ERP or field-operations tool) in sync with bookings WITHOUT re-listing everything: returns the job requests (work orders) whose state changed (created, status transition, reschedule, soft-delete/archive) at or after the `since` cursor, ordered oldest-change-first (updated_at ASC). How to use it: (1) On your first poll OMIT `since` — the server primes the cursor at \"now\", returns no items and a `next_since`. (2) Store `next_since` and pass it as `since` on the next poll. (3) Apply each returned item to your store by UPSERTING on `id` (the server re-scans a ~5s safety window, so the same job may appear again — never blindly append). (4) If `has_more` is true the page filled to `limit` and more changes are already waiting — poll again immediately; otherwise wait your normal interval (e.g. 5–15s). This is NOT pagination — it is a time-keyed change feed. Use the paginated GET /job-requests for the initial bulk load, then this endpoint to stay live. Filters (status_keys, customer_id, …) narrow the feed to the slice you care about.
|
|
887
|
+
# @param [Hash] opts the optional parameters
|
|
888
|
+
# @option opts [String] :status_keys Comma-separated status slugs — only surface changes to jobs in these statuses
|
|
889
|
+
# @option opts [String] :priority Priority filter (p0|p1|p2|p3)
|
|
890
|
+
# @option opts [String] :customer_id Only changes to this customer's jobs (UUID)
|
|
891
|
+
# @option opts [String] :technician_id Only changes to jobs assigned to this technician (UUID)
|
|
892
|
+
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to)
|
|
893
|
+
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
894
|
+
# @option opts [String] :since RFC3339 cursor from the prior response's next_since. OMIT on the first poll to prime the cursor at server-now.
|
|
895
|
+
# @option opts [Integer] :limit Max changes per poll (default 15, max 1000). If the page fills, has_more=true.
|
|
896
|
+
# @return [Array<(ListJobRequestChanges200Response, Integer, Hash)>] ListJobRequestChanges200Response data, response status code and response headers
|
|
897
|
+
def list_job_request_changes_with_http_info(opts = {})
|
|
898
|
+
if @api_client.config.debugging
|
|
899
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_job_request_changes ...'
|
|
900
|
+
end
|
|
901
|
+
# resource path
|
|
902
|
+
local_var_path = '/job-requests/changes'
|
|
903
|
+
|
|
904
|
+
# query parameters
|
|
905
|
+
query_params = opts[:query_params] || {}
|
|
906
|
+
query_params[:'status_keys'] = opts[:'status_keys'] if !opts[:'status_keys'].nil?
|
|
907
|
+
query_params[:'priority'] = opts[:'priority'] if !opts[:'priority'].nil?
|
|
908
|
+
query_params[:'customer_id'] = opts[:'customer_id'] if !opts[:'customer_id'].nil?
|
|
909
|
+
query_params[:'technician_id'] = opts[:'technician_id'] if !opts[:'technician_id'].nil?
|
|
910
|
+
query_params[:'scheduled_from'] = opts[:'scheduled_from'] if !opts[:'scheduled_from'].nil?
|
|
911
|
+
query_params[:'scheduled_to'] = opts[:'scheduled_to'] if !opts[:'scheduled_to'].nil?
|
|
912
|
+
query_params[:'since'] = opts[:'since'] if !opts[:'since'].nil?
|
|
913
|
+
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
914
|
+
|
|
915
|
+
# header parameters
|
|
916
|
+
header_params = opts[:header_params] || {}
|
|
917
|
+
# HTTP header 'Accept' (if needed)
|
|
918
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
919
|
+
|
|
920
|
+
# form parameters
|
|
921
|
+
form_params = opts[:form_params] || {}
|
|
922
|
+
|
|
923
|
+
# http body (model)
|
|
924
|
+
post_body = opts[:debug_body]
|
|
925
|
+
|
|
926
|
+
# return_type
|
|
927
|
+
return_type = opts[:debug_return_type] || 'ListJobRequestChanges200Response'
|
|
928
|
+
|
|
929
|
+
# auth_names
|
|
930
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
931
|
+
|
|
932
|
+
new_options = opts.merge(
|
|
933
|
+
:operation => :"JobRequestBusinessApi.list_job_request_changes",
|
|
934
|
+
:header_params => header_params,
|
|
935
|
+
:query_params => query_params,
|
|
936
|
+
:form_params => form_params,
|
|
937
|
+
:body => post_body,
|
|
938
|
+
:auth_names => auth_names,
|
|
939
|
+
:return_type => return_type
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
943
|
+
if @api_client.config.debugging
|
|
944
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_job_request_changes\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
945
|
+
end
|
|
946
|
+
return data, status_code, headers
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
# List job requests
|
|
950
|
+
# Paginated list of the business's bookings (work orders) with dispatch-oriented filters: workflow status, customer, assigned technician, scheduled date range and free-text search over code/description. This is also the SCHEDULE query: combine technician_id + scheduled_from/scheduled_to to read one technician's agenda for a day or week (e.g. \"what is Alex doing tomorrow\"), or just the date range for the whole team's calendar.
|
|
951
|
+
# @param [Hash] opts the optional parameters
|
|
952
|
+
# @option opts [String] :status_keys Comma-separated status slugs
|
|
953
|
+
# @option opts [String] :status active (default) | archived | all
|
|
954
|
+
# @option opts [String] :priority Priority filter (p0|p1|p2|p3)
|
|
955
|
+
# @option opts [String] :customer_id Customer UUID
|
|
956
|
+
# @option opts [String] :technician_id Technician UUID
|
|
957
|
+
# @option opts [String] :service_area_id Service-area UUID (board zone filter)
|
|
958
|
+
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to)
|
|
959
|
+
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
960
|
+
# @option opts [String] :completed_from Filter by completion time from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to). Counts jobs by when they were completed regardless of reschedules.
|
|
961
|
+
# @option opts [String] :completed_to Filter by completion time to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
962
|
+
# @option opts [String] :q Search short_code or description (case-insensitive, partial match)
|
|
963
|
+
# @option opts [String] :sort Sort key: created_at:desc (default) | created_at:asc | scheduled_at:asc | scheduled_at:desc | priority:asc (P0 first) | priority:desc
|
|
964
|
+
# @option opts [Integer] :page Page number
|
|
965
|
+
# @option opts [Integer] :limit Page size
|
|
966
|
+
# @return [ListJobRequests200Response]
|
|
967
|
+
def list_job_requests(opts = {})
|
|
968
|
+
data, _status_code, _headers = list_job_requests_with_http_info(opts)
|
|
969
|
+
data
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
# List job requests
|
|
973
|
+
# Paginated list of the business's bookings (work orders) with dispatch-oriented filters: workflow status, customer, assigned technician, scheduled date range and free-text search over code/description. This is also the SCHEDULE query: combine technician_id + scheduled_from/scheduled_to to read one technician's agenda for a day or week (e.g. \"what is Alex doing tomorrow\"), or just the date range for the whole team's calendar.
|
|
974
|
+
# @param [Hash] opts the optional parameters
|
|
975
|
+
# @option opts [String] :status_keys Comma-separated status slugs
|
|
976
|
+
# @option opts [String] :status active (default) | archived | all
|
|
977
|
+
# @option opts [String] :priority Priority filter (p0|p1|p2|p3)
|
|
978
|
+
# @option opts [String] :customer_id Customer UUID
|
|
979
|
+
# @option opts [String] :technician_id Technician UUID
|
|
980
|
+
# @option opts [String] :service_area_id Service-area UUID (board zone filter)
|
|
981
|
+
# @option opts [String] :scheduled_from Filter from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to)
|
|
982
|
+
# @option opts [String] :scheduled_to Filter to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
983
|
+
# @option opts [String] :completed_from Filter by completion time from (YYYY-MM-DD = start of that day in the business timezone, or RFC3339); range is [from, to). Counts jobs by when they were completed regardless of reschedules.
|
|
984
|
+
# @option opts [String] :completed_to Filter by completion time to (YYYY-MM-DD = end of that day in the business timezone, or RFC3339), exclusive
|
|
985
|
+
# @option opts [String] :q Search short_code or description (case-insensitive, partial match)
|
|
986
|
+
# @option opts [String] :sort Sort key: created_at:desc (default) | created_at:asc | scheduled_at:asc | scheduled_at:desc | priority:asc (P0 first) | priority:desc
|
|
987
|
+
# @option opts [Integer] :page Page number
|
|
988
|
+
# @option opts [Integer] :limit Page size
|
|
989
|
+
# @return [Array<(ListJobRequests200Response, Integer, Hash)>] ListJobRequests200Response data, response status code and response headers
|
|
990
|
+
def list_job_requests_with_http_info(opts = {})
|
|
991
|
+
if @api_client.config.debugging
|
|
992
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_job_requests ...'
|
|
993
|
+
end
|
|
994
|
+
# resource path
|
|
995
|
+
local_var_path = '/job-requests'
|
|
996
|
+
|
|
997
|
+
# query parameters
|
|
998
|
+
query_params = opts[:query_params] || {}
|
|
999
|
+
query_params[:'status_keys'] = opts[:'status_keys'] if !opts[:'status_keys'].nil?
|
|
1000
|
+
query_params[:'status'] = opts[:'status'] if !opts[:'status'].nil?
|
|
1001
|
+
query_params[:'priority'] = opts[:'priority'] if !opts[:'priority'].nil?
|
|
1002
|
+
query_params[:'customer_id'] = opts[:'customer_id'] if !opts[:'customer_id'].nil?
|
|
1003
|
+
query_params[:'technician_id'] = opts[:'technician_id'] if !opts[:'technician_id'].nil?
|
|
1004
|
+
query_params[:'service_area_id'] = opts[:'service_area_id'] if !opts[:'service_area_id'].nil?
|
|
1005
|
+
query_params[:'scheduled_from'] = opts[:'scheduled_from'] if !opts[:'scheduled_from'].nil?
|
|
1006
|
+
query_params[:'scheduled_to'] = opts[:'scheduled_to'] if !opts[:'scheduled_to'].nil?
|
|
1007
|
+
query_params[:'completed_from'] = opts[:'completed_from'] if !opts[:'completed_from'].nil?
|
|
1008
|
+
query_params[:'completed_to'] = opts[:'completed_to'] if !opts[:'completed_to'].nil?
|
|
1009
|
+
query_params[:'q'] = opts[:'q'] if !opts[:'q'].nil?
|
|
1010
|
+
query_params[:'sort'] = opts[:'sort'] if !opts[:'sort'].nil?
|
|
1011
|
+
query_params[:'page'] = opts[:'page'] if !opts[:'page'].nil?
|
|
1012
|
+
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
1013
|
+
|
|
1014
|
+
# header parameters
|
|
1015
|
+
header_params = opts[:header_params] || {}
|
|
1016
|
+
# HTTP header 'Accept' (if needed)
|
|
1017
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1018
|
+
|
|
1019
|
+
# form parameters
|
|
1020
|
+
form_params = opts[:form_params] || {}
|
|
1021
|
+
|
|
1022
|
+
# http body (model)
|
|
1023
|
+
post_body = opts[:debug_body]
|
|
1024
|
+
|
|
1025
|
+
# return_type
|
|
1026
|
+
return_type = opts[:debug_return_type] || 'ListJobRequests200Response'
|
|
1027
|
+
|
|
1028
|
+
# auth_names
|
|
1029
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1030
|
+
|
|
1031
|
+
new_options = opts.merge(
|
|
1032
|
+
:operation => :"JobRequestBusinessApi.list_job_requests",
|
|
1033
|
+
:header_params => header_params,
|
|
1034
|
+
:query_params => query_params,
|
|
1035
|
+
:form_params => form_params,
|
|
1036
|
+
:body => post_body,
|
|
1037
|
+
:auth_names => auth_names,
|
|
1038
|
+
:return_type => return_type
|
|
1039
|
+
)
|
|
1040
|
+
|
|
1041
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
1042
|
+
if @api_client.config.debugging
|
|
1043
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_job_requests\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1044
|
+
end
|
|
1045
|
+
return data, status_code, headers
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
# Matching time slots for a quoted job
|
|
1049
|
+
# Bookable arrival-window slots for a quoted job, computed by the smart-assignment matching engine: each slot lists the technicians actually available to start then (skills, weekly availability, existing schedule, time off and travel all checked), with a per-technician match score. Use it to find and offer appointment times an agent or integration can then confirm (POST /job-requests/{id}/confirm with the slot's business_time.datetime). Same grid the end-customer's slot picker shows; slot width defaults to the business's arrival window — override via ?step_minutes (5–240). The job must be quoted first (the quote sets the visit duration the matcher schedules).
|
|
1050
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
1051
|
+
# @param [Hash] opts the optional parameters
|
|
1052
|
+
# @option opts [Integer] :step_minutes Slot step in minutes (default: business arrival window, 5–240)
|
|
1053
|
+
# @return [ListMatchingSlots200Response]
|
|
1054
|
+
def list_matching_slots(id, opts = {})
|
|
1055
|
+
data, _status_code, _headers = list_matching_slots_with_http_info(id, opts)
|
|
1056
|
+
data
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
# Matching time slots for a quoted job
|
|
1060
|
+
# Bookable arrival-window slots for a quoted job, computed by the smart-assignment matching engine: each slot lists the technicians actually available to start then (skills, weekly availability, existing schedule, time off and travel all checked), with a per-technician match score. Use it to find and offer appointment times an agent or integration can then confirm (POST /job-requests/{id}/confirm with the slot's business_time.datetime). Same grid the end-customer's slot picker shows; slot width defaults to the business's arrival window — override via ?step_minutes (5–240). The job must be quoted first (the quote sets the visit duration the matcher schedules).
|
|
1061
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
1062
|
+
# @param [Hash] opts the optional parameters
|
|
1063
|
+
# @option opts [Integer] :step_minutes Slot step in minutes (default: business arrival window, 5–240)
|
|
1064
|
+
# @return [Array<(ListMatchingSlots200Response, Integer, Hash)>] ListMatchingSlots200Response data, response status code and response headers
|
|
1065
|
+
def list_matching_slots_with_http_info(id, opts = {})
|
|
1066
|
+
if @api_client.config.debugging
|
|
1067
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_matching_slots ...'
|
|
1068
|
+
end
|
|
1069
|
+
# verify the required parameter 'id' is set
|
|
1070
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
1071
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.list_matching_slots"
|
|
1072
|
+
end
|
|
1073
|
+
# resource path
|
|
1074
|
+
local_var_path = '/job-requests/{id}/time-segments'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
1075
|
+
|
|
1076
|
+
# query parameters
|
|
1077
|
+
query_params = opts[:query_params] || {}
|
|
1078
|
+
query_params[:'step_minutes'] = opts[:'step_minutes'] if !opts[:'step_minutes'].nil?
|
|
1079
|
+
|
|
1080
|
+
# header parameters
|
|
1081
|
+
header_params = opts[:header_params] || {}
|
|
1082
|
+
# HTTP header 'Accept' (if needed)
|
|
1083
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1084
|
+
|
|
1085
|
+
# form parameters
|
|
1086
|
+
form_params = opts[:form_params] || {}
|
|
1087
|
+
|
|
1088
|
+
# http body (model)
|
|
1089
|
+
post_body = opts[:debug_body]
|
|
1090
|
+
|
|
1091
|
+
# return_type
|
|
1092
|
+
return_type = opts[:debug_return_type] || 'ListMatchingSlots200Response'
|
|
1093
|
+
|
|
1094
|
+
# auth_names
|
|
1095
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1096
|
+
|
|
1097
|
+
new_options = opts.merge(
|
|
1098
|
+
:operation => :"JobRequestBusinessApi.list_matching_slots",
|
|
1099
|
+
:header_params => header_params,
|
|
1100
|
+
:query_params => query_params,
|
|
1101
|
+
:form_params => form_params,
|
|
1102
|
+
:body => post_body,
|
|
1103
|
+
:auth_names => auth_names,
|
|
1104
|
+
:return_type => return_type
|
|
1105
|
+
)
|
|
1106
|
+
|
|
1107
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
1108
|
+
if @api_client.config.debugging
|
|
1109
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_matching_slots\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1110
|
+
end
|
|
1111
|
+
return data, status_code, headers
|
|
1112
|
+
end
|
|
1113
|
+
|
|
1114
|
+
# Find nearby feasible technicians (job-less location query)
|
|
1115
|
+
# Ranks who could serve a hypothetical visit at (lat,lng) starting `at` for `duration_minutes` — the engine applies the REAL hard filters (weekly hours, existing schedule, approved time-off, geographic service areas, optional skill floor) and returns candidates nearest-arrival first. ETA origin is each technician's start location (no live GPS). Use before creating a booking to propose realistic arrivals.
|
|
1116
|
+
# @param lat [Float] Latitude of the service location
|
|
1117
|
+
# @param lng [Float] Longitude of the service location
|
|
1118
|
+
# @param [Hash] opts the optional parameters
|
|
1119
|
+
# @option opts [String] :at Visit start (RFC3339, e.g. 2026-07-20T14:00:00Z; default now)
|
|
1120
|
+
# @option opts [Integer] :duration_minutes Visit length in minutes (default 60; 15–480)
|
|
1121
|
+
# @option opts [String] :skill_ids Comma-separated skill UUIDs to require/match
|
|
1122
|
+
# @option opts [Integer] :limit Max candidates (default 10, max 20)
|
|
1123
|
+
# @return [ListNearbyTechnicians200Response]
|
|
1124
|
+
def list_nearby_technicians(lat, lng, opts = {})
|
|
1125
|
+
data, _status_code, _headers = list_nearby_technicians_with_http_info(lat, lng, opts)
|
|
1126
|
+
data
|
|
1127
|
+
end
|
|
1128
|
+
|
|
1129
|
+
# Find nearby feasible technicians (job-less location query)
|
|
1130
|
+
# Ranks who could serve a hypothetical visit at (lat,lng) starting `at` for `duration_minutes` — the engine applies the REAL hard filters (weekly hours, existing schedule, approved time-off, geographic service areas, optional skill floor) and returns candidates nearest-arrival first. ETA origin is each technician's start location (no live GPS). Use before creating a booking to propose realistic arrivals.
|
|
1131
|
+
# @param lat [Float] Latitude of the service location
|
|
1132
|
+
# @param lng [Float] Longitude of the service location
|
|
1133
|
+
# @param [Hash] opts the optional parameters
|
|
1134
|
+
# @option opts [String] :at Visit start (RFC3339, e.g. 2026-07-20T14:00:00Z; default now)
|
|
1135
|
+
# @option opts [Integer] :duration_minutes Visit length in minutes (default 60; 15–480)
|
|
1136
|
+
# @option opts [String] :skill_ids Comma-separated skill UUIDs to require/match
|
|
1137
|
+
# @option opts [Integer] :limit Max candidates (default 10, max 20)
|
|
1138
|
+
# @return [Array<(ListNearbyTechnicians200Response, Integer, Hash)>] ListNearbyTechnicians200Response data, response status code and response headers
|
|
1139
|
+
def list_nearby_technicians_with_http_info(lat, lng, opts = {})
|
|
1140
|
+
if @api_client.config.debugging
|
|
1141
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.list_nearby_technicians ...'
|
|
1142
|
+
end
|
|
1143
|
+
# verify the required parameter 'lat' is set
|
|
1144
|
+
if @api_client.config.client_side_validation && lat.nil?
|
|
1145
|
+
fail ArgumentError, "Missing the required parameter 'lat' when calling JobRequestBusinessApi.list_nearby_technicians"
|
|
1146
|
+
end
|
|
1147
|
+
# verify the required parameter 'lng' is set
|
|
1148
|
+
if @api_client.config.client_side_validation && lng.nil?
|
|
1149
|
+
fail ArgumentError, "Missing the required parameter 'lng' when calling JobRequestBusinessApi.list_nearby_technicians"
|
|
1150
|
+
end
|
|
1151
|
+
# resource path
|
|
1152
|
+
local_var_path = '/technicians/nearby'
|
|
1153
|
+
|
|
1154
|
+
# query parameters
|
|
1155
|
+
query_params = opts[:query_params] || {}
|
|
1156
|
+
query_params[:'lat'] = lat
|
|
1157
|
+
query_params[:'lng'] = lng
|
|
1158
|
+
query_params[:'at'] = opts[:'at'] if !opts[:'at'].nil?
|
|
1159
|
+
query_params[:'duration_minutes'] = opts[:'duration_minutes'] if !opts[:'duration_minutes'].nil?
|
|
1160
|
+
query_params[:'skill_ids'] = opts[:'skill_ids'] if !opts[:'skill_ids'].nil?
|
|
1161
|
+
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
1162
|
+
|
|
1163
|
+
# header parameters
|
|
1164
|
+
header_params = opts[:header_params] || {}
|
|
1165
|
+
# HTTP header 'Accept' (if needed)
|
|
1166
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1167
|
+
|
|
1168
|
+
# form parameters
|
|
1169
|
+
form_params = opts[:form_params] || {}
|
|
1170
|
+
|
|
1171
|
+
# http body (model)
|
|
1172
|
+
post_body = opts[:debug_body]
|
|
1173
|
+
|
|
1174
|
+
# return_type
|
|
1175
|
+
return_type = opts[:debug_return_type] || 'ListNearbyTechnicians200Response'
|
|
1176
|
+
|
|
1177
|
+
# auth_names
|
|
1178
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1179
|
+
|
|
1180
|
+
new_options = opts.merge(
|
|
1181
|
+
:operation => :"JobRequestBusinessApi.list_nearby_technicians",
|
|
1182
|
+
:header_params => header_params,
|
|
1183
|
+
:query_params => query_params,
|
|
1184
|
+
:form_params => form_params,
|
|
1185
|
+
:body => post_body,
|
|
1186
|
+
:auth_names => auth_names,
|
|
1187
|
+
:return_type => return_type
|
|
1188
|
+
)
|
|
1189
|
+
|
|
1190
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
1191
|
+
if @api_client.config.debugging
|
|
1192
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#list_nearby_technicians\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1193
|
+
end
|
|
1194
|
+
return data, status_code, headers
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
# Preview re-staffing a technician's whole day (sick call)
|
|
1198
|
+
# Solves (WITHOUT writing) the re-staffing of every job on a technician's board for a date range: each job is handed to an ALTERNATE lead technician at its UNCHANGED window — the customer's appointment never moves, two overlapping jobs never land on the same alternate, and the absent technician is never a candidate. `date`/`until_date` are business-local calendar days (inclusive, ≤ 14 days). Jobs the planner cannot re-staff come back in `unresolved` with a `reason_code` (no qualified technician free / crew job / multi-day job / already in progress) — a partial plan is a normal 200, not an error. `solver.duration_ms` is server-side planner time; `solver.deterministic` is true (same input ⇒ same plan). Read-only, safe to repeat; copy `resolved[]` into the commit body. No time-off record is required to preview. When the strict pass leaves a job unresolved, its row ALSO carries `alternatives[]` — the relaxation ladder's priced options, cheapest constraint first (ABSENCE_RESOLVE_DESIGN.md §9): `reassign_out_of_area` (same window, a lead outside the job's zone — cost.distance_km/travel_minutes), then `reschedule_same_day` / `reschedule_later_day` (the earliest free window on a qualified lead, in-area before out-of-area, up to 3 working days past until_date — cost.customer_renotified, cost.day_offset, cost.sla_breached). Each option is a PROPOSAL: nothing is applied until the coordinator copies it into the commit body with its `alternative_kind` (+ `start_at`/`end_at` for a reschedule). `alternatives` is an empty array when even the ladder found nothing; `solver.alternatives_truncated` is true when the ladder's time budget cut the search short. Displacing another customer's job and overtime are deliberately NOT offered. See ABSENCE_RESOLVE_DESIGN.md.
|
|
1199
|
+
# @param job_request_absence_preview_request [JobRequestAbsencePreviewRequest] absent technician + date range (+ optional job subset)
|
|
1200
|
+
# @param [Hash] opts the optional parameters
|
|
1201
|
+
# @return [CommitAbsenceResolve200Response]
|
|
1202
|
+
def preview_absence_resolve(job_request_absence_preview_request, opts = {})
|
|
1203
|
+
data, _status_code, _headers = preview_absence_resolve_with_http_info(job_request_absence_preview_request, opts)
|
|
1204
|
+
data
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
# Preview re-staffing a technician's whole day (sick call)
|
|
1208
|
+
# Solves (WITHOUT writing) the re-staffing of every job on a technician's board for a date range: each job is handed to an ALTERNATE lead technician at its UNCHANGED window — the customer's appointment never moves, two overlapping jobs never land on the same alternate, and the absent technician is never a candidate. `date`/`until_date` are business-local calendar days (inclusive, ≤ 14 days). Jobs the planner cannot re-staff come back in `unresolved` with a `reason_code` (no qualified technician free / crew job / multi-day job / already in progress) — a partial plan is a normal 200, not an error. `solver.duration_ms` is server-side planner time; `solver.deterministic` is true (same input ⇒ same plan). Read-only, safe to repeat; copy `resolved[]` into the commit body. No time-off record is required to preview. When the strict pass leaves a job unresolved, its row ALSO carries `alternatives[]` — the relaxation ladder's priced options, cheapest constraint first (ABSENCE_RESOLVE_DESIGN.md §9): `reassign_out_of_area` (same window, a lead outside the job's zone — cost.distance_km/travel_minutes), then `reschedule_same_day` / `reschedule_later_day` (the earliest free window on a qualified lead, in-area before out-of-area, up to 3 working days past until_date — cost.customer_renotified, cost.day_offset, cost.sla_breached). Each option is a PROPOSAL: nothing is applied until the coordinator copies it into the commit body with its `alternative_kind` (+ `start_at`/`end_at` for a reschedule). `alternatives` is an empty array when even the ladder found nothing; `solver.alternatives_truncated` is true when the ladder's time budget cut the search short. Displacing another customer's job and overtime are deliberately NOT offered. See ABSENCE_RESOLVE_DESIGN.md.
|
|
1209
|
+
# @param job_request_absence_preview_request [JobRequestAbsencePreviewRequest] absent technician + date range (+ optional job subset)
|
|
1210
|
+
# @param [Hash] opts the optional parameters
|
|
1211
|
+
# @return [Array<(CommitAbsenceResolve200Response, Integer, Hash)>] CommitAbsenceResolve200Response data, response status code and response headers
|
|
1212
|
+
def preview_absence_resolve_with_http_info(job_request_absence_preview_request, opts = {})
|
|
1213
|
+
if @api_client.config.debugging
|
|
1214
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.preview_absence_resolve ...'
|
|
1215
|
+
end
|
|
1216
|
+
# verify the required parameter 'job_request_absence_preview_request' is set
|
|
1217
|
+
if @api_client.config.client_side_validation && job_request_absence_preview_request.nil?
|
|
1218
|
+
fail ArgumentError, "Missing the required parameter 'job_request_absence_preview_request' when calling JobRequestBusinessApi.preview_absence_resolve"
|
|
1219
|
+
end
|
|
1220
|
+
# resource path
|
|
1221
|
+
local_var_path = '/job-requests/absence/preview'
|
|
1222
|
+
|
|
1223
|
+
# query parameters
|
|
1224
|
+
query_params = opts[:query_params] || {}
|
|
1225
|
+
|
|
1226
|
+
# header parameters
|
|
1227
|
+
header_params = opts[:header_params] || {}
|
|
1228
|
+
# HTTP header 'Accept' (if needed)
|
|
1229
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1230
|
+
# HTTP header 'Content-Type'
|
|
1231
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1232
|
+
if !content_type.nil?
|
|
1233
|
+
header_params['Content-Type'] = content_type
|
|
1234
|
+
end
|
|
1235
|
+
|
|
1236
|
+
# form parameters
|
|
1237
|
+
form_params = opts[:form_params] || {}
|
|
1238
|
+
|
|
1239
|
+
# http body (model)
|
|
1240
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_absence_preview_request)
|
|
1241
|
+
|
|
1242
|
+
# return_type
|
|
1243
|
+
return_type = opts[:debug_return_type] || 'CommitAbsenceResolve200Response'
|
|
1244
|
+
|
|
1245
|
+
# auth_names
|
|
1246
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1247
|
+
|
|
1248
|
+
new_options = opts.merge(
|
|
1249
|
+
:operation => :"JobRequestBusinessApi.preview_absence_resolve",
|
|
1250
|
+
:header_params => header_params,
|
|
1251
|
+
:query_params => query_params,
|
|
1252
|
+
:form_params => form_params,
|
|
1253
|
+
:body => post_body,
|
|
1254
|
+
:auth_names => auth_names,
|
|
1255
|
+
:return_type => return_type
|
|
1256
|
+
)
|
|
1257
|
+
|
|
1258
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1259
|
+
if @api_client.config.debugging
|
|
1260
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#preview_absence_resolve\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1261
|
+
end
|
|
1262
|
+
return data, status_code, headers
|
|
1263
|
+
end
|
|
1264
|
+
|
|
1265
|
+
# Preview emergency insert + cascade reschedule
|
|
1266
|
+
# Computes (WITHOUT writing) the cascade of inserting an emergency job onto a technician at a chosen time: where the emergency lands + every job pushed back, grouped per business-local day. `displacement_mode=reassign` instead hands each displaced job to another feasible technician at its ORIGINAL window (same-day promise) — jobs with no alternate capacity fall back to reschedule and stay in `days`. `mode=overtime` keeps everyone same-day (tech works late); `mode=next_day` rolls overflow to the next working day(s). On a day the business does not work the preview does NOT need `after_hours_override`: it plans as the override would and returns `after_hours_override_required: true` plus an AFTER_HOURS warning — ask the coordinator whether they have phoned the technician, then commit with after_hours_override=true (the commit refuses without it). This endpoint never runs the technician's working-hours/time-off feasibility check (that only happens on /candidates) — it validates the named technician exists and builds the cascade. Read-only — safe to call repeatedly; commit is a separate endpoint. Isolated feature (see EMERGENCY_RESCHEDULE_DESIGN.md). 409 NEXT STEPS: EMERGENCY_RESCHEDULE_SLOT_OCCUPIED — the landing window is blocked by a job the cascade may NOT move (another P0, a crew or multi-day job); `data.conflicts[]` names each blocking job (short_code/start_at/end_at/frozen_because): choose another technician (walk the /candidates ranking) or another time; displacement never touches P0/crew/multi-day anchors. EMERGENCY_RESCHEDULE_NOT_ELIGIBLE / CREW_UNSUPPORTED / MULTIDAY_UNSUPPORTED / IN_PAST — same remedies and `data` shapes as /candidates. EMERGENCY_RESCHEDULE_NO_WORKING_DAY is never returned by the preview: since 2026-10-03 a closed day answers 200 with after_hours_override_required=true instead.
|
|
1267
|
+
# @param job_request_emergency_preview_request [JobRequestEmergencyPreviewRequest] emergency insert spec
|
|
1268
|
+
# @param [Hash] opts the optional parameters
|
|
1269
|
+
# @return [CommitEmergencyReschedule200Response]
|
|
1270
|
+
def preview_emergency_reschedule(job_request_emergency_preview_request, opts = {})
|
|
1271
|
+
data, _status_code, _headers = preview_emergency_reschedule_with_http_info(job_request_emergency_preview_request, opts)
|
|
1272
|
+
data
|
|
1273
|
+
end
|
|
1274
|
+
|
|
1275
|
+
# Preview emergency insert + cascade reschedule
|
|
1276
|
+
# Computes (WITHOUT writing) the cascade of inserting an emergency job onto a technician at a chosen time: where the emergency lands + every job pushed back, grouped per business-local day. `displacement_mode=reassign` instead hands each displaced job to another feasible technician at its ORIGINAL window (same-day promise) — jobs with no alternate capacity fall back to reschedule and stay in `days`. `mode=overtime` keeps everyone same-day (tech works late); `mode=next_day` rolls overflow to the next working day(s). On a day the business does not work the preview does NOT need `after_hours_override`: it plans as the override would and returns `after_hours_override_required: true` plus an AFTER_HOURS warning — ask the coordinator whether they have phoned the technician, then commit with after_hours_override=true (the commit refuses without it). This endpoint never runs the technician's working-hours/time-off feasibility check (that only happens on /candidates) — it validates the named technician exists and builds the cascade. Read-only — safe to call repeatedly; commit is a separate endpoint. Isolated feature (see EMERGENCY_RESCHEDULE_DESIGN.md). 409 NEXT STEPS: EMERGENCY_RESCHEDULE_SLOT_OCCUPIED — the landing window is blocked by a job the cascade may NOT move (another P0, a crew or multi-day job); `data.conflicts[]` names each blocking job (short_code/start_at/end_at/frozen_because): choose another technician (walk the /candidates ranking) or another time; displacement never touches P0/crew/multi-day anchors. EMERGENCY_RESCHEDULE_NOT_ELIGIBLE / CREW_UNSUPPORTED / MULTIDAY_UNSUPPORTED / IN_PAST — same remedies and `data` shapes as /candidates. EMERGENCY_RESCHEDULE_NO_WORKING_DAY is never returned by the preview: since 2026-10-03 a closed day answers 200 with after_hours_override_required=true instead.
|
|
1277
|
+
# @param job_request_emergency_preview_request [JobRequestEmergencyPreviewRequest] emergency insert spec
|
|
1278
|
+
# @param [Hash] opts the optional parameters
|
|
1279
|
+
# @return [Array<(CommitEmergencyReschedule200Response, Integer, Hash)>] CommitEmergencyReschedule200Response data, response status code and response headers
|
|
1280
|
+
def preview_emergency_reschedule_with_http_info(job_request_emergency_preview_request, opts = {})
|
|
1281
|
+
if @api_client.config.debugging
|
|
1282
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.preview_emergency_reschedule ...'
|
|
1283
|
+
end
|
|
1284
|
+
# verify the required parameter 'job_request_emergency_preview_request' is set
|
|
1285
|
+
if @api_client.config.client_side_validation && job_request_emergency_preview_request.nil?
|
|
1286
|
+
fail ArgumentError, "Missing the required parameter 'job_request_emergency_preview_request' when calling JobRequestBusinessApi.preview_emergency_reschedule"
|
|
1287
|
+
end
|
|
1288
|
+
# resource path
|
|
1289
|
+
local_var_path = '/job-requests/emergency/preview'
|
|
1290
|
+
|
|
1291
|
+
# query parameters
|
|
1292
|
+
query_params = opts[:query_params] || {}
|
|
1293
|
+
|
|
1294
|
+
# header parameters
|
|
1295
|
+
header_params = opts[:header_params] || {}
|
|
1296
|
+
# HTTP header 'Accept' (if needed)
|
|
1297
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1298
|
+
# HTTP header 'Content-Type'
|
|
1299
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1300
|
+
if !content_type.nil?
|
|
1301
|
+
header_params['Content-Type'] = content_type
|
|
1302
|
+
end
|
|
1303
|
+
|
|
1304
|
+
# form parameters
|
|
1305
|
+
form_params = opts[:form_params] || {}
|
|
1306
|
+
|
|
1307
|
+
# http body (model)
|
|
1308
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_emergency_preview_request)
|
|
1309
|
+
|
|
1310
|
+
# return_type
|
|
1311
|
+
return_type = opts[:debug_return_type] || 'CommitEmergencyReschedule200Response'
|
|
1312
|
+
|
|
1313
|
+
# auth_names
|
|
1314
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1315
|
+
|
|
1316
|
+
new_options = opts.merge(
|
|
1317
|
+
:operation => :"JobRequestBusinessApi.preview_emergency_reschedule",
|
|
1318
|
+
:header_params => header_params,
|
|
1319
|
+
:query_params => query_params,
|
|
1320
|
+
:form_params => form_params,
|
|
1321
|
+
:body => post_body,
|
|
1322
|
+
:auth_names => auth_names,
|
|
1323
|
+
:return_type => return_type
|
|
1324
|
+
)
|
|
1325
|
+
|
|
1326
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1327
|
+
if @api_client.config.debugging
|
|
1328
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#preview_emergency_reschedule\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1329
|
+
end
|
|
1330
|
+
return data, status_code, headers
|
|
1331
|
+
end
|
|
1332
|
+
|
|
1333
|
+
# Preview a schedule-board job move
|
|
1334
|
+
# Computes (WITHOUT writing) the outcome of moving a confirmed job to a new time and/or technician: where it lands, every later job pushed back per `mode`, and the warnings the coordinator would accept (displaced jobs leaving their confirmed windows, overtime). Same technician = pure time move; different technician = manual reassign. Read-only — safe to call repeatedly while dragging; commit is a separate endpoint. On a day the business does not work, a p0 single-person job previews WITHOUT after_hours_override: the plan is computed as the override would place it and the response carries `after_hours_override_required: true` — ask the coordinator whether they have phoned the technician, then commit with after_hours_override=true. Any other job is refused with SCHEDULE_MOVE_NO_WORKING_DAY and `data.override_available: false`. See SCHEDULE_BOARD_DESIGN.md. Warning detail: a TECH_NOT_FEASIBLE warning carries `reason` (= `blockers[0].kind`) = `outside_service_area` | `missing_required_skills` | `not_lead_tier` | `no_working_day` | `on_time_off` | `off_shift` | `visit_too_long` | `cannot_arrive_in_time` (commute from the tech day-start location / shift start; `earliest_feasible_at`, RFC3339 UTC, is the first same-day time they CAN be on site — suggest it as the drop slot) | `not_available_today` (diagnosis unavailable). `blockers[]` names EVERY hard filter that failed, most-structural first — a client reading only `reason` still works. For a P0 move this warning is advisory (coordinator may commit anyway) and carries the SAME `blockers[]` a p1/p2/p3 move would get as the hard 409 SCHEDULE_MOVE_TECH_INFEASIBLE below. 409 NEXT STEPS: SCHEDULE_MOVE_NOT_ELIGIBLE (job unconfirmed/unquoted/archived/completed — `data.failed_precondition` names which) · SCHEDULE_MOVE_IN_PROGRESS (tech already executing — `data.fired_actions[]` lists the actions already fired; do not move) · SCHEDULE_MOVE_IN_PAST (pick a future time — its `data` carries `business_timezone`, the naive `start_at` and the `start_at_utc` it resolved to, which is what tells a caller whose own clock says otherwise where the difference came from) · SCHEDULE_MOVE_SLOT_OCCUPIED (landing window blocked by an immovable anchor; `data.conflicts[]` names it — another tech/time) · SCHEDULE_MOVE_TECH_INFEASIBLE (non-P0 hard block: target tech not qualified/available — its `data` carries `technician` (id+name), `reason` (same catalog as the TECH_NOT_FEASIBLE warning above), `blockers[]` (every cause, most-structural first) and, for `cannot_arrive_in_time`, `earliest_feasible_at` (RFC3339 UTC) to suggest as the drop slot; change tech or time) · SCHEDULE_MOVE_MULTIDAY_UNSUPPORTED (multi-day jobs not movable v1 — `data.session_count`/`data.session_dates`) · SCHEDULE_MOVE_NO_WORKING_DAY (`data.business_timezone`/`data.requested_weekday` — pick a working day, or set after_hours_override=true for a P0 whose technician has been phoned) · SCHEDULE_MOVE_REQUIRES_FREE_SLOT (non-P0 moves may not displace — `data.would_push[]` names the jobs that would be pushed, `data.allow_non_p0_displacement: false` names the setting that would permit it, unless the crew case sets `data.crew_never_displaces: true` instead — free capacity only) · SCHEDULE_MOVE_CREW_UNSTAFFABLE (a crew slot has no feasible replacement at the new time — another time). A landing outside the customer-confirmed window is NOT an error — it returns 200 with a MOVED_OUTSIDE_WINDOW warning (customer_window attached) that the coordinator overrides.
|
|
1335
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
1336
|
+
# @param job_request_move_preview_req [JobRequestMovePreviewReq] move spec
|
|
1337
|
+
# @param [Hash] opts the optional parameters
|
|
1338
|
+
# @return [CommitJobRequestMove200Response]
|
|
1339
|
+
def preview_job_request_move(id, job_request_move_preview_req, opts = {})
|
|
1340
|
+
data, _status_code, _headers = preview_job_request_move_with_http_info(id, job_request_move_preview_req, opts)
|
|
1341
|
+
data
|
|
1342
|
+
end
|
|
1343
|
+
|
|
1344
|
+
# Preview a schedule-board job move
|
|
1345
|
+
# Computes (WITHOUT writing) the outcome of moving a confirmed job to a new time and/or technician: where it lands, every later job pushed back per `mode`, and the warnings the coordinator would accept (displaced jobs leaving their confirmed windows, overtime). Same technician = pure time move; different technician = manual reassign. Read-only — safe to call repeatedly while dragging; commit is a separate endpoint. On a day the business does not work, a p0 single-person job previews WITHOUT after_hours_override: the plan is computed as the override would place it and the response carries `after_hours_override_required: true` — ask the coordinator whether they have phoned the technician, then commit with after_hours_override=true. Any other job is refused with SCHEDULE_MOVE_NO_WORKING_DAY and `data.override_available: false`. See SCHEDULE_BOARD_DESIGN.md. Warning detail: a TECH_NOT_FEASIBLE warning carries `reason` (= `blockers[0].kind`) = `outside_service_area` | `missing_required_skills` | `not_lead_tier` | `no_working_day` | `on_time_off` | `off_shift` | `visit_too_long` | `cannot_arrive_in_time` (commute from the tech day-start location / shift start; `earliest_feasible_at`, RFC3339 UTC, is the first same-day time they CAN be on site — suggest it as the drop slot) | `not_available_today` (diagnosis unavailable). `blockers[]` names EVERY hard filter that failed, most-structural first — a client reading only `reason` still works. For a P0 move this warning is advisory (coordinator may commit anyway) and carries the SAME `blockers[]` a p1/p2/p3 move would get as the hard 409 SCHEDULE_MOVE_TECH_INFEASIBLE below. 409 NEXT STEPS: SCHEDULE_MOVE_NOT_ELIGIBLE (job unconfirmed/unquoted/archived/completed — `data.failed_precondition` names which) · SCHEDULE_MOVE_IN_PROGRESS (tech already executing — `data.fired_actions[]` lists the actions already fired; do not move) · SCHEDULE_MOVE_IN_PAST (pick a future time — its `data` carries `business_timezone`, the naive `start_at` and the `start_at_utc` it resolved to, which is what tells a caller whose own clock says otherwise where the difference came from) · SCHEDULE_MOVE_SLOT_OCCUPIED (landing window blocked by an immovable anchor; `data.conflicts[]` names it — another tech/time) · SCHEDULE_MOVE_TECH_INFEASIBLE (non-P0 hard block: target tech not qualified/available — its `data` carries `technician` (id+name), `reason` (same catalog as the TECH_NOT_FEASIBLE warning above), `blockers[]` (every cause, most-structural first) and, for `cannot_arrive_in_time`, `earliest_feasible_at` (RFC3339 UTC) to suggest as the drop slot; change tech or time) · SCHEDULE_MOVE_MULTIDAY_UNSUPPORTED (multi-day jobs not movable v1 — `data.session_count`/`data.session_dates`) · SCHEDULE_MOVE_NO_WORKING_DAY (`data.business_timezone`/`data.requested_weekday` — pick a working day, or set after_hours_override=true for a P0 whose technician has been phoned) · SCHEDULE_MOVE_REQUIRES_FREE_SLOT (non-P0 moves may not displace — `data.would_push[]` names the jobs that would be pushed, `data.allow_non_p0_displacement: false` names the setting that would permit it, unless the crew case sets `data.crew_never_displaces: true` instead — free capacity only) · SCHEDULE_MOVE_CREW_UNSTAFFABLE (a crew slot has no feasible replacement at the new time — another time). A landing outside the customer-confirmed window is NOT an error — it returns 200 with a MOVED_OUTSIDE_WINDOW warning (customer_window attached) that the coordinator overrides.
|
|
1346
|
+
# @param id [String] Job request ID (UUID or short_code)
|
|
1347
|
+
# @param job_request_move_preview_req [JobRequestMovePreviewReq] move spec
|
|
1348
|
+
# @param [Hash] opts the optional parameters
|
|
1349
|
+
# @return [Array<(CommitJobRequestMove200Response, Integer, Hash)>] CommitJobRequestMove200Response data, response status code and response headers
|
|
1350
|
+
def preview_job_request_move_with_http_info(id, job_request_move_preview_req, opts = {})
|
|
1351
|
+
if @api_client.config.debugging
|
|
1352
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.preview_job_request_move ...'
|
|
1353
|
+
end
|
|
1354
|
+
# verify the required parameter 'id' is set
|
|
1355
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
1356
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.preview_job_request_move"
|
|
1357
|
+
end
|
|
1358
|
+
# verify the required parameter 'job_request_move_preview_req' is set
|
|
1359
|
+
if @api_client.config.client_side_validation && job_request_move_preview_req.nil?
|
|
1360
|
+
fail ArgumentError, "Missing the required parameter 'job_request_move_preview_req' when calling JobRequestBusinessApi.preview_job_request_move"
|
|
1361
|
+
end
|
|
1362
|
+
# resource path
|
|
1363
|
+
local_var_path = '/job-requests/{id}/move/preview'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
1364
|
+
|
|
1365
|
+
# query parameters
|
|
1366
|
+
query_params = opts[:query_params] || {}
|
|
1367
|
+
|
|
1368
|
+
# header parameters
|
|
1369
|
+
header_params = opts[:header_params] || {}
|
|
1370
|
+
# HTTP header 'Accept' (if needed)
|
|
1371
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1372
|
+
# HTTP header 'Content-Type'
|
|
1373
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1374
|
+
if !content_type.nil?
|
|
1375
|
+
header_params['Content-Type'] = content_type
|
|
1376
|
+
end
|
|
1377
|
+
|
|
1378
|
+
# form parameters
|
|
1379
|
+
form_params = opts[:form_params] || {}
|
|
1380
|
+
|
|
1381
|
+
# http body (model)
|
|
1382
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_move_preview_req)
|
|
1383
|
+
|
|
1384
|
+
# return_type
|
|
1385
|
+
return_type = opts[:debug_return_type] || 'CommitJobRequestMove200Response'
|
|
1386
|
+
|
|
1387
|
+
# auth_names
|
|
1388
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1389
|
+
|
|
1390
|
+
new_options = opts.merge(
|
|
1391
|
+
:operation => :"JobRequestBusinessApi.preview_job_request_move",
|
|
1392
|
+
:header_params => header_params,
|
|
1393
|
+
:query_params => query_params,
|
|
1394
|
+
:form_params => form_params,
|
|
1395
|
+
:body => post_body,
|
|
1396
|
+
:auth_names => auth_names,
|
|
1397
|
+
:return_type => return_type
|
|
1398
|
+
)
|
|
1399
|
+
|
|
1400
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1401
|
+
if @api_client.config.debugging
|
|
1402
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#preview_job_request_move\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1403
|
+
end
|
|
1404
|
+
return data, status_code, headers
|
|
1405
|
+
end
|
|
1406
|
+
|
|
1407
|
+
# Fire quote (FIXED action — business)
|
|
1408
|
+
# Sends the quote: sets quoted_at + duration cols, advances pending_action to confirm_booking. Status stays `booking`. job_duration_minutes may be omitted when the job's job type has a default_duration_minutes: the type's default duration and buffers are used (a buffer you send still wins). This is how an automation or voice agent schedules work it cannot size. Before writing, checks that the customer will see at least one slot: the same engine as the customer slot picker runs over the windows the customer asked for with THIS quote's duration (working hours, service areas, time-off, existing bookings, crew coverage). If no slot exists the quote is refused with 409 JOB_REQUEST_QUOTE_NOT_SCHEDULABLE; data.reason says why (outside_working_hours, requested_windows_passed, outside_service_area, off_shift, on_time_off, missing_required_skills, no_technician_available, ...) and data.blocked_by counts the roster per blocker. Send force=true to schedule it anyway after agreeing a time with the customer.
|
|
1409
|
+
# @param id [String] Job request ID
|
|
1410
|
+
# @param job_request_quote_request [JobRequestQuoteRequest] Quote payload
|
|
1411
|
+
# @param [Hash] opts the optional parameters
|
|
1412
|
+
# @return [QuoteJobRequest200Response]
|
|
1413
|
+
def quote_job_request(id, job_request_quote_request, opts = {})
|
|
1414
|
+
data, _status_code, _headers = quote_job_request_with_http_info(id, job_request_quote_request, opts)
|
|
1415
|
+
data
|
|
1416
|
+
end
|
|
1417
|
+
|
|
1418
|
+
# Fire quote (FIXED action — business)
|
|
1419
|
+
# Sends the quote: sets quoted_at + duration cols, advances pending_action to confirm_booking. Status stays `booking`. job_duration_minutes may be omitted when the job's job type has a default_duration_minutes: the type's default duration and buffers are used (a buffer you send still wins). This is how an automation or voice agent schedules work it cannot size. Before writing, checks that the customer will see at least one slot: the same engine as the customer slot picker runs over the windows the customer asked for with THIS quote's duration (working hours, service areas, time-off, existing bookings, crew coverage). If no slot exists the quote is refused with 409 JOB_REQUEST_QUOTE_NOT_SCHEDULABLE; data.reason says why (outside_working_hours, requested_windows_passed, outside_service_area, off_shift, on_time_off, missing_required_skills, no_technician_available, ...) and data.blocked_by counts the roster per blocker. Send force=true to schedule it anyway after agreeing a time with the customer.
|
|
1420
|
+
# @param id [String] Job request ID
|
|
1421
|
+
# @param job_request_quote_request [JobRequestQuoteRequest] Quote payload
|
|
1422
|
+
# @param [Hash] opts the optional parameters
|
|
1423
|
+
# @return [Array<(QuoteJobRequest200Response, Integer, Hash)>] QuoteJobRequest200Response data, response status code and response headers
|
|
1424
|
+
def quote_job_request_with_http_info(id, job_request_quote_request, opts = {})
|
|
1425
|
+
if @api_client.config.debugging
|
|
1426
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.quote_job_request ...'
|
|
1427
|
+
end
|
|
1428
|
+
# verify the required parameter 'id' is set
|
|
1429
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
1430
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.quote_job_request"
|
|
1431
|
+
end
|
|
1432
|
+
# verify the required parameter 'job_request_quote_request' is set
|
|
1433
|
+
if @api_client.config.client_side_validation && job_request_quote_request.nil?
|
|
1434
|
+
fail ArgumentError, "Missing the required parameter 'job_request_quote_request' when calling JobRequestBusinessApi.quote_job_request"
|
|
1435
|
+
end
|
|
1436
|
+
# resource path
|
|
1437
|
+
local_var_path = '/job-requests/{id}/quote'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
1438
|
+
|
|
1439
|
+
# query parameters
|
|
1440
|
+
query_params = opts[:query_params] || {}
|
|
1441
|
+
|
|
1442
|
+
# header parameters
|
|
1443
|
+
header_params = opts[:header_params] || {}
|
|
1444
|
+
# HTTP header 'Accept' (if needed)
|
|
1445
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1446
|
+
# HTTP header 'Content-Type'
|
|
1447
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1448
|
+
if !content_type.nil?
|
|
1449
|
+
header_params['Content-Type'] = content_type
|
|
1450
|
+
end
|
|
1451
|
+
|
|
1452
|
+
# form parameters
|
|
1453
|
+
form_params = opts[:form_params] || {}
|
|
1454
|
+
|
|
1455
|
+
# http body (model)
|
|
1456
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_quote_request)
|
|
1457
|
+
|
|
1458
|
+
# return_type
|
|
1459
|
+
return_type = opts[:debug_return_type] || 'QuoteJobRequest200Response'
|
|
1460
|
+
|
|
1461
|
+
# auth_names
|
|
1462
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1463
|
+
|
|
1464
|
+
new_options = opts.merge(
|
|
1465
|
+
:operation => :"JobRequestBusinessApi.quote_job_request",
|
|
1466
|
+
:header_params => header_params,
|
|
1467
|
+
:query_params => query_params,
|
|
1468
|
+
:form_params => form_params,
|
|
1469
|
+
:body => post_body,
|
|
1470
|
+
:auth_names => auth_names,
|
|
1471
|
+
:return_type => return_type
|
|
1472
|
+
)
|
|
1473
|
+
|
|
1474
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1475
|
+
if @api_client.config.debugging
|
|
1476
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#quote_job_request\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1477
|
+
end
|
|
1478
|
+
return data, status_code, headers
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
# Set job priority (scheduling staff)
|
|
1482
|
+
# Sets the P0–P3 priority on a non-archived, non-completed job (Owner / Administrator / Booking Coordinator). Allowed values: \"p0\" (emergency, interrupt-driven) | \"p1\" (top — displaced only by p0; may carry an sla_deadline arming auto-escalation) | \"p2\" (standard) | \"p3\" (deferrable, first displacement victim). sla_deadline is only valid with p1 and must be in the future (business-local naive datetime); moving away from p1 disarms the SLA clock. Accepts UUID or short_code in :id. Lowering a job to anything but p0 never moves it: when it still sits outside the business's working hours (typically placed there earlier through the after-hours override) the response carries an AFTER_HOURS warning per affected session, and the job should be moved back to a working day.
|
|
1483
|
+
# @param id [String] Job request ID or short_code
|
|
1484
|
+
# @param job_request_update_priority_request [JobRequestUpdatePriorityRequest] Priority payload
|
|
1485
|
+
# @param [Hash] opts the optional parameters
|
|
1486
|
+
# @return [ResponseEnvelope]
|
|
1487
|
+
def update_job_priority(id, job_request_update_priority_request, opts = {})
|
|
1488
|
+
data, _status_code, _headers = update_job_priority_with_http_info(id, job_request_update_priority_request, opts)
|
|
1489
|
+
data
|
|
1490
|
+
end
|
|
1491
|
+
|
|
1492
|
+
# Set job priority (scheduling staff)
|
|
1493
|
+
# Sets the P0–P3 priority on a non-archived, non-completed job (Owner / Administrator / Booking Coordinator). Allowed values: \"p0\" (emergency, interrupt-driven) | \"p1\" (top — displaced only by p0; may carry an sla_deadline arming auto-escalation) | \"p2\" (standard) | \"p3\" (deferrable, first displacement victim). sla_deadline is only valid with p1 and must be in the future (business-local naive datetime); moving away from p1 disarms the SLA clock. Accepts UUID or short_code in :id. Lowering a job to anything but p0 never moves it: when it still sits outside the business's working hours (typically placed there earlier through the after-hours override) the response carries an AFTER_HOURS warning per affected session, and the job should be moved back to a working day.
|
|
1494
|
+
# @param id [String] Job request ID or short_code
|
|
1495
|
+
# @param job_request_update_priority_request [JobRequestUpdatePriorityRequest] Priority payload
|
|
1496
|
+
# @param [Hash] opts the optional parameters
|
|
1497
|
+
# @return [Array<(ResponseEnvelope, Integer, Hash)>] ResponseEnvelope data, response status code and response headers
|
|
1498
|
+
def update_job_priority_with_http_info(id, job_request_update_priority_request, opts = {})
|
|
1499
|
+
if @api_client.config.debugging
|
|
1500
|
+
@api_client.config.logger.debug 'Calling API: JobRequestBusinessApi.update_job_priority ...'
|
|
1501
|
+
end
|
|
1502
|
+
# verify the required parameter 'id' is set
|
|
1503
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
1504
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling JobRequestBusinessApi.update_job_priority"
|
|
1505
|
+
end
|
|
1506
|
+
# verify the required parameter 'job_request_update_priority_request' is set
|
|
1507
|
+
if @api_client.config.client_side_validation && job_request_update_priority_request.nil?
|
|
1508
|
+
fail ArgumentError, "Missing the required parameter 'job_request_update_priority_request' when calling JobRequestBusinessApi.update_job_priority"
|
|
1509
|
+
end
|
|
1510
|
+
# resource path
|
|
1511
|
+
local_var_path = '/job-requests/{id}/priority'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
|
|
1512
|
+
|
|
1513
|
+
# query parameters
|
|
1514
|
+
query_params = opts[:query_params] || {}
|
|
1515
|
+
|
|
1516
|
+
# header parameters
|
|
1517
|
+
header_params = opts[:header_params] || {}
|
|
1518
|
+
# HTTP header 'Accept' (if needed)
|
|
1519
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1520
|
+
# HTTP header 'Content-Type'
|
|
1521
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1522
|
+
if !content_type.nil?
|
|
1523
|
+
header_params['Content-Type'] = content_type
|
|
1524
|
+
end
|
|
1525
|
+
|
|
1526
|
+
# form parameters
|
|
1527
|
+
form_params = opts[:form_params] || {}
|
|
1528
|
+
|
|
1529
|
+
# http body (model)
|
|
1530
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(job_request_update_priority_request)
|
|
1531
|
+
|
|
1532
|
+
# return_type
|
|
1533
|
+
return_type = opts[:debug_return_type] || 'ResponseEnvelope'
|
|
1534
|
+
|
|
1535
|
+
# auth_names
|
|
1536
|
+
auth_names = opts[:debug_auth_names] || ['ApiKeyAuth']
|
|
1537
|
+
|
|
1538
|
+
new_options = opts.merge(
|
|
1539
|
+
:operation => :"JobRequestBusinessApi.update_job_priority",
|
|
1540
|
+
:header_params => header_params,
|
|
1541
|
+
:query_params => query_params,
|
|
1542
|
+
:form_params => form_params,
|
|
1543
|
+
:body => post_body,
|
|
1544
|
+
:auth_names => auth_names,
|
|
1545
|
+
:return_type => return_type
|
|
1546
|
+
)
|
|
1547
|
+
|
|
1548
|
+
data, status_code, headers = @api_client.call_api(:PATCH, local_var_path, new_options)
|
|
1549
|
+
if @api_client.config.debugging
|
|
1550
|
+
@api_client.config.logger.debug "API called: JobRequestBusinessApi#update_job_priority\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
445
1551
|
end
|
|
446
1552
|
return data, status_code, headers
|
|
447
1553
|
end
|