We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
OrderCancel mutation throws error when asked not to restock inventory
### What I'm trying to achieve
Cancel order without doing restock.

### Steps to reproduce the problem
1. Execute query
```
mutation {
  orderCancel(id: "T3JkZXI6MTQ=", restock: false) {
    errors {
      field
      message
    }
    order {
      id
    }
  }
}
```
2. Get an error
3. Order is cancelled anyway

### What I expected to happen
To work perfectly. Note: if `restock: true`, mutation executes properly.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `saleor/graphql/order/mutations/orders.py`
Content:
```
1 import graphene
2 from django.utils.translation import pgettext_lazy
3 from graphql_jwt.decorators import permission_required
4 from payments import PaymentError, PaymentStatus
5 
6 from ....core.utils.taxes import ZERO_TAXED_MONEY
7 from ....order import CustomPaymentChoices, OrderEvents, models
8 from ....order.utils import cancel_order
9 from ....shipping.models import ShippingMethod as ShippingMethodModel
10 from ...account.types import AddressInput
11 from ...core.mutations import BaseMutation
12 from ...core.types.common import Decimal, Error
13 from ...order.mutations.draft_orders import DraftOrderUpdate
14 from ...order.types import Order, OrderEvent
15 from ...shipping.types import ShippingMethod
16 
17 
18 def clean_order_update_shipping(order, method, errors):
19     if not method:
20         return errors
21     if not order.shipping_address:
22         errors.append(
23             Error(
24                 field='order',
25                 message=(
26                     'Cannot choose a shipping method for an '
27                     'order without the shipping address.')))
28         return errors
29     valid_methods = (
30         ShippingMethodModel.objects.applicable_shipping_methods(
31             price=order.get_subtotal().gross.amount,
32             weight=order.get_total_weight(),
33             country_code=order.shipping_address.country.code))
34     valid_methods = valid_methods.values_list('id', flat=True)
35     if method.pk not in valid_methods:
36         errors.append(
37             Error(
38                 field='shippingMethod',
39                 message='Shipping method cannot be used with this order.'))
40     return errors
41 
42 
43 def try_payment_action(action, money, errors):
44     try:
45         action(money)
46     except (PaymentError, ValueError) as e:
47         errors.append(Error(field='payment', message=str(e)))
48 
49 
50 def clean_order_cancel(order, errors):
51     if order and not order.can_cancel():
52         errors.append(
53             Error(
54                 field='order',
55                 message='This order can\'t be canceled.'))
56     return errors
57 
58 
59 def clean_order_mark_as_paid(order, errors):
60     if order and order.payments.exists():
61         errors.append(
62             Error(
63                 field='payment',
64                 message='Orders with payments can not be manually '
65                         'marked as paid.'))
66     return errors
67 
68 
69 def clean_order_capture(payment, amount, errors):
70     if not payment:
71         errors.append(
72             Error(
73                 field='payment',
74                 message='There\'s no payment associated with the order.'))
75         return errors
76     if payment.status != PaymentStatus.PREAUTH:
77         errors.append(
78             Error(
79                 field='payment',
80                 message='Only pre-authorized payments can be captured'))
81     return errors
82 
83 
84 def clean_release_payment(payment, errors):
85     """Check for payment errors."""
86     if payment.status != PaymentStatus.PREAUTH:
87         errors.append(
88             Error(field='payment',
89                   message='Only pre-authorized payments can be released'))
90     try:
91         payment.release()
92     except (PaymentError, ValueError) as e:
93         errors.append(Error(field='payment', message=str(e)))
94     return errors
95 
96 
97 def clean_refund_payment(payment, amount, errors):
98     if payment.variant == CustomPaymentChoices.MANUAL:
99         errors.append(
100             Error(field='payment',
101                   message='Manual payments can not be refunded.'))
102     return errors
103 
104 
105 class OrderUpdateInput(graphene.InputObjectType):
106     billing_address = AddressInput(
107         description='Billing address of the customer.')
108     user_email = graphene.String(description='Email address of the customer.')
109     shipping_address = AddressInput(
110         description='Shipping address of the customer.')
111 
112 
113 class OrderUpdate(DraftOrderUpdate):
114     class Arguments:
115         id = graphene.ID(
116             required=True, description='ID of an order to update.')
117         input = OrderUpdateInput(
118             required=True,
119             description='Fields required to update an order.')
120 
121     class Meta:
122         description = 'Updates an order.'
123         model = models.Order
124 
125 
126 class OrderUpdateShippingInput(graphene.InputObjectType):
127     shipping_method = graphene.ID(
128         description='ID of the selected shipping method.',
129         name='shippingMethod')
130 
131 
132 class OrderUpdateShipping(BaseMutation):
133     order = graphene.Field(
134         Order, description='Order with updated shipping method.')
135 
136     class Arguments:
137         id = graphene.ID(
138             required=True, name='order',
139             description='ID of the order to update a shipping method.')
140         input = OrderUpdateShippingInput(
141             description='Fields required to change '
142                         'shipping method of the order.')
143 
144     class Meta:
145         description = 'Updates a shipping method of the order.'
146 
147     @classmethod
148     @permission_required('order.manage_orders')
149     def mutate(cls, root, info, id, input):
150         errors = []
151         order = cls.get_node_or_error(info, id, errors, 'id', Order)
152 
153         if not input['shipping_method']:
154             if order.is_shipping_required():
155                 cls.add_error(
156                     errors, 'shippingMethod',
157                     'Shipping method is required for this order.')
158                 return OrderUpdateShipping(errors=errors)
159             order.shipping_method = None
160             order.shipping_price = ZERO_TAXED_MONEY
161             order.shipping_method_name = None
162             order.save(
163                 update_fields=[
164                     'shipping_method', 'shipping_price_net',
165                     'shipping_price_gross', 'shipping_method_name'])
166             return OrderUpdateShipping(order=order)
167 
168         method = cls.get_node_or_error(
169             info, input['shipping_method'], errors,
170             'shipping_method', ShippingMethod)
171         clean_order_update_shipping(order, method, errors)
172         if errors:
173             return OrderUpdateShipping(errors=errors)
174 
175         order.shipping_method = method
176         order.shipping_price = method.get_total_price(info.context.taxes)
177         order.shipping_method_name = method.name
178         order.save(
179             update_fields=[
180                 'shipping_method', 'shipping_method_name',
181                 'shipping_price_net', 'shipping_price_gross'])
182         return OrderUpdateShipping(order=order)
183 
184 
185 class OrderAddNoteInput(graphene.InputObjectType):
186     message = graphene.String(description='Note message.', name='message')
187 
188 
189 class OrderAddNote(BaseMutation):
190     order = graphene.Field(Order, description='Order with the note added.')
191     event = graphene.Field(OrderEvent, description='Order note created.')
192 
193     class Arguments:
194         id = graphene.ID(
195             required=True,
196             description='ID of the order to add a note for.', name='order')
197         input = OrderAddNoteInput(
198             required=True,
199             description='Fields required to create a note for the order.')
200 
201     class Meta:
202         description = 'Adds note to the order.'
203 
204     @classmethod
205     @permission_required('order.manage_orders')
206     def mutate(cls, root, info, id, input):
207         errors = []
208         order = cls.get_node_or_error(info, id, errors, 'id', Order)
209         if errors:
210             return OrderAddNote(errors=errors)
211 
212         event = order.events.create(
213             type=OrderEvents.NOTE_ADDED.value,
214             user=info.context.user,
215             parameters={
216                 'message': input['message']})
217         return OrderAddNote(order=order, event=event)
218 
219 
220 class OrderCancel(BaseMutation):
221     order = graphene.Field(Order, description='Canceled order.')
222 
223     class Arguments:
224         id = graphene.ID(
225             required=True, description='ID of the order to cancel.')
226         restock = graphene.Boolean(
227             required=True,
228             description='Determine if lines will be restocked or not.')
229 
230     class Meta:
231         description = 'Cancel an order.'
232 
233     @classmethod
234     @permission_required('order.manage_orders')
235     def mutate(cls, root, info, id, restock):
236         errors = []
237         order = cls.get_node_or_error(info, id, errors, 'id', Order)
238         clean_order_cancel(order, errors)
239         if errors:
240             return OrderCancel(errors=errors)
241 
242         cancel_order(order=order, restock=restock)
243         if restock:
244             order.events.create(
245                 type=OrderEvents.FULFILLMENT_RESTOCKED_ITEMS.value,
246                 user=info.context.user,
247                 parameters={'quantity': order.get_total_quantity()})
248         else:
249             order.events.create(
250                 type=OrderEvents.ORDER_CANCELED.value,
251                 user=info.context.user)
252         return OrderCancel(order=order)
253 
254 
255 class OrderMarkAsPaid(BaseMutation):
256     order = graphene.Field(Order, description='Order marked as paid.')
257 
258     class Arguments:
259         id = graphene.ID(
260             required=True, description='ID of the order to mark paid.')
261 
262     class Meta:
263         description = 'Mark order as manually paid.'
264 
265     @classmethod
266     @permission_required('order.manage_orders')
267     def mutate(cls, root, info, id):
268         errors = []
269         order = cls.get_node_or_error(info, id, errors, 'id', Order)
270         clean_order_mark_as_paid(order, errors)
271         if errors:
272             return OrderMarkAsPaid(errors=errors)
273 
274         defaults = {
275             'total': order.total.gross.amount,
276             'tax': order.total.tax.amount,
277             'currency': order.total.currency,
278             'delivery': order.shipping_price.net.amount,
279             'description': pgettext_lazy(
280                 'Payment description', 'Order %(order)s') % {'order': order},
281             'captured_amount': order.total.gross.amount}
282         models.Payment.objects.get_or_create(
283             variant=CustomPaymentChoices.MANUAL,
284             status=PaymentStatus.CONFIRMED, order=order,
285             defaults=defaults)
286 
287         order.events.create(
288             type=OrderEvents.ORDER_MARKED_AS_PAID.value,
289             user=info.context.user)
290         return OrderMarkAsPaid(order=order)
291 
292 
293 class OrderCapture(BaseMutation):
294     order = graphene.Field(Order, description='Captured order.')
295 
296     class Arguments:
297         id = graphene.ID(
298             required=True, description='ID of the order to capture.')
299         amount = Decimal(
300             required=True, description='Amount of money to capture.')
301 
302     class Meta:
303         description = 'Capture an order.'
304 
305     @classmethod
306     @permission_required('order.manage_orders')
307     def mutate(cls, root, info, id, amount):
308         errors = []
309         order = cls.get_node_or_error(info, id, errors, 'id', Order)
310         payment = order.get_last_payment()
311         clean_order_capture(payment, amount, errors)
312         try_payment_action(payment.capture, amount, errors)
313         if errors:
314             return OrderCapture(errors=errors)
315 
316         order.events.create(
317             parameters={'amount': amount},
318             type=OrderEvents.PAYMENT_CAPTURED.value,
319             user=info.context.user)
320         return OrderCapture(order=order)
321 
322 
323 class OrderRelease(BaseMutation):
324     order = graphene.Field(Order, description='A released order.')
325 
326     class Arguments:
327         id = graphene.ID(
328             required=True, description='ID of the order to release.')
329 
330     class Meta:
331         description = 'Release an order.'
332 
333     @classmethod
334     @permission_required('order.manage_orders')
335     def mutate(cls, root, info, id):
336         errors = []
337         order = cls.get_node_or_error(info, id, errors, 'id', Order)
338         if order:
339             payment = order.get_last_payment()
340             clean_release_payment(payment, errors)
341 
342         if errors:
343             return OrderRelease(errors=errors)
344 
345         order.events.create(
346             type=OrderEvents.PAYMENT_RELEASED.value,
347             user=info.context.user)
348         return OrderRelease(order=order)
349 
350 
351 class OrderRefund(BaseMutation):
352     order = graphene.Field(Order, description='A refunded order.')
353 
354     class Arguments:
355         id = graphene.ID(
356             required=True, description='ID of the order to refund.')
357         amount = Decimal(
358             required=True, description='Amount of money to refund.')
359 
360     class Meta:
361         description = 'Refund an order.'
362 
363     @classmethod
364     @permission_required('order.manage_orders')
365     def mutate(cls, root, info, id, amount):
366         errors = []
367         order = cls.get_node_or_error(info, id, errors, 'id', Order)
368         if order:
369             payment = order.get_last_payment()
370             clean_refund_payment(payment, amount, errors)
371             try_payment_action(payment.refund, amount, errors)
372         if errors:
373             return OrderRefund(errors=errors)
374 
375         order.events.create(
376             type=OrderEvents.PAYMENT_REFUNDED.value,
377             user=info.context.user,
378             parameters={'amount': amount})
379         return OrderRefund(order=order)
380
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/saleor/graphql/order/mutations/orders.py b/saleor/graphql/order/mutations/orders.py
--- a/saleor/graphql/order/mutations/orders.py
+++ b/saleor/graphql/order/mutations/orders.py
@@ -247,8 +247,7 @@
                 parameters={'quantity': order.get_total_quantity()})
         else:
             order.events.create(
-                type=OrderEvents.ORDER_CANCELED.value,
-                user=info.context.user)
+                type=OrderEvents.CANCELED.value, user=info.context.user)
         return OrderCancel(order=order)

{"golden_diff": "diff --git a/saleor/graphql/order/mutations/orders.py b/saleor/graphql/order/mutations/orders.py\n--- a/saleor/graphql/order/mutations/orders.py\n+++ b/saleor/graphql/order/mutations/orders.py\n@@ -247,8 +247,7 @@\n                 parameters={'quantity': order.get_total_quantity()})\n         else:\n             order.events.create(\n-                type=OrderEvents.ORDER_CANCELED.value,\n-                user=info.context.user)\n+                type=OrderEvents.CANCELED.value, user=info.context.user)\n         return OrderCancel(order=order)\n", "issue": "OrderCancel mutation throws error when asked not to restock inventory\n### What I'm trying to achieve\r\nCancel order without doing restock.\r\n\r\n### Steps to reproduce the problem\r\n1. Execute query\r\n```\r\nmutation {\r\n  orderCancel(id: \"T3JkZXI6MTQ=\", restock: false) {\r\n    errors {\r\n      field\r\n      message\r\n    }\r\n    order {\r\n      id\r\n    }\r\n  }\r\n}\r\n```\r\n2. Get an error\r\n3. Order is cancelled anyway\r\n\r\n### What I expected to happen\r\nTo work perfectly. Note: if `restock: true`, mutation executes properly.\r\n\n", "before_files": [{"content": "import graphene\nfrom django.utils.translation import pgettext_lazy\nfrom graphql_jwt.decorators import permission_required\nfrom payments import PaymentError, PaymentStatus\n\nfrom ....core.utils.taxes import ZERO_TAXED_MONEY\nfrom ....order import CustomPaymentChoices, OrderEvents, models\nfrom ....order.utils import cancel_order\nfrom ....shipping.models import ShippingMethod as ShippingMethodModel\nfrom ...account.types import AddressInput\nfrom ...core.mutations import BaseMutation\nfrom ...core.types.common import Decimal, Error\nfrom ...order.mutations.draft_orders import DraftOrderUpdate\nfrom ...order.types import Order, OrderEvent\nfrom ...shipping.types import ShippingMethod\n\n\ndef clean_order_update_shipping(order, method, errors):\n    if not method:\n        return errors\n    if not order.shipping_address:\n        errors.append(\n            Error(\n                field='order',\n                message=(\n                    'Cannot choose a shipping method for an '\n                    'order without the shipping address.')))\n        return errors\n    valid_methods = (\n        ShippingMethodModel.objects.applicable_shipping_methods(\n            price=order.get_subtotal().gross.amount,\n            weight=order.get_total_weight(),\n            country_code=order.shipping_address.country.code))\n    valid_methods = valid_methods.values_list('id', flat=True)\n    if method.pk not in valid_methods:\n        errors.append(\n            Error(\n                field='shippingMethod',\n                message='Shipping method cannot be used with this order.'))\n    return errors\n\n\ndef try_payment_action(action, money, errors):\n    try:\n        action(money)\n    except (PaymentError, ValueError) as e:\n        errors.append(Error(field='payment', message=str(e)))\n\n\ndef clean_order_cancel(order, errors):\n    if order and not order.can_cancel():\n        errors.append(\n            Error(\n                field='order',\n                message='This order can\\'t be canceled.'))\n    return errors\n\n\ndef clean_order_mark_as_paid(order, errors):\n    if order and order.payments.exists():\n        errors.append(\n            Error(\n                field='payment',\n                message='Orders with payments can not be manually '\n                        'marked as paid.'))\n    return errors\n\n\ndef clean_order_capture(payment, amount, errors):\n    if not payment:\n        errors.append(\n            Error(\n                field='payment',\n                message='There\\'s no payment associated with the order.'))\n        return errors\n    if payment.status != PaymentStatus.PREAUTH:\n        errors.append(\n            Error(\n                field='payment',\n                message='Only pre-authorized payments can be captured'))\n    return errors\n\n\ndef clean_release_payment(payment, errors):\n    \"\"\"Check for payment errors.\"\"\"\n    if payment.status != PaymentStatus.PREAUTH:\n        errors.append(\n            Error(field='payment',\n                  message='Only pre-authorized payments can be released'))\n    try:\n        payment.release()\n    except (PaymentError, ValueError) as e:\n        errors.append(Error(field='payment', message=str(e)))\n    return errors\n\n\ndef clean_refund_payment(payment, amount, errors):\n    if payment.variant == CustomPaymentChoices.MANUAL:\n        errors.append(\n            Error(field='payment',\n                  message='Manual payments can not be refunded.'))\n    return errors\n\n\nclass OrderUpdateInput(graphene.InputObjectType):\n    billing_address = AddressInput(\n        description='Billing address of the customer.')\n    user_email = graphene.String(description='Email address of the customer.')\n    shipping_address = AddressInput(\n        description='Shipping address of the customer.')\n\n\nclass OrderUpdate(DraftOrderUpdate):\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of an order to update.')\n        input = OrderUpdateInput(\n            required=True,\n            description='Fields required to update an order.')\n\n    class Meta:\n        description = 'Updates an order.'\n        model = models.Order\n\n\nclass OrderUpdateShippingInput(graphene.InputObjectType):\n    shipping_method = graphene.ID(\n        description='ID of the selected shipping method.',\n        name='shippingMethod')\n\n\nclass OrderUpdateShipping(BaseMutation):\n    order = graphene.Field(\n        Order, description='Order with updated shipping method.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, name='order',\n            description='ID of the order to update a shipping method.')\n        input = OrderUpdateShippingInput(\n            description='Fields required to change '\n                        'shipping method of the order.')\n\n    class Meta:\n        description = 'Updates a shipping method of the order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, input):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n\n        if not input['shipping_method']:\n            if order.is_shipping_required():\n                cls.add_error(\n                    errors, 'shippingMethod',\n                    'Shipping method is required for this order.')\n                return OrderUpdateShipping(errors=errors)\n            order.shipping_method = None\n            order.shipping_price = ZERO_TAXED_MONEY\n            order.shipping_method_name = None\n            order.save(\n                update_fields=[\n                    'shipping_method', 'shipping_price_net',\n                    'shipping_price_gross', 'shipping_method_name'])\n            return OrderUpdateShipping(order=order)\n\n        method = cls.get_node_or_error(\n            info, input['shipping_method'], errors,\n            'shipping_method', ShippingMethod)\n        clean_order_update_shipping(order, method, errors)\n        if errors:\n            return OrderUpdateShipping(errors=errors)\n\n        order.shipping_method = method\n        order.shipping_price = method.get_total_price(info.context.taxes)\n        order.shipping_method_name = method.name\n        order.save(\n            update_fields=[\n                'shipping_method', 'shipping_method_name',\n                'shipping_price_net', 'shipping_price_gross'])\n        return OrderUpdateShipping(order=order)\n\n\nclass OrderAddNoteInput(graphene.InputObjectType):\n    message = graphene.String(description='Note message.', name='message')\n\n\nclass OrderAddNote(BaseMutation):\n    order = graphene.Field(Order, description='Order with the note added.')\n    event = graphene.Field(OrderEvent, description='Order note created.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True,\n            description='ID of the order to add a note for.', name='order')\n        input = OrderAddNoteInput(\n            required=True,\n            description='Fields required to create a note for the order.')\n\n    class Meta:\n        description = 'Adds note to the order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, input):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if errors:\n            return OrderAddNote(errors=errors)\n\n        event = order.events.create(\n            type=OrderEvents.NOTE_ADDED.value,\n            user=info.context.user,\n            parameters={\n                'message': input['message']})\n        return OrderAddNote(order=order, event=event)\n\n\nclass OrderCancel(BaseMutation):\n    order = graphene.Field(Order, description='Canceled order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to cancel.')\n        restock = graphene.Boolean(\n            required=True,\n            description='Determine if lines will be restocked or not.')\n\n    class Meta:\n        description = 'Cancel an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, restock):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        clean_order_cancel(order, errors)\n        if errors:\n            return OrderCancel(errors=errors)\n\n        cancel_order(order=order, restock=restock)\n        if restock:\n            order.events.create(\n                type=OrderEvents.FULFILLMENT_RESTOCKED_ITEMS.value,\n                user=info.context.user,\n                parameters={'quantity': order.get_total_quantity()})\n        else:\n            order.events.create(\n                type=OrderEvents.ORDER_CANCELED.value,\n                user=info.context.user)\n        return OrderCancel(order=order)\n\n\nclass OrderMarkAsPaid(BaseMutation):\n    order = graphene.Field(Order, description='Order marked as paid.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to mark paid.')\n\n    class Meta:\n        description = 'Mark order as manually paid.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        clean_order_mark_as_paid(order, errors)\n        if errors:\n            return OrderMarkAsPaid(errors=errors)\n\n        defaults = {\n            'total': order.total.gross.amount,\n            'tax': order.total.tax.amount,\n            'currency': order.total.currency,\n            'delivery': order.shipping_price.net.amount,\n            'description': pgettext_lazy(\n                'Payment description', 'Order %(order)s') % {'order': order},\n            'captured_amount': order.total.gross.amount}\n        models.Payment.objects.get_or_create(\n            variant=CustomPaymentChoices.MANUAL,\n            status=PaymentStatus.CONFIRMED, order=order,\n            defaults=defaults)\n\n        order.events.create(\n            type=OrderEvents.ORDER_MARKED_AS_PAID.value,\n            user=info.context.user)\n        return OrderMarkAsPaid(order=order)\n\n\nclass OrderCapture(BaseMutation):\n    order = graphene.Field(Order, description='Captured order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to capture.')\n        amount = Decimal(\n            required=True, description='Amount of money to capture.')\n\n    class Meta:\n        description = 'Capture an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, amount):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        payment = order.get_last_payment()\n        clean_order_capture(payment, amount, errors)\n        try_payment_action(payment.capture, amount, errors)\n        if errors:\n            return OrderCapture(errors=errors)\n\n        order.events.create(\n            parameters={'amount': amount},\n            type=OrderEvents.PAYMENT_CAPTURED.value,\n            user=info.context.user)\n        return OrderCapture(order=order)\n\n\nclass OrderRelease(BaseMutation):\n    order = graphene.Field(Order, description='A released order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to release.')\n\n    class Meta:\n        description = 'Release an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if order:\n            payment = order.get_last_payment()\n            clean_release_payment(payment, errors)\n\n        if errors:\n            return OrderRelease(errors=errors)\n\n        order.events.create(\n            type=OrderEvents.PAYMENT_RELEASED.value,\n            user=info.context.user)\n        return OrderRelease(order=order)\n\n\nclass OrderRefund(BaseMutation):\n    order = graphene.Field(Order, description='A refunded order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to refund.')\n        amount = Decimal(\n            required=True, description='Amount of money to refund.')\n\n    class Meta:\n        description = 'Refund an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, amount):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if order:\n            payment = order.get_last_payment()\n            clean_refund_payment(payment, amount, errors)\n            try_payment_action(payment.refund, amount, errors)\n        if errors:\n            return OrderRefund(errors=errors)\n\n        order.events.create(\n            type=OrderEvents.PAYMENT_REFUNDED.value,\n            user=info.context.user,\n            parameters={'amount': amount})\n        return OrderRefund(order=order)\n", "path": "saleor/graphql/order/mutations/orders.py"}], "after_files": [{"content": "import graphene\nfrom django.utils.translation import pgettext_lazy\nfrom graphql_jwt.decorators import permission_required\nfrom payments import PaymentError, PaymentStatus\n\nfrom ....core.utils.taxes import ZERO_TAXED_MONEY\nfrom ....order import CustomPaymentChoices, OrderEvents, models\nfrom ....order.utils import cancel_order\nfrom ....shipping.models import ShippingMethod as ShippingMethodModel\nfrom ...account.types import AddressInput\nfrom ...core.mutations import BaseMutation\nfrom ...core.types.common import Decimal, Error\nfrom ...order.mutations.draft_orders import DraftOrderUpdate\nfrom ...order.types import Order, OrderEvent\nfrom ...shipping.types import ShippingMethod\n\n\ndef clean_order_update_shipping(order, method, errors):\n    if not method:\n        return errors\n    if not order.shipping_address:\n        errors.append(\n            Error(\n                field='order',\n                message=(\n                    'Cannot choose a shipping method for an '\n                    'order without the shipping address.')))\n        return errors\n    valid_methods = (\n        ShippingMethodModel.objects.applicable_shipping_methods(\n            price=order.get_subtotal().gross.amount,\n            weight=order.get_total_weight(),\n            country_code=order.shipping_address.country.code))\n    valid_methods = valid_methods.values_list('id', flat=True)\n    if method.pk not in valid_methods:\n        errors.append(\n            Error(\n                field='shippingMethod',\n                message='Shipping method cannot be used with this order.'))\n    return errors\n\n\ndef try_payment_action(action, money, errors):\n    try:\n        action(money)\n    except (PaymentError, ValueError) as e:\n        errors.append(Error(field='payment', message=str(e)))\n\n\ndef clean_order_cancel(order, errors):\n    if order and not order.can_cancel():\n        errors.append(\n            Error(\n                field='order',\n                message='This order can\\'t be canceled.'))\n    return errors\n\n\ndef clean_order_mark_as_paid(order, errors):\n    if order and order.payments.exists():\n        errors.append(\n            Error(\n                field='payment',\n                message='Orders with payments can not be manually '\n                        'marked as paid.'))\n    return errors\n\n\ndef clean_order_capture(payment, amount, errors):\n    if not payment:\n        errors.append(\n            Error(\n                field='payment',\n                message='There\\'s no payment associated with the order.'))\n        return errors\n    if payment.status != PaymentStatus.PREAUTH:\n        errors.append(\n            Error(\n                field='payment',\n                message='Only pre-authorized payments can be captured'))\n    return errors\n\n\ndef clean_release_payment(payment, errors):\n    \"\"\"Check for payment errors.\"\"\"\n    if payment.status != PaymentStatus.PREAUTH:\n        errors.append(\n            Error(field='payment',\n                  message='Only pre-authorized payments can be released'))\n    try:\n        payment.release()\n    except (PaymentError, ValueError) as e:\n        errors.append(Error(field='payment', message=str(e)))\n    return errors\n\n\ndef clean_refund_payment(payment, amount, errors):\n    if payment.variant == CustomPaymentChoices.MANUAL:\n        errors.append(\n            Error(field='payment',\n                  message='Manual payments can not be refunded.'))\n    return errors\n\n\nclass OrderUpdateInput(graphene.InputObjectType):\n    billing_address = AddressInput(\n        description='Billing address of the customer.')\n    user_email = graphene.String(description='Email address of the customer.')\n    shipping_address = AddressInput(\n        description='Shipping address of the customer.')\n\n\nclass OrderUpdate(DraftOrderUpdate):\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of an order to update.')\n        input = OrderUpdateInput(\n            required=True,\n            description='Fields required to update an order.')\n\n    class Meta:\n        description = 'Updates an order.'\n        model = models.Order\n\n\nclass OrderUpdateShippingInput(graphene.InputObjectType):\n    shipping_method = graphene.ID(\n        description='ID of the selected shipping method.',\n        name='shippingMethod')\n\n\nclass OrderUpdateShipping(BaseMutation):\n    order = graphene.Field(\n        Order, description='Order with updated shipping method.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, name='order',\n            description='ID of the order to update a shipping method.')\n        input = OrderUpdateShippingInput(\n            description='Fields required to change '\n                        'shipping method of the order.')\n\n    class Meta:\n        description = 'Updates a shipping method of the order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, input):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n\n        if not input['shipping_method']:\n            if order.is_shipping_required():\n                cls.add_error(\n                    errors, 'shippingMethod',\n                    'Shipping method is required for this order.')\n                return OrderUpdateShipping(errors=errors)\n            order.shipping_method = None\n            order.shipping_price = ZERO_TAXED_MONEY\n            order.shipping_method_name = None\n            order.save(\n                update_fields=[\n                    'shipping_method', 'shipping_price_net',\n                    'shipping_price_gross', 'shipping_method_name'])\n            return OrderUpdateShipping(order=order)\n\n        method = cls.get_node_or_error(\n            info, input['shipping_method'], errors,\n            'shipping_method', ShippingMethod)\n        clean_order_update_shipping(order, method, errors)\n        if errors:\n            return OrderUpdateShipping(errors=errors)\n\n        order.shipping_method = method\n        order.shipping_price = method.get_total_price(info.context.taxes)\n        order.shipping_method_name = method.name\n        order.save(\n            update_fields=[\n                'shipping_method', 'shipping_method_name',\n                'shipping_price_net', 'shipping_price_gross'])\n        return OrderUpdateShipping(order=order)\n\n\nclass OrderAddNoteInput(graphene.InputObjectType):\n    message = graphene.String(description='Note message.', name='message')\n\n\nclass OrderAddNote(BaseMutation):\n    order = graphene.Field(Order, description='Order with the note added.')\n    event = graphene.Field(OrderEvent, description='Order note created.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True,\n            description='ID of the order to add a note for.', name='order')\n        input = OrderAddNoteInput(\n            required=True,\n            description='Fields required to create a note for the order.')\n\n    class Meta:\n        description = 'Adds note to the order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, input):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if errors:\n            return OrderAddNote(errors=errors)\n\n        event = order.events.create(\n            type=OrderEvents.NOTE_ADDED.value,\n            user=info.context.user,\n            parameters={\n                'message': input['message']})\n        return OrderAddNote(order=order, event=event)\n\n\nclass OrderCancel(BaseMutation):\n    order = graphene.Field(Order, description='Canceled order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to cancel.')\n        restock = graphene.Boolean(\n            required=True,\n            description='Determine if lines will be restocked or not.')\n\n    class Meta:\n        description = 'Cancel an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, restock):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        clean_order_cancel(order, errors)\n        if errors:\n            return OrderCancel(errors=errors)\n\n        cancel_order(order=order, restock=restock)\n        if restock:\n            order.events.create(\n                type=OrderEvents.FULFILLMENT_RESTOCKED_ITEMS.value,\n                user=info.context.user,\n                parameters={'quantity': order.get_total_quantity()})\n        else:\n            order.events.create(\n                type=OrderEvents.CANCELED.value, user=info.context.user)\n        return OrderCancel(order=order)\n\n\nclass OrderMarkAsPaid(BaseMutation):\n    order = graphene.Field(Order, description='Order marked as paid.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to mark paid.')\n\n    class Meta:\n        description = 'Mark order as manually paid.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        clean_order_mark_as_paid(order, errors)\n        if errors:\n            return OrderMarkAsPaid(errors=errors)\n\n        defaults = {\n            'total': order.total.gross.amount,\n            'tax': order.total.tax.amount,\n            'currency': order.total.currency,\n            'delivery': order.shipping_price.net.amount,\n            'description': pgettext_lazy(\n                'Payment description', 'Order %(order)s') % {'order': order},\n            'captured_amount': order.total.gross.amount}\n        models.Payment.objects.get_or_create(\n            variant=CustomPaymentChoices.MANUAL,\n            status=PaymentStatus.CONFIRMED, order=order,\n            defaults=defaults)\n\n        order.events.create(\n            type=OrderEvents.ORDER_MARKED_AS_PAID.value,\n            user=info.context.user)\n        return OrderMarkAsPaid(order=order)\n\n\nclass OrderCapture(BaseMutation):\n    order = graphene.Field(Order, description='Captured order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to capture.')\n        amount = Decimal(\n            required=True, description='Amount of money to capture.')\n\n    class Meta:\n        description = 'Capture an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, amount):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        payment = order.get_last_payment()\n        clean_order_capture(payment, amount, errors)\n        try_payment_action(payment.capture, amount, errors)\n        if errors:\n            return OrderCapture(errors=errors)\n\n        order.events.create(\n            parameters={'amount': amount},\n            type=OrderEvents.PAYMENT_CAPTURED.value,\n            user=info.context.user)\n        return OrderCapture(order=order)\n\n\nclass OrderRelease(BaseMutation):\n    order = graphene.Field(Order, description='A released order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to release.')\n\n    class Meta:\n        description = 'Release an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if order:\n            payment = order.get_last_payment()\n            clean_release_payment(payment, errors)\n\n        if errors:\n            return OrderRelease(errors=errors)\n\n        order.events.create(\n            type=OrderEvents.PAYMENT_RELEASED.value,\n            user=info.context.user)\n        return OrderRelease(order=order)\n\n\nclass OrderRefund(BaseMutation):\n    order = graphene.Field(Order, description='A refunded order.')\n\n    class Arguments:\n        id = graphene.ID(\n            required=True, description='ID of the order to refund.')\n        amount = Decimal(\n            required=True, description='Amount of money to refund.')\n\n    class Meta:\n        description = 'Refund an order.'\n\n    @classmethod\n    @permission_required('order.manage_orders')\n    def mutate(cls, root, info, id, amount):\n        errors = []\n        order = cls.get_node_or_error(info, id, errors, 'id', Order)\n        if order:\n            payment = order.get_last_payment()\n            clean_refund_payment(payment, amount, errors)\n            try_payment_action(payment.refund, amount, errors)\n        if errors:\n            return OrderRefund(errors=errors)\n\n        order.events.create(\n            type=OrderEvents.PAYMENT_REFUNDED.value,\n            user=info.context.user,\n            parameters={'amount': amount})\n        return OrderRefund(order=order)\n", "path": "saleor/graphql/order/mutations/orders.py"}]}