karrio-server-core 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.

Potentially problematic release.


This version of karrio-server-core might be problematic. Click here for more details.

Files changed (241) hide show
  1. karrio/server/conf.py +54 -0
  2. karrio/server/core/__init__.py +3 -0
  3. karrio/server/core/admin.py +1 -0
  4. karrio/server/core/apps.py +10 -0
  5. karrio/server/core/authentication.py +313 -0
  6. karrio/server/core/context_processors.py +12 -0
  7. karrio/server/core/datatypes.py +369 -0
  8. karrio/server/core/dataunits.py +156 -0
  9. karrio/server/core/exceptions.py +200 -0
  10. karrio/server/core/fields.py +12 -0
  11. karrio/server/core/filters.py +823 -0
  12. karrio/server/core/gateway.py +720 -0
  13. karrio/server/core/management/commands/cli.py +19 -0
  14. karrio/server/core/management/commands/create_oauth_client.py +41 -0
  15. karrio/server/core/middleware.py +95 -0
  16. karrio/server/core/migrations/0001_initial.py +28 -0
  17. karrio/server/core/migrations/0002_apilogindex.py +69 -0
  18. karrio/server/core/migrations/0003_apilogindex_test_mode.py +62 -0
  19. karrio/server/core/migrations/0004_metafield.py +74 -0
  20. karrio/server/core/migrations/0005_alter_metafield_type_alter_metafield_value.py +23 -0
  21. karrio/server/core/migrations/__init__.py +0 -0
  22. karrio/server/core/models/__init__.py +48 -0
  23. karrio/server/core/models/base.py +70 -0
  24. karrio/server/core/models/entity.py +22 -0
  25. karrio/server/core/models/metafield.py +144 -0
  26. karrio/server/core/models/third_party.py +21 -0
  27. karrio/server/core/oauth_validators.py +171 -0
  28. karrio/server/core/permissions.py +37 -0
  29. karrio/server/core/renderers.py +11 -0
  30. karrio/server/core/router.py +3 -0
  31. karrio/server/core/serializers.py +1898 -0
  32. karrio/server/core/signals.py +57 -0
  33. karrio/server/core/tests.py +98 -0
  34. karrio/server/core/urls.py +12 -0
  35. karrio/server/core/utils.py +479 -0
  36. karrio/server/core/validators.py +416 -0
  37. karrio/server/core/views/__init__.py +2 -0
  38. karrio/server/core/views/api.py +133 -0
  39. karrio/server/core/views/metadata.py +44 -0
  40. karrio/server/core/views/oauth.py +74 -0
  41. karrio/server/core/views/references.py +82 -0
  42. karrio/server/core/views/schema.py +310 -0
  43. karrio/server/filters/__init__.py +2 -0
  44. karrio/server/filters/abstract.py +26 -0
  45. karrio/server/iam/__init__.py +0 -0
  46. karrio/server/iam/admin.py +3 -0
  47. karrio/server/iam/apps.py +21 -0
  48. karrio/server/iam/migrations/0001_initial.py +33 -0
  49. karrio/server/iam/migrations/__init__.py +0 -0
  50. karrio/server/iam/models.py +48 -0
  51. karrio/server/iam/permissions.py +134 -0
  52. karrio/server/iam/serializers.py +39 -0
  53. karrio/server/iam/signals.py +20 -0
  54. karrio/server/iam/tests.py +3 -0
  55. karrio/server/iam/views.py +3 -0
  56. karrio/server/openapi.py +75 -0
  57. karrio/server/providers/__init__.py +1 -0
  58. karrio/server/providers/admin.py +364 -0
  59. karrio/server/providers/apps.py +10 -0
  60. karrio/server/providers/extension/__init__.py +1 -0
  61. karrio/server/providers/extension/models/__init__.py +1 -0
  62. karrio/server/providers/extension/models/allied_express.py +22 -0
  63. karrio/server/providers/extension/models/allied_express_local.py +22 -0
  64. karrio/server/providers/extension/models/amazon_shipping.py +27 -0
  65. karrio/server/providers/extension/models/aramex.py +25 -0
  66. karrio/server/providers/extension/models/asendia_us.py +21 -0
  67. karrio/server/providers/extension/models/australiapost.py +20 -0
  68. karrio/server/providers/extension/models/boxknight.py +19 -0
  69. karrio/server/providers/extension/models/bpost.py +21 -0
  70. karrio/server/providers/extension/models/canadapost.py +21 -0
  71. karrio/server/providers/extension/models/canpar.py +19 -0
  72. karrio/server/providers/extension/models/chronopost.py +22 -0
  73. karrio/server/providers/extension/models/colissimo.py +22 -0
  74. karrio/server/providers/extension/models/dhl_express.py +23 -0
  75. karrio/server/providers/extension/models/dhl_parcel_de.py +25 -0
  76. karrio/server/providers/extension/models/dhl_poland.py +22 -0
  77. karrio/server/providers/extension/models/dhl_universal.py +19 -0
  78. karrio/server/providers/extension/models/dicom.py +20 -0
  79. karrio/server/providers/extension/models/dpd.py +37 -0
  80. karrio/server/providers/extension/models/dpdhl.py +26 -0
  81. karrio/server/providers/extension/models/easypost.py +20 -0
  82. karrio/server/providers/extension/models/eshipper.py +21 -0
  83. karrio/server/providers/extension/models/fedex.py +25 -0
  84. karrio/server/providers/extension/models/fedex_ws.py +24 -0
  85. karrio/server/providers/extension/models/freightcom.py +21 -0
  86. karrio/server/providers/extension/models/generic.py +35 -0
  87. karrio/server/providers/extension/models/geodis.py +22 -0
  88. karrio/server/providers/extension/models/hay_post.py +22 -0
  89. karrio/server/providers/extension/models/laposte.py +19 -0
  90. karrio/server/providers/extension/models/locate2u.py +22 -0
  91. karrio/server/providers/extension/models/nationex.py +22 -0
  92. karrio/server/providers/extension/models/purolator.py +21 -0
  93. karrio/server/providers/extension/models/roadie.py +18 -0
  94. karrio/server/providers/extension/models/royalmail.py +19 -0
  95. karrio/server/providers/extension/models/sendle.py +22 -0
  96. karrio/server/providers/extension/models/tge.py +63 -0
  97. karrio/server/providers/extension/models/tnt.py +23 -0
  98. karrio/server/providers/extension/models/ups.py +23 -0
  99. karrio/server/providers/extension/models/usps.py +23 -0
  100. karrio/server/providers/extension/models/usps_international.py +23 -0
  101. karrio/server/providers/extension/models/usps_wt.py +24 -0
  102. karrio/server/providers/extension/models/usps_wt_international.py +24 -0
  103. karrio/server/providers/extension/models/zoom2u.py +23 -0
  104. karrio/server/providers/migrations/0001_initial.py +140 -0
  105. karrio/server/providers/migrations/0002_carrier_active.py +18 -0
  106. karrio/server/providers/migrations/0003_auto_20201230_0820.py +24 -0
  107. karrio/server/providers/migrations/0004_auto_20210212_0554.py +178 -0
  108. karrio/server/providers/migrations/0005_auto_20210212_0555.py +18 -0
  109. karrio/server/providers/migrations/0006_australiapostsettings.py +29 -0
  110. karrio/server/providers/migrations/0007_auto_20210213_0206.py +21 -0
  111. karrio/server/providers/migrations/0008_auto_20210214_0409.py +30 -0
  112. karrio/server/providers/migrations/0009_auto_20210308_0302.py +18 -0
  113. karrio/server/providers/migrations/0010_auto_20210409_0852.py +32 -0
  114. karrio/server/providers/migrations/0011_auto_20210409_0853.py +21 -0
  115. karrio/server/providers/migrations/0012_alter_carrier_options.py +17 -0
  116. karrio/server/providers/migrations/0013_tntsettings.py +30 -0
  117. karrio/server/providers/migrations/0014_auto_20210612_1608.py +46 -0
  118. karrio/server/providers/migrations/0015_auto_20210615_1601.py +28 -0
  119. karrio/server/providers/migrations/0016_alter_purolatorsettings_user_token.py +18 -0
  120. karrio/server/providers/migrations/0017_auto_20210805_0359.py +1293 -0
  121. karrio/server/providers/migrations/0018_alter_fedexsettings_user_key.py +18 -0
  122. karrio/server/providers/migrations/0019_dhlpolandsettings_servicelevel.py +65 -0
  123. karrio/server/providers/migrations/0020_genericsettings_labeltemplate.py +52 -0
  124. karrio/server/providers/migrations/0021_auto_20211231_2353.py +40 -0
  125. karrio/server/providers/migrations/0022_carrier_metadata.py +18 -0
  126. karrio/server/providers/migrations/0023_auto_20220124_1916.py +27 -0
  127. karrio/server/providers/migrations/0024_alter_genericsettings_custom_carrier_name.py +19 -0
  128. karrio/server/providers/migrations/0025_alter_servicelevel_service_code.py +19 -0
  129. karrio/server/providers/migrations/0026_auto_20220208_0132.py +59 -0
  130. karrio/server/providers/migrations/0027_auto_20220304_1340.py +29 -0
  131. karrio/server/providers/migrations/0028_auto_20220323_1500.py +33 -0
  132. karrio/server/providers/migrations/0029_easypostsettings.py +27 -0
  133. karrio/server/providers/migrations/0030_amazonmwssettings.py +29 -0
  134. karrio/server/providers/migrations/0031_delete_amazonmwssettings.py +18 -0
  135. karrio/server/providers/migrations/0032_alter_carrier_test.py +18 -0
  136. karrio/server/providers/migrations/0033_auto_20220708_1350.py +22 -0
  137. karrio/server/providers/migrations/0034_amazonmwssettings_dpdhlsettings.py +47 -0
  138. karrio/server/providers/migrations/0035_alter_carrier_capabilities.py +43 -0
  139. karrio/server/providers/migrations/0036_upsfreightsettings.py +31 -0
  140. karrio/server/providers/migrations/0037_chronopostsettings.py +29 -0
  141. karrio/server/providers/migrations/0038_alter_genericsettings_label_template.py +19 -0
  142. karrio/server/providers/migrations/0039_auto_20220906_0612.py +23 -0
  143. karrio/server/providers/migrations/0040_dpdhlsettings_services.py +18 -0
  144. karrio/server/providers/migrations/0041_auto_20221105_0705.py +38 -0
  145. karrio/server/providers/migrations/0042_auto_20221215_1642.py +23 -0
  146. karrio/server/providers/migrations/0043_alter_genericsettings_account_number_and_more.py +39 -0
  147. karrio/server/providers/migrations/0044_carrier_carrier_capabilities.py +64 -0
  148. karrio/server/providers/migrations/0045_alter_carrier_active_alter_carrier_carrier_id.py +31 -0
  149. karrio/server/providers/migrations/0046_remove_dpdhlsettings_signature_and_more.py +41 -0
  150. karrio/server/providers/migrations/0047_dpdsettings.py +286 -0
  151. karrio/server/providers/migrations/0048_servicelevel_min_weight_servicelevel_transit_days_and_more.py +64 -0
  152. karrio/server/providers/migrations/0049_boxknightsettings_geodissettings_lapostesettings_and_more.py +156 -0
  153. karrio/server/providers/migrations/0050_carrier_is_system_alter_carrier_metadata_and_more.py +106 -0
  154. karrio/server/providers/migrations/0051_rename_username_upssettings_client_id_and_more.py +31 -0
  155. karrio/server/providers/migrations/0052_alter_upssettings_account_number_and_more.py +20 -0
  156. karrio/server/providers/migrations/0053_locate2usettings.py +281 -0
  157. karrio/server/providers/migrations/0054_zoom2usettings.py +280 -0
  158. karrio/server/providers/migrations/0055_rename_amazonmwssettings_amazonshippingsettings_and_more.py +44 -0
  159. karrio/server/providers/migrations/0056_asendiaussettings_geodissettings_code_client_and_more.py +75 -0
  160. karrio/server/providers/migrations/0057_alter_servicelevel_weight_unit_belgianpostsettings.py +51 -0
  161. karrio/server/providers/migrations/0058_alliedexpresssettings.py +38 -0
  162. karrio/server/providers/migrations/0059_ratesheet.py +81 -0
  163. karrio/server/providers/migrations/0060_belgianpostsettings_rate_sheet_and_more.py +73 -0
  164. karrio/server/providers/migrations/0061_alliedexpresssettings_service_type.py +17 -0
  165. karrio/server/providers/migrations/0062_sendlesettings_account_country_code.py +257 -0
  166. karrio/server/providers/migrations/0063_servicelevel_metadata.py +25 -0
  167. karrio/server/providers/migrations/0064_alliedexpresslocalsettings.py +43 -0
  168. karrio/server/providers/migrations/0065_servicelevel_carrier_service_code_and_more.py +66 -0
  169. karrio/server/providers/migrations/0066_rename_fedexsettings_fedexwssettings_and_more.py +28 -0
  170. karrio/server/providers/migrations/0067_fedexsettings.py +283 -0
  171. karrio/server/providers/migrations/0068_fedexsettings_track_api_key_and_more.py +38 -0
  172. karrio/server/providers/migrations/0069_alter_canadapostsettings_contract_id_and_more.py +23 -0
  173. karrio/server/providers/migrations/0070_tgesettings_alter_carrier_capabilities.py +65 -0
  174. karrio/server/providers/migrations/0071_alter_tgesettings_my_toll_token.py +18 -0
  175. karrio/server/providers/migrations/0072_rename_eshippersettings_eshipperxmlsettings_and_more.py +28 -0
  176. karrio/server/providers/migrations/0073_delete_eshipperxmlsettings.py +41 -0
  177. karrio/server/providers/migrations/0074_eshippersettings.py +38 -0
  178. karrio/server/providers/migrations/0075_haypostsettings.py +40 -0
  179. karrio/server/providers/migrations/0076_rename_customer_registration_id_uspsinternationalsettings_account_number_and_more.py +125 -0
  180. karrio/server/providers/migrations/0077_uspswtinternationalsettings_uspswtsettings_and_more.py +165 -0
  181. karrio/server/providers/migrations/0078_auto_20240813_1552.py +120 -0
  182. karrio/server/providers/migrations/0079_alter_carrier_options_alter_ratesheet_created_by.py +31 -0
  183. karrio/server/providers/migrations/0080_alter_aramexsettings_account_country_code_and_more.py +3025 -0
  184. karrio/server/providers/migrations/0081_remove_alliedexpresssettings_carrier_ptr_and_more.py +338 -0
  185. karrio/server/providers/migrations/__init__.py +0 -0
  186. karrio/server/providers/models/__init__.py +17 -0
  187. karrio/server/providers/models/carrier.py +309 -0
  188. karrio/server/providers/models/config.py +30 -0
  189. karrio/server/providers/models/service.py +62 -0
  190. karrio/server/providers/models/sheet.py +60 -0
  191. karrio/server/providers/models/template.py +39 -0
  192. karrio/server/providers/models/utils.py +58 -0
  193. karrio/server/providers/router.py +3 -0
  194. karrio/server/providers/serializers/__init__.py +3 -0
  195. karrio/server/providers/serializers/base.py +277 -0
  196. karrio/server/providers/signals.py +27 -0
  197. karrio/server/providers/tests.py +3 -0
  198. karrio/server/providers/urls.py +11 -0
  199. karrio/server/providers/views/__init__.py +0 -0
  200. karrio/server/providers/views/carriers.py +269 -0
  201. karrio/server/providers/views/connections.py +176 -0
  202. karrio/server/samples.py +352 -0
  203. karrio/server/serializers/__init__.py +2 -0
  204. karrio/server/serializers/abstract.py +506 -0
  205. karrio/server/tracing/__init__.py +0 -0
  206. karrio/server/tracing/admin.py +63 -0
  207. karrio/server/tracing/apps.py +8 -0
  208. karrio/server/tracing/migrations/0001_initial.py +41 -0
  209. karrio/server/tracing/migrations/0002_auto_20220710_1307.py +22 -0
  210. karrio/server/tracing/migrations/0003_auto_20221105_0317.py +43 -0
  211. karrio/server/tracing/migrations/0004_tracingrecord_carrier_account_idx.py +24 -0
  212. karrio/server/tracing/migrations/0005_optimise_tracingrecord_request_log_idx.py +25 -0
  213. karrio/server/tracing/migrations/0006_alter_tracingrecord_options_and_more.py +49 -0
  214. karrio/server/tracing/migrations/__init__.py +0 -0
  215. karrio/server/tracing/models.py +80 -0
  216. karrio/server/tracing/tests.py +3 -0
  217. karrio/server/tracing/utils.py +112 -0
  218. karrio/server/user/__init__.py +0 -0
  219. karrio/server/user/admin.py +96 -0
  220. karrio/server/user/apps.py +7 -0
  221. karrio/server/user/forms.py +35 -0
  222. karrio/server/user/migrations/0001_initial.py +41 -0
  223. karrio/server/user/migrations/0002_token.py +29 -0
  224. karrio/server/user/migrations/0003_token_test_mode.py +20 -0
  225. karrio/server/user/migrations/0004_group.py +26 -0
  226. karrio/server/user/migrations/0005_token_label.py +21 -0
  227. karrio/server/user/migrations/0006_workspaceconfig.py +63 -0
  228. karrio/server/user/migrations/__init__.py +0 -0
  229. karrio/server/user/models.py +203 -0
  230. karrio/server/user/serializers.py +46 -0
  231. karrio/server/user/templates/registration/login.html +108 -0
  232. karrio/server/user/templates/registration/registration_confirm_email.html +10 -0
  233. karrio/server/user/templates/registration/registration_confirm_email.txt +3 -0
  234. karrio/server/user/tests.py +3 -0
  235. karrio/server/user/urls.py +10 -0
  236. karrio/server/user/utils.py +60 -0
  237. karrio/server/user/views.py +9 -0
  238. karrio_server_core-2025.5rc1.dist-info/METADATA +32 -0
  239. karrio_server_core-2025.5rc1.dist-info/RECORD +241 -0
  240. karrio_server_core-2025.5rc1.dist-info/WHEEL +5 -0
  241. karrio_server_core-2025.5rc1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,269 @@
1
+ import io
2
+ import base64
3
+ import logging
4
+ import re
5
+ from django.http import JsonResponse
6
+ from django.urls import path, re_path
7
+ from rest_framework import status, views
8
+ from rest_framework.request import Request
9
+ from rest_framework.response import Response
10
+ from django.core.files.base import ContentFile
11
+ from django_downloadview import VirtualDownloadView
12
+
13
+ import karrio.lib as lib
14
+ import karrio.server.openapi as openapi
15
+ import karrio.server.samples as samples
16
+ import karrio.server.core.views.api as api
17
+ import karrio.server.providers.models as models
18
+ from karrio.server.core import datatypes, dataunits, serializers
19
+
20
+ logger = logging.getLogger(__name__)
21
+ ENDPOINT_ID = "&&" # This endpoint id is used to make operation ids unique make sure not to duplicate
22
+
23
+
24
+ class CarrierList(views.APIView):
25
+ permission_classes = []
26
+
27
+ @openapi.extend_schema(
28
+ auth=[],
29
+ tags=["Carriers"],
30
+ operation_id=f"{ENDPOINT_ID}list",
31
+ extensions={"x-operationId": "listCarriers"},
32
+ summary="List all carriers",
33
+ responses={
34
+ 200: serializers.CarrierDetails(many=True),
35
+ 500: serializers.ErrorResponse(),
36
+ },
37
+ examples=[
38
+ openapi.OpenApiExample(
39
+ name="Carrier List",
40
+ value=lib.to_dict(samples.CARRIER_DETAILS_SAMPLE),
41
+ )
42
+ ],
43
+ )
44
+ def get(self, request: Request):
45
+ """Returns the list of configured carriers"""
46
+ references = dataunits.contextual_reference(reduced=False)
47
+ carriers = [
48
+ dataunits.get_carrier_details(
49
+ carrier_name,
50
+ contextual_reference=references,
51
+ )
52
+ for carrier_name in references["carriers"].keys()
53
+ ]
54
+
55
+ return Response(carriers, status=status.HTTP_200_OK)
56
+
57
+
58
+ class CarrierDetails(api.APIView):
59
+ permission_classes = []
60
+
61
+ @openapi.extend_schema(
62
+ auth=[],
63
+ tags=["Carriers"],
64
+ operation_id=f"{ENDPOINT_ID}get_details",
65
+ extensions={"x-operationId": "getDetails"},
66
+ summary="Get carrier details",
67
+ parameters=[
68
+ openapi.OpenApiParameter(
69
+ "carrier_name",
70
+ location=openapi.OpenApiParameter.PATH,
71
+ type=openapi.OpenApiTypes.STR,
72
+ description=(
73
+ "The unique carrier slug. <br/>"
74
+ f"Values: {', '.join([f'`{c}`' for c in dataunits.CARRIER_NAMES])}"
75
+ ),
76
+ )
77
+ ],
78
+ responses={
79
+ 200: serializers.CarrierDetails(),
80
+ 404: serializers.ErrorResponse(),
81
+ 500: serializers.ErrorResponse(),
82
+ },
83
+ )
84
+ def get(self, request: Request, carrier_name: str):
85
+ """
86
+ Retrieve a carrier's details
87
+ """
88
+ references = dataunits.contextual_reference(reduced=False)
89
+
90
+ if carrier_name not in references["carriers"]:
91
+ raise Exception(f"Unknown carrier: {carrier_name}")
92
+
93
+ carrier_details = dataunits.get_carrier_details(
94
+ carrier_name,
95
+ contextual_reference=references,
96
+ )
97
+
98
+ return Response(carrier_details, status=status.HTTP_200_OK)
99
+
100
+
101
+ class CarrierServices(api.APIView):
102
+ permission_classes = []
103
+
104
+ @openapi.extend_schema(
105
+ auth=[],
106
+ tags=["Carriers"],
107
+ operation_id=f"{ENDPOINT_ID}get_services",
108
+ extensions={"x-operationId": "getServices"},
109
+ summary="Get carrier services",
110
+ parameters=[
111
+ openapi.OpenApiParameter(
112
+ "carrier_name",
113
+ location=openapi.OpenApiParameter.PATH,
114
+ type=openapi.OpenApiTypes.STR,
115
+ description=(
116
+ "The unique carrier slug. <br/>"
117
+ f"Values: {', '.join([f'`{c}`' for c in dataunits.CARRIER_NAMES])}"
118
+ ),
119
+ )
120
+ ],
121
+ responses={
122
+ 200: openapi.OpenApiTypes.OBJECT,
123
+ 404: serializers.ErrorResponse(),
124
+ 500: serializers.ErrorResponse(),
125
+ },
126
+ examples=[
127
+ openapi.OpenApiExample(
128
+ name="Carrier List",
129
+ value=lib.to_dict(samples.CARRIER_SERICES_SAMPLE),
130
+ )
131
+ ],
132
+ )
133
+ def get(self, request: Request, carrier_name: str):
134
+ """
135
+ Retrieve a carrier's services
136
+ """
137
+ references = dataunits.contextual_reference()
138
+
139
+ if carrier_name not in references["carriers"]:
140
+ raise Exception(f"Unknown carrier: {carrier_name}")
141
+
142
+ services = references["services"].get(carrier_name, {})
143
+
144
+ return Response(services, status=status.HTTP_200_OK)
145
+
146
+
147
+ class CarrierOptions(api.APIView):
148
+ permission_classes = []
149
+
150
+ @openapi.extend_schema(
151
+ auth=[],
152
+ tags=["Carriers"],
153
+ operation_id=f"{ENDPOINT_ID}get_options",
154
+ extensions={"x-operationId": "getOptions"},
155
+ summary="Get carrier options",
156
+ parameters=[
157
+ openapi.OpenApiParameter(
158
+ "carrier_name",
159
+ location=openapi.OpenApiParameter.PATH,
160
+ type=openapi.OpenApiTypes.STR,
161
+ description=(
162
+ "The unique carrier slug. <br/>"
163
+ f"Values: {', '.join([f'`{c}`' for c in dataunits.CARRIER_NAMES])}"
164
+ ),
165
+ )
166
+ ],
167
+ responses={
168
+ 200: openapi.OpenApiTypes.OBJECT,
169
+ 404: serializers.ErrorResponse(),
170
+ 500: serializers.ErrorResponse(),
171
+ },
172
+ examples=[
173
+ openapi.OpenApiExample(
174
+ name="Carrier Options",
175
+ value=lib.to_dict(samples.CARRIER_OPTIONS_SAMPLE),
176
+ )
177
+ ],
178
+ )
179
+ def get(self, request: Request, carrier_name: str):
180
+ """
181
+ Retrieve a carrier's options
182
+ """
183
+ references = dataunits.contextual_reference()
184
+
185
+ if carrier_name not in references["carriers"]:
186
+ raise Exception(f"Unknown carrier: {carrier_name}")
187
+
188
+ options = references["options"].get(carrier_name, {})
189
+
190
+ return Response(options, status=status.HTTP_200_OK)
191
+
192
+
193
+ class CarrierLabelPreview(VirtualDownloadView):
194
+ def get(
195
+ self,
196
+ request: Request,
197
+ pk: str,
198
+ format: str = "pdf",
199
+ **kwargs,
200
+ ):
201
+ """
202
+ Preview a carrier label template...
203
+ """
204
+ try:
205
+ query_params = request.GET.dict()
206
+ carrier = models.Carrier.objects.get(carrier_code="generic", pk=pk)
207
+
208
+ self.document = self._generate_label(carrier, format)
209
+ self.name = f"{carrier.custom_carrier_name}_label.{format}"
210
+ self.attachment = query_params.get("download", False)
211
+
212
+ response = super(CarrierLabelPreview, self).get(
213
+ request, pk, format, **kwargs
214
+ )
215
+ response["X-Frame-Options"] = "ALLOWALL"
216
+ return response
217
+ except Exception as e:
218
+ return JsonResponse(dict(error=str(e)), status=status.HTTP_409_CONFLICT)
219
+
220
+ def get_file(self):
221
+ content = base64.b64decode(self.document or "")
222
+ buffer = io.BytesIO()
223
+ buffer.write(content)
224
+
225
+ return ContentFile(buffer.getvalue(), name=self.name)
226
+
227
+ def _generate_label(self, carrier, format):
228
+ import karrio.sdk as karrio
229
+ import karrio.providers.generic.units as units
230
+
231
+ template = carrier.label_template
232
+ data = lib.identity(
233
+ template.shipment_sample
234
+ if template is not None and len(template.shipment_sample.items()) > 0
235
+ else units.SAMPLE_SHIPMENT_REQUEST
236
+ )
237
+ service = lib.identity(
238
+ data.get("service") or next((s.service_code for s in carrier.services))
239
+ )
240
+ request = lib.to_object(
241
+ datatypes.ShipmentRequest,
242
+ {
243
+ **data,
244
+ "service": service,
245
+ "label_type": format.upper(),
246
+ "selected_rate_id": data.get("selected_rate_id") or "",
247
+ "rates": data.get("rates") or [],
248
+ },
249
+ )
250
+
251
+ shipment, _ = karrio.Shipment.create(request).from_(carrier.gateway).parse()
252
+
253
+ if shipment is None:
254
+ raise Exception("Failed to generate label")
255
+
256
+ return shipment.docs.label
257
+
258
+
259
+ urlpatterns = [
260
+ path("carriers", CarrierList.as_view(), name="carrier-list"),
261
+ path("carriers/<str:carrier_name>", CarrierDetails.as_view(), name="carrier-details"),
262
+ path("carriers/<str:carrier_name>/services", CarrierServices.as_view(), name="carrier-services"),
263
+ path("carriers/<str:carrier_name>/options", CarrierOptions.as_view(), name="carrier-options"),
264
+ re_path(
265
+ r"^carriers/(?P<pk>\w+)/label.(?P<format>[a-z0-9]+)",
266
+ CarrierLabelPreview.as_view(),
267
+ name="carrier-label",
268
+ ),
269
+ ]
@@ -0,0 +1,176 @@
1
+ import logging
2
+ import django.urls as urls
3
+ import rest_framework.status as status
4
+ import rest_framework.request as request
5
+ import rest_framework.response as response
6
+ import django_filters.rest_framework as drf
7
+ import rest_framework.pagination as pagination
8
+
9
+ import karrio.lib as lib
10
+ import karrio.server.openapi as openapi
11
+ import karrio.server.core.views.api as api
12
+ import karrio.server.core.filters as filters
13
+ import karrio.server.core.gateway as gateway
14
+ import karrio.server.providers.models as models
15
+ import karrio.server.providers.serializers as serializers
16
+
17
+ logger = logging.getLogger(__name__)
18
+ ENDPOINT_ID = "&&&" # This endpoint id is used to make operation ids unique make sure not to duplicate
19
+ CarrierConnectionList = serializers.PaginatedResult(
20
+ "CarrierConnectionList", serializers.CarrierConnection
21
+ )
22
+
23
+
24
+ class CarrierConnectionListView(api.GenericAPIView):
25
+ model = models.Carrier
26
+ serializer_class = serializers.CarrierConnection
27
+ filterset_class = filters.CarrierConnectionFilter
28
+ filter_backends = (drf.DjangoFilterBackend,)
29
+ pagination_class = type(
30
+ "CustomPagination",
31
+ (pagination.LimitOffsetPagination,),
32
+ dict(default_limit=20),
33
+ )
34
+
35
+ @openapi.extend_schema(
36
+ tags=["Connections"],
37
+ operation_id=f"{ENDPOINT_ID}list",
38
+ extensions={"x-operationId": "listCarrierConnections"},
39
+ summary="List carrier connections",
40
+ responses={
41
+ 200: CarrierConnectionList(),
42
+ 400: serializers.ErrorResponse(),
43
+ },
44
+ parameters=filters.CarrierConnectionFilter.parameters,
45
+ )
46
+ def get(self, request: request.Request):
47
+ """Retrieve all carrier connections"""
48
+ filter = {
49
+ **filters.CarrierFilters(request.query_params).to_dict(),
50
+ "context": request,
51
+ }
52
+
53
+ # fmt: off
54
+ connections = gateway.Carriers.list(**filter)
55
+ response = self.paginate_queryset(
56
+ [
57
+ {
58
+ **_,
59
+ "metadata": None if _["is_system"] else _["metadata"],
60
+ "credentials": None if _["is_system"] else _["credentials"]
61
+ }
62
+ for _ in serializers.CarrierConnection(connections, many=True).data
63
+ ]
64
+ )
65
+ # fmt: on
66
+
67
+ return self.get_paginated_response(response)
68
+
69
+ @openapi.extend_schema(
70
+ tags=["Connections"],
71
+ operation_id=f"{ENDPOINT_ID}add",
72
+ extensions={"x-operationId": "addCarrierConnection"},
73
+ summary="Add a carrier connection",
74
+ responses={
75
+ 201: serializers.CarrierConnection(),
76
+ 400: serializers.ErrorResponse(),
77
+ 424: serializers.ErrorMessages(),
78
+ 500: serializers.ErrorResponse(),
79
+ },
80
+ request=serializers.CarrierConnectionData(),
81
+ )
82
+ def post(self, request: request.Request):
83
+ """Add a new carrier connection."""
84
+ connection = lib.identity(
85
+ serializers.CarrierConnectionModelSerializer.map(
86
+ data=serializers.CarrierConnectionData.map(data=request.data).data,
87
+ context=request,
88
+ )
89
+ .save()
90
+ .instance
91
+ )
92
+
93
+ return response.Response(
94
+ serializers.CarrierConnection(connection).data,
95
+ status=status.HTTP_201_CREATED,
96
+ )
97
+
98
+
99
+ class CarrierConnectionDetail(api.APIView):
100
+ @openapi.extend_schema(
101
+ tags=["Connections"],
102
+ operation_id=f"{ENDPOINT_ID}retrieve",
103
+ extensions={"x-operationId": "retrieveCarrierConnection"},
104
+ summary="Retrieve a connection",
105
+ responses={
106
+ 200: serializers.CarrierConnection(),
107
+ 400: serializers.ErrorResponse(),
108
+ 500: serializers.ErrorResponse(),
109
+ },
110
+ )
111
+ def get(self, request: request.Request, pk: str):
112
+ """Retrieve carrier connection."""
113
+ connection = models.Carrier.access_by(request).get(pk=pk)
114
+ return response.Response(serializers.CarrierConnection(connection).data)
115
+
116
+ @openapi.extend_schema(
117
+ tags=["Connections"],
118
+ operation_id=f"{ENDPOINT_ID}update",
119
+ extensions={"x-operationId": "updateCarrierConnection"},
120
+ summary="Update a connection",
121
+ request=serializers.CarrierConnectionData(),
122
+ responses={
123
+ 200: serializers.CarrierConnection(),
124
+ 400: serializers.ErrorResponse(),
125
+ 404: serializers.ErrorResponse(),
126
+ 500: serializers.ErrorResponse(),
127
+ },
128
+ )
129
+ def patch(self, request: request.Request, pk: str):
130
+ """Update a carrier connection."""
131
+ connection = models.Carrier.access_by(request).get(pk=pk)
132
+ update = lib.identity(
133
+ serializers.CarrierConnectionModelSerializer.map(
134
+ connection,
135
+ data=request.data,
136
+ context=request,
137
+ )
138
+ .save()
139
+ .instance
140
+ )
141
+
142
+ return response.Response(serializers.CarrierConnection(update).data)
143
+
144
+ @openapi.extend_schema(
145
+ tags=["Connections"],
146
+ operation_id=f"{ENDPOINT_ID}remove",
147
+ extensions={"x-operationId": "removeCarrierConnection"},
148
+ summary="Remove a carrier connection",
149
+ responses={
150
+ 200: serializers.CarrierConnection(),
151
+ 404: serializers.ErrorResponse(),
152
+ 409: serializers.ErrorResponse(),
153
+ 500: serializers.ErrorResponse(),
154
+ },
155
+ )
156
+ def delete(self, request: request.Request, pk: str):
157
+ """Remove a carrier connection."""
158
+ connection = models.Carrier.access_by(request).get(pk=pk)
159
+
160
+ connection.delete(keep_parents=True)
161
+
162
+ return response.Response(serializers.CarrierConnection(connection).data)
163
+
164
+
165
+ urlpatterns = [
166
+ urls.path(
167
+ "connections",
168
+ CarrierConnectionListView.as_view(),
169
+ name="carrier-connection-list",
170
+ ),
171
+ urls.path(
172
+ "connections/<str:pk>",
173
+ CarrierConnectionDetail.as_view(),
174
+ name="carrier-connection-details",
175
+ ),
176
+ ]