karrio-server-graph 2025.5rc12__py3-none-any.whl → 2025.5rc14__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.
@@ -332,6 +332,24 @@ class Mutation:
332
332
  ) -> mutations.UpdateRateSheetMutation:
333
333
  return mutations.UpdateRateSheetMutation.mutate(info, **input.to_dict())
334
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
+
335
353
  @strawberry.mutation
336
354
  def delete_rate_sheet(
337
355
  self, info: Info, input: inputs.DeleteMutationInput
@@ -516,6 +516,35 @@ class UpdateRateSheetMutationInput(utils.BaseInput):
516
516
  metadata: typing.Optional[utils.JSON] = strawberry.UNSET
517
517
 
518
518
 
519
+ @strawberry.input
520
+ class UpdateRateSheetZoneCellMutationInput(utils.BaseInput):
521
+ id: str # Rate sheet ID
522
+ service_id: str # Service level ID
523
+ zone_id: str # Zone ID
524
+ field: str # Field name to update
525
+ value: utils.JSON # New value
526
+
527
+
528
+ @strawberry.input
529
+ class CellUpdate(utils.BaseInput):
530
+ service_id: str
531
+ zone_id: str
532
+ field: str
533
+ value: utils.JSON
534
+
535
+
536
+ @strawberry.input
537
+ class BatchUpdateRateSheetCellsMutationInput(utils.BaseInput):
538
+ id: str # Rate sheet ID
539
+ updates: typing.List[CellUpdate]
540
+
541
+
542
+ @strawberry.input
543
+ class DeleteRateSheetServiceMutationInput(utils.BaseInput):
544
+ rate_sheet_id: str
545
+ service_id: str
546
+
547
+
519
548
  @strawberry.input
520
549
  class RateSheetFilter(utils.Paginated):
521
550
  keyword: typing.Optional[str] = strawberry.UNSET
@@ -538,8 +538,8 @@ class CreateRateSheetMutation(utils.BaseMutation):
538
538
  carrier_name=rate_sheet.carrier_name,
539
539
  ).filter(id__in=carriers)
540
540
  for _ in _carriers:
541
- _.settings.rate_sheet = rate_sheet
542
- _.settings.save(update_fields=["rate_sheet"])
541
+ _.rate_sheet = rate_sheet
542
+ _.save(update_fields=["rate_sheet"])
543
543
 
544
544
  return CreateRateSheetMutation(rate_sheet=rate_sheet)
545
545
 
@@ -558,9 +558,10 @@ class UpdateRateSheetMutation(utils.BaseMutation):
558
558
  instance = providers.RateSheet.access_by(info.context.request).get(
559
559
  id=input["id"]
560
560
  )
561
+ data = input.copy()
561
562
  serializer = serializers.RateSheetModelSerializer(
562
563
  instance,
563
- data=input,
564
+ data=data,
564
565
  context=info.context.request,
565
566
  partial=True,
566
567
  )
@@ -568,11 +569,136 @@ class UpdateRateSheetMutation(utils.BaseMutation):
568
569
  serializer.is_valid(raise_exception=True)
569
570
  rate_sheet = serializer.save()
570
571
 
572
+ # Handle services updates like in CreateRateSheetMutation
573
+ if "services" in data:
574
+ save_many_to_many_data(
575
+ "services",
576
+ serializers.ServiceLevelModelSerializer,
577
+ rate_sheet,
578
+ payload=data,
579
+ context=info.context.request,
580
+ )
581
+
571
582
  return UpdateRateSheetMutation(
572
583
  rate_sheet=providers.RateSheet.objects.get(id=input["id"])
573
584
  )
574
585
 
575
586
 
587
+ @strawberry.type
588
+ class UpdateRateSheetZoneCellMutation(utils.BaseMutation):
589
+ rate_sheet: typing.Optional[types.RateSheetType] = None
590
+
591
+ @staticmethod
592
+ @transaction.atomic
593
+ @utils.authentication_required
594
+ @utils.authorization_required(["manage_carriers"])
595
+ def mutate(
596
+ info: Info, **input: inputs.UpdateRateSheetZoneCellMutationInput
597
+ ) -> "UpdateRateSheetZoneCellMutation":
598
+ rate_sheet = providers.RateSheet.access_by(info.context.request).get(
599
+ id=input["id"]
600
+ )
601
+ service = rate_sheet.services.get(id=input["service_id"])
602
+
603
+ try:
604
+ service.update_zone_cell(
605
+ zone_id=input["zone_id"], field=input["field"], value=input["value"]
606
+ )
607
+ except ValueError as e:
608
+ logger.error(f"Invalid zone id: {e}")
609
+ raise exceptions.ValidationError({"zone_id": "invalid zone id"})
610
+
611
+ return UpdateRateSheetZoneCellMutation(rate_sheet=rate_sheet)
612
+
613
+
614
+ @strawberry.type
615
+ class BatchUpdateRateSheetCellsMutation(utils.BaseMutation):
616
+ rate_sheet: typing.Optional[types.RateSheetType] = None
617
+
618
+ @staticmethod
619
+ @transaction.atomic
620
+ @utils.authentication_required
621
+ @utils.authorization_required(["manage_carriers"])
622
+ def mutate(
623
+ info: Info, **input: inputs.BatchUpdateRateSheetCellsMutationInput
624
+ ) -> "BatchUpdateRateSheetCellsMutation":
625
+ rate_sheet = providers.RateSheet.access_by(info.context.request).get(
626
+ id=input["id"]
627
+ )
628
+
629
+ # Group updates by service_id for efficient processing
630
+ service_updates = {}
631
+ for update in input["updates"]:
632
+ service_id = update["service_id"]
633
+ if service_id not in service_updates:
634
+ service_updates[service_id] = []
635
+ service_updates[service_id].append(
636
+ {
637
+ "zone_id": update["zone_id"],
638
+ "field": update["field"],
639
+ "value": update["value"],
640
+ }
641
+ )
642
+
643
+ # Use optimized structure if available, otherwise fall back to legacy
644
+ if rate_sheet.zones is not None and rate_sheet.service_rates is not None:
645
+ # Use optimized batch update on rate sheet
646
+ all_updates = []
647
+ for service_id, updates in service_updates.items():
648
+ for update in updates:
649
+ all_updates.append(
650
+ {
651
+ "service_id": service_id,
652
+ "zone_id": update["zone_id"],
653
+ "field": update["field"],
654
+ "value": update["value"],
655
+ }
656
+ )
657
+ try:
658
+ rate_sheet.batch_update_service_rates(all_updates)
659
+ except Exception as e:
660
+ logger.error(f"Invalid zone id: {e}")
661
+ raise exceptions.ValidationError(
662
+ {"rate_sheet": "failed to update rate sheet"}
663
+ )
664
+ else:
665
+ # Fall back to legacy per-service updates
666
+ for service_id, updates in service_updates.items():
667
+ try:
668
+ service = rate_sheet.services.get(id=service_id)
669
+ service.batch_update_cells(updates)
670
+ except ValueError as e:
671
+ logger.error(f"Invalid zone id: {e}")
672
+ raise exceptions.ValidationError(
673
+ {"service_id": "failed to update service"}
674
+ )
675
+
676
+ return BatchUpdateRateSheetCellsMutation(rate_sheet=rate_sheet)
677
+
678
+
679
+ @strawberry.type
680
+ class DeleteRateSheetServiceMutation(utils.BaseMutation):
681
+ rate_sheet: typing.Optional[types.RateSheetType] = None
682
+
683
+ @staticmethod
684
+ @transaction.atomic
685
+ @utils.authentication_required
686
+ @utils.authorization_required(["manage_carriers"])
687
+ def mutate(
688
+ info: Info, **input: inputs.DeleteRateSheetServiceMutationInput
689
+ ) -> "DeleteRateSheetServiceMutation":
690
+ rate_sheet = providers.RateSheet.access_by(info.context.request).get(
691
+ id=input["rate_sheet_id"]
692
+ )
693
+ service = rate_sheet.services.get(id=input["service_id"])
694
+
695
+ # Remove service from rate sheet and delete it
696
+ rate_sheet.services.remove(service)
697
+ service.delete()
698
+
699
+ return DeleteRateSheetServiceMutation(rate_sheet=rate_sheet)
700
+
701
+
576
702
  @strawberry.type
577
703
  class PartialShipmentMutation(utils.BaseMutation):
578
704
  shipment: typing.Optional[types.ShipmentType] = None
@@ -1117,6 +1117,7 @@ class ShipmentType:
1117
1117
  @strawberry.type
1118
1118
  class ServiceZoneType:
1119
1119
  object_type: str
1120
+ id: typing.Optional[str] = None
1120
1121
  label: typing.Optional[str] = None
1121
1122
  rate: typing.Optional[float] = None
1122
1123
 
@@ -1175,7 +1176,8 @@ class ServiceLevelType:
1175
1176
 
1176
1177
  @strawberry.field
1177
1178
  def zones(self: providers.ServiceLevel) -> typing.List[ServiceZoneType]:
1178
- return [ServiceZoneType.parse(zone) for zone in self.zones or []]
1179
+ # Use computed_zones for backward compatibility with optimized structure
1180
+ return [ServiceZoneType.parse(zone) for zone in self.computed_zones]
1179
1181
 
1180
1182
  @strawberry.field
1181
1183
  def metadata(self: providers.RateSheet) -> typing.Optional[utils.JSON]:
@@ -12,6 +12,7 @@ import karrio.server.manager.models as manager
12
12
  import karrio.server.graph.models as graph
13
13
  import karrio.server.core.models as core
14
14
  import karrio.server.user.models as auth
15
+ import karrio.server.core.gateway as gateway
15
16
 
16
17
 
17
18
  class UserModelSerializer(serializers.ModelSerializer):
@@ -268,10 +269,10 @@ class ServiceLevelModelSerializer(serializers.ModelSerializer):
268
269
  )
269
270
  self.instance.save(update_fields=["zones"])
270
271
 
271
- def update(self, instance, validated_data):
272
+ def update(self, instance, validated_data, context=None, **kwargs):
272
273
  """Handle partial updates of service level data including zones."""
273
274
  zones_data = validated_data.pop("zones", None)
274
- instance = super().update(instance, validated_data)
275
+ instance = super().update(instance, validated_data, context=context)
275
276
 
276
277
  if zones_data is not None:
277
278
  # Handle zone updates if provided
@@ -362,10 +363,10 @@ class RateSheetModelSerializer(serializers.ModelSerializer):
362
363
  ).filter(id__in=list(_ids))
363
364
 
364
365
  for carrier in _carriers:
365
- carrier.settings.rate_sheet = (
366
+ carrier.rate_sheet = (
366
367
  self.instance if carrier.id in carriers else None
367
368
  )
368
- carrier.settings.save(update_fields=["rate_sheet"])
369
+ carrier.save(update_fields=["rate_sheet"])
369
370
 
370
371
  def update(self, instance, validated_data, **kwargs):
371
372
  """Handle updates of rate sheet data including services and carriers."""
@@ -305,8 +305,14 @@ UPDATE_RATE_SHEET_RESPONSE = {
305
305
  "services": [
306
306
  {
307
307
  "id": ANY,
308
- "service_name": "UPS Standard",
309
- "zones": [{"label": "Zone 1", "rate": 10.0}],
308
+ "service_name": "Updated Service",
309
+ "zones": [
310
+ {
311
+ "country_codes": ["US", "CA"],
312
+ "label": "Updated Zone",
313
+ "rate": 20.0,
314
+ }
315
+ ],
310
316
  }
311
317
  ],
312
318
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karrio_server_graph
3
- Version: 2025.5rc12
3
+ Version: 2025.5rc14
4
4
  Summary: Multi-carrier shipping API Graph module
5
5
  Author-email: karrio <hello@karrio.io>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ karrio/server/graph/apps.py,sha256=grL5ySDnW2amzj0nTXFm-WCoTWViVYvKqGlsi4k5epI,9
4
4
  karrio/server/graph/forms.py,sha256=5iGC3hj6dsAsupYz4QubyygTeTKDRR56Q5mYq0vbGhI,1962
5
5
  karrio/server/graph/models.py,sha256=CEnE4AsVyjBufyK6ebWmUH3s8DwA0HvZg0fUoZb5Pn4,1321
6
6
  karrio/server/graph/schema.py,sha256=2dXM8nD1usOc1S6QSalajoFmgwYuXxsrwj20AJ5HtT4,1151
7
- karrio/server/graph/serializers.py,sha256=vwP_U59aLnsnYVjwn3jrpz7SxOFzT_vplzSK-2FcsrU,13692
7
+ karrio/server/graph/serializers.py,sha256=kAVpyoN74gkA20ZnmDycvr_yrwFOb_A9di2-vrkdL7U,13760
8
8
  karrio/server/graph/urls.py,sha256=HKo0gkx5TgoWDV0ap2QCtueNTmaAqvX6qVDe3c2UT1E,183
9
9
  karrio/server/graph/utils.py,sha256=eeIKeTfGP-8U6MkdMdTyobnk6wbNEE75Bm0cFu85RfU,9031
10
10
  karrio/server/graph/views.py,sha256=qWfa-wteB-Mb7glAYz6SVlZSwHPw_ImMm7XVmewdmTQ,2889
@@ -15,10 +15,10 @@ 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=aarmPw7csVZCeRxRaU6FNZ6tbN8SOla-nbYqlXFn3lw,14272
19
- karrio/server/graph/schemas/base/inputs.py,sha256=saFN6Sh4lU4_gcmq844Odi4WDBQXaH8Vyk4KcXURUOU,20710
20
- karrio/server/graph/schemas/base/mutations.py,sha256=F42QNh-rOnErprxK9DB_MAxe2q4H4fU1freGW9lVZcw,28859
21
- karrio/server/graph/schemas/base/types.py,sha256=Q0zpVP9ZlmLDmTYtBuZVxlvvmL1uCjirU1aPOu2ulYk,46338
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
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
@@ -28,11 +28,11 @@ karrio/server/graph/tests/base.py,sha256=m3k1CE-d9JHDsqfyXX0Fwksmkel33S7sh9-zkyp
28
28
  karrio/server/graph/tests/test_carrier_connections.py,sha256=PoXxJB53jBIz8j1GYCzTiaTW14Q0D1McdOkDYgcOqNM,6140
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
- karrio/server/graph/tests/test_rate_sheets.py,sha256=iNdN0GR26wv8lZd7slUbHTs1HbasKlMk8gk-A-XRZ5c,10079
31
+ karrio/server/graph/tests/test_rate_sheets.py,sha256=cUzPV8dXQFPFh1r7W8bY6Lou3fjh8f9VGpyZrfbMXec,10300
32
32
  karrio/server/graph/tests/test_templates.py,sha256=WVU6vcfr6tEk917uSn1dECU8bkQtgD7FNuE-GJuFido,21626
33
33
  karrio/server/graph/tests/test_user_info.py,sha256=K91BL7SgxLWflCZriSVI8Vt5M5RIqmSCHKrgN2w8GmM,1928
34
34
  karrio/server/settings/graph.py,sha256=cz2yQHbp3xCfyFKuUkPEFfkI2fFVggExIY49wGz7mt0,106
35
- karrio_server_graph-2025.5rc12.dist-info/METADATA,sha256=vQUivfRKLBanFOj5sLCUrQi96NbfcL9awu5AYsDzb4g,744
36
- karrio_server_graph-2025.5rc12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- karrio_server_graph-2025.5rc12.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
38
- karrio_server_graph-2025.5rc12.dist-info/RECORD,,
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,,