{"action":"created","comment":{"url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/comments/28989603","id":28989603,"diff_hunk":"@@ -0,0 +1,146 @@\n+import sqlite3\n+\n+class HTTPResponse(object):\n+    def __init__(self, status_code, body, mimetype=\"text/html\"):\n+        self.status_code = status_code\n+        self.body = body\n+        self.mimetype = mimetype\n+        # ... additional properties omitted ...\n+\n+    # ... omitted ...\n+\n+\n+class Cart(object):\n+    \"\"\" A user's shopping cart.\n+        \n+        ``.items``: a list of item IDs in the cart.\n+\n+        ``.item_quantities``: a dictionary mapping itemIDs to the number\n+            of that item in the cart.\n+\n+        ``.discounts``: a list of item-pair discounts that apply to this cart\n+            in the form ``(discount_name, discount_amount)``.\n+\n+        ... additional properties omitted ...\n+    \"\"\"\n+\n+    # ... omitted ...\n+\n+\n+class Template(object):\n+    \"\"\" Template renderer.\n+\n+        >>> Template(\"Hello, {{ what }}!\").render({ \"what\": \"world\" })\n+        'Hello, world!'\n+    \"\"\"\n+\n+    # ... omitted ...\n+\n+\n+class AddItemToCartView(object):\n+    \"\"\" Handles requests to `/cart/add?item_id=$id&quantity=$quantity`, adding\n+        `quantity` of `item_id` to the current user's shopping cart.\n+\n+        If the item already exists in in the cart, the quantity is updated.\n+\n+        Checks to see if the cart contains any item combinations which result\n+        in special deals.\n+\n+        Returns an \"added to cart\" page, confirming the name of the item which\n+        has been added, as well as the current quantity and messages about\n+        any special discounts. \"\"\"\n+\n+    def __init__(self, settings):\n+        self.settings = settings\n+\n+    def handle_GET(self, request):\n+        item_id = request.GET.get(\"item_id\")\n+        if not self.__validate_item_id(item_id):\n+            return HTTPResponse(500, \"No such item with id '\" + item_id + \"' does not exist.\")\n+\n+        cart = request.session.cart\n+\n+        # Find the item in the cart\n+        itemIndex = -1\n+        for i in range(len(cart.items)):\n+            if item_id == cart.items[i]:\n+                itemIndex = i\n+                break\n+\n+        if itemIndex < 0:\n+            itemIndex = len(cart.items)\n+            cart.items.append(item_id)\n+\n+        # Update the quantity of that item in the cart\n+        current_quantity = cart.item_quantities.get(item_id, 0)\n+        current_quantity += int(request.GET.get(\"quantity\"))\n+\n+        # Check to see if the cart is eligible for any special discounts\n+        special_discount_message = self.__check_cart_for_discounts(cart)\n+\n+        # Send back the response\n+        response_body = Template(\"\"\"\n+            <div class='addToCartConfirmation'>\n+                The item {{ item_name }} has been added to your cart.<br />\n+                There are {{ quantity }} of them in your cart.\n+            </div>\n+            <div class='specialDiscountMessage'>\n+                {{ special_discount_message }}\n+            </div>\n+        \"\"\").render({\n+            \"item_name\": request.GET[\"item_name\"],\n+            \"quantity\": current_quantity,\n+            \"special_discount_message\": special_discount_message,\n+        })\n+        return HTTPResponse(200, response_body)\n+\n+    def __check_cart_for_discounts(self, cart):\n+        \"\"\" Checks to see if the cart qualifies for any any of the item-pair\n+            discounts being offered (for example, if the cart contains\n+            a soccer ball and goalie gloves, the \"goal keeper\" discount\n+            would be applied).\n+\n+            Returns a description of the discounts, or `\"\"` if no\n+            discounts apply. \"\"\"\n+        cxn = sqlite3.connect(self.settings.DATABASE_PATH)\n+        discounts = []\n+        for item0 in cart.items:\n+            for item1 in cart.items:\n+                result = cxn.execute(\"\"\"\n+                    SELECT discount_name, discount_amount FROM item_discounts\n+                    WHERE item0 = %s and item1 = %s\n+                \"\"\" %(item0, item1))\n+                result = result.fetchone()\n+                if result == None:\n+                    continue\n+                discounts.append(result)","path":"cart.py","position":116,"original_position":116,"commit_id":"49e7f06fbc06b988dd5d1cc43fe0d09aaf7105f1","original_commit_id":"49e7f06fbc06b988dd5d1cc43fe0d09aaf7105f1","user":{"login":"brentc","id":466158,"avatar_url":"https://avatars.githubusercontent.com/u/466158?v=3","gravatar_id":"","url":"https://api.github.com/users/brentc","html_url":"https://github.com/brentc","followers_url":"https://api.github.com/users/brentc/followers","following_url":"https://api.github.com/users/brentc/following{/other_user}","gists_url":"https://api.github.com/users/brentc/gists{/gist_id}","starred_url":"https://api.github.com/users/brentc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brentc/subscriptions","organizations_url":"https://api.github.com/users/brentc/orgs","repos_url":"https://api.github.com/users/brentc/repos","events_url":"https://api.github.com/users/brentc/events{/privacy}","received_events_url":"https://api.github.com/users/brentc/received_events","type":"User","site_admin":false},"body":"`NxN` queries to determine if any items discounts with any other discount. Probably way faster to do a single query with `where item0 in [items] and item1 in [items]` and sort out the actual active discounts in the returned set.","created_at":"2015-04-23T18:27:01Z","updated_at":"2015-04-23T18:27:01Z","html_url":"https://github.com/kiratalent/kira-cart/pull/2#discussion_r28989603","pull_request_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2","_links":{"self":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/comments/28989603"},"html":{"href":"https://github.com/kiratalent/kira-cart/pull/2#discussion_r28989603"},"pull_request":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2"}}},"pull_request":{"url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2","id":33980971,"html_url":"https://github.com/kiratalent/kira-cart/pull/2","diff_url":"https://github.com/kiratalent/kira-cart/pull/2.diff","patch_url":"https://github.com/kiratalent/kira-cart/pull/2.patch","issue_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/2","number":2,"state":"open","locked":false,"title":"Stuff","user":{"login":"brentc","id":466158,"avatar_url":"https://avatars.githubusercontent.com/u/466158?v=3","gravatar_id":"","url":"https://api.github.com/users/brentc","html_url":"https://github.com/brentc","followers_url":"https://api.github.com/users/brentc/followers","following_url":"https://api.github.com/users/brentc/following{/other_user}","gists_url":"https://api.github.com/users/brentc/gists{/gist_id}","starred_url":"https://api.github.com/users/brentc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brentc/subscriptions","organizations_url":"https://api.github.com/users/brentc/orgs","repos_url":"https://api.github.com/users/brentc/repos","events_url":"https://api.github.com/users/brentc/events{/privacy}","received_events_url":"https://api.github.com/users/brentc/received_events","type":"User","site_admin":false},"body":"Fixes #1\r\n\r\n💩","created_at":"2015-04-23T18:05:31Z","updated_at":"2015-04-23T18:27:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cfef4fc13124903d1804b231f057a05abe953fed","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2/commits","review_comments_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2/comments","review_comment_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/2/comments","statuses_url":"https://api.github.com/repos/kiratalent/kira-cart/statuses/49e7f06fbc06b988dd5d1cc43fe0d09aaf7105f1","head":{"label":"kiratalent:new-cart","ref":"new-cart","sha":"49e7f06fbc06b988dd5d1cc43fe0d09aaf7105f1","user":{"login":"kiratalent","id":6978451,"avatar_url":"https://avatars.githubusercontent.com/u/6978451?v=3","gravatar_id":"","url":"https://api.github.com/users/kiratalent","html_url":"https://github.com/kiratalent","followers_url":"https://api.github.com/users/kiratalent/followers","following_url":"https://api.github.com/users/kiratalent/following{/other_user}","gists_url":"https://api.github.com/users/kiratalent/gists{/gist_id}","starred_url":"https://api.github.com/users/kiratalent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiratalent/subscriptions","organizations_url":"https://api.github.com/users/kiratalent/orgs","repos_url":"https://api.github.com/users/kiratalent/repos","events_url":"https://api.github.com/users/kiratalent/events{/privacy}","received_events_url":"https://api.github.com/users/kiratalent/received_events","type":"Organization","site_admin":false},"repo":{"id":34472084,"name":"kira-cart","full_name":"kiratalent/kira-cart","owner":{"login":"kiratalent","id":6978451,"avatar_url":"https://avatars.githubusercontent.com/u/6978451?v=3","gravatar_id":"","url":"https://api.github.com/users/kiratalent","html_url":"https://github.com/kiratalent","followers_url":"https://api.github.com/users/kiratalent/followers","following_url":"https://api.github.com/users/kiratalent/following{/other_user}","gists_url":"https://api.github.com/users/kiratalent/gists{/gist_id}","starred_url":"https://api.github.com/users/kiratalent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiratalent/subscriptions","organizations_url":"https://api.github.com/users/kiratalent/orgs","repos_url":"https://api.github.com/users/kiratalent/repos","events_url":"https://api.github.com/users/kiratalent/events{/privacy}","received_events_url":"https://api.github.com/users/kiratalent/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kiratalent/kira-cart","description":"Shopping Cart Test Repo","fork":false,"url":"https://api.github.com/repos/kiratalent/kira-cart","forks_url":"https://api.github.com/repos/kiratalent/kira-cart/forks","keys_url":"https://api.github.com/repos/kiratalent/kira-cart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kiratalent/kira-cart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kiratalent/kira-cart/teams","hooks_url":"https://api.github.com/repos/kiratalent/kira-cart/hooks","issue_events_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/events{/number}","events_url":"https://api.github.com/repos/kiratalent/kira-cart/events","assignees_url":"https://api.github.com/repos/kiratalent/kira-cart/assignees{/user}","branches_url":"https://api.github.com/repos/kiratalent/kira-cart/branches{/branch}","tags_url":"https://api.github.com/repos/kiratalent/kira-cart/tags","blobs_url":"https://api.github.com/repos/kiratalent/kira-cart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kiratalent/kira-cart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kiratalent/kira-cart/git/refs{/sha}","trees_url":"https://api.github.com/repos/kiratalent/kira-cart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kiratalent/kira-cart/statuses/{sha}","languages_url":"https://api.github.com/repos/kiratalent/kira-cart/languages","stargazers_url":"https://api.github.com/repos/kiratalent/kira-cart/stargazers","contributors_url":"https://api.github.com/repos/kiratalent/kira-cart/contributors","subscribers_url":"https://api.github.com/repos/kiratalent/kira-cart/subscribers","subscription_url":"https://api.github.com/repos/kiratalent/kira-cart/subscription","commits_url":"https://api.github.com/repos/kiratalent/kira-cart/commits{/sha}","git_commits_url":"https://api.github.com/repos/kiratalent/kira-cart/git/commits{/sha}","comments_url":"https://api.github.com/repos/kiratalent/kira-cart/comments{/number}","issue_comment_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/comments{/number}","contents_url":"https://api.github.com/repos/kiratalent/kira-cart/contents/{+path}","compare_url":"https://api.github.com/repos/kiratalent/kira-cart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kiratalent/kira-cart/merges","archive_url":"https://api.github.com/repos/kiratalent/kira-cart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kiratalent/kira-cart/downloads","issues_url":"https://api.github.com/repos/kiratalent/kira-cart/issues{/number}","pulls_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls{/number}","milestones_url":"https://api.github.com/repos/kiratalent/kira-cart/milestones{/number}","notifications_url":"https://api.github.com/repos/kiratalent/kira-cart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kiratalent/kira-cart/labels{/name}","releases_url":"https://api.github.com/repos/kiratalent/kira-cart/releases{/id}","created_at":"2015-04-23T17:47:45Z","updated_at":"2015-04-23T17:48:06Z","pushed_at":"2015-04-23T18:05:33Z","git_url":"git://github.com/kiratalent/kira-cart.git","ssh_url":"git@github.com:kiratalent/kira-cart.git","clone_url":"https://github.com/kiratalent/kira-cart.git","svn_url":"https://github.com/kiratalent/kira-cart","homepage":"","size":0,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"kiratalent:master","ref":"master","sha":"748fefd263d12ac407fb50c30c292ed1621da2d8","user":{"login":"kiratalent","id":6978451,"avatar_url":"https://avatars.githubusercontent.com/u/6978451?v=3","gravatar_id":"","url":"https://api.github.com/users/kiratalent","html_url":"https://github.com/kiratalent","followers_url":"https://api.github.com/users/kiratalent/followers","following_url":"https://api.github.com/users/kiratalent/following{/other_user}","gists_url":"https://api.github.com/users/kiratalent/gists{/gist_id}","starred_url":"https://api.github.com/users/kiratalent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiratalent/subscriptions","organizations_url":"https://api.github.com/users/kiratalent/orgs","repos_url":"https://api.github.com/users/kiratalent/repos","events_url":"https://api.github.com/users/kiratalent/events{/privacy}","received_events_url":"https://api.github.com/users/kiratalent/received_events","type":"Organization","site_admin":false},"repo":{"id":34472084,"name":"kira-cart","full_name":"kiratalent/kira-cart","owner":{"login":"kiratalent","id":6978451,"avatar_url":"https://avatars.githubusercontent.com/u/6978451?v=3","gravatar_id":"","url":"https://api.github.com/users/kiratalent","html_url":"https://github.com/kiratalent","followers_url":"https://api.github.com/users/kiratalent/followers","following_url":"https://api.github.com/users/kiratalent/following{/other_user}","gists_url":"https://api.github.com/users/kiratalent/gists{/gist_id}","starred_url":"https://api.github.com/users/kiratalent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiratalent/subscriptions","organizations_url":"https://api.github.com/users/kiratalent/orgs","repos_url":"https://api.github.com/users/kiratalent/repos","events_url":"https://api.github.com/users/kiratalent/events{/privacy}","received_events_url":"https://api.github.com/users/kiratalent/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kiratalent/kira-cart","description":"Shopping Cart Test Repo","fork":false,"url":"https://api.github.com/repos/kiratalent/kira-cart","forks_url":"https://api.github.com/repos/kiratalent/kira-cart/forks","keys_url":"https://api.github.com/repos/kiratalent/kira-cart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kiratalent/kira-cart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kiratalent/kira-cart/teams","hooks_url":"https://api.github.com/repos/kiratalent/kira-cart/hooks","issue_events_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/events{/number}","events_url":"https://api.github.com/repos/kiratalent/kira-cart/events","assignees_url":"https://api.github.com/repos/kiratalent/kira-cart/assignees{/user}","branches_url":"https://api.github.com/repos/kiratalent/kira-cart/branches{/branch}","tags_url":"https://api.github.com/repos/kiratalent/kira-cart/tags","blobs_url":"https://api.github.com/repos/kiratalent/kira-cart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kiratalent/kira-cart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kiratalent/kira-cart/git/refs{/sha}","trees_url":"https://api.github.com/repos/kiratalent/kira-cart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kiratalent/kira-cart/statuses/{sha}","languages_url":"https://api.github.com/repos/kiratalent/kira-cart/languages","stargazers_url":"https://api.github.com/repos/kiratalent/kira-cart/stargazers","contributors_url":"https://api.github.com/repos/kiratalent/kira-cart/contributors","subscribers_url":"https://api.github.com/repos/kiratalent/kira-cart/subscribers","subscription_url":"https://api.github.com/repos/kiratalent/kira-cart/subscription","commits_url":"https://api.github.com/repos/kiratalent/kira-cart/commits{/sha}","git_commits_url":"https://api.github.com/repos/kiratalent/kira-cart/git/commits{/sha}","comments_url":"https://api.github.com/repos/kiratalent/kira-cart/comments{/number}","issue_comment_url":"https://api.github.com/repos/kiratalent/kira-cart/issues/comments{/number}","contents_url":"https://api.github.com/repos/kiratalent/kira-cart/contents/{+path}","compare_url":"https://api.github.com/repos/kiratalent/kira-cart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kiratalent/kira-cart/merges","archive_url":"https://api.github.com/repos/kiratalent/kira-cart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kiratalent/kira-cart/downloads","issues_url":"https://api.github.com/repos/kiratalent/kira-cart/issues{/number}","pulls_url":"https://api.github.com/repos/kiratalent/kira-cart/pulls{/number}","milestones_url":"https://api.github.com/repos/kiratalent/kira-cart/milestones{/number}","notifications_url":"https://api.github.com/repos/kiratalent/kira-cart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kiratalent/kira-cart/labels{/name}","releases_url":"https://api.github.com/repos/kiratalent/kira-cart/releases{/id}","created_at":"2015-04-23T17:47:45Z","updated_at":"2015-04-23T17:48:06Z","pushed_at":"2015-04-23T18:05:33Z","git_url":"git://github.com/kiratalent/kira-cart.git","ssh_url":"git@github.com:kiratalent/kira-cart.git","clone_url":"https://github.com/kiratalent/kira-cart.git","svn_url":"https://github.com/kiratalent/kira-cart","homepage":"","size":0,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2"},"html":{"href":"https://github.com/kiratalent/kira-cart/pull/2"},"issue":{"href":"https://api.github.com/repos/kiratalent/kira-cart/issues/2"},"comments":{"href":"https://api.github.com/repos/kiratalent/kira-cart/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kiratalent/kira-cart/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/kiratalent/kira-cart/statuses/49e7f06fbc06b988dd5d1cc43fe0d09aaf7105f1"}}}}