# -*- coding: utf-8 -*-
# This file is part of Shuup.
#
# Copyright (c) 2012-2018, Shuup Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
from shuup.core.basket.commands import (  # noqa
    handle_add, handle_add_campaign_code, handle_add_var, handle_clear,
    handle_del, handle_update
)

shuup/front/basket/commands.py
# -*- coding: utf-8 -*-
# This file is part of Shuup.
#
# Copyright (c) 2012-2018, Shuup Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
from shuup.core.basket.commands import (  # noqa
    handle_add, handle_add_campaign_code, handle_add_var, handle_clear,
    handle_del, handle_remove_campaign_code, handle_update
)

shuup/front/basket/commands.py
diff --git a/shuup/front/basket/commands.py b/shuup/front/basket/commands.py
index 114b900857..fd13b1bc04 100644
--- a/shuup/front/basket/commands.py
+++ b/shuup/front/basket/commands.py
@@ -7,5 +7,5 @@
 # LICENSE file in the root directory of this source tree.
 from shuup.core.basket.commands import (  # noqa
     handle_add, handle_add_campaign_code, handle_add_var, handle_clear,
-    handle_del, handle_update
+    handle_del, handle_remove_campaign_code, handle_update
 )
diff --git a/shuup/front/locale/en/LC_MESSAGES/django.po b/shuup/front/locale/en/LC_MESSAGES/django.po
index 967e7d5e4a..75f33b0699 100644
--- a/shuup/front/locale/en/LC_MESSAGES/django.po
+++ b/shuup/front/locale/en/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-11-26 20:53+0000\n"
+"POT-Creation-Date: 2018-12-05 12:59+0000\n"
 "PO-Revision-Date: 2016-08-04 10:51-0700\n"
 "Last-Translator: \n"
 "Language-Team: en <LL@li.org>\n"
@@ -721,6 +721,9 @@ msgstr ""
 msgid "Proceed to checkout"
 msgstr ""
 
+msgid "Coupons applied"
+msgstr ""
+
 msgid "Have a coupon code? Enter it here"
 msgstr ""
 
@@ -742,6 +745,12 @@ msgstr ""
 msgid "Back to Products"
 msgstr ""
 
+msgid "Invalid coupon code."
+msgstr ""
+
+msgid "Error when removing coupon."
+msgstr ""
+
 msgid "Coupon is not available."
 msgstr ""
 
diff --git a/shuup/front/static_src/less/front/basket.less b/shuup/front/static_src/less/front/basket.less
index 5967fdf541..c5ea6b3a4c 100644
--- a/shuup/front/static_src/less/front/basket.less
+++ b/shuup/front/static_src/less/front/basket.less
@@ -130,6 +130,27 @@
     }
 }
 
+.basket-used-codes {
+    margin-top: 30px;
+
+    .used-coupon-text {
+        margin-bottom: 0;
+    }
+
+    .basket-used-code {
+        margin-top: 15px;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+
+        .basket-code {
+            font-weight: bold;
+            text-transform: uppercase;
+        }
+    }
+}
+
 .cart-actions {
     margin-bottom: 20px;
 }
diff --git a/shuup/front/templates/shuup/front/macros/basket.jinja b/shuup/front/templates/shuup/front/macros/basket.jinja
index 946e39fa52..b1fee8c737 100644
--- a/shuup/front/templates/shuup/front/macros/basket.jinja
+++ b/shuup/front/templates/shuup/front/macros/basket.jinja
@@ -10,6 +10,7 @@
             {{ render_basket_lines(basket) }}
             {{ render_unorderable_basket_lines(basket) }}
         </form>
+        {{ render_used_coupons(basket) }}
         {{ render_coupon_div(basket) }}
         {{ render_basket_summary(basket) }}
     </div>
@@ -158,6 +159,24 @@
     </a>
 {% endmacro %}
 
+{% macro render_used_coupons(basket) %}
+    {% if basket.codes %}
+    <div class="row basket-used-codes">
+        <div class="col-sm-6 col-sm-offset-6">
+            <p class="used-coupon-text">{% trans %}Coupons applied{% endtrans %}</p>
+            {% for code in basket.codes %}
+                <div class="basket-used-code">
+                    <span class="basket-code">{{ code }}</span>
+                    <button class="btn btn-primary basket-remove-code-btn" data-code="{{ code }}" type="button">
+                        <i class="fa fa-trash"></i>
+                    </button>
+                </div>
+            {% endfor %}
+        </div>
+    </div>
+    {% endif %}
+{% endmacro %}
+
 {% macro render_coupon_div(basket) %}
     <div class="row basket-discount-code">
         <div class="col-sm-6 pull-right">
@@ -165,10 +184,10 @@
             <div id="collapseCoupon">
                 <div class="input-group">
                     <input type="text"
-                           class="form-control"
-                           name="code"
-                           id="discount-code"
-                           placeholder="{% trans %}Coupon Code{% endtrans %}">
+                        class="form-control"
+                        name="code"
+                        id="discount-code"
+                        placeholder="{% trans %}Coupon Code{% endtrans %}">
                     <span class="input-group-btn">
                         <button type="submit"
                                 id="submit-code"
@@ -230,6 +249,7 @@
             {{ submit_coupon_code() }}
             {{ save_cart_js() }}
             {{ single_submit_form() }}
+            {{ remove_basket_code() }}
         });
     </script>
 {% endmacro %}
@@ -240,14 +260,41 @@
     });
 {% endmacro %}
 
+{% macro remove_basket_code() %}
+    $(".basket-remove-code-btn").click(function(evt) {
+        var code = $(evt.target).data("code");
+        if (code) {
+            var data = {
+                "command": "remove_campaign_code",
+                "code": code
+            };
+            $.ajax({
+                url: "",
+                method: "POST",
+                data: data,
+                success: function(response) {
+                    if (response.ok) {
+                        location.reload();
+                    } else {
+                        alert("{% trans %}Invalid coupon code.{% endtrans %}")
+                    }
+                },
+                error: function() {
+                    alert("{% trans %}Error when removing coupon.{% endtrans %}")
+                }
+            });
+        }
+    });
+{% endmacro %}
+
 {% macro submit_coupon_code() %}
     $("#submit-code").click(function(e){
         e.preventDefault();
-        const coupon = $("#discount-code").val();
+        var coupon = $("#discount-code").val();
 
         if (coupon.length) {
             // ajax request to command
-            const data = {
+            var data = {
                 "command": "add_campaign_code",
                 "code": coupon
             };
@@ -259,8 +306,7 @@
                 success: function(response) {
                     if (response.ok) {
                         location.reload();
-                    }
-                    else {
+                    } else {
                         alert("{% trans %}Coupon is not available.{% endtrans %}")
                     }
                 },
@@ -276,7 +322,7 @@
     {% if shuup.urls.has_url("shuup:saved_cart.save") %}
         $("#save-cart").click(function(e){
             e.preventDefault();
-            const title = $("#cart-title").val();
+            var title = $("#cart-title").val();
             $("#save-cart-status").empty();
             $.ajax({
                 url: "{{ url('shuup:saved_cart.save') }}",
diff --git a/shuup_tests/campaigns/test_basket_campaigns.py b/shuup_tests/campaigns/test_basket_campaigns.py
index da15957181..3a871c91ad 100644
--- a/shuup_tests/campaigns/test_basket_campaigns.py
+++ b/shuup_tests/campaigns/test_basket_campaigns.py
@@ -28,7 +28,7 @@
 )
 from shuup.core.order_creator import OrderCreator
 from shuup.front.basket import get_basket
-from shuup.front.basket.commands import handle_add_campaign_code
+from shuup.front.basket.commands import handle_add_campaign_code, handle_remove_campaign_code
 from shuup.testing.factories import (
     CategoryFactory, create_product, get_default_product, get_default_shop,
     get_default_supplier, get_shipping_method
@@ -258,24 +258,34 @@ def test_multiple_campaigns_match_with_coupon(rf):
 
     dc = Coupon.objects.create(code="TEST", active=True)
     campaign2 = BasketCampaign.objects.create(
-            shop=shop, public_name="test",
-            name="test",
-            coupon=dc,
-            active=True
+        shop=shop, public_name="test",
+        name="test",
+        coupon=dc,
+        active=True
     )
 
     BasketDiscountAmount.objects.create(discount_amount=discount2, campaign=campaign2)
-
     basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
 
     resp = handle_add_campaign_code(request, basket, dc.code)
     assert resp.get("ok")
 
-    discount_lines_values = [line.discount_amount for line in basket.get_final_lines()]
+    discount_lines_values = [line.discount_amount for line in basket.get_final_lines() if line.type == OrderLineType.DISCOUNT]
     assert price(discount1) in discount_lines_values
     assert price(discount2) in discount_lines_values
     assert basket.total_price == (price(product_price) * basket.product_count - price(discount1) - price(discount2))
 
+    assert basket.codes == [dc.code]
+
+    # test code removal
+    resp = handle_remove_campaign_code(request, basket, dc.code)
+    assert resp.get("ok")
+
+    assert basket.codes == []
+    discount_lines_values = [line.discount_amount for line in basket.get_final_lines() if line.type == OrderLineType.DISCOUNT]
+    assert price(discount1) in discount_lines_values
+    assert not price(discount2) in discount_lines_values
+
 
 @pytest.mark.django_db
 def test_percentage_campaign(rf):

Add option to remove coupon code from basket
There isn't option to remove coupon code from basket. Should likely be done with basket command at basket view [this](https://github.com/shuup/shuup/blob/master/shuup/core/basket/commands.py#L177).
