Skip to content

Commit

Permalink
Updated how WooCommerce deletions are handled (Closes #264)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelurben committed Apr 9, 2024
1 parent a6e1508 commit 3a215d3
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 55 deletions.
40 changes: 40 additions & 0 deletions kmuhelper/migrations/0113_customer_woocommerce_deleted_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 5.0.4 on 2024-04-09 14:22

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("kmuhelper", "0112_product_parent"),
]

operations = [
migrations.AddField(
model_name="customer",
name="woocommerce_deleted",
field=models.BooleanField(
blank=True, default=False, verbose_name="Deleted in WooCommerce?"
),
),
migrations.AddField(
model_name="order",
name="woocommerce_deleted",
field=models.BooleanField(
blank=True, default=False, verbose_name="Deleted in WooCommerce?"
),
),
migrations.AddField(
model_name="product",
name="woocommerce_deleted",
field=models.BooleanField(
blank=True, default=False, verbose_name="Deleted in WooCommerce?"
),
),
migrations.AddField(
model_name="productcategory",
name="woocommerce_deleted",
field=models.BooleanField(
blank=True, default=False, verbose_name="Deleted in WooCommerce?"
),
),
]
1 change: 1 addition & 0 deletions kmuhelper/modules/integrations/woocommerce/api/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def update_object_from_api(self, db_object) -> bool:
str(db_object),
)
db_object.woocommerceid = 0
db_object.woocommerce_deleted = True
db_object.save()
else:
self.log(wc_obj)
Expand Down
71 changes: 71 additions & 0 deletions kmuhelper/modules/integrations/woocommerce/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _

from kmuhelper.modules.integrations.woocommerce.utils import is_connected


class WooCommerceStateFilter(admin.SimpleListFilter):
"""Filter that filters views based on WooCommerce state."""

# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _("WooCommerce State")

# Parameter for the filter that will be used in the URL query.
parameter_name = "wc_state"

def __init__(self, request, params, model, model_admin):
super(WooCommerceStateFilter, self).__init__(
request, params, model, model_admin
)

def lookups(self, request, model_admin):
return [
("all", _("All")),
("linked", _("Linked")),
("not_linked", _("Not linked")),
("deleted", _("Deleted")),
("not_deleted", _("Not deleted")),
]

def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""

if self.value() is None:
# default option
self.used_parameters[self.parameter_name] = "not_deleted"

if self.value() == "linked":
return queryset.exclude(woocommerceid=0)
if self.value() == "not_linked":
return queryset.filter(woocommerceid=0)
if self.value() == "deleted":
return queryset.filter(woocommerce_deleted=True)
if self.value() == "not_deleted":
return queryset.exclude(woocommerce_deleted=True)

return queryset

def choices(self, changelist):
add_facets = changelist.add_facets
facet_counts = self.get_facet_queryset(changelist) if add_facets else None
for i, (lookup, title) in enumerate(self.lookup_choices):
if add_facets:
if (count := facet_counts.get(f"{i}__c", -1)) != -1:
title = f"{title} ({count})"
else:
title = f"{title} (-)"
yield {
"selected": self.value() == str(lookup),
"query_string": changelist.get_query_string(
{self.parameter_name: lookup}
),
"display": title,
}

def has_output(self):
return is_connected() and super().has_output()
28 changes: 21 additions & 7 deletions kmuhelper/modules/integrations/woocommerce/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from django.utils.translation import gettext_lazy as _
from kmuhelper import settings

WC_ID_PRESENT_DESCRIPTION = format_html(
'<abbr title="{}"><i class="fa-solid fa-link"></i></abbr>',
_("Mit WooCommerce-Objekt verknüpft?"),
WC_STATE_DESCRIPTION = format_html(
'<abbr title="{}"><i class="fa-solid fa-cloud"></i></abbr>',
_(
"WooCommerce-Status (grün = verknüpft, rot = verknüpft, aber auf WooCommerce gelöscht, grau = nicht verknüpft)"
),
)


Expand All @@ -18,6 +20,13 @@ class WooCommerceModelMixin(models.Model):
default=0,
)

woocommerce_deleted = models.BooleanField(
verbose_name=_("Deleted in WooCommerce?"),
default=False,
blank=True,
null=False,
)

def get_woocommerce_url(self):
return self.WOOCOMMERCE_URL_FORMAT.format(
settings.get_secret_db_setting("wc-url"), self.woocommerceid
Expand All @@ -33,16 +42,21 @@ def display_woocommerce_id(self):
link = self.get_woocommerce_url()

return format_html(
'<a target="_blank" href="{}">#{}</a>',
'<a target="_blank" href="{}">#{}</a> {}',
link,
str(self.woocommerceid),
_("(Deleted)") if self.woocommerce_deleted else "",
)

@admin.display(
description=WC_ID_PRESENT_DESCRIPTION, ordering="woocommerceid", boolean=True
description=WC_STATE_DESCRIPTION,
ordering="woocommerceid",
boolean=True,
)
def display_woocommerce_id_present(self):
return bool(self.woocommerceid)
def display_woocommerce_state(self):
if not self.woocommerceid:
return None
return not self.woocommerce_deleted

class Meta:
abstract = True
87 changes: 45 additions & 42 deletions kmuhelper/modules/integrations/woocommerce/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,53 +350,56 @@ def wc_webhooks(request):

log("WooCommerce Webhook is being processed...")

delivery_id = request.headers["x-wc-webhook-delivery-id"]
topic = request.headers["x-wc-webhook-topic"]
wc_obj = json.loads(request.body)

log("Delivery ID: ", delivery_id)
log("Topic: ", topic)
log("ID: ", wc_obj.get("id"))

if topic in ("product.updated", "product.created"):
if Product.objects.filter(woocommerceid=wc_obj["id"]).exists():
WCProductsAPI().update_object_from_data(
Product.objects.get(woocommerceid=wc_obj["id"]), wc_obj
)
else:
WCProductsAPI().create_object_from_data(wc_obj)
elif topic == "product.deleted":
if Product.objects.filter(woocommerceid=wc_obj["id"]).exists():
product = Product.objects.get(woocommerceid=wc_obj["id"])
product.woocommerceid = 0
product.save()
elif topic in ("customer.updated", "customer.created"):
if Customer.objects.filter(woocommerceid=wc_obj["id"]).exists():
WCCustomersAPI().update_object_from_data(
Customer.objects.get(woocommerceid=wc_obj["id"]), wc_obj
)
else:
WCCustomersAPI().create_object_from_data(wc_obj)
elif topic == "customer.deleted":
if Customer.objects.filter(woocommerceid=wc_obj["id"]).exists():
customer = Customer.objects.get(woocommerceid=wc_obj["id"])
customer.woocommerceid = 0
customer.save()
elif topic in ("order.updated", "order.created"):
if Order.objects.filter(woocommerceid=wc_obj["id"]).exists():
WCOrdersAPI().update_object_from_data(
Order.objects.get(woocommerceid=wc_obj["id"]), wc_obj
log("Object ID: ", wc_obj.get("id"))

match topic:
case "product.updated" | "product.created" | "product.restored":
if Product.objects.filter(woocommerceid=wc_obj["id"]).exists():
product = Product.objects.get(woocommerceid=wc_obj["id"])
product.woocommerce_deleted = False
WCProductsAPI().update_object_from_data(product, wc_obj)
else:
WCProductsAPI().create_object_from_data(wc_obj)
case "product.deleted":
if Product.objects.filter(woocommerceid=wc_obj["id"]).exists():
product = Product.objects.get(woocommerceid=wc_obj["id"])
product.woocommerce_deleted = True
product.save()
case "customer.updated" | "customer.created" | "customer.restored":
if Customer.objects.filter(woocommerceid=wc_obj["id"]).exists():
customer = Customer.objects.get(woocommerceid=wc_obj["id"])
customer.woocommerce_deleted = False
WCCustomersAPI().update_object_from_data(customer, wc_obj)
else:
WCCustomersAPI().create_object_from_data(wc_obj)
case "customer.deleted":
if Customer.objects.filter(woocommerceid=wc_obj["id"]).exists():
customer = Customer.objects.get(woocommerceid=wc_obj["id"])
customer.woocommerce_deleted = True
customer.save()
case "order.updated" | "order.created" | "order.restored":
if Order.objects.filter(woocommerceid=wc_obj["id"]).exists():
order = Order.objects.get(woocommerceid=wc_obj["id"])
order.woocommerce_deleted = False
WCOrdersAPI().update_object_from_data(order, wc_obj)
else:
WCOrdersAPI().create_object_from_data(wc_obj)
case "order.deleted":
if Order.objects.filter(woocommerceid=wc_obj["id"]).exists():
order = Order.objects.get(woocommerceid=wc_obj["id"])
order.woocommerce_deleted = True
order.save()
case _:
log(f"[orange_red1]Unknown topic: '{topic}'")
return JsonResponse(
{"accepted": False, "message": "Topic not supported!"}, status=400
)
else:
WCOrdersAPI().create_object_from_data(wc_obj)
elif topic == "order.deleted":
if Order.objects.filter(woocommerceid=wc_obj["id"]).exists():
order = Order.objects.get(woocommerceid=wc_obj["id"])
order.woocommerceid = 0
order.save()
else:
log(f"[orange_red1]Unknown topic: '{topic}'")
return JsonResponse(
{"accepted": False, "message": "Topic not supported!"}, status=400
)

return JsonResponse({"accepted": True})

Expand Down
14 changes: 9 additions & 5 deletions kmuhelper/modules/main/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
WCProductsAPI,
WCProductCategoriesAPI,
)
from kmuhelper.modules.integrations.woocommerce.filters import WooCommerceStateFilter
from kmuhelper.modules.integrations.woocommerce.utils import is_connected
from kmuhelper.modules.main import views
from kmuhelper.modules.main.models import (
Expand Down Expand Up @@ -266,6 +267,7 @@ class OrderAdmin(CustomModelAdmin):
"status",
"is_paid",
"is_shipped",
WooCommerceStateFilter,
"payment_method",
"payment_receiver",
"contact_person",
Expand Down Expand Up @@ -300,7 +302,7 @@ class OrderAdmin(CustomModelAdmin):
def get_list_display(self, request):
if is_connected():
ls = self.list_display.copy()
ls.insert(1, "display_woocommerce_id_present")
ls.insert(1, "display_woocommerce_state")
return ls
return self.list_display

Expand Down Expand Up @@ -613,6 +615,8 @@ class CustomerAdmin(CustomModelAdmin):

readonly_fields = ["linked_note_html", "display_woocommerce_id"]

list_filter = [WooCommerceStateFilter]

list_select_related = ["linked_note"]

autocomplete_fields = ["combine_with"]
Expand All @@ -624,7 +628,7 @@ class CustomerAdmin(CustomModelAdmin):
def get_list_display(self, request):
if is_connected():
ls = self.list_display.copy()
ls.insert(1, "display_woocommerce_id_present")
ls.insert(1, "display_woocommerce_state")
return ls
return self.list_display

Expand Down Expand Up @@ -1081,7 +1085,7 @@ class ProductAdmin(CustomModelAdmin):

ordering = ("article_number", "name")

list_filter = ("supplier", "categories", "stock_current")
list_filter = ("supplier", WooCommerceStateFilter, "categories")
search_fields = [
"pk",
"article_number",
Expand All @@ -1106,7 +1110,7 @@ class ProductAdmin(CustomModelAdmin):
def get_list_display(self, request):
if is_connected():
ls = self.list_display.copy()
ls.insert(1, "display_woocommerce_id_present")
ls.insert(1, "display_woocommerce_state")
return ls
return self.list_display

Expand Down Expand Up @@ -1296,7 +1300,7 @@ class ProductCategoryAdmin(CustomModelAdmin):
def get_list_display(self, request):
if is_connected():
ls = self.list_display.copy()
ls.insert(1, "display_woocommerce_id_present")
ls.insert(1, "display_woocommerce_state")
return ls
return self.list_display

Expand Down
2 changes: 1 addition & 1 deletion kmuhelper/static/admin/kmuhelper/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ form .wide textarea + div.help {
/* Icon columns width fix for boolean columns */

.column-pkfill,
.column-display_woocommerce_id_present,
.column-display_woocommerce_state,
.column-display_is_paid,
.column-display_is_shipped {
width: 1px;
Expand Down

0 comments on commit 3a215d3

Please sign in to comment.