karrio-server-graph 2025.5__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 (39) hide show
  1. karrio/server/graph/__init__.py +1 -0
  2. karrio/server/graph/admin.py +3 -0
  3. karrio/server/graph/apps.py +5 -0
  4. karrio/server/graph/forms.py +57 -0
  5. karrio/server/graph/management/__init__.py +0 -0
  6. karrio/server/graph/management/commands/__init__.py +0 -0
  7. karrio/server/graph/management/commands/export_schema.py +9 -0
  8. karrio/server/graph/migrations/0001_initial.py +37 -0
  9. karrio/server/graph/migrations/0002_auto_20210512_1353.py +22 -0
  10. karrio/server/graph/migrations/__init__.py +0 -0
  11. karrio/server/graph/models.py +44 -0
  12. karrio/server/graph/schema.py +44 -0
  13. karrio/server/graph/schemas/__init__.py +2 -0
  14. karrio/server/graph/schemas/base/__init__.py +385 -0
  15. karrio/server/graph/schemas/base/inputs.py +612 -0
  16. karrio/server/graph/schemas/base/mutations.py +1033 -0
  17. karrio/server/graph/schemas/base/types.py +1406 -0
  18. karrio/server/graph/serializers.py +388 -0
  19. karrio/server/graph/templates/graphql/graphiql.html +142 -0
  20. karrio/server/graph/templates/karrio/email_change_email.html +13 -0
  21. karrio/server/graph/templates/karrio/email_change_email.txt +13 -0
  22. karrio/server/graph/templates/karrio/password_reset_email.html +14 -0
  23. karrio/server/graph/tests/__init__.py +9 -0
  24. karrio/server/graph/tests/base.py +153 -0
  25. karrio/server/graph/tests/test_carrier_connections.py +239 -0
  26. karrio/server/graph/tests/test_metafield.py +404 -0
  27. karrio/server/graph/tests/test_partial_shipments.py +603 -0
  28. karrio/server/graph/tests/test_rate_sheets.py +354 -0
  29. karrio/server/graph/tests/test_registration.py +209 -0
  30. karrio/server/graph/tests/test_templates.py +677 -0
  31. karrio/server/graph/tests/test_user_info.py +71 -0
  32. karrio/server/graph/urls.py +10 -0
  33. karrio/server/graph/utils.py +308 -0
  34. karrio/server/graph/views.py +91 -0
  35. karrio/server/settings/graph.py +7 -0
  36. karrio_server_graph-2025.5.dist-info/METADATA +29 -0
  37. karrio_server_graph-2025.5.dist-info/RECORD +39 -0
  38. karrio_server_graph-2025.5.dist-info/WHEEL +5 -0
  39. karrio_server_graph-2025.5.dist-info/top_level.txt +2 -0
@@ -0,0 +1 @@
1
+ __path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
@@ -0,0 +1,3 @@
1
+ from django.contrib import admin
2
+
3
+ # Register your models here.
@@ -0,0 +1,5 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class GraphConfig(AppConfig):
5
+ name = 'karrio.server.graph'
@@ -0,0 +1,57 @@
1
+ import django.forms as forms
2
+ import django.contrib.auth.forms as auth
3
+ import django.core.exceptions as exceptions
4
+ import django.contrib.auth.tokens as tokens
5
+ import django_email_verification.confirm as confirm
6
+
7
+ import karrio.server.conf as conf
8
+ import karrio.server.user.forms as user_forms
9
+ from karrio.server.core.logging import logger
10
+
11
+
12
+ class UserRegistrationForm(user_forms.SignUpForm):
13
+ pass
14
+
15
+
16
+ class PasswordChangeForm(auth.PasswordChangeForm):
17
+ def __init__(self, user=None, *args, **kwargs):
18
+ super().__init__(user, *args, **kwargs)
19
+
20
+
21
+ class ConfirmPasswordResetForm(auth.SetPasswordForm):
22
+ uid = forms.CharField(required=True, max_length=100)
23
+ token = forms.CharField(required=True, max_length=100)
24
+
25
+ def __init__(self, user=None, *args, **kwargs):
26
+ super().__init__(user, *args, **kwargs)
27
+
28
+ def clean_token(self):
29
+ token = self.cleaned_data["token"]
30
+ valid_link = tokens.default_token_generator.check_token(self.user, token)
31
+
32
+ if not valid_link:
33
+ raise exceptions.ValidationError("invalid or expired url token")
34
+
35
+
36
+ class ResetPasswordRequestForm(auth.PasswordResetForm):
37
+ redirect_url = forms.URLField()
38
+ from_email = confirm._get_validated_field("EMAIL_FROM_ADDRESS")
39
+
40
+ def save(self, **kwargs):
41
+ try:
42
+ super().save(
43
+ **{
44
+ **kwargs,
45
+ "extra_email_context": dict(
46
+ app_name=conf.settings.app_name,
47
+ redirect_url=self.cleaned_data["redirect_url"],
48
+ ),
49
+ "email_template_name": "karrio/password_reset_email.html",
50
+ "from_email": self.from_email,
51
+ }
52
+ )
53
+ except Exception as e:
54
+ logger.error("Password reset email failed", error=str(e))
55
+ raise exceptions.ValidationError(
56
+ "An error occurred while sending the email"
57
+ )
File without changes
File without changes
@@ -0,0 +1,9 @@
1
+ from django.core.management import BaseCommand
2
+ from strawberry.printer import print_schema
3
+
4
+ from karrio.server.graph.schema import schema
5
+
6
+ class Command(BaseCommand):
7
+ help = 'Exports the strawberry graphql schema'
8
+ def handle(self, *args, **options):
9
+ print(print_schema(schema))
@@ -0,0 +1,37 @@
1
+ # Generated by Django 3.1.7 on 2021-03-26 14:53
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import karrio.server.core.models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ initial = True
12
+
13
+ dependencies = [
14
+ ('manager', '0009_auto_20210326_1425'),
15
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.CreateModel(
20
+ name='Template',
21
+ fields=[
22
+ ('created_at', models.DateTimeField(auto_now_add=True)),
23
+ ('updated_at', models.DateTimeField(auto_now=True)),
24
+ ('id', models.CharField(default=karrio.server.core.models.uuid, editable=False, max_length=50, primary_key=True, serialize=False)),
25
+ ('label', models.CharField(max_length=50)),
26
+ ('is_default', models.BooleanField(null=True)),
27
+ ('address', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='manager.address')),
28
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
29
+ ('customs', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='manager.customs')),
30
+ ('parcel', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='manager.parcel')),
31
+ ],
32
+ options={
33
+ 'db_table': 'template',
34
+ 'ordering': ['-created_at'],
35
+ },
36
+ ),
37
+ ]
@@ -0,0 +1,22 @@
1
+ # Generated by Django 3.2.2 on 2021-05-12 13:53
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('graph', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterModelOptions(
14
+ name='template',
15
+ options={'ordering': ['-is_default', '-created_by']},
16
+ ),
17
+ migrations.AlterField(
18
+ model_name='template',
19
+ name='is_default',
20
+ field=models.BooleanField(blank=True, default=False),
21
+ ),
22
+ ]
File without changes
@@ -0,0 +1,44 @@
1
+ from django.conf import settings
2
+ from django.db import models
3
+
4
+ from karrio.server.core.models import OwnedEntity, uuid, register_model
5
+ from karrio.server.manager.models import Customs, Parcel, Address
6
+
7
+
8
+ @register_model
9
+ class Template(OwnedEntity):
10
+ HIDDEN_PROPS = (*(("org",) if settings.MULTI_ORGANIZATIONS else tuple()),)
11
+
12
+ class Meta:
13
+ db_table = "template"
14
+ ordering = ["-is_default", "-created_by"]
15
+
16
+ id = models.CharField(max_length=50, primary_key=True, default=uuid, editable=False)
17
+ label = models.CharField(max_length=50)
18
+ is_default = models.BooleanField(blank=True, default=False)
19
+
20
+ address = models.OneToOneField(
21
+ Address, on_delete=models.CASCADE, null=True, blank=True
22
+ )
23
+ customs = models.OneToOneField(
24
+ Customs, on_delete=models.CASCADE, null=True, blank=True
25
+ )
26
+ parcel = models.OneToOneField(
27
+ Parcel, on_delete=models.CASCADE, null=True, blank=True
28
+ )
29
+
30
+ def delete(self, *args, **kwargs):
31
+ attachment = next(
32
+ (
33
+ entity
34
+ for entity in [self.address, self.customs, self.parcel]
35
+ if entity is not None
36
+ ),
37
+ super(),
38
+ )
39
+
40
+ return attachment.delete(*args, **kwargs)
41
+
42
+ @property
43
+ def object_type(self):
44
+ return "template"
@@ -0,0 +1,44 @@
1
+ import pkgutil
2
+ import strawberry
3
+ import strawberry
4
+ import strawberry.schema.config as config
5
+
6
+ from karrio.server.core.logging import logger
7
+ import karrio.server.graph.schemas as schemas
8
+
9
+ QUERIES: list = []
10
+ MUTATIONS: list = []
11
+ EXTRA_TYPES: list = []
12
+
13
+ # Register karrio graphql schemas
14
+ for _, name, _ in pkgutil.iter_modules(schemas.__path__): # type: ignore
15
+ try:
16
+ schema = __import__(f"{schemas.__name__}.{name}", fromlist=[name])
17
+ if hasattr(schema, "Query"):
18
+ QUERIES.append(schema.Query)
19
+ if hasattr(schema, "Mutation"):
20
+ MUTATIONS.append(schema.Mutation)
21
+ if hasattr(schema, "extra_types"):
22
+ EXTRA_TYPES += schema.extra_types
23
+ except Exception as e:
24
+ logger.warning("Failed to register GraphQL schema", schema_name=name, error=str(e))
25
+ logger.exception("GraphQL schema registration error", schema_name=name)
26
+
27
+
28
+ @strawberry.type
29
+ class Query(*QUERIES): # type: ignore
30
+ pass
31
+
32
+
33
+ @strawberry.type
34
+ class Mutation(*MUTATIONS): # type: ignore
35
+ pass
36
+
37
+
38
+ schema = strawberry.Schema( # type: ignore
39
+ query=Query,
40
+ mutation=Mutation,
41
+ types=[*EXTRA_TYPES],
42
+ config=config.StrawberryConfig(auto_camel_case=False),
43
+ extensions=[],
44
+ )
@@ -0,0 +1,2 @@
1
+ # type: ignore
2
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1,385 @@
1
+ import typing
2
+ import strawberry
3
+ from strawberry.types import Info
4
+
5
+ import karrio.server.core.models as core
6
+ import karrio.server.graph.models as graph
7
+ import karrio.server.manager.models as manager
8
+ import karrio.server.providers.models as providers
9
+ import karrio.server.manager.serializers as manager_serializers
10
+ import karrio.server.graph.schemas.base.mutations as mutations
11
+ import karrio.server.graph.schemas.base.inputs as inputs
12
+ import karrio.server.graph.schemas.base.types as types
13
+ import karrio.server.graph.utils as utils
14
+
15
+ # extra_types = [*types.CarrierSettings.values()]
16
+ extra_types = []
17
+
18
+
19
+ @strawberry.type
20
+ class Query:
21
+ user: types.UserType = strawberry.field(resolver=types.UserType.resolve)
22
+ token: types.TokenType = strawberry.field(resolver=types.TokenType.resolve)
23
+ api_keys: typing.List[types.APIKeyType] = strawberry.field(
24
+ resolver=types.APIKeyType.resolve_list
25
+ )
26
+ workspace_config: typing.Optional[types.WorkspaceConfigType] = strawberry.field(
27
+ resolver=types.WorkspaceConfigType.resolve
28
+ )
29
+ system_usage: types.SystemUsageType = strawberry.field(
30
+ resolver=types.SystemUsageType.resolve
31
+ )
32
+
33
+ user_connections: utils.Connection[types.CarrierConnectionType] = strawberry.field(
34
+ resolver=types.CarrierConnectionType.resolve_list
35
+ )
36
+ system_connections: utils.Connection[types.SystemConnectionType] = strawberry.field(
37
+ resolver=types.SystemConnectionType.resolve_list
38
+ )
39
+
40
+ default_templates: types.DefaultTemplatesType = strawberry.field(
41
+ resolver=types.DefaultTemplatesType.resolve
42
+ )
43
+ address_templates: utils.Connection[types.AddressTemplateType] = strawberry.field(
44
+ resolver=types.AddressTemplateType.resolve_list
45
+ )
46
+ customs_templates: utils.Connection[types.CustomsTemplateType] = strawberry.field(
47
+ resolver=types.CustomsTemplateType.resolve_list
48
+ )
49
+ parcel_templates: utils.Connection[types.ParcelTemplateType] = strawberry.field(
50
+ resolver=types.ParcelTemplateType.resolve_list
51
+ )
52
+
53
+ log: typing.Optional[types.LogType] = strawberry.field(
54
+ resolver=types.LogType.resolve
55
+ )
56
+ logs: utils.Connection[types.LogType] = strawberry.field(
57
+ resolver=types.LogType.resolve_list
58
+ )
59
+
60
+ tracing_record: typing.Optional[types.TracingRecordType] = strawberry.field(
61
+ resolver=types.TracingRecordType.resolve
62
+ )
63
+ tracing_records: utils.Connection[types.TracingRecordType] = strawberry.field(
64
+ resolver=types.TracingRecordType.resolve_list
65
+ )
66
+
67
+ shipment: typing.Optional[types.ShipmentType] = strawberry.field(
68
+ resolver=types.ShipmentType.resolve
69
+ )
70
+ shipments: utils.Connection[types.ShipmentType] = strawberry.field(
71
+ resolver=types.ShipmentType.resolve_list
72
+ )
73
+
74
+ tracker: typing.Optional[types.TrackerType] = strawberry.field(
75
+ resolver=types.TrackerType.resolve
76
+ )
77
+ trackers: utils.Connection[types.TrackerType] = strawberry.field(
78
+ resolver=types.TrackerType.resolve_list
79
+ )
80
+
81
+ rate_sheet: typing.Optional[types.RateSheetType] = strawberry.field(
82
+ resolver=types.RateSheetType.resolve
83
+ )
84
+ rate_sheets: utils.Connection[types.RateSheetType] = strawberry.field(
85
+ resolver=types.RateSheetType.resolve_list
86
+ )
87
+
88
+ manifest: typing.Optional[types.ManifestType] = strawberry.field(
89
+ resolver=types.ManifestType.resolve
90
+ )
91
+ manifests: utils.Connection[types.ManifestType] = strawberry.field(
92
+ resolver=types.ManifestType.resolve_list
93
+ )
94
+
95
+ carrier_connection: typing.Optional[types.CarrierConnectionType] = strawberry.field(
96
+ resolver=types.CarrierConnectionType.resolve
97
+ )
98
+ carrier_connections: utils.Connection[types.CarrierConnectionType] = (
99
+ strawberry.field(resolver=types.CarrierConnectionType.resolve_list)
100
+ )
101
+
102
+ metafield: typing.Optional[types.MetafieldType] = strawberry.field(
103
+ resolver=types.MetafieldType.resolve
104
+ )
105
+ metafields: utils.Connection[types.MetafieldType] = strawberry.field(
106
+ resolver=types.MetafieldType.resolve_list
107
+ )
108
+
109
+
110
+ @strawberry.type
111
+ class Mutation:
112
+ @strawberry.mutation
113
+ def update_user(
114
+ self, info: Info, input: inputs.UpdateUserInput
115
+ ) -> mutations.UserUpdateMutation:
116
+ return mutations.UserUpdateMutation.mutate(info, **input.to_dict())
117
+
118
+ @strawberry.mutation
119
+ def register_user(
120
+ self, info: Info, input: inputs.RegisterUserMutationInput
121
+ ) -> mutations.RegisterUserMutation:
122
+ return mutations.RegisterUserMutation.mutate(info, **input.to_dict())
123
+
124
+ @strawberry.mutation
125
+ def update_workspace_config(
126
+ self, info: Info, input: inputs.WorkspaceConfigMutationInput
127
+ ) -> mutations.WorkspaceConfigMutation:
128
+ return mutations.WorkspaceConfigMutation.mutate(info, **input.to_dict())
129
+
130
+ @strawberry.mutation
131
+ def mutate_token(
132
+ self, info: Info, input: inputs.TokenMutationInput
133
+ ) -> mutations.TokenMutation:
134
+ return mutations.TokenMutation.mutate(info, **input.to_dict())
135
+
136
+ @strawberry.mutation
137
+ def create_api_key(
138
+ self, info: Info, input: inputs.CreateAPIKeyMutationInput
139
+ ) -> mutations.CreateAPIKeyMutation:
140
+ return mutations.CreateAPIKeyMutation.mutate(info, **input.to_dict())
141
+
142
+ @strawberry.mutation
143
+ def delete_api_key(
144
+ self, info: Info, input: inputs.DeleteAPIKeyMutationInput
145
+ ) -> mutations.DeleteAPIKeyMutation:
146
+ return mutations.DeleteAPIKeyMutation.mutate(info, **input.to_dict())
147
+
148
+ @strawberry.mutation
149
+ def request_email_change(
150
+ self, info: Info, input: inputs.RequestEmailChangeMutationInput
151
+ ) -> mutations.RequestEmailChangeMutation:
152
+ return mutations.RequestEmailChangeMutation.mutate(info, **input.to_dict())
153
+
154
+ @strawberry.mutation
155
+ def confirm_email_change(
156
+ self, info: Info, input: inputs.ConfirmEmailChangeMutationInput
157
+ ) -> mutations.ConfirmEmailChangeMutation:
158
+ return mutations.ConfirmEmailChangeMutation.mutate(info, **input.to_dict())
159
+
160
+ @strawberry.mutation
161
+ def confirm_email(
162
+ self, info: Info, input: inputs.ConfirmEmailMutationInput
163
+ ) -> mutations.ConfirmEmailMutation:
164
+ return mutations.ConfirmEmailMutation.mutate(info, **input.to_dict())
165
+
166
+ @strawberry.mutation
167
+ def change_password(
168
+ self, info: Info, input: inputs.ChangePasswordMutationInput
169
+ ) -> mutations.ChangePasswordMutation:
170
+ return mutations.ChangePasswordMutation.mutate(info, **input.to_dict())
171
+
172
+ @strawberry.mutation
173
+ def request_password_reset(
174
+ self, info: Info, input: inputs.RequestPasswordResetMutationInput
175
+ ) -> mutations.RequestPasswordResetMutation:
176
+ return mutations.RequestPasswordResetMutation.mutate(info, **input.to_dict())
177
+
178
+ @strawberry.mutation
179
+ def confirm_password_reset(
180
+ self, info: Info, input: inputs.ConfirmPasswordResetMutationInput
181
+ ) -> mutations.ConfirmPasswordResetMutation:
182
+ return mutations.ConfirmPasswordResetMutation.mutate(info, **input.to_dict())
183
+
184
+ @strawberry.mutation
185
+ def enable_multi_factor(
186
+ self, info: Info, input: inputs.EnableMultiFactorMutationInput
187
+ ) -> mutations.EnableMultiFactorMutation:
188
+ return mutations.EnableMultiFactorMutation.mutate(info, **input.to_dict())
189
+
190
+ @strawberry.mutation
191
+ def confirm_multi_factor(
192
+ self, info: Info, input: inputs.ConfirmMultiFactorMutationInput
193
+ ) -> mutations.ConfirmMultiFactorMutation:
194
+ return mutations.ConfirmMultiFactorMutation.mutate(info, **input.to_dict())
195
+
196
+ @strawberry.mutation
197
+ def disable_multi_factor(
198
+ self, info: Info, input: inputs.DisableMultiFactorMutationInput
199
+ ) -> mutations.DisableMultiFactorMutation:
200
+ return mutations.DisableMultiFactorMutation.mutate(info, **input.to_dict())
201
+
202
+ @strawberry.mutation
203
+ def create_address_template(
204
+ self, info: Info, input: inputs.CreateAddressTemplateInput
205
+ ) -> mutations.CreateAddressTemplateMutation:
206
+ return mutations.CreateAddressTemplateMutation.mutate(info, **input.to_dict())
207
+
208
+ @strawberry.mutation
209
+ def update_address_template(
210
+ self, info: Info, input: inputs.UpdateAddressTemplateInput
211
+ ) -> mutations.UpdateAddressTemplateMutation:
212
+ return mutations.UpdateAddressTemplateMutation.mutate(info, **input.to_dict())
213
+
214
+ @strawberry.mutation
215
+ def create_customs_template(
216
+ self, info: Info, input: inputs.CreateCustomsTemplateInput
217
+ ) -> mutations.CreateCustomsTemplateMutation:
218
+ return mutations.CreateCustomsTemplateMutation.mutate(info, **input.to_dict())
219
+
220
+ @strawberry.mutation
221
+ def update_customs_template(
222
+ self, info: Info, input: inputs.UpdateCustomsTemplateInput
223
+ ) -> mutations.UpdateCustomsTemplateMutation:
224
+ return mutations.UpdateCustomsTemplateMutation.mutate(info, **input.to_dict())
225
+
226
+ @strawberry.mutation
227
+ def create_parcel_template(
228
+ self, info: Info, input: inputs.CreateParcelTemplateInput
229
+ ) -> mutations.CreateParcelTemplateMutation:
230
+ return mutations.CreateParcelTemplateMutation.mutate(info, **input.to_dict())
231
+
232
+ @strawberry.mutation
233
+ def update_parcel_template(
234
+ self, info: Info, input: inputs.UpdateParcelTemplateInput
235
+ ) -> mutations.UpdateParcelTemplateMutation:
236
+ return mutations.UpdateParcelTemplateMutation.mutate(info, **input.to_dict())
237
+
238
+ @strawberry.mutation
239
+ def create_carrier_connection(
240
+ self, info: Info, input: inputs.CreateCarrierConnectionMutationInput
241
+ ) -> mutations.CreateCarrierConnectionMutation:
242
+ return mutations.CreateCarrierConnectionMutation.mutate(info, **input.to_dict())
243
+
244
+ @strawberry.mutation
245
+ def update_carrier_connection(
246
+ self, info: Info, input: inputs.UpdateCarrierConnectionMutationInput
247
+ ) -> mutations.UpdateCarrierConnectionMutation:
248
+ return mutations.UpdateCarrierConnectionMutation.mutate(info, **input.to_dict())
249
+
250
+ @strawberry.mutation
251
+ def mutate_system_connection(
252
+ self, info: Info, input: inputs.SystemCarrierMutationInput
253
+ ) -> mutations.SystemCarrierMutation:
254
+ return mutations.SystemCarrierMutation.mutate(info, **input.to_dict())
255
+
256
+ @strawberry.mutation
257
+ def delete_carrier_connection(
258
+ self, info: Info, input: inputs.DeleteMutationInput
259
+ ) -> mutations.DeleteMutation:
260
+ return mutations.DeleteMutation.mutate(
261
+ info, model=providers.Carrier, **input.to_dict()
262
+ )
263
+
264
+ @strawberry.mutation
265
+ def partial_shipment_update(
266
+ self, info: Info, input: inputs.PartialShipmentMutationInput
267
+ ) -> mutations.PartialShipmentMutation:
268
+ return mutations.PartialShipmentMutation.mutate(info, **input.to_dict())
269
+
270
+ @strawberry.mutation
271
+ def mutate_metadata(
272
+ self, info: Info, input: inputs.MetadataMutationInput
273
+ ) -> mutations.MetadataMutation:
274
+ return mutations.MetadataMutation.mutate(info, **input.to_dict())
275
+
276
+ @strawberry.mutation
277
+ def change_shipment_status(
278
+ self, info: Info, input: inputs.ChangeShipmentStatusMutationInput
279
+ ) -> mutations.ChangeShipmentStatusMutation:
280
+ return mutations.ChangeShipmentStatusMutation.mutate(info, **input.to_dict())
281
+
282
+ @strawberry.mutation
283
+ def delete_template(
284
+ self, info: Info, input: inputs.DeleteMutationInput
285
+ ) -> mutations.DeleteMutation:
286
+ return mutations.DeleteMutation.mutate(
287
+ info, model=graph.Template, **input.to_dict()
288
+ )
289
+
290
+ @strawberry.mutation
291
+ def discard_commodity(
292
+ self, info: Info, input: inputs.DeleteMutationInput
293
+ ) -> mutations.DeleteMutation:
294
+ return mutations.DeleteMutation.mutate(
295
+ info,
296
+ model=manager.Commodity,
297
+ validator=manager_serializers.can_mutate_commodity,
298
+ **input.to_dict()
299
+ )
300
+
301
+ @strawberry.mutation
302
+ def discard_customs(
303
+ self, info: Info, input: inputs.DeleteMutationInput
304
+ ) -> mutations.DeleteMutation:
305
+ return mutations.DeleteMutation.mutate(
306
+ info,
307
+ model=manager.Customs,
308
+ validator=manager_serializers.can_mutate_customs,
309
+ **input.to_dict()
310
+ )
311
+
312
+ @strawberry.mutation
313
+ def discard_parcel(
314
+ self, info: Info, input: inputs.DeleteMutationInput
315
+ ) -> mutations.DeleteMutation:
316
+ return mutations.DeleteMutation.mutate(
317
+ info,
318
+ model=manager.Parcel,
319
+ validator=manager_serializers.can_mutate_parcel,
320
+ **input.to_dict()
321
+ )
322
+
323
+ @strawberry.mutation
324
+ def create_rate_sheet(
325
+ self, info: Info, input: inputs.CreateRateSheetMutationInput
326
+ ) -> mutations.CreateRateSheetMutation:
327
+ return mutations.CreateRateSheetMutation.mutate(info, **input.to_dict())
328
+
329
+ @strawberry.mutation
330
+ def update_rate_sheet(
331
+ self, info: Info, input: inputs.UpdateRateSheetMutationInput
332
+ ) -> mutations.UpdateRateSheetMutation:
333
+ return mutations.UpdateRateSheetMutation.mutate(info, **input.to_dict())
334
+
335
+ @strawberry.mutation
336
+ def update_rate_sheet_zone_cell(
337
+ self, info: Info, input: inputs.UpdateRateSheetZoneCellMutationInput
338
+ ) -> mutations.UpdateRateSheetZoneCellMutation:
339
+ return mutations.UpdateRateSheetZoneCellMutation.mutate(info, **input.to_dict())
340
+
341
+ @strawberry.mutation
342
+ def batch_update_rate_sheet_cells(
343
+ self, info: Info, input: inputs.BatchUpdateRateSheetCellsMutationInput
344
+ ) -> mutations.BatchUpdateRateSheetCellsMutation:
345
+ return mutations.BatchUpdateRateSheetCellsMutation.mutate(info, **input.to_dict())
346
+
347
+ @strawberry.mutation
348
+ def delete_rate_sheet_service(
349
+ self, info: Info, input: inputs.DeleteRateSheetServiceMutationInput
350
+ ) -> mutations.DeleteRateSheetServiceMutation:
351
+ return mutations.DeleteRateSheetServiceMutation.mutate(info, **input.to_dict())
352
+
353
+ @strawberry.mutation
354
+ def delete_rate_sheet(
355
+ self, info: Info, input: inputs.DeleteMutationInput
356
+ ) -> mutations.DeleteMutation:
357
+ return mutations.DeleteMutation.mutate(
358
+ info, model=providers.RateSheet, **input.to_dict()
359
+ )
360
+
361
+ @strawberry.mutation
362
+ def create_metafield(
363
+ self, info: Info, input: inputs.CreateMetafieldInput
364
+ ) -> mutations.CreateMetafieldMutation:
365
+ return mutations.CreateMetafieldMutation.mutate(info, **input.to_dict())
366
+
367
+ @strawberry.mutation
368
+ def update_metafield(
369
+ self, info: Info, input: inputs.UpdateMetafieldInput
370
+ ) -> mutations.UpdateMetafieldMutation:
371
+ return mutations.UpdateMetafieldMutation.mutate(info, **input.to_dict())
372
+
373
+ @strawberry.mutation
374
+ def delete_metafield(
375
+ self, info: Info, input: inputs.DeleteMutationInput
376
+ ) -> mutations.DeleteMutation:
377
+ return mutations.DeleteMutation.mutate(
378
+ info, model=core.Metafield, **input.to_dict()
379
+ )
380
+
381
+ @strawberry.mutation
382
+ def update_service_zone(
383
+ self, info: Info, input: inputs.UpdateServiceZoneMutationInput
384
+ ) -> mutations.UpdateServiceZoneMutation:
385
+ return mutations.UpdateServiceZoneMutation.mutate(info, **input.to_dict())