karrio-server-events 2025.5rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. karrio/server/events/__init__.py +3 -0
  2. karrio/server/events/admin.py +3 -0
  3. karrio/server/events/apps.py +11 -0
  4. karrio/server/events/filters.py +63 -0
  5. karrio/server/events/migrations/0001_initial.py +65 -0
  6. karrio/server/events/migrations/0002_event.py +39 -0
  7. karrio/server/events/migrations/0003_auto_20220303_1210.py +25 -0
  8. karrio/server/events/migrations/0004_custom_migration_2022_4.py +41 -0
  9. karrio/server/events/migrations/0005_event_event_object_idx.py +18 -0
  10. karrio/server/events/migrations/0006_webhook_events_alter_event_data.py +85 -0
  11. karrio/server/events/migrations/0007_auto_20221130_0255.py +30 -0
  12. karrio/server/events/migrations/0008_alter_event_type.py +18 -0
  13. karrio/server/events/migrations/0009_alter_webhook_enabled_events.py +45 -0
  14. karrio/server/events/migrations/__init__.py +0 -0
  15. karrio/server/events/models.py +83 -0
  16. karrio/server/events/router.py +3 -0
  17. karrio/server/events/serializers/__init__.py +1 -0
  18. karrio/server/events/serializers/base.py +63 -0
  19. karrio/server/events/serializers/event.py +9 -0
  20. karrio/server/events/serializers/webhook.py +27 -0
  21. karrio/server/events/signals.py +138 -0
  22. karrio/server/events/task_definitions/__init__.py +1 -0
  23. karrio/server/events/task_definitions/base/__init__.py +64 -0
  24. karrio/server/events/task_definitions/base/archiving.py +58 -0
  25. karrio/server/events/task_definitions/base/tracking.py +227 -0
  26. karrio/server/events/task_definitions/base/webhook.py +116 -0
  27. karrio/server/events/tasks.py +20 -0
  28. karrio/server/events/tests/__init__.py +7 -0
  29. karrio/server/events/tests/test_events.py +138 -0
  30. karrio/server/events/tests/test_tracking_tasks.py +345 -0
  31. karrio/server/events/tests/test_webhooks.py +132 -0
  32. karrio/server/events/tests.py +3 -0
  33. karrio/server/events/urls.py +10 -0
  34. karrio/server/events/views/__init__.py +2 -0
  35. karrio/server/events/views/webhooks.py +173 -0
  36. karrio/server/graph/schemas/__init__.py +1 -0
  37. karrio/server/graph/schemas/events/__init__.py +47 -0
  38. karrio/server/graph/schemas/events/inputs.py +43 -0
  39. karrio/server/graph/schemas/events/mutations.py +56 -0
  40. karrio/server/graph/schemas/events/types.py +79 -0
  41. karrio_server_events-2025.5rc1.dist-info/METADATA +28 -0
  42. karrio_server_events-2025.5rc1.dist-info/RECORD +44 -0
  43. karrio_server_events-2025.5rc1.dist-info/WHEEL +5 -0
  44. karrio_server_events-2025.5rc1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,3 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
2
+
3
+ default_app_config = "karrio.server.events.apps.EventsConfig"
@@ -0,0 +1,3 @@
1
+ from django.contrib import admin
2
+
3
+ # Register your models here.
@@ -0,0 +1,11 @@
1
+ from django.apps import AppConfig
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+
5
+ class EventsConfig(AppConfig):
6
+ name = 'karrio.server.events'
7
+ verbose_name = _('Custom Pricing')
8
+
9
+ def ready(self):
10
+ from karrio.server.events import signals
11
+ signals.register_signals()
@@ -0,0 +1,63 @@
1
+ import typing
2
+ from django.db.models import Q
3
+
4
+ import karrio.server.events.serializers as serializers
5
+ import karrio.server.events.models as models
6
+ import karrio.server.filters as filters
7
+
8
+
9
+ class WebhookFilter(filters.FilterSet):
10
+ created_after = filters.DateTimeFilter(field_name="created_at", lookup_expr="gte")
11
+ created_before = filters.DateTimeFilter(field_name="created_at", lookup_expr="lte")
12
+ description = filters.CharFilter(field_name="description", lookup_expr="icontains")
13
+ events = filters.MultipleChoiceFilter(
14
+ field_name="enabled_events",
15
+ method="events_filter",
16
+ choices=[(s, s) for s in serializers.EVENT_TYPES],
17
+ )
18
+ disabled = filters.BooleanFilter(field_name="disabled")
19
+ test_mode = filters.BooleanFilter(field_name="test_mode")
20
+ url = filters.CharFilter(field_name="url", lookup_expr="icontains")
21
+
22
+ class Meta:
23
+ model = models.Webhook
24
+ fields: typing.List[str] = []
25
+
26
+ def events_filter(self, queryset, name, values):
27
+ if any(values):
28
+ query = Q(enabled_events__icontains=values[0])
29
+
30
+ for value in values[1:]:
31
+ query &= Q(enabled_events__icontains=value)
32
+
33
+ return queryset.filter(query | Q(enabled_events__icontains="all"))
34
+
35
+ return queryset.filter(enabled_events__icontains="all")
36
+
37
+
38
+ class EventFilter(filters.FilterSet):
39
+ entity_id = filters.CharFilter(method="entity_filter", field_name="response")
40
+ date_after = filters.DateTimeFilter(field_name="created_at", lookup_expr="gte")
41
+ date_before = filters.DateTimeFilter(field_name="created_at", lookup_expr="lte")
42
+ type = filters.MultipleChoiceFilter(
43
+ field_name="type",
44
+ method="types_filter",
45
+ choices=[
46
+ (c.value, c.value)
47
+ for c in list(serializers.EventTypes)
48
+ if c != serializers.EventTypes.all
49
+ ],
50
+ )
51
+
52
+ class Meta:
53
+ model = models.Event
54
+ fields: typing.List[str] = []
55
+
56
+ def entity_filter(self, queryset, name, value):
57
+ try:
58
+ return queryset.filter(data__id=value)
59
+ except:
60
+ return queryset
61
+
62
+ def types_filter(self, queryset, name, values):
63
+ return queryset.filter(Q(type__in=values))
@@ -0,0 +1,65 @@
1
+ # Generated by Django 3.1.7 on 2021-03-16 23:17
2
+
3
+ from django.conf import settings
4
+ import django.contrib.postgres.fields
5
+ from django.db import migrations, models
6
+ import django.db.models.deletion
7
+ import functools
8
+ import karrio.server.core.models
9
+
10
+
11
+ class Migration(migrations.Migration):
12
+
13
+ initial = True
14
+
15
+ dependencies = [
16
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17
+ ]
18
+
19
+ operations = [
20
+ migrations.CreateModel(
21
+ name="Webhook",
22
+ fields=[
23
+ ("created_at", models.DateTimeField(auto_now_add=True)),
24
+ ("updated_at", models.DateTimeField(auto_now=True)),
25
+ (
26
+ "id",
27
+ models.CharField(
28
+ default=functools.partial(
29
+ karrio.server.core.models.uuid, *(), **{"prefix": "web_"}
30
+ ),
31
+ editable=False,
32
+ max_length=50,
33
+ primary_key=True,
34
+ serialize=False,
35
+ ),
36
+ ),
37
+ (
38
+ "enabled_events",
39
+ karrio.server.core.fields.MultiChoiceField(blank=True),
40
+ ),
41
+ ("url", models.URLField()),
42
+ ("test_mode", models.BooleanField()),
43
+ ("disabled", models.BooleanField(default=False, null=True)),
44
+ (
45
+ "description",
46
+ models.CharField(blank=True, max_length=200, null=True),
47
+ ),
48
+ ("last_event_at", models.DateTimeField(null=True)),
49
+ ("failure_streak_count", models.IntegerField(default=0)),
50
+ (
51
+ "created_by",
52
+ models.ForeignKey(
53
+ on_delete=django.db.models.deletion.CASCADE,
54
+ to=settings.AUTH_USER_MODEL,
55
+ ),
56
+ ),
57
+ ],
58
+ options={
59
+ "verbose_name": "Webhook",
60
+ "verbose_name_plural": "Webhooks",
61
+ "db_table": "webhook",
62
+ "ordering": ["-created_at"],
63
+ },
64
+ ),
65
+ ]
@@ -0,0 +1,39 @@
1
+ # Generated by Django 3.2.9 on 2021-11-13 13:38
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import functools
7
+ import karrio.server.core.models.base
8
+ import karrio.server.core.utils
9
+
10
+
11
+ class Migration(migrations.Migration):
12
+
13
+ dependencies = [
14
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
+ ('events', '0001_initial'),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.CreateModel(
20
+ name='Event',
21
+ fields=[
22
+ ('created_at', models.DateTimeField(auto_now_add=True)),
23
+ ('updated_at', models.DateTimeField(auto_now=True)),
24
+ ('id', models.CharField(default=functools.partial(karrio.server.core.models.base.uuid, *(), **{'prefix': 'evt_'}), editable=False, max_length=50, primary_key=True, serialize=False)),
25
+ ('type', models.CharField(max_length=50)),
26
+ ('data', models.JSONField(default=functools.partial(karrio.server.core.utils.identity, *(), **{'value': {}}))),
27
+ ('test_mode', models.BooleanField()),
28
+ ('pending_webhooks', models.IntegerField(default=0)),
29
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
30
+ ],
31
+ options={
32
+ 'verbose_name': 'Event',
33
+ 'verbose_name_plural': 'Events',
34
+ 'db_table': 'event',
35
+ 'ordering': ['-created_at'],
36
+ },
37
+ bases=(karrio.server.core.models.base.ControlledAccessModel, models.Model),
38
+ ),
39
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 3.2.11 on 2022-03-03 12:10
2
+
3
+ from django.db import migrations, models
4
+ import functools
5
+ import karrio.server.core.models.base
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('events', '0002_event'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddField(
16
+ model_name='webhook',
17
+ name='secret',
18
+ field=models.CharField(default=functools.partial(karrio.server.core.models.base.uuid, *(), **{'prefix': 'whsec_'}), max_length=100),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name='webhook',
22
+ name='id',
23
+ field=models.CharField(default=functools.partial(karrio.server.core.models.base.uuid, *(), **{'prefix': 'weh_'}), editable=False, max_length=50, primary_key=True, serialize=False),
24
+ ),
25
+ ]
@@ -0,0 +1,41 @@
1
+ # Generated by Django 3.2.3 on 2022-03-28 03:40
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ def forwards_func(apps, schema_editor):
7
+ db_alias = schema_editor.connection.alias
8
+ Event = apps.get_model("events", "Event")
9
+ Webhook = apps.get_model("events", "Webhook")
10
+
11
+ for event in Event.objects.using(db_alias).filter(type__icontains=".").iterator():
12
+ event.type = event.type.replace(".", "_")
13
+ event.save()
14
+
15
+ for webhook in Webhook.objects.using(db_alias).all():
16
+ webhook.enabled_events = [e.replace(".", "_") for e in webhook.enabled_events]
17
+ webhook.save()
18
+
19
+
20
+ def reverse_func(apps, schema_editor):
21
+ db_alias = schema_editor.connection.alias
22
+ Event = apps.get_model("events", "Event")
23
+ Webhook = apps.get_model("events", "Webhook")
24
+
25
+ for event in Event.objects.using(db_alias).filter(type__icontains=".").iterator():
26
+ event.type = event.type.replace("_", ".")
27
+ event.save()
28
+
29
+ for webhook in Webhook.objects.using(db_alias).all():
30
+ webhook.enabled_events = [e.replace("_", ".") for e in webhook.enabled_events]
31
+ webhook.save()
32
+
33
+
34
+ class Migration(migrations.Migration):
35
+ dependencies = [
36
+ ("events", "0003_auto_20220303_1210"),
37
+ ]
38
+
39
+ operations = [
40
+ migrations.RunPython(forwards_func, reverse_func),
41
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 3.2.13 on 2022-07-10 13:07
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.fields.json
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('events', '0004_custom_migration_2022_4'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddIndex(
15
+ model_name='event',
16
+ index=models.Index(django.db.models.fields.json.KeyTextTransform('id', 'data'), condition=models.Q(('data__id__isnull', False)), name='event_object_idx'),
17
+ ),
18
+ ]
@@ -0,0 +1,85 @@
1
+ # Generated by Django 4.1.3 on 2022-11-30 00:34
2
+
3
+ from django.db import migrations, models
4
+ from django.conf import settings
5
+ import functools
6
+ import karrio.server.core.fields
7
+ import karrio.server.core.models
8
+
9
+
10
+ def forwards_func(apps, schema_editor):
11
+ db_alias = schema_editor.connection.alias
12
+ Webhook = apps.get_model("events", "Webhook")
13
+ webhooks = (
14
+ Webhook.objects.using(db_alias).raw(
15
+ "SELECT id, to_jsonb(enabled_events) AS enabled_events FROM webhook"
16
+ )
17
+ if "postgres" in settings.DB_ENGINE
18
+ else Webhook.objects.using(db_alias).all()
19
+ )
20
+ _webhooks = []
21
+
22
+ for webhook in webhooks:
23
+ webhook.events = webhook.enabled_events
24
+ _webhooks.append(webhook)
25
+
26
+ Webhook.objects.using(db_alias).bulk_update(_webhooks, ["events"])
27
+
28
+
29
+ def reverse_func(apps, schema_editor):
30
+ pass
31
+
32
+
33
+ class Migration(migrations.Migration):
34
+ dependencies = [
35
+ ("events", "0005_event_event_object_idx"),
36
+ ]
37
+
38
+ operations = [
39
+ migrations.AddField(
40
+ model_name="webhook",
41
+ name="events",
42
+ field=karrio.server.core.fields.MultiChoiceField(
43
+ choices=[
44
+ ("all", "all"),
45
+ ("shipment_purchased", "shipment_purchased"),
46
+ ("shipment_cancelled", "shipment_cancelled"),
47
+ ("shipment_fulfilled", "shipment_fulfilled"),
48
+ ("tracker_created", "tracker_created"),
49
+ ("tracker_updated", "tracker_updated"),
50
+ ("order_created", "order_created"),
51
+ ("order_updated", "order_updated"),
52
+ ("order_fulfilled", "order_fulfilled"),
53
+ ("order_cancelled", "order_cancelled"),
54
+ ("order_delivered", "order_delivered"),
55
+ ("batch_queued", "batch_queued"),
56
+ ("batch_failed", "batch_failed"),
57
+ ("batch_running", "batch_running"),
58
+ ("batch_completed", "batch_completed"),
59
+ ],
60
+ default=functools.partial(
61
+ karrio.server.core.models._identity, *(), **{"value": []}
62
+ ),
63
+ help_text="Webhook events",
64
+ ),
65
+ ),
66
+ migrations.AlterField(
67
+ model_name="event",
68
+ name="data",
69
+ field=models.JSONField(
70
+ default=functools.partial(
71
+ karrio.server.core.models._identity, *(), **{"value": {}}
72
+ )
73
+ ),
74
+ ),
75
+ migrations.RunPython(forwards_func, reverse_func),
76
+ migrations.RemoveField(
77
+ model_name="webhook",
78
+ name="enabled_events",
79
+ ),
80
+ migrations.RenameField(
81
+ model_name="webhook",
82
+ old_name="events",
83
+ new_name="enabled_events",
84
+ ),
85
+ ]
@@ -0,0 +1,30 @@
1
+ # Generated by Django 4.1.3 on 2022-11-30 02:55
2
+
3
+ from django.db import migrations
4
+ import karrio.lib as lib
5
+
6
+
7
+ def forwards_func(apps, schema_editor):
8
+ db_alias = schema_editor.connection.alias
9
+ Webhook = apps.get_model("events", "Webhook")
10
+ _webhooks = []
11
+
12
+ for webhook in Webhook.objects.using(db_alias).all().iterator():
13
+ webhook.enabled_events = lib.to_dict(webhook.enabled_events)
14
+ _webhooks.append(webhook)
15
+
16
+ Webhook.objects.using(db_alias).bulk_update(_webhooks, ["enabled_events"])
17
+
18
+
19
+ def reverse_func(apps, schema_editor):
20
+ pass
21
+
22
+
23
+ class Migration(migrations.Migration):
24
+ dependencies = [
25
+ ("events", "0006_webhook_events_alter_event_data"),
26
+ ]
27
+
28
+ operations = [
29
+ migrations.RunPython(forwards_func, reverse_func),
30
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.1.3 on 2022-12-10 17:09
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("events", "0007_auto_20221130_0255"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="event",
15
+ name="type",
16
+ field=models.CharField(db_index=True, max_length=50),
17
+ ),
18
+ ]
@@ -0,0 +1,45 @@
1
+ # Generated by Django 4.2 on 2023-04-18 10:18
2
+
3
+ from django.db import migrations
4
+ import functools
5
+ import karrio.server.core.fields
6
+ import karrio.server.core.models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+ dependencies = [
11
+ ("events", "0008_alter_event_type"),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterField(
16
+ model_name="webhook",
17
+ name="enabled_events",
18
+ field=karrio.server.core.fields.MultiChoiceField(
19
+ choices=[
20
+ ("all", "all"),
21
+ ("shipment_purchased", "shipment_purchased"),
22
+ ("shipment_cancelled", "shipment_cancelled"),
23
+ ("shipment_fulfilled", "shipment_fulfilled"),
24
+ ("shipment_out_for_delivery", "shipment_out_for_delivery"),
25
+ ("shipment_needs_attention", "shipment_needs_attention"),
26
+ ("shipment_delivery_failed", "shipment_delivery_failed"),
27
+ ("tracker_created", "tracker_created"),
28
+ ("tracker_updated", "tracker_updated"),
29
+ ("order_created", "order_created"),
30
+ ("order_updated", "order_updated"),
31
+ ("order_fulfilled", "order_fulfilled"),
32
+ ("order_cancelled", "order_cancelled"),
33
+ ("order_delivered", "order_delivered"),
34
+ ("batch_queued", "batch_queued"),
35
+ ("batch_failed", "batch_failed"),
36
+ ("batch_running", "batch_running"),
37
+ ("batch_completed", "batch_completed"),
38
+ ],
39
+ default=functools.partial(
40
+ karrio.server.core.models._identity, *(), **{"value": []}
41
+ ),
42
+ help_text="Webhook events",
43
+ ),
44
+ ),
45
+ ]
File without changes
@@ -0,0 +1,83 @@
1
+ from functools import partial
2
+ from django.db import models
3
+ from django.conf import settings
4
+ from django.db.models.fields import json
5
+
6
+ import karrio.server.core.models as core
7
+ import karrio.server.core.fields as core_fields
8
+ import karrio.server.events.serializers.base as serializers
9
+
10
+
11
+ @core.register_model
12
+ class Webhook(core.OwnedEntity):
13
+ HIDDEN_PROPS = (*(("org",) if settings.MULTI_ORGANIZATIONS else tuple()),)
14
+
15
+ class Meta:
16
+ db_table = "webhook"
17
+ verbose_name = "Webhook"
18
+ verbose_name_plural = "Webhooks"
19
+ ordering = ["-created_at"]
20
+
21
+ id = models.CharField(
22
+ max_length=50,
23
+ primary_key=True,
24
+ default=partial(core.uuid, prefix="weh_"),
25
+ editable=False,
26
+ )
27
+
28
+ enabled_events = core_fields.MultiChoiceField(
29
+ choices=serializers.EVENT_TYPES,
30
+ default=core.field_default([]),
31
+ help_text="Webhook events",
32
+ )
33
+ url = models.URLField(max_length=200)
34
+ secret = models.CharField(
35
+ max_length=100, default=partial(core.uuid, prefix="whsec_")
36
+ )
37
+ test_mode = models.BooleanField(null=False)
38
+ disabled = models.BooleanField(null=True, default=False)
39
+ description = models.CharField(max_length=200, null=True, blank=True)
40
+ last_event_at = models.DateTimeField(null=True)
41
+
42
+ # System Reference fields
43
+ failure_streak_count = models.IntegerField(default=0)
44
+
45
+ def __str__(self):
46
+ return f"{self.id} + {self.url}"
47
+
48
+ @property
49
+ def object_type(self):
50
+ return "webhook"
51
+
52
+
53
+ class Event(core.OwnedEntity):
54
+ HIDDEN_PROPS = (*(("org",) if settings.MULTI_ORGANIZATIONS else tuple()),)
55
+
56
+ class Meta:
57
+ db_table = "event"
58
+ verbose_name = "Event"
59
+ verbose_name_plural = "Events"
60
+ ordering = ["-created_at"]
61
+ indexes = [
62
+ models.Index(
63
+ json.KeyTextTransform("id", "data"),
64
+ condition=models.Q(data__id__isnull=False),
65
+ name="event_object_idx",
66
+ ),
67
+ ]
68
+
69
+ id = models.CharField(
70
+ max_length=50,
71
+ primary_key=True,
72
+ default=partial(core.uuid, prefix="evt_"),
73
+ editable=False,
74
+ )
75
+
76
+ type = models.CharField(max_length=50, db_index=True)
77
+ data = models.JSONField(default=core.field_default({}))
78
+ test_mode = models.BooleanField(null=False)
79
+ pending_webhooks = models.IntegerField(default=0)
80
+
81
+ @property
82
+ def object_type(self):
83
+ return "event"
@@ -0,0 +1,3 @@
1
+ from rest_framework.routers import DefaultRouter
2
+
3
+ router = DefaultRouter(trailing_slash=False)
@@ -0,0 +1 @@
1
+ from karrio.server.events.serializers.base import *
@@ -0,0 +1,63 @@
1
+ import karrio.lib as lib
2
+ import karrio.server.serializers as serializers
3
+
4
+
5
+ class EventTypes(lib.StrEnum):
6
+ all = "all"
7
+ shipment_purchased = "shipment_purchased"
8
+ shipment_cancelled = "shipment_cancelled"
9
+ shipment_fulfilled = "shipment_fulfilled"
10
+ shipment_out_for_delivery = "shipment_out_for_delivery"
11
+ shipment_needs_attention = "shipment_needs_attention"
12
+ shipment_delivery_failed = "shipment_delivery_failed"
13
+ tracker_created = "tracker_created"
14
+ tracker_updated = "tracker_updated"
15
+ order_created = "order_created"
16
+ order_updated = "order_updated"
17
+ order_fulfilled = "order_fulfilled"
18
+ order_cancelled = "order_cancelled"
19
+ order_delivered = "order_delivered"
20
+ batch_queued = "batch_queued"
21
+ batch_failed = "batch_failed"
22
+ batch_running = "batch_running"
23
+ batch_completed = "batch_completed"
24
+
25
+
26
+ EVENT_TYPES = [(c.value, c.value) for c in list(EventTypes)]
27
+
28
+
29
+ class WebhookData(serializers.Serializer):
30
+ url = serializers.URLField(
31
+ required=True, help_text="The URL of the webhook endpoint."
32
+ )
33
+ description = serializers.CharField(
34
+ required=False,
35
+ allow_blank=True,
36
+ allow_null=True,
37
+ help_text="An optional description of what the webhook is used for.",
38
+ )
39
+ enabled_events = serializers.ListField(
40
+ required=True,
41
+ child=serializers.ChoiceField(choices=EVENT_TYPES),
42
+ help_text="The list of events to enable for this endpoint.",
43
+ )
44
+ disabled = serializers.BooleanField(
45
+ required=False,
46
+ allow_null=True,
47
+ help_text="Indicates that the webhook is disabled",
48
+ )
49
+
50
+
51
+ class Webhook(serializers.EntitySerializer, WebhookData):
52
+ object_type = serializers.CharField(
53
+ default="webhook", help_text="Specifies the object type"
54
+ )
55
+ last_event_at = serializers.DateTimeField(
56
+ required=False,
57
+ allow_null=True,
58
+ help_text="The datetime of the last event sent.",
59
+ )
60
+ secret = serializers.CharField(help_text="Header signature secret")
61
+ test_mode = serializers.BooleanField(
62
+ help_text="Specified whether it was created with a carrier in test mode",
63
+ )
@@ -0,0 +1,9 @@
1
+ import karrio.server.serializers as serializers
2
+ import karrio.server.events.models as models
3
+
4
+
5
+ @serializers.owned_model_serializer
6
+ class EventSerializer(serializers.ModelSerializer):
7
+ class Meta:
8
+ model = models.Event
9
+ exclude = ["created_at", "updated_at", "created_by"]
@@ -0,0 +1,27 @@
1
+ from karrio.server.serializers import owned_model_serializer
2
+ from karrio.server.events.serializers import WebhookData, Webhook
3
+ import karrio.server.events.models as models
4
+
5
+
6
+ @owned_model_serializer
7
+ class WebhookSerializer(WebhookData):
8
+ def create(self, validated_data: dict, context, **kwargs) -> models.Webhook:
9
+ return models.Webhook.objects.create(
10
+ test_mode=getattr(context, "test_mode", False),
11
+ **validated_data,
12
+ )
13
+
14
+ def update(
15
+ self, instance: models.Webhook, validated_data: dict, **kwargs
16
+ ) -> models.Webhook:
17
+ if (
18
+ "disabled" in validated_data
19
+ and validated_data["disabled"] != instance.disabled
20
+ ):
21
+ instance.failure_streak_count = 0
22
+
23
+ for key, val in validated_data.items():
24
+ setattr(instance, key, val)
25
+
26
+ instance.save()
27
+ return instance