Skip to content

Commit

Permalink
Fix relation between order and click and collect address (#15697)
Browse files Browse the repository at this point in the history
* Create a copy of collection point address during checkout completion

* Add migration for creating order shipping addresses
  • Loading branch information
IKarbowiak committed Mar 27, 2024
1 parent ce4b317 commit 47cedfd
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 5 deletions.
3 changes: 3 additions & 0 deletions saleor/checkout/complete_checkout.py
Expand Up @@ -145,6 +145,9 @@ def _process_shipping_data_for_order(
if checkout_info.user.addresses.filter(pk=shipping_address.pk).exists():
shipping_address = shipping_address.get_copy()

if shipping_address and delivery_method_info.warehouse_pk:
shipping_address = shipping_address.get_copy()

shipping_method = delivery_method_info.delivery_method
tax_class = getattr(shipping_method, "tax_class", None)

Expand Down
Expand Up @@ -3105,7 +3105,7 @@ def test_complete_checkout_for_local_click_and_collect(
order_count = Order.objects.count()
checkout = checkout_with_item_for_cc
checkout.collection_point = warehouse_for_cc
checkout.shipping_address = None
checkout.shipping_address = warehouse_for_cc.address
checkout.save(update_fields=["collection_point", "shipping_address"])

variables = {
Expand Down Expand Up @@ -3147,7 +3147,8 @@ def test_complete_checkout_for_local_click_and_collect(

assert order.collection_point == warehouse_for_cc
assert order.shipping_method is None
assert order.shipping_address == warehouse_for_cc.address
assert order.shipping_address
assert order.shipping_address.id != warehouse_for_cc.address.id
assert order.shipping_price == zero_taxed_money(payment.currency)
assert order.lines.count() == 1

Expand Down Expand Up @@ -3215,7 +3216,8 @@ def test_complete_checkout_for_global_click_and_collect(

assert order.collection_point == warehouse_for_cc
assert order.shipping_method is None
assert order.shipping_address == warehouse_for_cc.address
assert order.shipping_address
assert order.shipping_address.id != warehouse_for_cc.address.id
assert order.shipping_price == zero_taxed_money(payment.currency)
assert order.lines.count() == 1

Expand Down
Expand Up @@ -2773,7 +2773,8 @@ def test_complete_checkout_for_local_click_and_collect(

assert order.collection_point == warehouse_for_cc
assert order.shipping_method is None
assert order.shipping_address == warehouse_for_cc.address
assert order.shipping_address
assert order.shipping_address.id != warehouse_for_cc.address.id
assert order.shipping_price == zero_taxed_money(order.channel.currency_code)
assert order.lines.count() == 1

Expand Down Expand Up @@ -2833,7 +2834,8 @@ def test_complete_checkout_for_global_click_and_collect(

assert order.collection_point == warehouse_for_cc
assert order.shipping_method is None
assert order.shipping_address == warehouse_for_cc.address
assert order.shipping_address
assert order.shipping_address.id != warehouse_for_cc.address.id
assert order.shipping_price == zero_taxed_money(order.channel.currency_code)
assert order.lines.count() == 1

Expand Down
39 changes: 39 additions & 0 deletions saleor/order/migrations/0172_update_order_cc_addresses.py
@@ -0,0 +1,39 @@
from django.db import migrations
from django.db.models import Exists, OuterRef
from django.forms.models import model_to_dict

from .tasks.saleor3_19 import update_order_addresses_task

# The batch of size 250 takes ~0.5 second and consumes ~20MB memory at peak
ADDRESS_UPDATE_BATCH_SIZE = 250


def update_order_addresses(apps, schema_editor):
Order = apps.get_model("order", "Order")
Warehouse = apps.get_model("warehouse", "Warehouse")
Address = apps.get_model("account", "Address")
qs = Order.objects.filter(
Exists(Warehouse.objects.filter(address_id=OuterRef("shipping_address_id"))),
)
order_ids = qs.values_list("pk", flat=True)[:ADDRESS_UPDATE_BATCH_SIZE]
addresses = []
if order_ids:
orders = Order.objects.filter(id__in=order_ids)
for order in orders:
if cc_address := order.shipping_address:
order_address = Address(**model_to_dict(cc_address, exclude=["id"]))
order.shipping_address = order_address
addresses.append(order_address)
Address.objects.bulk_create(addresses, ignore_conflicts=True)
Order.objects.bulk_update(orders, ["shipping_address"])
update_order_addresses_task.delay()


class Migration(migrations.Migration):
dependencies = [
("order", "0171_order_order_user_email_user_id_idx"),
]

operations = [
migrations.RunPython(update_order_addresses, migrations.RunPython.noop),
]
12 changes: 12 additions & 0 deletions saleor/order/migrations/0176_merge_20240325_1315.py
@@ -0,0 +1,12 @@
# Generated by Django 3.2.22 on 2024-03-25 13:15

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("order", "0172_update_order_cc_addresses"),
("order", "0175_merge_20231122_1040"),
]

operations = []
12 changes: 12 additions & 0 deletions saleor/order/migrations/0177_merge_20240325_1329.py
@@ -0,0 +1,12 @@
# Generated by Django 3.2.22 on 2024-03-25 13:29

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("order", "0176_merge_20231122_1346"),
("order", "0176_merge_20240325_1315"),
]

operations = []
12 changes: 12 additions & 0 deletions saleor/order/migrations/0180_merge_20240325_1333.py
@@ -0,0 +1,12 @@
# Generated by Django 3.2.22 on 2024-03-25 13:33

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("order", "0177_merge_20240325_1329"),
("order", "0179_merge_20231122_1348"),
]

operations = []
12 changes: 12 additions & 0 deletions saleor/order/migrations/0182_merge_20240325_1338.py
@@ -0,0 +1,12 @@
# Generated by Django 3.2.22 on 2024-03-25 13:38

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("order", "0180_merge_20240325_1333"),
("order", "0181_order_subtotal_as_a_field"),
]

operations = []
@@ -0,0 +1,12 @@
# Generated by Django 3.2.22 on 2024-03-25 13:42

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("order", "0182_merge_20240325_1338"),
("order", "0183_order_tax_error"),
]

operations = []
29 changes: 29 additions & 0 deletions saleor/order/migrations/tasks/saleor3_19.py
@@ -0,0 +1,29 @@
from django.db.models import Exists, OuterRef
from django.forms.models import model_to_dict

from ....account.models import Address
from ....celeryconf import app
from ....warehouse.models import Warehouse
from ...models import Order

# The batch of size 250 takes ~0.5 second and consumes ~20MB memory at peak
ADDRESS_UPDATE_BATCH_SIZE = 250


@app.task
def update_order_addresses_task():
qs = Order.objects.filter(
Exists(Warehouse.objects.filter(address_id=OuterRef("shipping_address_id"))),
)
order_ids = qs.values_list("pk", flat=True)[:ADDRESS_UPDATE_BATCH_SIZE]
addresses = []
if order_ids:
orders = Order.objects.filter(id__in=order_ids)
for order in orders:
if cc_address := order.shipping_address:
order_address = Address(**model_to_dict(cc_address, exclude=["id"]))
order.shipping_address = order_address
addresses.append(order_address)
Address.objects.bulk_create(addresses, ignore_conflicts=True)
Order.objects.bulk_update(orders, ["shipping_address"])
update_order_addresses_task.delay()

0 comments on commit 47cedfd

Please sign in to comment.