# Food Slotting API ## PRD link https://docs.google.com/document/d/19b6DrGQPwiDT661XN5XMs5W9WDr8Pd2fCfcjFkrEEW8/edit#heading=h.fh5g162b1vdk ## Dashboard API ### List zones by city - API: `/api/v1/cities/<city_id>/zones` - Method: `GET` - Query Param: n/a - Request Body: n/a - note: - zones lists are ordered by it's name ascending order - Response: ```json { "success": true, "message": "...", "data": [ { "id": 1, "name": "Gulshan", "description": "description", "is_active": true } ] } ``` ```json { "success": false, "message": "invalid 'city_id' param" } ``` ### Get zone by id - API: `/api/v1/zones/<zone-id>` - Method: `GET` - Query Param: n/a - Request Body: n/a - Response: ```json { "success": true, "message": "request is successful", "data": { "id": 1, "name": "Gulshan", "description": "This is test zone", "is_active": true, "polygon_points": [ { "latitude": 23.7806881188067, "longitude": 90.4254029762162 }, { "latitude": 23.7760539823181, "longitude": 90.425853587303 }, { "latitude": 23.7735601201866, "longitude": 90.4257677566198 }, { "latitude": 23.7720284331277, "longitude": 90.4254458915578 } ] } } ``` ### List subzones by zone id - API: `/api/v1/zones/<zone_id>/subzones` - Method: `GET` - Query Param: n/a - Request Body: n/a - note: - subzones lists are ordered by it's name ascending order - Response: ```json { "success": true, "message": "...", "data": [ { "id": 1, "zone_id": 1, "name": "gulshan-2", } ] } ``` ```json { "success": false, "message": "invalid 'zone_id' param" } ``` ### Get subzone by id - API: `/api/v1/subzones/<subzone-id>` - Method: `GET` - Query Param: n/a - Request Body: n/a - Response: ```json { "success": true, "message": "result is successful", "data": { "id": 1, "zone_id": 1, "name": "gulshan-1", "polygon_points": [ { "latitude": 23.7806881188067, "longitude": 90.4254029762162 }, { "latitude": 23.7760539823181, "longitude": 90.425853587303 }, { "latitude": 23.7735601201866, "longitude": 90.4257677566198 }, { "latitude": 23.7720284331277, "longitude": 90.4254458915578 } ] } } ``` ### Create time slots - API: `/api/v1/time-slots` - Method: `POST` - Query Param: n/a - Request Body: Required. ```json { "created_by": "<user>", "slots": [ { "subzone_id": 1, "start_at": "2021-10-03T12:30:00+0000", "end_at": "2021-10-03T13:00:00+0000", "categories": [{ "id": 1, "allotted_size": 100 }] } ] } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Udpate time slot - API: `/api/v1/time-slots/<time_slot_id>` - Method: `PUT` - Query Param: n/a - Request Body: Required. ```json { "updated_by": "<user>", "start_at": "2021-09-30T07:00:00+0000", "end_at": "2021-09-30T08:00:00+0000", "categories": [ { "id": 1, "allotted_size": 100 } ] } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Patch time slot publish - API: `/api/v1/time-slots/<time_slot_id>` - Method: `PATCH` - Query Param: n/a - Request Body: ```json { "updated_by": "<user>", "is_published": true } ``` - Response: ```json { "success": true, "message": "..." } ``` #3# Delete time slot - API: `/api/v1/time-slots/<time_slot_id>` - Method: `DELETE` - Query Param: n/a - Request Body: ```json { "deleted_by": "<user>", } ``` - Response: ```json { "success": true, "message": "..." } ``` ### List time slots by subzone and date - API: `/api/v1/subzones/<subzone_id>/time-slots` - Method: `GET` - Query Param: - `date`: Required. Format: `yyyy-mm-dd` - `time_zone_city_id`: Optional. Default: `1`. This will determine which time zone to use for `date` comparison. - Request Body: n/a - Response: ```json { "success": true, "message": "...", "data": [ { "id": 1, "start_at": "2021-10-03T18:30:00+0000", "end_at": "2021-10-03T19:30:00+0000", "status": "running", } ] } ``` ```json { "success": false, "message": "'date' query param is required" } ``` ### List unpublished time slots by subzone - API: `/api/v1/subzones/<subzone_id>/time-slots/unpublished` - Method: `GET` - Query Param: - `page`: default 1. - `page_size`: default 50. - Request Body: n/a - Response: ```json { "success": true, "message": "request is successful", "count": 1, "page_size": 50, "current_page": 1, "data": [ { "id": 16, "start_at": "2021-10-21T18:00:00+0000", "end_at": "2021-10-21T19:00:00+0000", "created_by": "me", "categories": [ { "id": 1, "name": "A", "allotted_size": 50 } ] } ] } ``` ### Get time slot details - API: `/api/v1/time-slots/<time_slot_id>` - Method: `GET` - Query Param: n/a - Request Body: n/a - Response: ```json { "success": true, "message": "operation is successful", "data": { "id": 14, "subzone_id": 1, "subzone_name": "gullshan-1", "zone_name": "Gulshan", "start_at": "2021-10-07T18:00:00+0000", "end_at": "2021-10-08T00:00:00+0000", "status": "completed", "total_slot": 10, "total_booked": 0, "categories": [ { "category_id": 1, "category_name": "A", "allotted_size": 10, "booked": 0 } ] } } ``` ### List time slots with details - API: `/api/v1/cities/<city_id>/time-slots` - Method: `GET` - Query Param: - `from`: Required for `upcoming` and `completed`. Format: `yyyy-mm-dd` - `to`: Required for `upcoming` and `completed`. Format: `yyyy-mm-dd` - `zone_id`: Optional. Defaults to all zone. - `subzone_id`: Optional. Defaults to all subzone. - `status`: Required. Options: `active`, `upcoming`, `completed` - `page_size`: default 7 - `page`: default 1 - Request Body: n/a - Response: ```json { "success": true, "message": "operation is successful", "count": 3, "page_size": 1, "previous_page": 1, "next_page": 3, "current_page": 2, "data": [ { "date": "2021-10-03", "num_of_slots": 1, "zone_name": "Gulshan", "subzone_name": "gullshan-1", "slots": [ { "id": 12, "start_at": "2021-10-03T12:30:00+0000", "end_at": "2021-10-03T13:30:00+0000", "total_slot": 199, "total_booked": 0, "categories": [ { "category_id": 1, "category_name": "A", "allotted_size": 199, "booked": 0 } ] } ] } ] } ``` ### List booked time slots by driver id - API: `/api/v1/drivers/<driver_id>/time-slots` - Method: `GET` - Query Param: - `from`: Required. Format: `yyyy-mm-dd` - `to`: Required. Format: `yyyy-mm-dd` - `city_id`: Required. - `zone_id`: Optional. Defaults to all zone. - `page_size`: default 7 - `page`: default 1 - Request Body: n/a - Response: ```json { "success": true, "message": "operation is successful", "count": 1, "page_size": 7, "current_page": 1, "data": [ { "date": "2021-10-05", "num_of_slots": 1, "active_durations_in_seconds": 100, "completion_rate": 10.25, "request_received": 10, "request_accepted": 5, "request_completed": 4, "request_cancelled": 1, "request_skipped": 5, "slots": [ { "id": 1, "start_at": "2021-10-05T12:00:00+0000", "end_at": "2021-10-05T13:00:00+0000", "city_name": "dhaka", "zone_name": "ghulsan", "subzone_name": "ghulsan-1", "status": "completed", "active_durations_in_seconds": 100, "completion_rate": 10.25, "request_received": 10, "request_accepted": 5, "request_completed": 4, "request_cancelled": 1, "request_skipped": 5 } ] } ] } ``` ### Add drivers to time slot - API: `/api/v1/time-slots/<time_slot_id>/drivers` - Method: `POST` - Query Param: n/a - Request Body: Drivers id or phone number is required. ```json { "ids": [1, 2], "created_by": "<user_name>" } ``` or ```json { "phone_numbers": ["01821111111", "01821122222"], "created_by": "<user_name>" } ``` - Response: ```json { "success": true, "message": "..." } ``` ##^ Request driver booking - API: `/api/v1/time-slots/<time_slot_id>/drivers/<driver_id>` - Method: `POST` - Query Param: n/a - Request Body: Required. ```json { "created_by": "<user_name>" } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Approve single driver booking - API: `/api/v1/time-slots/<time_slot_id>/drivers/<driver_id>` - Method: `PUT` - Query Param: n/a - Request Body: Required. ```json { "updated_by": "<user_name>" } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Approve list of drivers booking - API: `/api/v1/time-slots/<time_slot_id>/drivers` - Method: `PUT` - Query Param: n/a - Request Body: Required. ```json { "updated_by": "me", "ids": [1] } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Reject single driver booking - API: `/api/v1/time-slots/<time_slot_id>/drivers/<driver_id>` - Method: `DELETE` - Query Param: n/a - Request Body: Required. ```json { "cancelled_by": "new_me", "cancellation_reason": "don't like him" } ``` - Response: ```json { "success": true, "message": "..." } ``` ### Reject list of drivers booking - API: `/api/v1/time-slots/<time_slot_id>/drivers` - Method: `DELETE` - Query Param: n/a - Request Body: Required. ```json { "cancelled_by": "new_me", "cancellation_reason": "don't like him", "ids": [1] } ``` - Response: ```json { "success": true, "message": "..." } ``` ### List drivers by time slot - API: `/api/v1/time-slots/<time_slot_id>/drivers` - Method: `GET` - Query Param: - `status`: Optional. Denotes driver active status. Options: `online`, `offline` - `assign_status`: Optional. Denotes time slot assignment status. Options: `pending`, `assigned`, `rejected` - `page_size`: default 50 - `page`: default 1 - `search`: Optional. Driver name or phone - Request Body: n/a - Response: ```json { "success": true, "message": "operation is successful", "count": 2, "page_size": 50, "current_page": 1, "data": [ { "id": 1, "name": "rahim", "phone": "01821111111", "category": "A", "status": "assigned", "rating": "4.8", "cash_in_hand": 1000, "cancelled": 0, "skipped": 0, "active_durations_in_seconds": 0 }, { "id": 2, "name": "kuddus", "phone": "0000000000", "category": "A", "status": "pending", "rating": "4.8", "cash_in_hand": 0, "cancelled": 0, "skipped": 0, "active_durations_in_seconds": 0 } ] } ``` ### List driver categories - API: `/api/v1/driver-categories` - Method: `GET` - Query Param: n/a - Request Body: n/a - Response: ```json { "success": true, "message": "...", "data": [ { "id": 1, "name": "A" }, { "id": 2, "name": "B" } ] } ``` ### Create slot driver list download job - API: `/api/v1/jobs/download/slot-driver-list` - Method: `POST` - Query Param: n/a - Request Body: ```json { "city_id": 1, "time_slot_id": 1, "status": "online", // optional. options: "online" or "offline" "assign_status": "pending", // optional. options: "pending" or "assigned" or "rejected" "created_by": "me", "description": "description" // optional } ``` - Response: ```json { "success": true, "message": "request is successful", "data": { "job_id": 3 } } ``` ### Create driver time slot list download job - API: `/api/v1/jobs/download/driver-slot-list` - Method: `POST` - Query Param: n/a - Request Body: ```json { "from": "2021-10-05", "to": "2021-10-15", "driver_id": 1, "city_id": 1, "created_by": "me", "description": "description" // optional } ``` ```json { "from": "2021-10-05", "to": "2021-10-15", "driver_id": 1, "city_id": 1, "zone_id": 1, "created_by": "me", "description": "description" // optional } ``` - Response: ```json { "success": true, "message": "request is successful", "data": { "job_id": 3 } } ``` ### Create time slot list download job - API: `/api/v1/jobs/download/slot-list` - Method: `POST` - Query Param: n/a - Request Body: ```json { "from": "2021-09-01", "to": "2021-10-15", "status": "completed", "city_id": 1, "created_by":"me", "description": "description" // optional } ``` ```json { "from": "2021-09-01", "to": "2021-10-15", "status": "completed", "city_id": 1, "zone_id": 1, "subzone_id": 1, "created_by":"me", "description": "description" // optional } ``` - Response: ```json { "success": true, "message": "request is successful", "data": { "job_id": 3 } } ``` ### Create time slot upload job - API: `/api/v1/jobs/upload/slot-list` - Method: `POST` - Query Param: n/a - Multipart Form: - `created_by`: Required. - `file`: Required. - `description`: Optional. - Response: ```json { "success": true, "message": "request is successful", "data": { "job_id": 3 } } ``` ### List jobs - API: `/api/v1/jobs` - Method: `GET` - Query Param: - `job_type`: Required. Options: `download`, `upload` and `all` - `page_size`: default 50 - `page`: default 1 - Request Body: n/a - Response: ```json { "success": true, "message": "request is successful", "count": 2, "page_size": 50, "current_page": 1, "data": [ { "id": 2, "job_type": "download", "task_name": "slot-driver-list", "description": "description", "status": "pending", "file_url": "", "payload": { "status": "assigned", "created_by": "me", "time_slot_id": 1 }, "error": null, "created_at": "2021-10-17T17:16:12+0000", "updated_at": "2021-10-17T17:16:12+0000", "created_by": "me" }, { "id": 1, "job_type": "download", "task_name": "slot-driver-list", "description": "description", "status": "pending", "file_url": "", "payload": { "status": "assigned", "created_by": "me", "time_slot_id": 1 }, "error": null, "created_at": "2021-10-25T17:07:06+0000", "updated_at": "2021-10-25T17:07:06+0000", "created_by": "me" } ] } ``` ### Get job by ID - API: `/api/v1/jobs/<job_id>` - Method: `GET` - Query Param: n/a - Request Body: n/a - Response: ```json { "success": true, "message": "request is successful", "data": { "id": 7, "job_type": "download", "task_name": "driver-slot-list", "description": "", "status": "completed", "file_url": "http://localhost:9000/karagar/Job_7_Driver_1.csv", "payload": { "to": "2021-10-15", "from": "2021-10-05", "zone_id": null, "driver_id": 1, "created_by": "me" }, "error": null, "created_at": "2021-10-25T11:04:00+0000", "updated_at": "2021-10-25T11:06:42+0000", "created_by": "me" } } ``` ## Driver App Api ### List zones by city - API: `/api/v1/users/<user_id>/zones` - Kong-gateway: `/v1/me/foods/zones` - Method: `GET` - Headers: - `City-ID`: Required. - `Authorization`: Required. - Query Param: n/a - Request Body: n/a - note: - zones lists are ordered by it's name ascending order - Response: - code: `200` ```json { "success": true, "message": "...", "data": [ { "id": 1, "name": "Gulshan", "description": "description", "is_active": true } ] } ``` - code: `200` ```json { "success": true, "message": "request is successful", "data": [] } ``` - code: `400` ```json { "success": false, "message": "invalid 'city_id' param" } ``` ### Get zone by id - API: `/api/v1/users/<user_id>/zones/<zone-id>` - Kong-gateway: `/v1/me/foods/zones/<zone-id>` - Method: `GET` - Headers: - `Authorization`: Required. - Query Param: n/a - Request Body: n/a - Response: - code: `200` ```json { "success": true, "message": "request is successful", "data": { "id": 1, "name": "Gulshan", "description": "This is test zone", "is_active": true, "polygon_points": [ { "latitude": 23.7806881188067, "longitude": 90.4254029762162 }, { "latitude": 23.7760539823181, "longitude": 90.425853587303 }, { "latitude": 23.7735601201866, "longitude": 90.4257677566198 }, { "latitude": 23.7720284331277, "longitude": 90.4254458915578 } ] } } ``` - code: `404` ```json { "success": false, "message": "resource not found" } ``` ### List subzones by zone id - API: `/api/v1/users/<user-id>/zones/<zone_id>/subzones` - Kong-gateway: `/v1/me/foods/zones/<zone-id>/subzones` - Method: `GET` - Headers: - `Authorization`: Required. - Query Param: n/a - Request Body: n/a - note: - subzones lists are ordered by it's name ascending order - Response: - code: `200` ```json { "success": true, "message": "...", "data": [ { "id": 1, "zone_id": 1, "name": "gulshan-2", } ] } ``` - code: `400` ```json { "success": false, "message": "invalid 'zone_id' param" } ``` ### Get subzone by id - API: `/api/v1/users/<user-id>/subzones/<subzone-id>` - Kong-gateway: `/v1/me/foods/subzones/<subzone-id>` - Method: `GET` - Headers: - `Authorization`: Required. - Query Param: n/a - Request Body: n/a - Response: - code: `200` ```json { "success": true, "message": "result is successful", "data": { "id": 1, "zone_id": 1, "name": "gulshan-1", "polygon_points": [ { "latitude": 23.7806881188067, "longitude": 90.4254029762162 }, { "latitude": 23.7760539823181, "longitude": 90.425853587303 }, { "latitude": 23.7735601201866, "longitude": 90.4257677566198 }, { "latitude": 23.7720284331277, "longitude": 90.4254458915578 } ] } } ``` ### Get drivers today's booked and upcoming time slot - API: `/api/v1/users/<user-id>/time-slots/today` - Kong-gateway: `/v1/me/foods/time-slots/today` - Method: `GET` - Headers: - `City-ID`: Required. - `Authorization`: Required. - Query Param: n/a - Request Body: n/a - Response: - code : `200` ```json { "success": true, "message": "request is successful", "data": { "slot_booking_day_limit": 7, "current": { "id": "d62b84cf-191d-4bec-be1c-4a1a9c9a050a", "start_at": "2021-12-06T12:00:00+0000", "end_at": "2021-12-06T18:00:00+0000", "status": "running", "zone_id": 1, "zone_name": "Gulshan", "subzone_id": 1, "subzone_name": "gullshan-1", "expires_in_seconds": 17753, "polygon_points": [ { "latitude": 23.7806881188067, "longitude": 90.4254029762162 }, { "latitude": 23.7760539823181, "longitude": 90.425853587303 }, { "latitude": 23.7735601201866, "longitude": 90.4257677566198 }, { "latitude": 23.7720284331277, "longitude": 90.4254458915578 } ] }, "upcoming": { "id": "422c9e43-4861-422b-8e06-c884bb98e22c", "start_at": "2021-12-06T19:00:00+0000", "end_at": "2021-12-07T05:00:00+0000", "status": "pending", "zone_id": 1, "zone_name": "Gulshan", "subzone_id": 1, "subzone_name": "gullshan-1", "expires_in_seconds": 17753 } } } ``` - code: `200` ```json { "success": false, "message": "request is successful", "data": { "slot_booking_day_limit": 7, "current": null, "upcoming": null } } ``` ### Get driver specific time slot details - API: `/api/v1/users/<user-id>/time-slots/<time-slot-id>/stats` - Kong-gateway: `/v1/me/foods/time-slots/<time-slot-id>/stats` - Method: `GET` - Headers: - `Authorization`: Required. - Query Param: `n/a` - Request Body: n/a - Response: ```json { "success": false, "data": { "id": "422c9e43-4861-422b-8e06-c884bb98e22c", "zone_id": 1, "zone_name": "Gulshan", "subzone_id": 1, "subzone_name": "gulshan 2", "status": "completed", "start_at": "2021-10-03T18:30:00+0000", "end_at": "2021-10-03T19:30:00+0000", "active_durations_in_seconds": 100, "completion_rate": 10.25, "total_earning": 614.44, "request_received": 10, "request_accepted": 5, "request_completed": 4, "request_cancelled": 1, "request_skipped": 5, "is_reported": false } } ``` ### List driver booked time slots - API: `/api/v1/users/<user-id>/booked/time-slots` - Kong-gateway: `/v1/me/foods/booked/time-slots` - Method: `GET` - Headers: - `Authorization`: Required. - Query Param: - `status`: Required. Options: `upcoming` and `completed` - Request Body: n/a - Response: - code: `200` ```json { "success": true, "message": "request is successful", "data": [ { "id": "422c9e43-4861-422b-8e06-c884bb98e22c", "start_at": "2022-01-30T05:00:00+0000", "end_at": "2022-01-30T16:30:00+0000", "status": "completed", "zone_id": 1, "zone_name": "Gulshan", "subzone_id": 1, "subzone_name": "gullshan-1" }, { "id": "2136cf75-09ff-495d-8c34-a5d68e13010c", "start_at": "2022-01-27T04:30:00+0000", "end_at": "2022-01-27T05:00:00+0000", "status": "completed", "zone_id": 1, "zone_name": "Gulshan", "subzone_id": 1, "subzone_name": "gullshan-1" } ] } ``` - code: `200` ```json { "success": true, "message": "request is successful", "data": [] } ``` ### Book time slots - API: `/api/v1/users/<users_id>/time-slots` - Kong-gateway: `/v1/me/foods/time-slots` - Method: `POST` - Headers: - `Authorization`: Required. - Query Param: n/a - note: - it will book all slots or give an error - Request Body: Required. ```json { "ids": [ "f0cdac35-ca3d-4181-afc4-6231736b6c9d", "422c9e43-4861-422b-8e06-c884bb98e22c" ] } ``` - Response: - code: `200` ```json { "success": true, "message": "request is successful" } ``` - code: `400` ```json { "success": false, "code": "FOOD_0001", "message": "slot is full", "data": [ "26d37579-daac-435a-bbfb-583decea7f32" ] } ``` - code: `400` ```json { "success": false, "code": "FOOD_0002", "message": "driver per day book limit reached", "data": null } ``` - code: `400` ```json { "success": false, "code": "FOOD_0005", "message": "slot request api limit exceeded", "data": null } ``` - code: `400` ```json { "success": false, "code": "FOOD_0004", "message": "slot is already finished", "data": [ "2136cf75-09ff-495d-8c34-a5d68e13010c" ] } ``` - code: `400` ```json { "success": false, "code": "FOOD_0003", "message": "time slots overlaps with already requested or booked time slot", "data": [ "d62b84cf-191d-4bec-be1c-4a1a9c9a050a" ] } ``` - code: `400` ```json { "success": false, "code": "FOOD_0006", "message": "booking this time slot is not allowed, book a time slot within next 7 days", "data": [ "f0cdac35-ca3d-4181-afc4-6231736b6c9d" ] } ``` - code: `404` ```json { "success": false, "code": "FOOD_0008", "message": "error from aam jonota, status: 404, reason: Not Found" } ``` - code: `500` ```json { "success": false, "code": "FOOD_0010", "message": "internal server error" } ``` ### List time slots by subzone and date for driver - API: `/api/v1/users/<user_id>/subzones/<subzone-id>/time-slots` - Kong-gateway: `/v1/me/foods/subzones/<subzone-id>/time-slots` - Method: `GET` - Headers: - `City-ID`: Required. - `Authorization`: Required. - Query Param: - `date`: Required. Format: `yyyy-mm-dd` - note: - only show the slots that are not booked/requested and not filled - show empty list if driver booking limit crosses - Request Body: - Response: - code: `200` ```json { "success": true, "message": "request is successful", "data": { "limit": 7, "per_api_limit": 3, "slots": [ { "id": "d62b84cf-191d-4bec-be1c-4a1a9c9a050a", "start_at": "2021-12-06T19:00:00+0000", "end_at": "2021-12-07T05:00:00+0000", "status": "pending" } ] } } ``` - code: `200` ```json { "success": true, "message": "request is successful", "data": { "limit": 3, "per_api_limit": 3, "slots": [] } } ``` - code: `404` ```json { "success": false, "code": "FOOD_0008", "message": "error from aam jonota, status: 404, reason: Not Found" } ``` - code: `500` ```json { "success": false, "code": "FOOD_0010", "message": "internal server error" } ``` ### Report issue for driver time slot - API: `/api/v1/users/<user_id>/time-slots/<time_slot_id>/issue-report` - Kong-gateway: `/v1/me/foods/time-slots/<time_slot_id>/issue-report` - Method: `POST` - Headers: - `Authorization`: Required. - Query Param: N/A - Request Body: N/A - Response: - code: `201` ```json { "success": true, "message": "request is created" } ``` - code; `400` ```json { "success": false, "message": "..." } ```