Skip to content

Commit

Permalink
Fix discounts resolver to work like in docs (#15882)
Browse files Browse the repository at this point in the history
* Fix discounts resolver to work like in docs

* order payload generator takes voucher type into account when returning discounts
  • Loading branch information
tomaszszymanski129 committed May 10, 2024
1 parent cd445a1 commit 99f8785
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 8 deletions.
12 changes: 6 additions & 6 deletions saleor/graphql/core/types/taxes.py
Expand Up @@ -375,16 +375,16 @@ def resolve_discounts(root: Union[Checkout, Order], info: ResolveInfo):
if isinstance(root, Checkout):

def calculate_checkout_discounts(checkout_info):
is_shipping_voucher = (
checkout_info.voucher.type == VoucherType.SHIPPING
if checkout_info.voucher
else False
)
checkout = checkout_info.checkout
discount_name = checkout.discount_name
return (
[{"name": discount_name, "amount": checkout.discount}]
if checkout.discount and not is_shipping_voucher
if checkout.discount
and (
checkout_info.voucher
and checkout_info.voucher.type == VoucherType.ENTIRE_ORDER
and not checkout_info.voucher.apply_once_per_order
)
else []
)

Expand Down
Expand Up @@ -190,7 +190,7 @@ def test_checkout_calculate_taxes_with_free_shipping_voucher(


@freeze_time("2020-03-18 12:00:00")
def test_checkout_calculate_taxes_with_voucher(
def test_checkout_calculate_taxes_with_entire_order_voucher(
checkout_with_voucher,
webhook_app,
permission_handle_taxes,
Expand Down Expand Up @@ -244,6 +244,64 @@ def test_checkout_calculate_taxes_with_voucher(
}


@freeze_time("2020-03-18 12:00:00")
def test_checkout_calculate_taxes_with_entire_order_voucher_once_per_order(
voucher,
checkout_with_voucher,
webhook_app,
permission_handle_taxes,
):
# given
webhook_app.permissions.add(permission_handle_taxes)
webhook = Webhook.objects.create(
name="Webhook",
app=webhook_app,
target_url="http://www.example.com/any",
subscription_query=TAXES_SUBSCRIPTION_QUERY,
)
event_type = WebhookEventSyncType.CHECKOUT_CALCULATE_TAXES
webhook.events.create(event_type=event_type)
voucher.apply_once_per_order = True
voucher.save()

# when
deliveries = create_delivery_for_subscription_sync_event(
event_type, checkout_with_voucher, webhook
)

# then
assert json.loads(deliveries.payload.payload) == {
"__typename": "CalculateTaxes",
"taxBase": {
"address": None,
"currency": "USD",
"discounts": [],
"channel": {"id": to_global_id_or_none(checkout_with_voucher.channel)},
"lines": [
{
"chargeTaxes": True,
"productName": "Test product",
"productSku": "123",
"quantity": 3,
"sourceLine": {
"id": to_global_id_or_none(checkout_with_voucher.lines.first()),
"__typename": "CheckoutLine",
},
"totalPrice": {"amount": 20.0},
"unitPrice": {"amount": 6.67},
"variantName": "",
}
],
"pricesEnteredWithTax": True,
"shippingPrice": {"amount": 0.0},
"sourceObject": {
"id": to_global_id_or_none(checkout_with_voucher),
"__typename": "Checkout",
},
},
}


@freeze_time("2020-03-18 12:00:00")
def test_checkout_calculate_taxes_with_shipping_voucher(
checkout_with_voucher,
Expand Down
3 changes: 3 additions & 0 deletions saleor/webhook/payloads.py
Expand Up @@ -1406,6 +1406,9 @@ def generate_order_payload_for_tax_calculation(order: "Order"):
discounts = order.discounts.all()
discounts_dict = []
for discount in discounts:
if discount.voucher and discount.voucher.type == VoucherType.ENTIRE_ORDER:
if discount.voucher.apply_once_per_order:
continue
quantize_price_fields(discount, ("amount_value",), order.currency)
discount_amount = quantize_price(discount.amount_value, order.currency)
discounts_dict.append({"name": discount.name, "amount": discount_amount})
Expand Down
82 changes: 81 additions & 1 deletion saleor/webhook/tests/test_webhook_payloads.py
Expand Up @@ -20,7 +20,7 @@
from ...checkout.fetch import fetch_checkout_info, fetch_checkout_lines
from ...core.prices import quantize_price
from ...core.utils.json_serializer import CustomJsonEncoder
from ...discount import DiscountType, DiscountValueType
from ...discount import DiscountType, DiscountValueType, VoucherType
from ...graphql.utils import get_user_or_app_from_context
from ...order import FulfillmentLineData, OrderOrigin
from ...order.actions import fulfill_order_lines
Expand Down Expand Up @@ -306,6 +306,7 @@ def test_generate_order_payload_for_tax_calculation(
order_for_payload,
prices_entered_with_tax,
):
# given
order = order_for_payload

tax_configuration = order.channel.tax_configuration
Expand All @@ -320,7 +321,10 @@ def test_generate_order_payload_for_tax_calculation(
discount_1, discount_2 = list(order.discounts.all())
user = order.user

# when
payload = json.loads(generate_order_payload_for_tax_calculation(order))[0]

# then
currency = order.currency

assert payload == {
Expand Down Expand Up @@ -371,6 +375,82 @@ def test_generate_order_payload_for_tax_calculation(
mocked_order_lines.assert_called_once()


@freeze_time()
@pytest.mark.parametrize("prices_entered_with_tax", [True, False])
@mock.patch("saleor.webhook.payloads._generate_order_lines_payload_for_tax_calculation")
def test_generate_order_payload_for_tax_calculation_voucher_discounts(
mocked_order_lines, order_for_payload, prices_entered_with_tax, voucher
):
# given
order = order_for_payload

tax_configuration = order.channel.tax_configuration
tax_configuration.prices_entered_with_tax = prices_entered_with_tax
tax_configuration.save(update_fields=["prices_entered_with_tax"])
tax_configuration.country_exceptions.all().delete()

order_lines = '"order_lines"'
mocked_order_lines.return_value = order_lines

order = order_for_payload
discount_1, discount_2 = list(order.discounts.all())
voucher.type = VoucherType.ENTIRE_ORDER
voucher.apply_once_per_order = True
voucher.save()
discount_1.voucher = voucher
discount_1.save()
user = order.user

# when
payload = json.loads(generate_order_payload_for_tax_calculation(order))[0]

# then
currency = order.currency

assert payload == {
"type": "Order",
"id": graphene.Node.to_global_id("Order", order.id),
"channel": {
"id": graphene.Node.to_global_id("Channel", order.channel_id),
"type": "Channel",
"slug": order.channel.slug,
"currency_code": order.channel.currency_code,
},
"address": {
"id": graphene.Node.to_global_id("Address", order.shipping_address_id),
"type": "Address",
"first_name": order.shipping_address.first_name,
"last_name": order.shipping_address.last_name,
"company_name": order.shipping_address.company_name,
"street_address_1": order.shipping_address.street_address_1,
"street_address_2": order.shipping_address.street_address_2,
"city": order.shipping_address.city,
"city_area": order.shipping_address.city_area,
"postal_code": order.shipping_address.postal_code,
"country": order.shipping_address.country.code,
"country_area": order.shipping_address.country_area,
"phone": str(order.shipping_address.phone),
},
"user_id": graphene.Node.to_global_id("User", user.pk),
"user_public_metadata": user.metadata,
"included_taxes_in_prices": prices_entered_with_tax,
"currency": order.currency,
"shipping_name": order.shipping_method.name,
"shipping_amount": str(
quantize_price(order.base_shipping_price_amount, currency)
),
"metadata": order.metadata,
"discounts": [
{
"name": discount_2.name,
"amount": str(quantize_price(discount_2.amount_value, currency)),
},
],
"lines": json.loads(order_lines),
}
mocked_order_lines.assert_called_once()


@freeze_time()
@mock.patch("saleor.webhook.payloads.generate_order_lines_payload")
@mock.patch("saleor.webhook.payloads.generate_fulfillment_lines_payload")
Expand Down

0 comments on commit 99f8785

Please sign in to comment.