Skip to content
Shopify Summer 2019 Developer Intern Challenge
Python
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
README.md
shop.py

README.md

Shopify Summer 2019 Developer Intern Challenge

Run Locally

Clone:

$ git clone https://github.com/raymondtruong/shopify-intern-challenge.git
$ cd shopify-intern-challenge

Populate with sample data:

$ python3
>>> from shop import db, Product
>>> db.create_all()
>>> db.session.add(Product(title="Product One", price=12.34, inventory_count=3))
>>> db.session.add(Product(title="Product Two", price=23.45, inventory_count=6))
...
>>> db.session.commit()
>>> exit()

Run:

$ python3 shop.py

The server is now running on 127.0.0.1:5000 by default.

Dependencies

  • Python 3
  • Flask 1.0.2
  • Flask-SQLAlchemy 2.3.2

API Documentation

Get all products: Returns all products. With the optional query string, only products that are in stock are returned.

  • URL: /api/products
  • Method: GET
  • Query Strings: ?in_stock=true (optional)
  • Success Response: JSON containing all products
  • Failure Response: N/A
  • Sample Call: GET /api/products
  • Sample Response:
[
    {
      "id": 1,
      "inventory_count": 3,
      "price": 12.34,
      "title": "Product One"
    },
    {
      "id": 2,
      "inventory_count": 6,
      "price": 23.45,
      "title": "Product Two"
    }
]

Get a specific product: Returns the specified product (by ID). Returns an error if an invalid product is specified.

  • URL: /api/products/<product_id>
  • Method: GET
  • Query Strings: N/A
  • Success Response: JSON containing the product with ID product_id
  • Failure Response: An applicable error message
  • Sample Call: GET /api/products/1
  • Sample Response:
{
    "id": 1,
    "inventory_count": 3,
    "price": 12.34,
    "title": "Product One"
}

Purchase an item: Purchases the specified object, reducing its inventory by one, and returns the specified product. Returns an error if the product is out of stock, or if an invalid product is specified.

  • URL: /api/products/<product_id>/purchase
  • Method: POST
  • Query Strings: N/A
  • Success Response: JSON containing the product with ID product_id
  • Failure Response: An applicable error message
  • Sample Call: POST /api/products/1/purchase
  • Sample Response:
{
    "id": 1,
    "inventory_count": 2,
    "price": 12.34,
    "title": "Product One"
}

Get all carts: Returns all carts.

  • URL: /api/carts
  • Method: GET
  • Query Strings: N/A
  • Success Response: JSON containing all carts
  • Failure Response: N/A
  • Sample Call: GET /api/carts
  • Sample Response:
[
    {
      "cart_items": [
        {
          "product": {
            "id": 3,
            "inventory_count": 12,
            "price": 34.56,
            "title": "Product Three"
          },
          "quantity": 1
        }
      ],
      "id": 1,
      "total_price": 34.56
    },
    {
      "cart_items": [],
      "id": 2,
      "total_price": 0.0
    }
]

Get a specific cart: Returns the specified cart (by ID). Returns an error if an invalid cart is specified.

  • URL: /api/carts/<cart_id>
  • Method: GET
  • Query Strings: N/A
  • Success Response: JSON containing the cart with ID cart_id
  • Failure Response: An applicable error message
  • Sample Call: GET /api/carts/1
  • Sample Response:
{
    "cart_items": [
      {
        "product": {
          "id": 3,
          "inventory_count": 12,
          "price": 34.56,
          "title": "Product Three"
        },
        "quantity": 1
      }
    ],
    "id": 1,
    "total_price": 34.56
}

Create a cart: Creates a new empty cart, and returns it.

  • URL: /api/carts
  • Method: POST
  • Query Strings: N/A
  • Success Response: JSON containing the new cart
  • Failure Response: N/A
  • Sample Call: POST /api/carts
  • Sample Response:
{
    "cart_items": [],
    "id": 3,
    "total_price": 0
}

Add a product to a cart: Adds the specified product to the specified cart, updates the total price, and returns the updated cart. Returns an error if an invalid cart or product are specified. Returns an error if the product cannot be added to the cart because it is not in stock, or because all the available inventory has already been added to the cart.

  • URL: /api/carts/<cart_id>/add
  • Method: POST
  • Query Strings: ?product=<product_id> (required)
  • Success Response: JSON containing the updated cart with ID cart_id now containing the product with ID product_id
  • Failure Response: An applicable error message
  • Sample Call: POST /api/carts/3/add?product=3
  • Sample Response:
{
    "cart_items": [
        {
            "product": {
                "id": 3,
                "inventory_count": 12,
                "price": 34.56,
                "title": "Product Three"
            },
            "quantity": 1
        }
    ],
    "id": 3,
    "total_price": 34.56
}

Check out a cart: Checks out the specified cart, clears it, and returns it. Returns an error if an invalid cart is specified.

  • URL: /api/carts/<cart_id>/checkout
  • Method: POST
  • Query Strings: N/A
  • Success Response: JSON containing the checked-out cart with ID cart_id
  • Failure Response: An applicable error message
  • Sample Call: POST /api/carts/3/checkout
  • Sample Response:
{
    "cart_items": [],
    "id": 3,
    "total_price": 0
}

Next Steps

  • Deploy (on Heroku, etc.)
  • Write unit tests
  • Perhaps return errors as JSON data rather than raw text
  • Bug: Ensure products are actually in stock at time of checkout (to prevent race condition)
  • Implement user model (secure authentication, etc.)
  • Document sample failure responses instead of only success responses
  • Utilize HTTP response codes for more descriptive errors
  • Fix cart total price decimal precision issues
You can’t perform that action at this time.