karrio-server-graph 2025.5rc14__py3-none-any.whl → 2025.5rc15__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.
@@ -30,10 +30,10 @@ class Query:
30
30
  resolver=types.SystemUsageType.resolve
31
31
  )
32
32
 
33
- user_connections: typing.List[types.CarrierConnectionType] = strawberry.field(
34
- resolver=types.CarrierConnectionType.resolve_list_legacy
33
+ user_connections: utils.Connection[types.CarrierConnectionType] = strawberry.field(
34
+ resolver=types.CarrierConnectionType.resolve_list
35
35
  )
36
- system_connections: typing.List[types.SystemConnectionType] = strawberry.field(
36
+ system_connections: utils.Connection[types.SystemConnectionType] = strawberry.field(
37
37
  resolver=types.SystemConnectionType.resolve_list
38
38
  )
39
39
 
@@ -31,8 +31,8 @@ class TracingRecordFilter(utils.Paginated):
31
31
  @strawberry.input
32
32
  class TrackerFilter(utils.Paginated):
33
33
  tracking_number: typing.Optional[str] = strawberry.UNSET
34
- created_after: typing.Optional[datetime.datetime] = strawberry.UNSET
35
- created_before: typing.Optional[datetime.datetime] = strawberry.UNSET
34
+ created_after: typing.Optional[str] = strawberry.UNSET
35
+ created_before: typing.Optional[str] = strawberry.UNSET
36
36
  carrier_name: typing.Optional[typing.List[str]] = strawberry.UNSET
37
37
  status: typing.Optional[typing.List[str]] = strawberry.UNSET
38
38
 
@@ -42,8 +42,8 @@ class ShipmentFilter(utils.Paginated):
42
42
  keyword: typing.Optional[str] = strawberry.UNSET
43
43
  address: typing.Optional[str] = strawberry.UNSET
44
44
  id: typing.Optional[typing.List[str]] = strawberry.UNSET
45
- created_after: typing.Optional[datetime.datetime] = strawberry.UNSET
46
- created_before: typing.Optional[datetime.datetime] = strawberry.UNSET
45
+ created_after: typing.Optional[str] = strawberry.UNSET
46
+ created_before: typing.Optional[str] = strawberry.UNSET
47
47
  carrier_name: typing.Optional[typing.List[str]] = strawberry.UNSET
48
48
  reference: typing.Optional[str] = strawberry.UNSET
49
49
  service: typing.Optional[typing.List[str]] = strawberry.UNSET
@@ -260,7 +260,14 @@ class RegisterUserMutation(utils.BaseMutation):
260
260
  )
261
261
 
262
262
  try:
263
- form = user_forms.SignUpForm(input)
263
+ form = user_forms.SignUpForm(data=input)
264
+ if not form.is_valid():
265
+ errors = []
266
+ for field, messages in form.errors.items():
267
+ for message in messages:
268
+ errors.append(f"{field}: {message}")
269
+ raise Exception(". ".join(errors))
270
+
264
271
  user = form.save()
265
272
 
266
273
  return RegisterUserMutation(user=user) # type:ignore
@@ -533,13 +540,12 @@ class CreateRateSheetMutation(utils.BaseMutation):
533
540
  )
534
541
 
535
542
  if any(carriers):
536
- _carriers = gateway.Carriers.list(
537
- context=info.context.request,
538
- carrier_name=rate_sheet.carrier_name,
539
- ).filter(id__in=carriers)
540
- for _ in _carriers:
541
- _.rate_sheet = rate_sheet
542
- _.save(update_fields=["rate_sheet"])
543
+ (
544
+ providers.Carrier.access_by(info.context.request).filter(
545
+ carrier_code=rate_sheet.carrier_name,
546
+ id__in=carriers,
547
+ ).update(rate_sheet=rate_sheet)
548
+ )
543
549
 
544
550
  return CreateRateSheetMutation(rate_sheet=rate_sheet)
545
551
 
@@ -559,6 +565,7 @@ class UpdateRateSheetMutation(utils.BaseMutation):
559
565
  id=input["id"]
560
566
  )
561
567
  data = input.copy()
568
+ carriers = data.pop("carriers", [])
562
569
  serializer = serializers.RateSheetModelSerializer(
563
570
  instance,
564
571
  data=data,
@@ -579,6 +586,24 @@ class UpdateRateSheetMutation(utils.BaseMutation):
579
586
  context=info.context.request,
580
587
  )
581
588
 
589
+ if any(carriers):
590
+ # Link listed carriers to rate sheet
591
+ (
592
+ providers.Carrier.access_by(info.context.request).filter(
593
+ carrier_code=rate_sheet.carrier_name,
594
+ id__in=carriers,
595
+ ).update(rate_sheet=rate_sheet)
596
+ )
597
+ # Unlink missing carriers from rate sheet
598
+ (
599
+ providers.Carrier.access_by(info.context.request).filter(
600
+ carrier_code=rate_sheet.carrier_name,
601
+ rate_sheet=rate_sheet,
602
+ )
603
+ .exclude(id__in=carriers)
604
+ .update(rate_sheet=None)
605
+ )
606
+
582
607
  return UpdateRateSheetMutation(
583
608
  rate_sheet=providers.RateSheet.objects.get(id=input["id"])
584
609
  )
@@ -177,7 +177,16 @@ class WorkspaceConfigType:
177
177
  @staticmethod
178
178
  @utils.authentication_required
179
179
  def resolve(info) -> typing.Optional["WorkspaceConfigType"]:
180
- return auth.WorkspaceConfig.access_by(info.context.request).first()
180
+ workspace_config = auth.WorkspaceConfig.access_by(info.context.request).first()
181
+
182
+ # Create a default workspace config if none exists
183
+ if workspace_config is None:
184
+ workspace_config = auth.WorkspaceConfig.objects.create(
185
+ created_by=info.context.request.user,
186
+ config={}
187
+ )
188
+
189
+ return workspace_config
181
190
 
182
191
 
183
192
  @strawberry.type
@@ -277,7 +286,8 @@ class SystemUsageType:
277
286
  .qs.annotate(date=functions.TruncDay("created_at"))
278
287
  .values("date")
279
288
  .annotate(
280
- count=models.Sum(
289
+ count=models.Count("id"),
290
+ amount=models.Sum(
281
291
  functions.Cast("selected_rate__total_charge", models.FloatField())
282
292
  )
283
293
  )
@@ -301,9 +311,11 @@ class SystemUsageType:
301
311
  total_requests = sum([item["count"] for item in api_requests], 0)
302
312
  total_trackers = sum([item["count"] for item in tracker_count], 0)
303
313
  total_shipments = sum([item["count"] for item in shipment_count], 0)
304
- order_volume = lib.to_money(sum([item["count"] for item in order_volumes], 0.0))
305
- total_shipping_spend = lib.to_money(
306
- sum([item["count"] for item in shipping_spend], 0.0)
314
+ order_volume = lib.to_decimal(
315
+ sum([item["count"] for item in order_volumes if item["count"] is not None], 0.0)
316
+ )
317
+ total_shipping_spend = lib.to_decimal(
318
+ sum([item["amount"] for item in shipping_spend if item["amount"] is not None], 0.0)
307
319
  )
308
320
  user_count = User.objects.count()
309
321
  organization_count = 1
@@ -314,20 +326,20 @@ class SystemUsageType:
314
326
  organization_count = orgs.Organization.objects.count()
315
327
 
316
328
  return SystemUsageType(
329
+ user_count=user_count,
317
330
  order_volume=order_volume,
318
331
  total_errors=total_errors,
319
332
  total_requests=total_requests,
320
333
  total_trackers=total_trackers,
321
334
  total_shipments=total_shipments,
322
335
  organization_count=organization_count,
323
- user_count=user_count,
324
336
  total_shipping_spend=total_shipping_spend,
325
- api_errors=[utils.UsageStatType.parse(item) for item in api_errors],
326
- api_requests=[utils.UsageStatType.parse(item) for item in api_requests],
327
- order_volumes=[utils.UsageStatType.parse(item) for item in order_volumes],
328
- shipment_count=[utils.UsageStatType.parse(item) for item in shipment_count],
329
- shipping_spend=[utils.UsageStatType.parse(item) for item in shipping_spend],
330
- tracker_count=[utils.UsageStatType.parse(item) for item in tracker_count],
337
+ api_errors=[utils.UsageStatType.parse(item, label="api_errors") for item in api_errors],
338
+ api_requests=[utils.UsageStatType.parse(item, label="api_requests") for item in api_requests],
339
+ order_volumes=[utils.UsageStatType.parse(item, label="order_volumes") for item in order_volumes],
340
+ shipment_count=[utils.UsageStatType.parse(item, label="shipment_count") for item in shipment_count],
341
+ shipping_spend=[utils.UsageStatType.parse(item, label="shipping_spend") for item in shipping_spend],
342
+ tracker_count=[utils.UsageStatType.parse(item, label="tracker_count") for item in tracker_count],
331
343
  )
332
344
 
333
345
 
@@ -566,6 +578,7 @@ class ChargeType:
566
578
  name: typing.Optional[str] = None
567
579
  amount: typing.Optional[float] = None
568
580
  currency: utils.CurrencyCodeEnum = None
581
+ id: typing.Optional[str] = None
569
582
 
570
583
  @staticmethod
571
584
  def parse(charge: dict):
@@ -1273,7 +1286,7 @@ class SystemConnectionType:
1273
1286
  def resolve_list(
1274
1287
  info,
1275
1288
  filter: typing.Optional[inputs.CarrierFilter] = strawberry.UNSET,
1276
- ) -> typing.List["SystemConnectionType"]:
1289
+ ) -> utils.Connection["SystemConnectionType"]:
1277
1290
  _filter = filter if not utils.is_unset(filter) else inputs.CarrierFilter()
1278
1291
  connections = filters.CarrierFilters(
1279
1292
  _filter.to_dict(),
@@ -1282,7 +1295,7 @@ class SystemConnectionType:
1282
1295
  test_mode=getattr(info.context.request, "test_mode", False),
1283
1296
  ),
1284
1297
  ).qs
1285
- return connections
1298
+ return utils.paginated_connection(connections, **_filter.pagination())
1286
1299
 
1287
1300
 
1288
1301
  @strawberry.type
@@ -9,11 +9,15 @@ class TestSystemConnections(GraphTestCase):
9
9
  """
10
10
  query get_system_connections {
11
11
  system_connections {
12
- id
13
- carrier_id
14
- carrier_name
15
- test_mode
16
- active
12
+ edges {
13
+ node {
14
+ id
15
+ carrier_id
16
+ carrier_name
17
+ active
18
+ test_mode
19
+ }
20
+ }
17
21
  }
18
22
  }
19
23
  """,
@@ -34,14 +38,18 @@ class TestUserConnections(GraphTestCase):
34
38
  """
35
39
  query get_user_connections {
36
40
  user_connections {
41
+ edges {
42
+ node {
37
43
  id
38
44
  carrier_id
39
45
  carrier_name
40
- test_mode
41
46
  active
47
+ test_mode
42
48
  credentials
49
+ }
43
50
  }
44
51
  }
52
+ }
45
53
  """,
46
54
  operation_name="get_user_connections",
47
55
  )
@@ -62,8 +70,8 @@ class TestUserConnections(GraphTestCase):
62
70
  id
63
71
  carrier_id
64
72
  carrier_name
65
- test_mode
66
73
  active
74
+ test_mode
67
75
  credentials
68
76
  }
69
77
  }
@@ -108,54 +116,66 @@ class TestUserConnections(GraphTestCase):
108
116
 
109
117
  SYSTEM_CONNECTIONS = {
110
118
  "data": {
111
- "system_connections": [
112
- {
113
- "active": True,
114
- "carrier_id": "dhl_universal",
115
- "carrier_name": "dhl_universal",
116
- "id": ANY,
117
- "test_mode": False,
118
- },
119
- {
120
- "active": True,
121
- "carrier_id": "fedex_express",
122
- "carrier_name": "fedex",
123
- "id": ANY,
124
- "test_mode": False,
125
- },
126
- ]
119
+ "system_connections": {
120
+ "edges": [
121
+ {
122
+ "node": {
123
+ "active": True,
124
+ "carrier_id": "dhl_universal",
125
+ "carrier_name": "dhl_universal",
126
+ "id": ANY,
127
+ "test_mode": False,
128
+ }
129
+ },
130
+ {
131
+ "node": {
132
+ "active": True,
133
+ "carrier_id": "fedex_express",
134
+ "carrier_name": "fedex",
135
+ "id": ANY,
136
+ "test_mode": False,
137
+ }
138
+ },
139
+ ]
140
+ }
127
141
  }
128
142
  }
129
143
 
130
144
  USER_CONNECTIONS = {
131
145
  "data": {
132
- "user_connections": [
133
- {
134
- "active": True,
135
- "carrier_id": "ups_package",
136
- "carrier_name": "ups",
137
- "credentials": {
138
- "account_number": "000000",
139
- "client_id": "test",
140
- "client_secret": "test",
146
+ "user_connections": {
147
+ "edges": [
148
+ {
149
+ "node": {
150
+ "active": True,
151
+ "carrier_id": "ups_package",
152
+ "carrier_name": "ups",
153
+ "credentials": {
154
+ "account_number": "000000",
155
+ "client_id": "test",
156
+ "client_secret": "test",
157
+ },
158
+ "id": ANY,
159
+ "test_mode": False,
160
+ }
141
161
  },
142
- "id": ANY,
143
- "test_mode": False,
144
- },
145
- {
146
- "active": True,
147
- "carrier_id": "canadapost",
148
- "carrier_name": "canadapost",
149
- "credentials": {
150
- "contract_id": "42708517",
151
- "customer_number": "2004381",
152
- "password": "0bfa9fcb9853d1f51ee57a",
153
- "username": "6e93d53968881714",
162
+ {
163
+ "node": {
164
+ "active": True,
165
+ "carrier_id": "canadapost",
166
+ "carrier_name": "canadapost",
167
+ "credentials": {
168
+ "contract_id": "42708517",
169
+ "customer_number": "2004381",
170
+ "password": "0bfa9fcb9853d1f51ee57a",
171
+ "username": "6e93d53968881714",
172
+ },
173
+ "id": ANY,
174
+ "test_mode": False,
175
+ }
154
176
  },
155
- "id": ANY,
156
- "test_mode": False,
157
- },
158
- ]
177
+ ]
178
+ }
159
179
  }
160
180
  }
161
181
 
@@ -0,0 +1,205 @@
1
+ from unittest.mock import patch, MagicMock
2
+ from karrio.server.graph.tests.base import GraphTestCase
3
+ from django.contrib.auth import get_user_model
4
+
5
+ User = get_user_model()
6
+
7
+
8
+ class TestUserRegistration(GraphTestCase):
9
+
10
+ @patch('karrio.server.conf.settings.ALLOW_SIGNUP', True)
11
+ @patch('karrio.server.conf.settings.EMAIL_ENABLED', False)
12
+ def test_register_user_mutation(self):
13
+ """Test successful user registration"""
14
+ # Ensure user doesn't exist
15
+ User.objects.filter(email="newuser@example.com").delete()
16
+
17
+ response = self.query(
18
+ """
19
+ mutation register_user($data: RegisterUserMutationInput!) {
20
+ register_user(input: $data) {
21
+ user {
22
+ email
23
+ full_name
24
+ is_active
25
+ }
26
+ }
27
+ }
28
+ """,
29
+ operation_name="register_user",
30
+ variables={
31
+ "data": {
32
+ "email": "newuser@example.com",
33
+ "full_name": "New Test User",
34
+ "password1": "TestPassword123!",
35
+ "password2": "TestPassword123!",
36
+ "redirect_url": "http://localhost:3000/email"
37
+ }
38
+ }
39
+ )
40
+
41
+ self.assertResponseNoErrors(response)
42
+ self.assertIsNotNone(response.data['data']['register_user']['user'])
43
+ self.assertEqual(response.data['data']['register_user']['user']['email'], "newuser@example.com")
44
+ self.assertEqual(response.data['data']['register_user']['user']['full_name'], "New Test User")
45
+
46
+ # Verify user was created in database
47
+ user = User.objects.get(email="newuser@example.com")
48
+ self.assertEqual(user.full_name, "New Test User")
49
+
50
+ @patch('karrio.server.conf.settings.ALLOW_SIGNUP', True)
51
+ def test_register_user_password_mismatch(self):
52
+ """Test registration fails with mismatched passwords"""
53
+ response = self.query(
54
+ """
55
+ mutation register_user($data: RegisterUserMutationInput!) {
56
+ register_user(input: $data) {
57
+ user {
58
+ email
59
+ }
60
+ }
61
+ }
62
+ """,
63
+ operation_name="register_user",
64
+ variables={
65
+ "data": {
66
+ "email": "mismatch@example.com",
67
+ "full_name": "Mismatch User",
68
+ "password1": "TestPassword123!",
69
+ "password2": "DifferentPassword123!",
70
+ "redirect_url": "http://localhost:3000/email"
71
+ }
72
+ }
73
+ )
74
+
75
+ # Should have errors
76
+ self.assertIsNotNone(response.data.get('errors'))
77
+ self.assertIn("password", str(response.data['errors'][0]))
78
+
79
+ @patch('karrio.server.conf.settings.ALLOW_SIGNUP', True)
80
+ def test_register_user_duplicate_email(self):
81
+ """Test registration fails with duplicate email"""
82
+ # First create a user
83
+ User.objects.create_user(
84
+ email="existing@example.com",
85
+ password="ExistingPass123!",
86
+ full_name="Existing User"
87
+ )
88
+
89
+ response = self.query(
90
+ """
91
+ mutation register_user($data: RegisterUserMutationInput!) {
92
+ register_user(input: $data) {
93
+ user {
94
+ email
95
+ }
96
+ }
97
+ }
98
+ """,
99
+ operation_name="register_user",
100
+ variables={
101
+ "data": {
102
+ "email": "existing@example.com",
103
+ "full_name": "Duplicate User",
104
+ "password1": "TestPassword123!",
105
+ "password2": "TestPassword123!",
106
+ "redirect_url": "http://localhost:3000/email"
107
+ }
108
+ }
109
+ )
110
+
111
+ # Should have errors about duplicate email
112
+ self.assertIsNotNone(response.data.get('errors'))
113
+
114
+ @patch('karrio.server.conf.settings.ALLOW_SIGNUP', False)
115
+ def test_register_user_signup_disabled(self):
116
+ """Test registration fails when signup is disabled"""
117
+ response = self.query(
118
+ """
119
+ mutation register_user($data: RegisterUserMutationInput!) {
120
+ register_user(input: $data) {
121
+ user {
122
+ email
123
+ }
124
+ }
125
+ }
126
+ """,
127
+ operation_name="register_user",
128
+ variables={
129
+ "data": {
130
+ "email": "disabled@example.com",
131
+ "full_name": "Disabled User",
132
+ "password1": "TestPassword123!",
133
+ "password2": "TestPassword123!",
134
+ "redirect_url": "http://localhost:3000/email"
135
+ }
136
+ }
137
+ )
138
+
139
+ # Should have errors about signup not allowed
140
+ self.assertIsNotNone(response.data.get('errors'))
141
+ self.assertIn("Signup is not allowed", str(response.data['errors'][0]))
142
+
143
+
144
+ class TestPasswordReset(GraphTestCase):
145
+
146
+ def setUp(self):
147
+ super().setUp()
148
+ # Create a test user for password reset
149
+ self.reset_user = User.objects.create_user(
150
+ email="resetuser@example.com",
151
+ password="OldPassword123!",
152
+ full_name="Reset User"
153
+ )
154
+
155
+ @patch('django.core.mail.send_mail')
156
+ def test_request_password_reset(self, mock_send_mail):
157
+ """Test requesting a password reset"""
158
+ response = self.query(
159
+ """
160
+ mutation request_password_reset($data: RequestPasswordResetMutationInput!) {
161
+ request_password_reset(input: $data) {
162
+ email
163
+ redirect_url
164
+ }
165
+ }
166
+ """,
167
+ operation_name="request_password_reset",
168
+ variables={
169
+ "data": {
170
+ "email": "resetuser@example.com",
171
+ "redirect_url": "http://localhost:3000/password/reset"
172
+ }
173
+ }
174
+ )
175
+
176
+ self.assertResponseNoErrors(response)
177
+ self.assertEqual(response.data['data']['request_password_reset']['email'], "resetuser@example.com")
178
+
179
+
180
+ class TestEmailConfirmation(GraphTestCase):
181
+
182
+ @patch('karrio.server.graph.schemas.base.mutations.email_verification.verify_token')
183
+ def test_confirm_email(self, mock_verify):
184
+ """Test email confirmation"""
185
+ mock_verify.return_value = (True, None)
186
+
187
+ response = self.query(
188
+ """
189
+ mutation confirm_email($data: ConfirmEmailMutationInput!) {
190
+ confirm_email(input: $data) {
191
+ success
192
+ }
193
+ }
194
+ """,
195
+ operation_name="confirm_email",
196
+ variables={
197
+ "data": {
198
+ "token": "test-confirmation-token"
199
+ }
200
+ }
201
+ )
202
+
203
+ self.assertResponseNoErrors(response)
204
+ self.assertTrue(response.data['data']['confirm_email']['success'])
205
+ mock_verify.assert_called_once_with("test-confirmation-token")
@@ -179,12 +179,16 @@ class UsageStatType:
179
179
  date: typing.Optional[str] = None
180
180
  label: typing.Optional[str] = None
181
181
  count: typing.Optional[float] = None
182
+ amount: typing.Optional[float] = None
183
+ currency: typing.Optional[str] = None
182
184
 
183
185
  @staticmethod
184
- def parse(value: dict) -> "UsageStatType":
185
- return UsageStatType(
186
- **{k: v for k, v in value.items() if k in UsageStatType.__annotations__}
187
- )
186
+ def parse(value: dict, label: str = None) -> "UsageStatType":
187
+ return UsageStatType(**{
188
+ **(dict(label=label) if label else {}),
189
+ **{k: v for k, v in value.items() if k in UsageStatType.__annotations__},
190
+ "amount": lib.to_decimal(value.get("amount")),
191
+ })
188
192
 
189
193
 
190
194
  @strawberry.input
@@ -192,6 +196,7 @@ class UsageFilter(BaseInput):
192
196
  date_after: typing.Optional[str] = strawberry.UNSET
193
197
  date_before: typing.Optional[str] = strawberry.UNSET
194
198
  omit: typing.Optional[typing.List[str]] = strawberry.UNSET
199
+ surcharge_id: typing.Optional[str] = strawberry.UNSET
195
200
 
196
201
 
197
202
  @dataclasses.dataclass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karrio_server_graph
3
- Version: 2025.5rc14
3
+ Version: 2025.5rc15
4
4
  Summary: Multi-carrier shipping API Graph module
5
5
  Author-email: karrio <hello@karrio.io>
6
6
  License-Expression: Apache-2.0
@@ -6,7 +6,7 @@ karrio/server/graph/models.py,sha256=CEnE4AsVyjBufyK6ebWmUH3s8DwA0HvZg0fUoZb5Pn4
6
6
  karrio/server/graph/schema.py,sha256=2dXM8nD1usOc1S6QSalajoFmgwYuXxsrwj20AJ5HtT4,1151
7
7
  karrio/server/graph/serializers.py,sha256=kAVpyoN74gkA20ZnmDycvr_yrwFOb_A9di2-vrkdL7U,13760
8
8
  karrio/server/graph/urls.py,sha256=HKo0gkx5TgoWDV0ap2QCtueNTmaAqvX6qVDe3c2UT1E,183
9
- karrio/server/graph/utils.py,sha256=eeIKeTfGP-8U6MkdMdTyobnk6wbNEE75Bm0cFu85RfU,9031
9
+ karrio/server/graph/utils.py,sha256=kfg8y8IBOilHobb1cf4tB59VwZr3vPgB0SeSelLim_M,9308
10
10
  karrio/server/graph/views.py,sha256=qWfa-wteB-Mb7glAYz6SVlZSwHPw_ImMm7XVmewdmTQ,2889
11
11
  karrio/server/graph/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  karrio/server/graph/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -15,24 +15,25 @@ karrio/server/graph/migrations/0001_initial.py,sha256=oeaS5JSkQP6w9ulYar3mdn695y
15
15
  karrio/server/graph/migrations/0002_auto_20210512_1353.py,sha256=TnUwR9EP0qp3gJ38f9w0PYawK2VheDtqXEgyRhYZS2M,538
16
16
  karrio/server/graph/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  karrio/server/graph/schemas/__init__.py,sha256=Kn-I1j3HP3jwZccpz6FL9r1k6b3UEAMVh2kFPCKNS0w,80
18
- karrio/server/graph/schemas/base/__init__.py,sha256=J6pf4SzfAtQ4yaNapEuHuoyOA0-UGhueqDD3n0JzTb0,15118
19
- karrio/server/graph/schemas/base/inputs.py,sha256=T1T7cNVGudgVGOkPnus6TfK_i-lT_cjOBlpaPTHummk,21363
20
- karrio/server/graph/schemas/base/mutations.py,sha256=1S-aUpoKwwDslLtbReJb_5kx9tDr3-EfAhQQ9D7-6K0,33583
21
- karrio/server/graph/schemas/base/types.py,sha256=lKC-mdLluLNaPn9DXQDxh7Vl8JT9b_s_CIqZkiO0NWo,46458
18
+ karrio/server/graph/schemas/base/__init__.py,sha256=nnOfynQW842qOA0qD6bYz8GSHQCQeBW36vbq0sqRkJs,15121
19
+ karrio/server/graph/schemas/base/inputs.py,sha256=i6_PN-WD1mu_qH-2oIgfDUbgMRyUZmdr6gyySwyEShg,21307
20
+ karrio/server/graph/schemas/base/mutations.py,sha256=IUe7rvV4bI95iJ-pEg3YK9Qb0PVM9xgd0IvjOwDPvsM,34538
21
+ karrio/server/graph/schemas/base/types.py,sha256=TGgvJdvtrsUDIoXZuab3-_XWqBzBWxZq-xm-j9DfPzo,47120
22
22
  karrio/server/graph/templates/graphql/graphiql.html,sha256=MQjQbBqoRE0QLsOUck8SaXo6B2oJO8dT6YZzUqbDan0,3786
23
23
  karrio/server/graph/templates/karrio/email_change_email.html,sha256=YHqTy9VGV_s7kio57Tg3v7TCIN3QlnPHi2ioTOcHJLE,467
24
24
  karrio/server/graph/templates/karrio/email_change_email.txt,sha256=NXXuzLR63hn2F1fVAjzmuguptuuTvujwqI7YLSrQoio,431
25
25
  karrio/server/graph/templates/karrio/password_reset_email.html,sha256=dttqYVL73cQNuTFsVdn2GV4Ckee8PTY8oEF53GbDRcg,553
26
26
  karrio/server/graph/tests/__init__.py,sha256=dPzsYY5hoO5gmY6fhL8tiz7Bfst8RB3JzsBVHZazHRE,338
27
27
  karrio/server/graph/tests/base.py,sha256=m3k1CE-d9JHDsqfyXX0Fwksmkel33S7sh9-zkypp8wc,4004
28
- karrio/server/graph/tests/test_carrier_connections.py,sha256=PoXxJB53jBIz8j1GYCzTiaTW14Q0D1McdOkDYgcOqNM,6140
28
+ karrio/server/graph/tests/test_carrier_connections.py,sha256=qZ1OL8CgZrHuluKJd7cjFXaRZ0VpogN5Srjk2EApLWU,6892
29
29
  karrio/server/graph/tests/test_metafield.py,sha256=K7Oon0CLEm_MUMbmcu0t2iAZvFN8Wl7Kp4QAWeUXo_Y,12783
30
30
  karrio/server/graph/tests/test_partial_shipments.py,sha256=dPIdIq4wiyovOaIIzbIX69eZnBqCA4ZvBSiGKYADM2g,19031
31
31
  karrio/server/graph/tests/test_rate_sheets.py,sha256=cUzPV8dXQFPFh1r7W8bY6Lou3fjh8f9VGpyZrfbMXec,10300
32
+ karrio/server/graph/tests/test_registration.py,sha256=jK8ZCmhtvKZ9L3yqSIK1-JXzYT2PWwxQ3Md1_ff9818,7192
32
33
  karrio/server/graph/tests/test_templates.py,sha256=WVU6vcfr6tEk917uSn1dECU8bkQtgD7FNuE-GJuFido,21626
33
34
  karrio/server/graph/tests/test_user_info.py,sha256=K91BL7SgxLWflCZriSVI8Vt5M5RIqmSCHKrgN2w8GmM,1928
34
35
  karrio/server/settings/graph.py,sha256=cz2yQHbp3xCfyFKuUkPEFfkI2fFVggExIY49wGz7mt0,106
35
- karrio_server_graph-2025.5rc14.dist-info/METADATA,sha256=BPbJEWnbbNoCiAE-LLe8mFhLc7bGQ4Ci1YtR9EetHe8,744
36
- karrio_server_graph-2025.5rc14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- karrio_server_graph-2025.5rc14.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
38
- karrio_server_graph-2025.5rc14.dist-info/RECORD,,
36
+ karrio_server_graph-2025.5rc15.dist-info/METADATA,sha256=YT3yl8qMK24AoSodvtliaYbRcesRKHpelootMSaTI8I,744
37
+ karrio_server_graph-2025.5rc15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ karrio_server_graph-2025.5rc15.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
39
+ karrio_server_graph-2025.5rc15.dist-info/RECORD,,