BookingService

Requirements

Note : I dont finish the Unit Test yet, but i have provided all the API serive including test case for every endpoints in folder /postman

unit test available for the main bisnic logic, Booking Service

Settings & Configuring

App config

Please check the file env.example and change to .env

APP_ENV             = development
APP_PORT            = 3000
APP_ISSUER          = gitbub.com/mrbontor

....

Database config

This service is using MongoDb Cloud Atlas. If you are going to use your local MongoDb, please change the connection url /app/libraries/db/mongoDb/index.js Line 12

const mongoUrl = `mongodb+srv://....`
//to
const mongoUrl = `mongodb://...`

example existing user:

admin

username: "superadmin"
password: "Haruslolos123!"

admin

username: "masalalu"
password: "Haruslolos123!"

Deployment && Testing

Deployment && Usage

By default, you can run this service following command below:

# install dependencies
$ npm install

# run app
$ npm start

# or
$ node index.js

And you can also running thi service using Docker and Docker-Compose

# start
$ docker-compose up

# stop
$ docker-compose down

# remove
$ docker-compose down -v

Running the test

As i mentioned before, the Unit Test Code not finish yet, but already finish with documentation in /postman

how to run:

# start
$ npm test

Running in Postman

Please follow this Postman Doc Import Api for better information

Endpoints


AUTH

User admin need to authenticate before accessing all API

1. LOGIN

User login with username and password

Login API will return accessToken and `refreshToken`

accessToken provided in Response `body` where refreshToken in `Cookies `

Endpoint:

Method: POST
Type: RAW
URL: {{local}}/v1/auth/login

Body:

{
    "username": "superadmin",
    "password": "Haruslolos123!"
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "username": "superadmin",
    "password": "Haruslolos123!"
}

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVzZXJJZCI6IjYzOGIzNDJlN2ZkYzBjZGY5NWY2MTcxMCIsInVzZXJuYW1lIjoic3VwZXJhZG1pbiIsImZpcnN0TmFtZSI6InN1cGVyIiwiZW1haWwiOiJzdXBlcmFkbWluQGdtYWlsLmNvbSIsImlzQWN0aXZlIjp0cnVlLCJpc0FkbWluIjp0cnVlfSwiaWF0IjoxNjcwMjA5NDI0LCJleHAiOjE2NzAyMDk1NDQsImF1ZCI6ImNvc21hcnQuY28uaWQiLCJpc3MiOiJjb3NtYXJ0LmNvLmlkIn0.16Qz04MPVgjgiTIvqOebIf9xWZO-Ta8VUXH-9a0R0hk"
    }
}

Status Code: 200


II. Example Request: Wrong Password

Body:

{
    "username": "superadmin",
    "password": "Haruslolos123!!"
}

II. Example Response: Wrong Password

{
    "status": false,
    "message": "Un Authorized!"
}

Status Code: 401


III. Example Request: Wrong Username

Body:

{
    "username": "superadmins",
    "password": "Haruslolos123!"
}

III. Example Response: Wrong Username

{
    "status": false,
    "message": "Un Authorized!"
}

Status Code: 401


2. REFRESH

Fetch new Token as a refresh token

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/auth/refresh-token

More example Requests/Responses:

I. Example Request: Success

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVzZXJJZCI6IjYzOGIzNDJlN2ZkYzBjZGY5NWY2MTcxMCIsInVzZXJuYW1lIjoic3VwZXJhZG1pbiIsImZpcnN0TmFtZSI6InN1cGVyIiwiZW1haWwiOiJzdXBlcmFkbWluQGdtYWlsLmNvbSIsImlzQWN0aXZlIjp0cnVlLCJpc0FkbWluIjp0cnVlfSwiaWF0IjoxNjcwMjA5NzkxLCJleHAiOjE2NzAyMDk5MTEsImF1ZCI6ImNvc21hcnQuY28uaWQiLCJpc3MiOiJjb3NtYXJ0LmNvLmlkIn0.qslAe_3dioFs0bOtN1wOpfhuLwNsAE7UAf50Fj7ueIM"
    }
}

Status Code: 200


II. Example Request: UnAuthorize

Body: None

II. Example Response: UnAuthorize

Unauthorized

Status Code: 401


3. LOGOUT

User Logout and remove token, cookies etc

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/auth/logout

Query params:

Key Value Description
allDevices true true or false

More example Requests/Responses:

I. Example Request: Success

Query:

Key Value Description
allDevices true true or false

Body: None

Status Code: 204


II. Example Request: UnAuthorize

Query:

Key Value Description
allDevices true true or false

Body: None

II. Example Response: UnAuthorize

Unauthorized

Status Code: 401


USER

Users directory contains all the user related APIs. For authentication these apis requrie BasicAuth

1. CREATE

Create user use JSON payload to create a user

Endpoint:

Method: POST
Type: RAW
URL: {{local}}/v1/users

Body:

{
    "firstName": "super1",
    "lastName": "admin2",
    "username": "superadmin1",
    "email": "superadmin1@gmail.com",
    "password": "Haruslolos123!",
    "address": "di hati cosmart"
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "firstName": "need",
    "lastName": "job",
    "username": "needjob",
    "email": "needjob@gmail.com",
    "password": "Haruslolos123!",
    "address": "di hati cosmart"
}

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": "638cdb32cf642a10585cef4c"
}

Status Code: 200


II. Example Request: Validation error

Body:

{
    "firstName": 132,
    "lastName": "admin",
    "username": "superadmin",
    "email": "superadmin@gmail.com",
    "password": "123",
    "address": "di hati cosmart"
}

II. Example Response: Validation error

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "firstName",
            "key": "type",
            "message": "Firstname must be string"
        },
        {
            "param": "password",
            "key": "minLength",
            "message": "Password should be greater than 6"
        },
        {
            "param": "password",
            "key": "format",
            "message": "Password should be including 1 Uppercase, 1 number and 1 special character(#?!@$%^&*-)"
        }
    ]
}

Status Code: 400


2. GET ALL

Fetch all list users

can be filtered by user fields

[
    "userId",
     "firstName",
     "username",
     "email",
     "isActive",
]

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/users

More example Requests/Responses:

I. Example Request: Success

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "_id": "638c85b7bedda18dfa65fdd8",
            "firstName": "masa",
            "username": "masalalu",
            "email": "masalalu@gmail.com",
            "isActive": true
        },
        {
            "_id": "638cdb32cf642a10585cef4c",
            "firstName": "need",
            "username": "needjob",
            "email": "needjob@gmail.com",
            "isActive": true
        },
        {
            "_id": "638b342e7fdc0cdf95f61710",
            "firstName": "super",
            "username": "superadmin",
            "email": "superadmin@gmail.com",
            "isActive": true
        }
    ]
}

Status Code: 200


II. Example Request: Success with filter

Query:

Key Value Description
userId 638c85b7bedda18dfa65fdd8,638b342e7fdc0cdf95f61710

Body: None

II. Example Response: Success with filter

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "_id": "638c85b7bedda18dfa65fdd8",
            "firstName": "masa",
            "username": "masalalu",
            "email": "masalalu@gmail.com",
            "isActive": true
        },
        {
            "_id": "638b342e7fdc0cdf95f61710",
            "firstName": "super",
            "username": "superadmin",
            "email": "superadmin@gmail.com",
            "isActive": true
        }
    ]
}

Status Code: 200


3. GET TABLE

Fetch User using pagination

allowed filter/search by multiple fields

  • firstName
  • username
  • email
  • status

can be sorted by those fields as well

sortBy = status

sortType = desc or asc

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/users/table

Query params:

Key Value Description
sortBy status firstName, username, email, status
sortType desc asc, desc and/or 0, 1

More example Requests/Responses:

I. Example Request: Success

Query:

Key Value Description
sortBy status
sortType desc

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "status": "DESC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 3,
        "totalPage": 1,
        "data": [
            {
                "_id": "638b342e7fdc0cdf95f61710",
                "firstName": "super",
                "username": "superadmin",
                "email": "superadmin@gmail.com",
                "isActive": true,
                "updatedAt": "2022-12-04T19:53:20.387Z"
            },
            {
                "_id": "638c85b7bedda18dfa65fdd8",
                "firstName": "masa",
                "username": "masalalu",
                "email": "masalalu@gmail.com",
                "isActive": true,
                "updatedAt": "2022-12-04T11:34:15.729Z"
            },
            {
                "_id": "638cdb32cf642a10585cef4c",
                "firstName": "need",
                "username": "needjob",
                "email": "needjob@gmail.com",
                "isActive": false,
                "updatedAt": "2022-12-04T17:38:58.088Z"
            }
        ]
    }
}

Status Code: 200


II. Example Request: No user found

Query:

Key Value Description
sortBy status
sortType desc
search nothing

Body: None

II. Example Response: No user found

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "status": "DESC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 0,
        "totalPage": 1,
        "data": []
    }
}

Status Code: 200


4. GET ONE

Fetch a single user using id with ObjectId format

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/users/638b342e7fdc0cdf95f61710

More example Requests/Responses:

I. Example Request: Success

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "_id": "638b342e7fdc0cdf95f61710",
        "firstName": "super",
        "lastName": "admin",
        "username": "superadmin",
        "email": "superadmin@gmail.com",
        "address": "di hati cosmart",
        "isActive": true,
        "infoLogin": {
            "hash": "d7d53541df690651e8b6748a587003010b39dd77e14f97fd6b81e5c7f22012dfd9fa69b7b0c11a76d4de5bd8f7f72e19fa7bca1a5ef6bca91b9d3b076b97747c",
            "salt": "qt1Sa7e3d5DGj/mVv2PIJOB0t6ofhKzJ+rhdBAIMbhrzgzNpz3rPKEjjmTuEb8yNX2intdE7NesGuznqmLMY9qwS/9DZJ7YrBu/9Dz3xyTUzStV5EZHglyCLR2YS/XNcHMMiIw6t7XMMN3yHCDuQ4dyRZnT+vyPD7VW84Pl1WXI=",
            "iterations": 8912
        },
        "updatedAt": "2022-12-04T19:53:20.387Z",
        "gender": "Man"
    }
}

Status Code: 200


II. Example Request: User not found

Body: None

II. Example Response: User not found

{
    "status": false,
    "message": "User not found!"
}

Status Code: 400


5. PUT

Update user use JSON payload to update a user

Note: only below field can be updated using PUT.

Endpoint:

Method: PUT
Type: RAW
URL: {{local}}/v1/users/638b342e7fdc0cdf95f61710

Body:

{
    "firstName": "super",
    "lastName": "admin",    
    "address": "di hati cosmart",
    "gender": "Man"
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "firstName": "super",
    "lastName": "admin",    
    "address": "di hati cosmart",
    "gender": "Man"
}

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "_id": "638b342e7fdc0cdf95f61710",
        "firstName": "super",
        "lastName": "admin",
        "username": "superadmin",
        "email": "superadmin@gmail.com",
        "address": "di hati cosmart",
        "isActive": false,
        "infoLogin": {
            "hash": "f6cd5fad5b1c120fce3e1f87961d1ff65021e873e3e49be587671f7157369c4ccd2467bc98f069b2a7997d2fa1fe047f8896cc96bb2f186202feb5943dce9977",
            "salt": "87Om/3NARWYw4gb1NLoHd8wDPax68kA8qkjtV1hk34E2zyvQ9bGzUrvkPF/3ZWmdijWLZfBEvKxVmyFfCbJiFA1bwrSuMwk2TOXyiwqEF60lNTIbwBwaRZ45LLXyVggnUaVW1A4B+sYczxc7VooHPS3qTO7ClJinANgWkTVsL1U=",
            "iterations": 1434
        },
        "updatedAt": "2022-12-04T19:53:20.387Z",
        "gender": "Man"
    }
}

Status Code: 200


II. Example Request: Validation Error

Body:

{
    "firstName": 123,
    "lastName": "admin",    
    "address": "di hati cosmart",
    "gender": "Man",
    
    "other": "oalah"
}

II. Example Response: Validation Error

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "other",
            "key": "additionalProperties",
            "message": "must NOT have additional properties"
        },
        {
            "param": "firstName",
            "key": "type",
            "message": "Firstname must be string."
        }
    ]
}

Status Code: 400


III. Example Request: User not found

Body:

{
    "firstName": "super",
    "lastName": "admin",    
    "address": "di hati cosmart",
    "gender": "Man"
}

III. Example Response: User not found

{
    "status": false,
    "message": "User not found!"
}

Status Code: 400


6. PATCH CREDENTIAL

Update user password use JSON payload to update a user

Endpoint:

Method: PATCH
Type: RAW
URL: {{local}}/v1/users/638b342e7fdc0cdf95f61710

Body:

{
    "password": "Haruslolos123!",
    "newPassword": "!Haruslolos123"
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "password": "Haruslolos123!",
    "newPassword": "!Haruslolos123"
}

Status Code: 204


II. Example Request: Wrong Password

Body:

{
    "password": "!Haruslolos123",
    "newPassword": "Haruslolos123!"
}

II. Example Response: Wrong Password

{
    "status": false,
    "message": "Incorect Password"
}

Status Code: 400


III. Example Request: validation error

Body:

{
    
}

III. Example Response: validation error

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "password",
            "key": "required",
            "message": "Password is required"
        },
        {
            "param": "newPassword",
            "key": "required",
            "message": "New Password is required"
        }
    ]
}

Status Code: 400


IV. Example Request: Validation error other field

Body:

{
    "password": "Haruslolos123!",
    "newPassword": "!Haruslolos123",

    "otherfield": "lol"
}

IV. Example Response: Validation error other field

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "otherfield",
            "key": "additionalProperties",
            "message": "must NOT have additional properties"
        }
    ]
}

Status Code: 400


V. Example Request: User not found

Body:

{
    "password": "Haruslolos123!",
    "newPassword": "!Haruslolos123"
}

V. Example Response: User not found

{
    "status": false,
    "message": "User not found!"
}

Status Code: 400


7. PATCH USER STATUS

Update user status use JSON payload to update

Endpoint:

Method: PATCH
Type: RAW
URL: {{local}}/v1/users/status/638b342e7fdc0cdf95f61710

Body:

{
    "isActive": true
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "isActive": true
}

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "isActive": true
    }
}

Status Code: 200


II. Example Request: Validation error

Body:

{
    "isActive": "true"
}

II. Example Response: Validation error

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "isActive",
            "key": "type",
            "message": "Status should be boolean"
        },
        {
            "param": "isActive",
            "key": "enum",
            "message": "Please select one from the options"
        }
    ]
}

Status Code: 400


III. Example Request: User not found

Body:

{
    "isActive": true
}

III. Example Response: User not found

{
    "status": false,
    "message": "User not found!"
}

Status Code: 400


8. DELETE

Delete a single user using id

Endpoint:

Method: DELETE
Type: 
URL: {{local}}/v1/users/638cfdd0e18440b7d43ddbcd

More example Requests/Responses:

I. Example Request: Success

Body: None

Status Code: 204


II. Example Request: User not found

Body: None

II. Example Response: User not found

{
    "status": false,
    "message": "User not found!"
}

Status Code: 400


III. Example Request: Url not found

Body: None

III. Example Response: Url not found

Not Found

Status Code: 404


OPENLIBRARY

OpenLibrary API

this is an open source library

for more detail. follow this link

Open Library API

1. GET BY SUBJECT

Fetch list book by Subject from Open Library API

Use param Search to get list subject

can also using limit where limit default to 10

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/books

Query params:

Key Value Description
search love string
limit 1 number

More example Requests/Responses:

I. Example Request: Success

Query:

Key Value Description
search love

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "key": "/works/OL21177W",
            "title": "Wuthering Heights",
            "authors": [
                {
                    "key": "/authors/OL4327048A",
                    "name": "Emily Brontë"
                }
            ],
            "edition_count": 1608,
            "cover_id": 12818862
        },
        {
            "key": "/works/OL362427W",
            "title": "Romeo and Juliet",
            "authors": [
                {
                    "key": "/authors/OL9388A",
                    "name": "William Shakespeare"
                }
            ],
            "edition_count": 969,
            "cover_id": 8257991
        },
        {
            "key": "/works/OL98501W",
            "title": "Ethan Frome",
            "authors": [
                {
                    "key": "/authors/OL20188A",
                    "name": "Edith Wharton"
                }
            ],
            "edition_count": 718,
            "cover_id": 8303480
        },
        {
            "key": "/works/OL27776452W",
            "title": "The Importance of Being Earnest",
            "authors": [
                {
                    "key": "/authors/OL20646A",
                    "name": "Oscar Wilde"
                }
            ],
            "edition_count": 442,
            "cover_id": 1260453
        },
        {
            "key": "/works/OL267096W",
            "title": "Anna Karénina",
            "authors": [
                {
                    "key": "/authors/OL26783A",
                    "name": "Lev Nikolaevič Tolstoy"
                }
            ],
            "edition_count": 388,
            "cover_id": 2560652
        },
        {
            "key": "/works/OL8193420W",
            "title": "The Republic",
            "authors": [
                {
                    "key": "/authors/OL189658A",
                    "name": "Πλάτων"
                },
                {
                    "key": "/authors/OL2933723A",
                    "name": "G.M.A. Grube"
                }
            ],
            "edition_count": 349,
            "cover_id": 8235511
        },
        {
            "key": "/works/OL551668W",
            "title": "Cyrano de Bergerac",
            "authors": [
                {
                    "key": "/authors/OL39281A",
                    "name": "Edmond Rostand"
                }
            ],
            "edition_count": 307,
            "cover_id": 8236320
        },
        {
            "key": "/works/OL10264W",
            "title": "Le Petit Prince",
            "authors": [
                {
                    "key": "/authors/OL31901A",
                    "name": "Antoine de Saint-Exupéry"
                }
            ],
            "edition_count": 267,
            "cover_id": 10708272
        },
        {
            "key": "/works/OL15100036W",
            "title": "The Dialogues of Plato",
            "authors": [
                {
                    "key": "/authors/OL189658A",
                    "name": "Πλάτων"
                }
            ],
            "edition_count": 246,
            "cover_id": 8236248
        },
        {
            "key": "/works/OL239940W",
            "title": "कामसूत्र",
            "authors": [
                {
                    "key": "/authors/OL2531003A",
                    "name": "Vātsyāyana"
                }
            ],
            "edition_count": 236,
            "cover_id": 8003766
        }
    ]
}

Status Code: 200


II. Example Request: Succes with limit

Query:

Key Value Description
search love
limit 1

Body: None

II. Example Response: Succes with limit

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "key": "/works/OL21177W",
            "title": "Wuthering Heights",
            "authors": [
                {
                    "key": "/authors/OL4327048A",
                    "name": "Emily Brontë"
                }
            ],
            "edition_count": 1608,
            "cover_id": 12818862
        }
    ]
}

Status Code: 200


III. Example Request: No book(s) found

Query:

Key Value Description
search layoff
limit 1

Body: None

III. Example Response: No book(s) found

{
    "status": false,
    "message": "No book(s) found!"
}

Status Code: 404


2. GET DETAIL

Fetch detail book from Subject from Open Library API

Use param key to get detail of the book.

Noted : need to request to Api Book first than use field key from the array

exe: ?key=/works/OL21177W

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/books/detail

Query params:

Key Value Description
key /works/OL21177W data.key

More example Requests/Responses:

I. Example Request: Success

Query:

Key Value Description
key /works/OL21177W

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "key": "/works/OL21177W",
        "title": "Wuthering Heights",
        "authors": [
            {
                "author": {
                    "key": "/authors/OL4327048A"
                },
                "type": {
                    "key": "/type/author_role"
                }
            }
        ],
        "description": "Wuthering Heights is an 1847 novel by Emily Brontë, initially published under the pseudonym Ellis Bell. It concerns two families of the landed gentry living on the West Yorkshire moors, the Earnshaws and the Lintons, and their turbulent relationships with Earnshaw's adopted son, Heathcliff. The novel was influenced by Romanticism and Gothic fiction.",
        "first_sentence": {
            "type": "/type/text",
            "value": "1801.-I have just returned from a visit to my landlord-the solitary neighbour that I shall be troubled with."
        },
        "first_publish_date": "April 1, 2000",
        "links": [
            {
                "url": "https://en.wikipedia.org/wiki/Wuthering_Heights",
                "title": "Wuthering Heights - Wikipedia",
                "type": {
                    "key": "/type/link"
                }
            },
            {
                "url": "https://www.cliffsnotes.com/literature/w/wuthering-heights/wuthering-heights-at-a-glance",
                "title": "Wuthering Heights at a glance (cliffsnotes.com)",
                "type": {
                    "key": "/type/link"
                }
            },
            {
                "url": "https://www.theguardian.com/books/2013/dec/16/emily-bronte-wuthering-heights-100-best",
                "title": "The 100 best novels: No 13 – Wuthering Heights by Emily Brontë (1847) (theguardian.com)",
                "type": {
                    "key": "/type/link"
                }
            },
            {
                "title": "The reader's guide to Emily Bronte's classic 'Wuthering Heights' (wuthering-heights.co.uk)",
                "url": "https://www.wuthering-heights.co.uk/",
                "type": {
                    "key": "/type/link"
                }
            },
            {
                "url": "https://thegreatestbooks.org/items/108",
                "title": "thegreatestbooks.org/items/108",
                "type": {
                    "key": "/type/link"
                }
            }
        ],
        "revision": 101
    }
}

Status Code: 200


II. Example Request: Not book detail found

Query:

Key Value Description
key /works/OL21177W1

Body: None

II. Example Response: Not book detail found

{
    "status": false,
    "message": "Request failed with status code 404"
}

Status Code: 404


BOOKINGS

This API have more logic to implemented

  • user need to register first and must be active
  • should can't choose date in the previous day
  • there are limitation for cook count, book booking and how long book can be borrowed

Info:

there are 3 uri for GET,

  • /v1/bookings
  • /v1/bookings/{bookingId}
  • /v1/bookings/table

ill suggest to use table version bacause it support pagination, search, filter by etc.

1. CREATE

Create Booking use JSON payload to create a booking/appointment

Endpoint:

Method: POST
Type: RAW
URL: {{local}}/v1/bookings

Body:

{
    "userId": "638d3fb01ae7b78318c8dd00",
    "startDate": "2022-12-12 12:00:00",
    "endDate": "2022-12-15 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

More example Requests/Responses:

I. Example Request: Success booking

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 12:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

I. Example Response: Success booking

{
    "status": true,
    "message": "Success",
    "data": "638d205a766f97ff1c40d8e6"
}

Status Code: 200


II. Example Request: Invalid Date ranges

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

II. Example Response: Invalid Date ranges

{
    "status": false,
    "message": "Dont stuck in the past, there is still a lot of sand in the ocean"
}

Status Code: 400


III. Example Request: Duplciate book and not return yet

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 12:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

III. Example Response: Duplciate book and not return yet

{
    "status": false,
    "message": "Please check you list, one/some of them is still you borrowed"
}

Status Code: 422


IV. Example Request: Invali Long borrowing date

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 12:00:00",
    "endDate": "2022-12-18 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

IV. Example Response: Invali Long borrowing date

{
    "status": false,
    "message": "You can only borrow maximal for 3 days"
}

Status Code: 400


V. Example Request: Validation Error Empty Item

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 12:00:00",
    "endDate": "2022-12-18 02:00:00",
    "list": []
}

V. Example Response: Validation Error Empty Item

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "list",
            "key": "minItems",
            "message": "Please pick at least one book!"
        }
    ]
}

Status Code: 400


VI. Example Request: Validation error field required

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 12:00:00",
    "endDate": "2022-12-18 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W"
            
        }
    ]
}

VI. Example Response: Validation error field required

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "bookTitle",
            "key": "required",
            "message": "Book Title required!"
        }
    ]
}

Status Code: 400


2. GET ALL

Fetch all list booking/appointment

also support for filtering/search

available fields:

  • bookingId
  • status
  • search
  • limit1

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/bookings

Query params:

Key Value Description
bookingId 638d205a766f97ff1c40d8e6 ObjectId

More example Requests/Responses:

I. Example Request: Success without filter

Query:

Key Value Description
search neighborhood for field bookKey and bookTitle

Body: None

I. Example Response: Success without filter

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "_id": "638d205a766f97ff1c40d8e6",
            "userId": {
                "_id": "638cdb32cf642a10585cef4c",
                "fullname": "need job"
            },
            "startDate": "2022-12-05T12:00:00+07:00",
            "endDate": "2022-12-08T02:00:00+07:00",
            "list": [
                {
                    "bookKey": "/works/OL1859783W",
                    "bookTitle": "The Artificial Kingdom"
                },
                {
                    "bookKey": "/works/OL4279057W",
                    "bookTitle": "The Old Neighborhood"
                }
            ],
            "status": "pending"
        }
    ]
}

Status Code: 200


II. Example Request: Success with filter search

Query:

Key Value Description
search neighborhood

Body: None

II. Example Response: Success with filter search

{
    "status": true,
    "message": "Success",
    "data": [
        {
            "_id": "638d205a766f97ff1c40d8e6",
            "userId": {
                "_id": "638cdb32cf642a10585cef4c",
                "fullname": "need job"
            },
            "startDate": "2022-12-05T12:00:00+07:00",
            "endDate": "2022-12-08T02:00:00+07:00",
            "list": [
                {
                    "bookKey": "/works/OL1859783W",
                    "bookTitle": "The Artificial Kingdom"
                },
                {
                    "bookKey": "/works/OL4279057W",
                    "bookTitle": "The Old Neighborhood"
                }
            ],
            "status": "pending"
        }
    ]
}

Status Code: 200


III. Example Request: Filter not match to any

Query:

Key Value Description
search begadang for field bookKey and bookTitle

Body: None

III. Example Response: Filter not match to any

{
    "status": false,
    "message": "No Data booking found!"
}

Status Code: 404


3. GET ONE

Fetch a single booking using id with ObjectId format

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/bookings/638d205a766f97ff1c40d8e6

More example Requests/Responses:

I. Example Request: Success

Body: None

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "_id": "638d205a766f97ff1c40d8e6",
        "userId": "638cdb32cf642a10585cef4c",
        "startDate": "2022-12-05T12:00:00+07:00",
        "endDate": "2022-12-08T02:00:00+07:00",
        "list": [
            {
                "bookKey": "/works/OL1859783W",
                "bookTitle": "The Artificial Kingdom"
            },
            {
                "bookKey": "/works/OL4279057W",
                "bookTitle": "The Old Neighborhood"
            }
        ],
        "status": "pending",
        "createdAt": "2022-12-05T05:34:02+07:00"
    }
}

Status Code: 200


II. Example Request: Not found

Body: None

II. Example Response: Not found

{
    "status": false,
    "message": "Booking Id is not found!"
}

Status Code: 404


4. GET TABLE

Fetch Bookings using pagination

allowed filter/search by multiple fields

  • userId
  • list.bookKey
  • list.bookTitle
  • status

can be sorted by those fields as well

sortBy = status

sortType = desc or asc

noted: API will always return 200

Endpoint:

Method: GET
Type: 
URL: {{local}}/v1/bookings/table

Query params:

Key Value Description
status done, cancelled approved, rejected, pending, done, cancelled

More example Requests/Responses:

I. Example Request: Success without default data

Body: None

I. Example Response: Success without default data

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "updatedAt": "ASC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 3,
        "totalPage": 1,
        "data": [
            {
                "_id": "638c8691b1a20b1247f0ede0",
                "userId": {
                    "_id": "638c85b7bedda18dfa65fdd8",
                    "fullname": "masa lalu"
                },
                "list": [
                    {
                        "bookKey": "/works/OL1859783W",
                        "bookTitle": "The Artificial Kingdom"
                    }
                ],
                "startDate": "2022-12-06T02:00:00+07:00",
                "endDate": "2022-12-08T02:00:00+07:00",
                "status": "pending"
            },
            {
                "_id": "638cd3e390b9b62be62a87e3",
                "userId": {
                    "_id": "638cdb32cf642a10585cef4c",
                    "fullname": "need job"
                },
                "startDate": "2022-12-06T02:00:00+07:00",
                "endDate": "2022-11-08T02:00:00+07:00",
                "list": [
                    {
                        "bookKey": "/works/OL1859783W",
                        "bookTitle": "The Artificial Kingdom"
                    },
                    {
                        "bookKey": "/works/OL16800971W",
                        "bookTitle": "Die Zeit, die Zeit"
                    }
                ],
                "status": "done"
            },
            {
                "_id": "638d205a766f97ff1c40d8e6",
                "userId": {
                    "_id": "638cdb32cf642a10585cef4c",
                    "fullname": "need job"
                },
                "startDate": "2022-12-05T12:00:00+07:00",
                "endDate": "2022-12-08T02:00:00+07:00",
                "list": [
                    {
                        "bookKey": "/works/OL1859783W",
                        "bookTitle": "The Artificial Kingdom"
                    },
                    {
                        "bookKey": "/works/OL4279057W",
                        "bookTitle": "The Old Neighborhood"
                    }
                ],
                "status": "pending"
            }
        ]
    }
}

Status Code: 200


II. Example Request: Success with filter userIds

Query:

Key Value Description
userId 638c85b7bedda18dfa65fdd8,638b342e7fdc0cdf95f61710 string array

Body: None

II. Example Response: Success with filter userIds

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "updatedAt": "ASC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 3,
        "totalPage": 1,
        "data": [
            {
                "_id": "638c8691b1a20b1247f0ede0",
                "userId": {
                    "_id": "638c85b7bedda18dfa65fdd8",
                    "fullname": "masa lalu"
                },
                "list": [
                    {
                        "bookKey": "/works/OL1859783W",
                        "bookTitle": "The Artificial Kingdom"
                    }
                ],
                "startDate": "2022-12-06T02:00:00+07:00",
                "endDate": "2022-12-08T02:00:00+07:00",
                "status": "pending"
            }
        ]
    }
}

Status Code: 200


III. Example Request: Success filter nested list

Query:

Key Value Description
search Neighborhood bookKey or bookTtitle of list's field

Body: None

III. Example Response: Success filter nested list

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "updatedAt": "ASC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 3,
        "totalPage": 1,
        "data": [
            {
                "_id": "638d205a766f97ff1c40d8e6",
                "userId": {
                    "_id": "638cdb32cf642a10585cef4c",
                    "fullname": "need job"
                },
                "startDate": "2022-12-05T12:00:00+07:00",
                "endDate": "2022-12-08T02:00:00+07:00",
                "list": [
                    {
                        "bookKey": "/works/OL1859783W",
                        "bookTitle": "The Artificial Kingdom"
                    },
                    {
                        "bookKey": "/works/OL4279057W",
                        "bookTitle": "The Old Neighborhood"
                    }
                ],
                "status": "pending"
            }
        ]
    }
}

Status Code: 200


IV. Example Request: Success but no data found

Query:

Key Value Description
search begadang

Body: None

IV. Example Response: Success but no data found

{
    "status": true,
    "message": "Success",
    "data": {
        "sort": {
            "updatedAt": "ASC"
        },
        "page": 1,
        "size": 10,
        "totalRecord": 0,
        "totalPage": 1,
        "data": []
    }
}

Status Code: 200


5. UPDATE

Update Booking use JSON payload to update booking

Or you can just replace those field from GET ../detail/{id}

Note: only below field can be updated using PUT

Endpoint:

Method: PUT
Type: RAW
URL: {{local}}/v1/bookings/638d205a766f97ff1c40d8e6

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ]
}

More example Requests/Responses:

I. Example Request: Success

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ] 
}

I. Example Response: Success

{
    "status": true,
    "message": "Success",
    "data": {
        "_id": "638d205a766f97ff1c40d8e6",
        "userId": "638cdb32cf642a10585cef4c",
        "startDate": "2022-12-05T02:00:00+07:00",
        "endDate": "2022-12-08T02:00:00+07:00",
        "list": [
            {
                "bookKey": "/works/OL1859783W",
                "bookTitle": "The Artificial Kingdom"
            },
            {
                "bookKey": "/works/OL4279057W",
                "bookTitle": "The Old Neighborhood"
            }
        ],
        "status": "pending",
        "createdAt": "2022-12-05T07:23:11+07:00"
    }
}

Status Code: 200


II. Example Request: Validation Error on Items

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [] 
}

II. Example Response: Validation Error on Items

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "list",
            "key": "minItems",
            "message": "Please pick at least one book!"
        }
    ]
}

Status Code: 400


III. Example Request: Validation error required

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W"
        }
    ] 
}

III. Example Response: Validation error required

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "bookTitle",
            "key": "required",
            "message": "Book Title required!"
        }
    ]
}

Status Code: 400


IV. Example Request: Invalid maximal days

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-20 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ] 
}

IV. Example Response: Invalid maximal days

{
    "status": false,
    "message": "You can only borrow maximal for 3 days"
}

Status Code: 400


V. Example Request: Validation error additional field

Body:

{
    "userId": "638cdb32cf642a10585cef4c",
    "startDate": "2022-12-05 02:00:00",
    "endDate": "2022-12-08 02:00:00",
    "list": [
        {
            "bookKey": "/works/OL1859783W",
            "bookTitle": "The Artificial Kingdom"
        },
        {
            "bookKey": "/works/OL4279057W",
            "bookTitle": "The Old Neighborhood"
        }
    ],
    "status": ""
}

V. Example Response: Validation error additional field

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "status",
            "key": "additionalProperties",
            "message": "must NOT have additional properties"
        }
    ]
}

Status Code: 400


6. PATCH BOOKING STATUS

This is used to handle booking status

list status

  • pending,
  • rejected,
  • approved,
  • done,
  • cancelled

Endpoint:

Method: PATCH
Type: RAW
URL: {{local}}/v1/bookings/status/638d41cfb8b5e4ba794fe9bf

Body:

{
    "status": "approved",
    "reason": "oke, take them all"
}

More example Requests/Responses:

I. Example Request: Success Approved

Body:

{
    "status": "approved"
}

I. Example Response: Success Approved

{
    "status": true,
    "message": "Success",
    "data": {
        "status": "approved"
    }
}

Status Code: 200


II. Example Request: Success Done

Body:

{
    "status": "done"
}

II. Example Response: Success Done

{
    "status": true,
    "message": "Success",
    "data": {
        "status": "done"
    }
}

Status Code: 200


III. Example Request: Success Cancelled

Body:

{
    "status": "cancelled"
}

III. Example Response: Success Cancelled

{
    "status": true,
    "message": "Success",
    "data": {
        "status": "cancelled"
    }
}

Status Code: 200


IV. Example Request: Validation error when rejected

Body:

{
    "status": "rejected"
}

IV. Example Response: Validation error when rejected

{
    "status": false,
    "message": "Validation Error!",
    "errors": [
        {
            "param": "reason",
            "key": "required",
            "message": "must have required property 'reason'"
        },
        {
            "key": "if",
            "message": "must match \"then\" schema"
        },
        {
            "key": "oneOf",
            "message": "must match exactly one schema in oneOf"
        }
    ]
}

Status Code: 400


V. Example Request: Invalid to rollback approved-> pending

Body:

{
    "status": "pending"
}

V. Example Response: Invalid to rollback approved-> pending

{
    "status": false,
    "message": "The Booking is already approved, please return our book for new booking"
}

Status Code: 422


VI. Example Request: Invalid to rollback approved-> rejected

Body:

{
    "status": "rejected",
    "reason": "no employee"
}

VI. Example Response: Invalid to rollback approved-> rejected

{
    "status": false,
    "message": "The Booking is already approved, please return our book for new booking"
}

Status Code: 422


VII. Example Request: Invalid to rollback approved-> cancelled

Body:

{
    "status": "cancelled"
}

VII. Example Response: Invalid to rollback approved-> cancelled

{
    "status": false,
    "message": "The Booking is already approved, please return our book for new booking"
}

Status Code: 422


VIII. Example Request: Invalid, cannot modify status done

Body:

{
    "status": "done"
}

VIII. Example Response: Invalid, cannot modify status done

{
    "status": false,
    "message": "You cannot modify this boking anymore"
}

Status Code: 422


IX. Example Request: Success rejected

Body:

{
    "status": "rejected",
    "reason": "malas"
}

IX. Example Response: Success rejected

{
    "status": true,
    "message": "Success",
    "data": {
        "status": "rejected",
        "reason": "malas"
    }
}

Status Code: 200


7. DELETE

Delete a single booking using id

Note: cannot delete booking with status approved, but API will alway re

Endpoint:

Method: DELETE
Type: 
URL: {{local}}/v1/bookings/638d41cfb8b5e4ba794fe9bf

More example Requests/Responses:

I. Example Request: Success delete

Body: None

Status Code: 204


II. Example Request: Not found id

Body: None

II. Example Response: Not found id

{
    "status": false,
    "message": "Booking Id not found!"
}

Status Code: 400


III. Example Request: Invalid when status apprvoed

Body: None

III. Example Response: Invalid when status apprvoed

{
    "status": false,
    "message": "Booking Id is not found or book(s) still borrowed!"
}

Status Code: 400



Back to top