Repository: saleor/saleor

Issue:
Bug: can't compare offset-naive and offset-aware datetimes
### What are you trying to achieve?

I'm testing the `orderBulkCreate` mutation. When passing `createdAt` that uses incorrect format, a Python exception is raised.

### Steps to reproduce the problem

Example mutation with a value `createdAt: "2023-08-23T08:58:47"`:

```graphql
mutation {
  orderBulkCreate(
    errorPolicy: REJECT_EVERYTHING
    stockUpdatePolicy: SKIP
    orders: [
      {
        channel: "default-channel",
        createdAt: "2023-08-23T08:58:47",
        user: {
          email: "test@example.com"},
        currency: "USD",
        billingAddress: {
          firstName: "test",
          lastName: "test",
          streetAddress1: "test",
          postalCode: "12-123",
          city: "test",
          country: PL
        },
        languageCode: EN,
        lines: []
      }
    ]
  ) {
    count
    results {
      order {
        id
      }
      errors {
        path
        message
      }
    }
    errors {
      path
      message
    }
  }
}
```

Result:
```
2023-08-23 09:16:21,537 ERROR saleor.graphql.errors.unhandled A query failed unexpectedly [PID:14670:ThreadPoolExecutor-0_0]
Traceback (most recent call last):
  File "/Users/marcin/.pyenv/versions/3.9.1/envs/saleor/lib/python3.9/site-packages/graphql/execution/executor.py", line 452, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/Users/marcin/.pyenv/versions/3.9.1/envs/saleor/lib/python3.9/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/core/mutations.py", line 540, in mutate
    response = cls.perform_mutation(root, info, **data)
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 2199, in perform_mutation
    orders_data.append(cls.create_single_order(order_input, object_storage))
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 1827, in create_single_order
    cls.validate_order_input(order_input, order_data, object_storage)
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 768, in validate_order_input
    if date and not cls.is_datetime_valid(date):
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 751, in is_datetime_valid
    return date < timezone.now() + timedelta(minutes=MINUTES_DIFF)
TypeError: can't compare offset-naive and offset-aware datetimes
```

### What did you expect to happen?

A handled validation error should be returned informing that the provided datetime is invalid. Error message could include information about expected format.

### Logs

_No response_

### Environment

Saleor version: 3.15




Discussion:
BTW after passing correct datetime, the above query also fails:
```
2023-08-23 09:19:45,104 ERROR saleor.graphql.errors.unhandled A query failed unexpectedly [PID:14670:ThreadPoolExecutor-0_0]
Traceback (most recent call last):
  File "/Users/marcin/.pyenv/versions/3.9.1/envs/saleor/lib/python3.9/site-packages/graphql/execution/executor.py", line 452, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/Users/marcin/.pyenv/versions/3.9.1/envs/saleor/lib/python3.9/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/core/mutations.py", line 540, in mutate
    response = cls.perform_mutation(root, info, **data)
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 2199, in perform_mutation
    orders_data.append(cls.create_single_order(order_input, object_storage))
  File "/Users/marcin/mirumee/saleor-platform/saleor/saleor/graphql/order/bulk_mutations/order_bulk_create.py", line 1874, in create_single_order
    cls.validate_order_status(order_input["status"], order_data)
KeyError: 'status'
```
I want to work on this. Can you assign it to me, @maarcingebala ? 
Hi @maarcingebala , in the order_list there is key with status, so it is showing the KeyError: 'status', we need to add 'status' 
to the  order_list

@maarcingebala Can I work on this ?
No one from our team is currently working on it so you can go ahead!

Resolving patch:
diff --git a/saleor/graphql/order/bulk_mutations/order_bulk_create.py b/saleor/graphql/order/bulk_mutations/order_bulk_create.py
--- a/saleor/graphql/order/bulk_mutations/order_bulk_create.py
+++ b/saleor/graphql/order/bulk_mutations/order_bulk_create.py
@@ -747,7 +747,15 @@ def is_datetime_valid(cls, date: datetime) -> bool:
         Some systems might have incorrect time that is in the future compared to Saleor.
         At the same time, we don't want to create orders that are too far in the future.
         """
-        return date < timezone.now() + timedelta(minutes=MINUTES_DIFF)
+        current_time = timezone.now()
+        future_time = current_time + timedelta(minutes=MINUTES_DIFF)
+        if not date.tzinfo:
+            raise ValidationError(
+                message="Input 'date' must be timezone-aware. "
+                "Expected format: 'YYYY-MM-DD HH:MM:SS TZ'.",
+                code=OrderBulkCreateErrorCode.INVALID.value,
+            )
+        return date < future_time
 
     @classmethod
     def is_shipping_required(cls, order_input: Dict[str, Any]) -> bool:


Test patch:
diff --git a/saleor/graphql/order/tests/mutations/test_order_bulk_create.py b/saleor/graphql/order/tests/mutations/test_order_bulk_create.py
--- a/saleor/graphql/order/tests/mutations/test_order_bulk_create.py
+++ b/saleor/graphql/order/tests/mutations/test_order_bulk_create.py
@@ -1,5 +1,5 @@
 import copy
-from datetime import timedelta
+from datetime import datetime, timedelta
 from decimal import Decimal
 from unittest.mock import patch
 
@@ -257,6 +257,10 @@
                     code
                 }
             }
+            errors {
+                message
+                code
+            }
         }
     }
 """
@@ -1995,6 +1999,43 @@ def test_order_bulk_create_error_order_future_date(
     assert Order.objects.count() == orders_count
 
 
+def test_order_bulk_create_invalid_date_format(
+    staff_api_client,
+    permission_manage_orders,
+    permission_manage_orders_import,
+    order_bulk_input,
+):
+    # given
+    orders_count = Order.objects.count()
+
+    order = order_bulk_input
+    current_time = datetime.now() + timedelta(minutes=MINUTES_DIFF + 1)
+    order["createdAt"] = current_time.strftime("%Y-%m-%dT%H:%M:%S")
+
+    staff_api_client.user.user_permissions.add(
+        permission_manage_orders_import,
+        permission_manage_orders,
+    )
+    variables = {
+        "orders": [order],
+        "stockUpdatePolicy": StockUpdatePolicyEnum.SKIP.name,
+    }
+
+    # when
+    response = staff_api_client.post_graphql(ORDER_BULK_CREATE, variables)
+    content = get_graphql_content(response)
+
+    # then
+    error = content["data"]["orderBulkCreate"]["errors"][0]
+    assert (
+        error["message"] == "Input 'date' must be timezone-aware. "
+        "Expected format: 'YYYY-MM-DD HH:MM:SS TZ'."
+    )
+    assert error["code"] == OrderBulkCreateErrorCode.INVALID.name
+
+    assert Order.objects.count() == orders_count
+
+
 def test_order_bulk_create_error_order_line_future_date(
     staff_api_client,
     permission_manage_orders,