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.
- karrio/server/conf.py +54 -0
- karrio/server/core/__init__.py +3 -0
- karrio/server/core/admin.py +1 -0
- karrio/server/core/apps.py +10 -0
- karrio/server/core/authentication.py +313 -0
- karrio/server/core/context_processors.py +12 -0
- karrio/server/core/datatypes.py +369 -0
- karrio/server/core/dataunits.py +156 -0
- karrio/server/core/exceptions.py +200 -0
- karrio/server/core/fields.py +12 -0
- karrio/server/core/filters.py +823 -0
- karrio/server/core/gateway.py +720 -0
- karrio/server/core/management/commands/cli.py +19 -0
- karrio/server/core/management/commands/create_oauth_client.py +41 -0
- karrio/server/core/middleware.py +95 -0
- karrio/server/core/migrations/0001_initial.py +28 -0
- karrio/server/core/migrations/0002_apilogindex.py +69 -0
- karrio/server/core/migrations/0003_apilogindex_test_mode.py +62 -0
- karrio/server/core/migrations/0004_metafield.py +74 -0
- karrio/server/core/migrations/0005_alter_metafield_type_alter_metafield_value.py +23 -0
- karrio/server/core/migrations/__init__.py +0 -0
- karrio/server/core/models/__init__.py +48 -0
- karrio/server/core/models/base.py +70 -0
- karrio/server/core/models/entity.py +22 -0
- karrio/server/core/models/metafield.py +144 -0
- karrio/server/core/models/third_party.py +21 -0
- karrio/server/core/oauth_validators.py +171 -0
- karrio/server/core/permissions.py +37 -0
- karrio/server/core/renderers.py +11 -0
- karrio/server/core/router.py +3 -0
- karrio/server/core/serializers.py +1898 -0
- karrio/server/core/signals.py +57 -0
- karrio/server/core/tests.py +98 -0
- karrio/server/core/urls.py +12 -0
- karrio/server/core/utils.py +479 -0
- karrio/server/core/validators.py +416 -0
- karrio/server/core/views/__init__.py +2 -0
- karrio/server/core/views/api.py +133 -0
- karrio/server/core/views/metadata.py +44 -0
- karrio/server/core/views/oauth.py +74 -0
- karrio/server/core/views/references.py +82 -0
- karrio/server/core/views/schema.py +310 -0
- karrio/server/filters/__init__.py +2 -0
- karrio/server/filters/abstract.py +26 -0
- karrio/server/iam/__init__.py +0 -0
- karrio/server/iam/admin.py +3 -0
- karrio/server/iam/apps.py +21 -0
- karrio/server/iam/migrations/0001_initial.py +33 -0
- karrio/server/iam/migrations/__init__.py +0 -0
- karrio/server/iam/models.py +48 -0
- karrio/server/iam/permissions.py +134 -0
- karrio/server/iam/serializers.py +39 -0
- karrio/server/iam/signals.py +20 -0
- karrio/server/iam/tests.py +3 -0
- karrio/server/iam/views.py +3 -0
- karrio/server/openapi.py +75 -0
- karrio/server/providers/__init__.py +1 -0
- karrio/server/providers/admin.py +364 -0
- karrio/server/providers/apps.py +10 -0
- karrio/server/providers/extension/__init__.py +1 -0
- karrio/server/providers/extension/models/__init__.py +1 -0
- karrio/server/providers/extension/models/allied_express.py +22 -0
- karrio/server/providers/extension/models/allied_express_local.py +22 -0
- karrio/server/providers/extension/models/amazon_shipping.py +27 -0
- karrio/server/providers/extension/models/aramex.py +25 -0
- karrio/server/providers/extension/models/asendia_us.py +21 -0
- karrio/server/providers/extension/models/australiapost.py +20 -0
- karrio/server/providers/extension/models/boxknight.py +19 -0
- karrio/server/providers/extension/models/bpost.py +21 -0
- karrio/server/providers/extension/models/canadapost.py +21 -0
- karrio/server/providers/extension/models/canpar.py +19 -0
- karrio/server/providers/extension/models/chronopost.py +22 -0
- karrio/server/providers/extension/models/colissimo.py +22 -0
- karrio/server/providers/extension/models/dhl_express.py +23 -0
- karrio/server/providers/extension/models/dhl_parcel_de.py +25 -0
- karrio/server/providers/extension/models/dhl_poland.py +22 -0
- karrio/server/providers/extension/models/dhl_universal.py +19 -0
- karrio/server/providers/extension/models/dicom.py +20 -0
- karrio/server/providers/extension/models/dpd.py +37 -0
- karrio/server/providers/extension/models/dpdhl.py +26 -0
- karrio/server/providers/extension/models/easypost.py +20 -0
- karrio/server/providers/extension/models/eshipper.py +21 -0
- karrio/server/providers/extension/models/fedex.py +25 -0
- karrio/server/providers/extension/models/fedex_ws.py +24 -0
- karrio/server/providers/extension/models/freightcom.py +21 -0
- karrio/server/providers/extension/models/generic.py +35 -0
- karrio/server/providers/extension/models/geodis.py +22 -0
- karrio/server/providers/extension/models/hay_post.py +22 -0
- karrio/server/providers/extension/models/laposte.py +19 -0
- karrio/server/providers/extension/models/locate2u.py +22 -0
- karrio/server/providers/extension/models/nationex.py +22 -0
- karrio/server/providers/extension/models/purolator.py +21 -0
- karrio/server/providers/extension/models/roadie.py +18 -0
- karrio/server/providers/extension/models/royalmail.py +19 -0
- karrio/server/providers/extension/models/sendle.py +22 -0
- karrio/server/providers/extension/models/tge.py +63 -0
- karrio/server/providers/extension/models/tnt.py +23 -0
- karrio/server/providers/extension/models/ups.py +23 -0
- karrio/server/providers/extension/models/usps.py +23 -0
- karrio/server/providers/extension/models/usps_international.py +23 -0
- karrio/server/providers/extension/models/usps_wt.py +24 -0
- karrio/server/providers/extension/models/usps_wt_international.py +24 -0
- karrio/server/providers/extension/models/zoom2u.py +23 -0
- karrio/server/providers/migrations/0001_initial.py +140 -0
- karrio/server/providers/migrations/0002_carrier_active.py +18 -0
- karrio/server/providers/migrations/0003_auto_20201230_0820.py +24 -0
- karrio/server/providers/migrations/0004_auto_20210212_0554.py +178 -0
- karrio/server/providers/migrations/0005_auto_20210212_0555.py +18 -0
- karrio/server/providers/migrations/0006_australiapostsettings.py +29 -0
- karrio/server/providers/migrations/0007_auto_20210213_0206.py +21 -0
- karrio/server/providers/migrations/0008_auto_20210214_0409.py +30 -0
- karrio/server/providers/migrations/0009_auto_20210308_0302.py +18 -0
- karrio/server/providers/migrations/0010_auto_20210409_0852.py +32 -0
- karrio/server/providers/migrations/0011_auto_20210409_0853.py +21 -0
- karrio/server/providers/migrations/0012_alter_carrier_options.py +17 -0
- karrio/server/providers/migrations/0013_tntsettings.py +30 -0
- karrio/server/providers/migrations/0014_auto_20210612_1608.py +46 -0
- karrio/server/providers/migrations/0015_auto_20210615_1601.py +28 -0
- karrio/server/providers/migrations/0016_alter_purolatorsettings_user_token.py +18 -0
- karrio/server/providers/migrations/0017_auto_20210805_0359.py +1293 -0
- karrio/server/providers/migrations/0018_alter_fedexsettings_user_key.py +18 -0
- karrio/server/providers/migrations/0019_dhlpolandsettings_servicelevel.py +65 -0
- karrio/server/providers/migrations/0020_genericsettings_labeltemplate.py +52 -0
- karrio/server/providers/migrations/0021_auto_20211231_2353.py +40 -0
- karrio/server/providers/migrations/0022_carrier_metadata.py +18 -0
- karrio/server/providers/migrations/0023_auto_20220124_1916.py +27 -0
- karrio/server/providers/migrations/0024_alter_genericsettings_custom_carrier_name.py +19 -0
- karrio/server/providers/migrations/0025_alter_servicelevel_service_code.py +19 -0
- karrio/server/providers/migrations/0026_auto_20220208_0132.py +59 -0
- karrio/server/providers/migrations/0027_auto_20220304_1340.py +29 -0
- karrio/server/providers/migrations/0028_auto_20220323_1500.py +33 -0
- karrio/server/providers/migrations/0029_easypostsettings.py +27 -0
- karrio/server/providers/migrations/0030_amazonmwssettings.py +29 -0
- karrio/server/providers/migrations/0031_delete_amazonmwssettings.py +18 -0
- karrio/server/providers/migrations/0032_alter_carrier_test.py +18 -0
- karrio/server/providers/migrations/0033_auto_20220708_1350.py +22 -0
- karrio/server/providers/migrations/0034_amazonmwssettings_dpdhlsettings.py +47 -0
- karrio/server/providers/migrations/0035_alter_carrier_capabilities.py +43 -0
- karrio/server/providers/migrations/0036_upsfreightsettings.py +31 -0
- karrio/server/providers/migrations/0037_chronopostsettings.py +29 -0
- karrio/server/providers/migrations/0038_alter_genericsettings_label_template.py +19 -0
- karrio/server/providers/migrations/0039_auto_20220906_0612.py +23 -0
- karrio/server/providers/migrations/0040_dpdhlsettings_services.py +18 -0
- karrio/server/providers/migrations/0041_auto_20221105_0705.py +38 -0
- karrio/server/providers/migrations/0042_auto_20221215_1642.py +23 -0
- karrio/server/providers/migrations/0043_alter_genericsettings_account_number_and_more.py +39 -0
- karrio/server/providers/migrations/0044_carrier_carrier_capabilities.py +64 -0
- karrio/server/providers/migrations/0045_alter_carrier_active_alter_carrier_carrier_id.py +31 -0
- karrio/server/providers/migrations/0046_remove_dpdhlsettings_signature_and_more.py +41 -0
- karrio/server/providers/migrations/0047_dpdsettings.py +286 -0
- karrio/server/providers/migrations/0048_servicelevel_min_weight_servicelevel_transit_days_and_more.py +64 -0
- karrio/server/providers/migrations/0049_boxknightsettings_geodissettings_lapostesettings_and_more.py +156 -0
- karrio/server/providers/migrations/0050_carrier_is_system_alter_carrier_metadata_and_more.py +106 -0
- karrio/server/providers/migrations/0051_rename_username_upssettings_client_id_and_more.py +31 -0
- karrio/server/providers/migrations/0052_alter_upssettings_account_number_and_more.py +20 -0
- karrio/server/providers/migrations/0053_locate2usettings.py +281 -0
- karrio/server/providers/migrations/0054_zoom2usettings.py +280 -0
- karrio/server/providers/migrations/0055_rename_amazonmwssettings_amazonshippingsettings_and_more.py +44 -0
- karrio/server/providers/migrations/0056_asendiaussettings_geodissettings_code_client_and_more.py +75 -0
- karrio/server/providers/migrations/0057_alter_servicelevel_weight_unit_belgianpostsettings.py +51 -0
- karrio/server/providers/migrations/0058_alliedexpresssettings.py +38 -0
- karrio/server/providers/migrations/0059_ratesheet.py +81 -0
- karrio/server/providers/migrations/0060_belgianpostsettings_rate_sheet_and_more.py +73 -0
- karrio/server/providers/migrations/0061_alliedexpresssettings_service_type.py +17 -0
- karrio/server/providers/migrations/0062_sendlesettings_account_country_code.py +257 -0
- karrio/server/providers/migrations/0063_servicelevel_metadata.py +25 -0
- karrio/server/providers/migrations/0064_alliedexpresslocalsettings.py +43 -0
- karrio/server/providers/migrations/0065_servicelevel_carrier_service_code_and_more.py +66 -0
- karrio/server/providers/migrations/0066_rename_fedexsettings_fedexwssettings_and_more.py +28 -0
- karrio/server/providers/migrations/0067_fedexsettings.py +283 -0
- karrio/server/providers/migrations/0068_fedexsettings_track_api_key_and_more.py +38 -0
- karrio/server/providers/migrations/0069_alter_canadapostsettings_contract_id_and_more.py +23 -0
- karrio/server/providers/migrations/0070_tgesettings_alter_carrier_capabilities.py +65 -0
- karrio/server/providers/migrations/0071_alter_tgesettings_my_toll_token.py +18 -0
- karrio/server/providers/migrations/0072_rename_eshippersettings_eshipperxmlsettings_and_more.py +28 -0
- karrio/server/providers/migrations/0073_delete_eshipperxmlsettings.py +41 -0
- karrio/server/providers/migrations/0074_eshippersettings.py +38 -0
- karrio/server/providers/migrations/0075_haypostsettings.py +40 -0
- karrio/server/providers/migrations/0076_rename_customer_registration_id_uspsinternationalsettings_account_number_and_more.py +125 -0
- karrio/server/providers/migrations/0077_uspswtinternationalsettings_uspswtsettings_and_more.py +165 -0
- karrio/server/providers/migrations/0078_auto_20240813_1552.py +120 -0
- karrio/server/providers/migrations/0079_alter_carrier_options_alter_ratesheet_created_by.py +31 -0
- karrio/server/providers/migrations/0080_alter_aramexsettings_account_country_code_and_more.py +3025 -0
- karrio/server/providers/migrations/0081_remove_alliedexpresssettings_carrier_ptr_and_more.py +338 -0
- karrio/server/providers/migrations/__init__.py +0 -0
- karrio/server/providers/models/__init__.py +17 -0
- karrio/server/providers/models/carrier.py +309 -0
- karrio/server/providers/models/config.py +30 -0
- karrio/server/providers/models/service.py +62 -0
- karrio/server/providers/models/sheet.py +60 -0
- karrio/server/providers/models/template.py +39 -0
- karrio/server/providers/models/utils.py +58 -0
- karrio/server/providers/router.py +3 -0
- karrio/server/providers/serializers/__init__.py +3 -0
- karrio/server/providers/serializers/base.py +277 -0
- karrio/server/providers/signals.py +27 -0
- karrio/server/providers/tests.py +3 -0
- karrio/server/providers/urls.py +11 -0
- karrio/server/providers/views/__init__.py +0 -0
- karrio/server/providers/views/carriers.py +269 -0
- karrio/server/providers/views/connections.py +176 -0
- karrio/server/samples.py +352 -0
- karrio/server/serializers/__init__.py +2 -0
- karrio/server/serializers/abstract.py +506 -0
- karrio/server/tracing/__init__.py +0 -0
- karrio/server/tracing/admin.py +63 -0
- karrio/server/tracing/apps.py +8 -0
- karrio/server/tracing/migrations/0001_initial.py +41 -0
- karrio/server/tracing/migrations/0002_auto_20220710_1307.py +22 -0
- karrio/server/tracing/migrations/0003_auto_20221105_0317.py +43 -0
- karrio/server/tracing/migrations/0004_tracingrecord_carrier_account_idx.py +24 -0
- karrio/server/tracing/migrations/0005_optimise_tracingrecord_request_log_idx.py +25 -0
- karrio/server/tracing/migrations/0006_alter_tracingrecord_options_and_more.py +49 -0
- karrio/server/tracing/migrations/__init__.py +0 -0
- karrio/server/tracing/models.py +80 -0
- karrio/server/tracing/tests.py +3 -0
- karrio/server/tracing/utils.py +112 -0
- karrio/server/user/__init__.py +0 -0
- karrio/server/user/admin.py +96 -0
- karrio/server/user/apps.py +7 -0
- karrio/server/user/forms.py +35 -0
- karrio/server/user/migrations/0001_initial.py +41 -0
- karrio/server/user/migrations/0002_token.py +29 -0
- karrio/server/user/migrations/0003_token_test_mode.py +20 -0
- karrio/server/user/migrations/0004_group.py +26 -0
- karrio/server/user/migrations/0005_token_label.py +21 -0
- karrio/server/user/migrations/0006_workspaceconfig.py +63 -0
- karrio/server/user/migrations/__init__.py +0 -0
- karrio/server/user/models.py +203 -0
- karrio/server/user/serializers.py +46 -0
- karrio/server/user/templates/registration/login.html +108 -0
- karrio/server/user/templates/registration/registration_confirm_email.html +10 -0
- karrio/server/user/templates/registration/registration_confirm_email.txt +3 -0
- karrio/server/user/tests.py +3 -0
- karrio/server/user/urls.py +10 -0
- karrio/server/user/utils.py +60 -0
- karrio/server/user/views.py +9 -0
- karrio_server_core-2025.5rc1.dist-info/METADATA +32 -0
- karrio_server_core-2025.5rc1.dist-info/RECORD +241 -0
- karrio_server_core-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_server_core-2025.5rc1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import karrio.lib as lib
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PermissionGroup(lib.StrEnum):
|
|
6
|
+
manage_apps = "manage_apps"
|
|
7
|
+
manage_team = "manage_team"
|
|
8
|
+
manage_system = "manage_system"
|
|
9
|
+
manage_orders = "manage_orders"
|
|
10
|
+
manage_data = "manage_data"
|
|
11
|
+
manage_pickups = "manage_pickups"
|
|
12
|
+
manage_carriers = "manage_carriers"
|
|
13
|
+
manage_trackers = "manage_trackers"
|
|
14
|
+
manage_webhooks = "manage_webhooks"
|
|
15
|
+
manage_shipments = "manage_shipments"
|
|
16
|
+
manage_org_owner = "manage_org_owner"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
PERMISSION_GROUPS = [(p.name, p.name) for p in list(PermissionGroup)]
|
|
20
|
+
ROLES_GROUPS: typing.Dict[str, typing.List[str]] = {
|
|
21
|
+
"owner": [
|
|
22
|
+
PermissionGroup.manage_org_owner.value,
|
|
23
|
+
],
|
|
24
|
+
"admin": [
|
|
25
|
+
PermissionGroup.manage_team.value,
|
|
26
|
+
PermissionGroup.manage_apps.value,
|
|
27
|
+
PermissionGroup.manage_carriers.value,
|
|
28
|
+
],
|
|
29
|
+
"developer": [
|
|
30
|
+
PermissionGroup.manage_webhooks.value,
|
|
31
|
+
],
|
|
32
|
+
"member": [
|
|
33
|
+
PermissionGroup.manage_data.value,
|
|
34
|
+
PermissionGroup.manage_orders.value,
|
|
35
|
+
PermissionGroup.manage_pickups.value,
|
|
36
|
+
PermissionGroup.manage_trackers.value,
|
|
37
|
+
PermissionGroup.manage_shipments.value,
|
|
38
|
+
],
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from django.db.models import signals
|
|
3
|
+
|
|
4
|
+
import karrio.server.core.utils as utils
|
|
5
|
+
import karrio.server.user.models as user
|
|
6
|
+
import karrio.server.iam.models as models
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def register_all():
|
|
12
|
+
signals.post_delete.connect(context_object_deleted, sender=user.Token)
|
|
13
|
+
|
|
14
|
+
logger.info("karrio.iam signals registered...")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@utils.disable_for_loaddata
|
|
18
|
+
def context_object_deleted(sender, instance, *args, **kwargs):
|
|
19
|
+
# clean up permission contexts when related objects are removed.
|
|
20
|
+
models.ContextPermission.objects.filter(object_pk=instance.pk).delete()
|
karrio/server/openapi.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from drf_spectacular.types import *
|
|
3
|
+
from drf_spectacular.utils import *
|
|
4
|
+
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class JWTAuthentication(OpenApiAuthenticationExtension):
|
|
8
|
+
target_class = "karrio.server.core.authentication.JWTAuthentication"
|
|
9
|
+
name = "JWT"
|
|
10
|
+
|
|
11
|
+
def get_security_definition(self, auto_schema):
|
|
12
|
+
return {
|
|
13
|
+
"in": "header",
|
|
14
|
+
"type": "apiKey",
|
|
15
|
+
"scheme": "bearer",
|
|
16
|
+
"bearerFormat": "JWT",
|
|
17
|
+
"name": "Authorization",
|
|
18
|
+
"description": "Authorization: Bearer xxx.xxx.xxx",
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TokenAuthentication(OpenApiAuthenticationExtension):
|
|
23
|
+
target_class = "karrio.server.core.authentication.TokenAuthentication"
|
|
24
|
+
name = "Token"
|
|
25
|
+
|
|
26
|
+
def get_security_definition(self, auto_schema):
|
|
27
|
+
return {
|
|
28
|
+
"type": "apiKey",
|
|
29
|
+
"in": "header",
|
|
30
|
+
"name": "Authorization",
|
|
31
|
+
"description": "Authorization: Token key_xxxxxxxx",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TokenBasicAuthentication(OpenApiAuthenticationExtension):
|
|
36
|
+
target_class = "karrio.server.core.authentication.TokenBasicAuthentication"
|
|
37
|
+
name = "TokenBasic"
|
|
38
|
+
|
|
39
|
+
def get_security_definition(self, auto_schema):
|
|
40
|
+
return {
|
|
41
|
+
"type": "http",
|
|
42
|
+
"scheme": "basic",
|
|
43
|
+
"name": "Authorization",
|
|
44
|
+
"description": "-u key_xxxxxxxx:",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class OAuth2Authentication(OpenApiAuthenticationExtension):
|
|
49
|
+
target_class = "karrio.server.core.authentication.OAuth2Authentication"
|
|
50
|
+
name = "OAuth2"
|
|
51
|
+
|
|
52
|
+
def get_security_definition(self, auto_schema):
|
|
53
|
+
return {
|
|
54
|
+
"type": "oauth2",
|
|
55
|
+
"in": "header",
|
|
56
|
+
"name": "Authorization",
|
|
57
|
+
"flows": {
|
|
58
|
+
"authorizationCode": {
|
|
59
|
+
"authorizationUrl": "/oauth/authorize/",
|
|
60
|
+
"tokenUrl": "/oauth/token/",
|
|
61
|
+
"scopes": settings.OAUTH2_PROVIDER["SCOPES"],
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"description": "Authorization: Bearer xxxxxxxx",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def custom_postprocessing_hook(result, generator, request, public):
|
|
69
|
+
if "docs" in request.query_params:
|
|
70
|
+
for path in result["paths"].values():
|
|
71
|
+
for method in path.values():
|
|
72
|
+
if "x-operationId" in method:
|
|
73
|
+
method["operationId"] = method["x-operationId"]
|
|
74
|
+
|
|
75
|
+
return result
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from django import forms
|
|
3
|
+
from django.db import models
|
|
4
|
+
from django.contrib import admin
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
from django.contrib.auth import get_user_model
|
|
7
|
+
from django.utils.translation import gettext_lazy as _
|
|
8
|
+
|
|
9
|
+
import karrio.lib as lib
|
|
10
|
+
import karrio.references as ref
|
|
11
|
+
import karrio.server.core.utils as utils
|
|
12
|
+
import karrio.server.serializers as serializers
|
|
13
|
+
import karrio.server.core.dataunits as dataunits
|
|
14
|
+
import karrio.server.providers.models as providers
|
|
15
|
+
|
|
16
|
+
User = get_user_model()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def model_admin(ext: str, carrierProxy):
|
|
20
|
+
references = dataunits.contextual_reference(reduced=False)
|
|
21
|
+
class_name = carrierProxy.__name__
|
|
22
|
+
connection_fields = references["connection_fields"].get(ext) or {}
|
|
23
|
+
connection_configs = references["connection_configs"].get(ext) or {}
|
|
24
|
+
carrier_services = (references["services"].get(ext) or {}).keys()
|
|
25
|
+
carrier_options = (references["options"].get(ext) or {}).keys()
|
|
26
|
+
|
|
27
|
+
class _Form(forms.ModelForm):
|
|
28
|
+
|
|
29
|
+
for key, field in connection_fields.items():
|
|
30
|
+
if field["type"] == "boolean":
|
|
31
|
+
locals()[key] = forms.NullBooleanField(
|
|
32
|
+
required=field.get("required", False),
|
|
33
|
+
initial=None,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
elif field["type"] == "integer":
|
|
37
|
+
locals()[key] = forms.IntegerField(
|
|
38
|
+
required=field.get("required", False),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
elif field["type"] == "float":
|
|
42
|
+
locals()[key] = forms.FloatField(
|
|
43
|
+
required=field.get("required", False),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
elif field["type"] == "string" and any(field.get("enum", [])):
|
|
47
|
+
locals()[key] = forms.ChoiceField(
|
|
48
|
+
choices=[(None, ""), *[(_, _) for _ in field.get("enum", [])]],
|
|
49
|
+
widget=forms.Select(attrs={"class": "vTextField"}),
|
|
50
|
+
required=field.get("required", False),
|
|
51
|
+
initial=field.get("default"),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
elif field["type"] == "string":
|
|
55
|
+
locals()[key] = forms.CharField(
|
|
56
|
+
required=field.get("required", False),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
else:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
for key, field in connection_configs.items():
|
|
63
|
+
|
|
64
|
+
if key == "shipping_services":
|
|
65
|
+
shipping_services = forms.MultipleChoiceField(
|
|
66
|
+
choices=[(_, _) for _ in carrier_services],
|
|
67
|
+
widget=forms.SelectMultiple(attrs={"class": "vTextField"}),
|
|
68
|
+
required=False,
|
|
69
|
+
initial=None,
|
|
70
|
+
)
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
if key == "shipping_options":
|
|
74
|
+
shipping_options = forms.MultipleChoiceField(
|
|
75
|
+
choices=[(_, _) for _ in carrier_options],
|
|
76
|
+
widget=forms.SelectMultiple(attrs={"class": "vTextField"}),
|
|
77
|
+
required=False,
|
|
78
|
+
initial=None,
|
|
79
|
+
)
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
if field["type"] == "boolean":
|
|
83
|
+
locals()[key] = forms.NullBooleanField(
|
|
84
|
+
required=False,
|
|
85
|
+
initial=None,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
elif field["type"] == "integer":
|
|
89
|
+
locals()[key] = forms.IntegerField(
|
|
90
|
+
required=False,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
elif field["type"] == "float":
|
|
94
|
+
locals()[key] = forms.FloatField(
|
|
95
|
+
required=False,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
elif field["type"] == "string" and any(field.get("enum", [])):
|
|
99
|
+
locals()[key] = forms.ChoiceField(
|
|
100
|
+
choices=[(None, ""), *[(_, _) for _ in field.get("enum", [])]],
|
|
101
|
+
widget=forms.Select(attrs={"class": "vTextField"}),
|
|
102
|
+
required=field.get("required", False),
|
|
103
|
+
initial=field.get("default"),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
elif field["type"] == "string":
|
|
107
|
+
locals()[key] = forms.CharField(
|
|
108
|
+
required=False,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
class Meta:
|
|
115
|
+
model = carrierProxy
|
|
116
|
+
fields = "__all__"
|
|
117
|
+
|
|
118
|
+
def __init__(self, *args, instance: providers.Carrier = None, **kwargs):
|
|
119
|
+
if instance is not None:
|
|
120
|
+
kwargs.update({"instance": instance})
|
|
121
|
+
credentials = instance.credentials
|
|
122
|
+
config = providers.Carrier.resolve_config(
|
|
123
|
+
instance, is_system_config=True
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
for key in [
|
|
127
|
+
_ for _ in self.base_fields.keys() if _ in connection_fields.keys()
|
|
128
|
+
]:
|
|
129
|
+
self.base_fields[key].initial = (
|
|
130
|
+
None if credentials is None else credentials.get(key)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
for key in [
|
|
134
|
+
_ for _ in self.base_fields.keys() if _ in connection_configs.keys()
|
|
135
|
+
]:
|
|
136
|
+
self.base_fields[key].initial = (
|
|
137
|
+
None if config is None else config.config.get(key)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
super(_Form, self).__init__(*args, **kwargs)
|
|
141
|
+
|
|
142
|
+
def save(self, commit: bool = True):
|
|
143
|
+
config_data = lib.to_dict(
|
|
144
|
+
{key: self.cleaned_data.get(key) for key in connection_configs.keys()}
|
|
145
|
+
)
|
|
146
|
+
credentials_data = lib.to_dict(
|
|
147
|
+
{key: self.cleaned_data.get(key) for key in connection_fields.keys()}
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
for key in connection_fields.keys():
|
|
151
|
+
if key in self.cleaned_data:
|
|
152
|
+
self.cleaned_data.pop(key)
|
|
153
|
+
|
|
154
|
+
for key in connection_configs.keys():
|
|
155
|
+
if key in self.cleaned_data:
|
|
156
|
+
self.cleaned_data.pop(key)
|
|
157
|
+
|
|
158
|
+
carrier = super(_Form, self).save(commit)
|
|
159
|
+
|
|
160
|
+
if any(connection_fields.keys()) and (commit or carrier.pk is not None):
|
|
161
|
+
carrier.credentials = serializers.process_dictionaries_mutations(
|
|
162
|
+
["credentials"], credentials_data, carrier
|
|
163
|
+
)
|
|
164
|
+
carrier.save()
|
|
165
|
+
|
|
166
|
+
if any(connection_configs.keys()) and (commit or carrier.pk is not None):
|
|
167
|
+
config = providers.Carrier.resolve_config(
|
|
168
|
+
carrier, is_system_config=True
|
|
169
|
+
)
|
|
170
|
+
created_by = getattr(config, "created_by", self.request.user)
|
|
171
|
+
config_value = lib.to_dict(
|
|
172
|
+
serializers.process_dictionaries_mutations(
|
|
173
|
+
["config"], config_data, config
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if config is None and len(config_value.keys()) == 0:
|
|
178
|
+
# Skip configuration persistence...
|
|
179
|
+
return carrier
|
|
180
|
+
|
|
181
|
+
# Save or update the carrier config...
|
|
182
|
+
lib.identity(
|
|
183
|
+
providers.CarrierConfig.objects.create(
|
|
184
|
+
created_by=created_by,
|
|
185
|
+
carrier=carrier,
|
|
186
|
+
config=config_value,
|
|
187
|
+
)
|
|
188
|
+
if config is None
|
|
189
|
+
else providers.CarrierConfig.objects.filter(carrier=carrier).update(
|
|
190
|
+
config=config_value
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return carrier
|
|
195
|
+
|
|
196
|
+
_form: forms.ModelForm = type(f"{class_name}AdminForm", (_Form,), {})
|
|
197
|
+
_fields = _form.base_fields.keys()
|
|
198
|
+
|
|
199
|
+
class _Admin(admin.ModelAdmin):
|
|
200
|
+
form = _form
|
|
201
|
+
inlines = []
|
|
202
|
+
list_display = ("__str__", "test_mode", "active")
|
|
203
|
+
exclude = ["active_users"]
|
|
204
|
+
fieldsets = [
|
|
205
|
+
(
|
|
206
|
+
None,
|
|
207
|
+
{
|
|
208
|
+
"fields": [
|
|
209
|
+
_
|
|
210
|
+
for _ in _fields
|
|
211
|
+
if _
|
|
212
|
+
not in [
|
|
213
|
+
*connection_fields.keys(),
|
|
214
|
+
*connection_configs.keys(),
|
|
215
|
+
"carrier_code",
|
|
216
|
+
"credentials",
|
|
217
|
+
"active_users",
|
|
218
|
+
"is_system",
|
|
219
|
+
"rate_sheet",
|
|
220
|
+
"metadata",
|
|
221
|
+
]
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
),
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
if any(connection_fields.keys()):
|
|
228
|
+
fieldsets += [
|
|
229
|
+
( # type: ignore
|
|
230
|
+
"Connection Fields",
|
|
231
|
+
{
|
|
232
|
+
"fields": [_ for _ in connection_fields.keys() if _ in _fields],
|
|
233
|
+
},
|
|
234
|
+
),
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
if any(connection_configs.keys()):
|
|
238
|
+
fieldsets += [
|
|
239
|
+
( # type: ignore
|
|
240
|
+
"Connection Config",
|
|
241
|
+
{
|
|
242
|
+
"fields": [
|
|
243
|
+
_ for _ in connection_configs.keys() if _ in _fields
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
),
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
formfield_overrides = {
|
|
250
|
+
models.CharField: {
|
|
251
|
+
"widget": forms.TextInput(
|
|
252
|
+
attrs={
|
|
253
|
+
"type": "text",
|
|
254
|
+
"readonly": "true",
|
|
255
|
+
"class": "vTextField",
|
|
256
|
+
"data - lpignore": "true",
|
|
257
|
+
"autocomplete": "keep-off",
|
|
258
|
+
"onfocus": "this.removeAttribute('readonly');",
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
},
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if settings.MULTI_ORGANIZATIONS:
|
|
265
|
+
|
|
266
|
+
class ActiveOrgInline(admin.TabularInline):
|
|
267
|
+
model = carrierProxy.active_orgs.through
|
|
268
|
+
verbose_name = "Activated for organization"
|
|
269
|
+
extra = 0
|
|
270
|
+
|
|
271
|
+
def get_formset(self, request, obj, **kwargs):
|
|
272
|
+
from karrio.server.orgs.models import Organization
|
|
273
|
+
|
|
274
|
+
initial = []
|
|
275
|
+
orgs = Organization.objects.filter(
|
|
276
|
+
users__id=request.user.id
|
|
277
|
+
).distinct()
|
|
278
|
+
self.max_num = orgs.count()
|
|
279
|
+
|
|
280
|
+
if obj is None and request.method == "GET":
|
|
281
|
+
self.extra = orgs.count()
|
|
282
|
+
initial += [{"organization": o.id} for o in orgs]
|
|
283
|
+
|
|
284
|
+
formset = super().get_formset(request, obj, **kwargs)
|
|
285
|
+
formset.__init__ = functools.partialmethod(
|
|
286
|
+
formset.__init__, initial=initial
|
|
287
|
+
)
|
|
288
|
+
organization_field = formset.form.base_fields["organization"]
|
|
289
|
+
organization_field.queryset = orgs
|
|
290
|
+
organization_field.widget.can_add_related = False
|
|
291
|
+
organization_field.widget.can_change_related = False
|
|
292
|
+
|
|
293
|
+
return formset
|
|
294
|
+
|
|
295
|
+
inlines += [ActiveOrgInline]
|
|
296
|
+
|
|
297
|
+
else:
|
|
298
|
+
|
|
299
|
+
class ActiveUserInline(admin.TabularInline):
|
|
300
|
+
model = carrierProxy.active_users.through
|
|
301
|
+
exta = 0
|
|
302
|
+
verbose_name = "Activated for user"
|
|
303
|
+
|
|
304
|
+
def get_formset(self, request, obj, **kwargs):
|
|
305
|
+
initial = []
|
|
306
|
+
users = User.objects.all()
|
|
307
|
+
self.max_num = users.count()
|
|
308
|
+
|
|
309
|
+
if obj is None and request.method == "GET":
|
|
310
|
+
self.extra = users.count()
|
|
311
|
+
initial += [{"user": o.id} for o in users]
|
|
312
|
+
|
|
313
|
+
formset = super().get_formset(request, obj, **kwargs)
|
|
314
|
+
formset.__init__ = functools.partialmethod(
|
|
315
|
+
formset.__init__, initial=initial
|
|
316
|
+
)
|
|
317
|
+
user_field = formset.form.base_fields["user"]
|
|
318
|
+
user_field.queryset = users
|
|
319
|
+
user_field.widget.can_add_related = False
|
|
320
|
+
user_field.widget.can_change_related = False
|
|
321
|
+
|
|
322
|
+
return formset
|
|
323
|
+
|
|
324
|
+
inlines += [ActiveUserInline]
|
|
325
|
+
|
|
326
|
+
def get_queryset(self, request):
|
|
327
|
+
query = super().get_queryset(request)
|
|
328
|
+
return query.filter(models.Q(is_system=True) | models.Q(created_by=None))
|
|
329
|
+
|
|
330
|
+
def get_form(self, request, *args, **kwargs):
|
|
331
|
+
form = super(_Admin, self).get_form(request, *args, **kwargs)
|
|
332
|
+
form.request = request
|
|
333
|
+
|
|
334
|
+
# Customize capabilities options specific to a carrier.
|
|
335
|
+
raw_capabilities = ref.get_carrier_capabilities(ext)
|
|
336
|
+
form.base_fields["capabilities"].choices = [
|
|
337
|
+
(c, c) for c in raw_capabilities
|
|
338
|
+
]
|
|
339
|
+
form.base_fields["capabilities"].initial = raw_capabilities
|
|
340
|
+
|
|
341
|
+
return form
|
|
342
|
+
|
|
343
|
+
def save_model(self, request, obj, form, change):
|
|
344
|
+
obj.is_system = True
|
|
345
|
+
obj.carrier_code = ext
|
|
346
|
+
return super().save_model(request, obj, form, change)
|
|
347
|
+
|
|
348
|
+
return type(f"{class_name}Admin", (_Admin,), {})
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@admin.register(providers.LabelTemplate)
|
|
352
|
+
class LabelTemplateAdmin(admin.ModelAdmin):
|
|
353
|
+
def has_module_permission(self, request):
|
|
354
|
+
return False
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
@utils.skip_on_commands()
|
|
358
|
+
def register_carrier_admins():
|
|
359
|
+
for carrier_name, display_name in ref.REFERENCES["carriers"].items():
|
|
360
|
+
proxy = providers.create_carrier_proxy(carrier_name, display_name)
|
|
361
|
+
admin.site.register(proxy, model_admin(carrier_name, proxy))
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
register_carrier_admins()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import django.db.models as models
|
|
2
|
+
|
|
3
|
+
import karrio.server.providers.models.carrier as providers
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AlliedExpressSettings(providers.Carrier):
|
|
7
|
+
class Meta:
|
|
8
|
+
db_table = "allied-express-settings"
|
|
9
|
+
verbose_name = "Allied Express Settings"
|
|
10
|
+
verbose_name_plural = "Allied Express Settings"
|
|
11
|
+
|
|
12
|
+
username = models.CharField(max_length=50)
|
|
13
|
+
password = models.CharField(max_length=50)
|
|
14
|
+
account = models.CharField(max_length=50, null=True, blank=True)
|
|
15
|
+
service_type = models.CharField(max_length=50, null=True, blank=True)
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def carrier_name(self) -> str:
|
|
19
|
+
return "allied_express"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SETTINGS = AlliedExpressSettings
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import django.db.models as models
|
|
2
|
+
|
|
3
|
+
import karrio.server.providers.models.carrier as providers
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AlliedExpressLocalSettings(providers.Carrier):
|
|
7
|
+
class Meta:
|
|
8
|
+
db_table = "allied-express-local-settings"
|
|
9
|
+
verbose_name = "Allied Express Local Settings"
|
|
10
|
+
verbose_name_plural = "Allied Express Local Settings"
|
|
11
|
+
|
|
12
|
+
username = models.CharField(max_length=50)
|
|
13
|
+
password = models.CharField(max_length=50)
|
|
14
|
+
account = models.CharField(max_length=50, null=True, blank=True)
|
|
15
|
+
service_type = models.CharField(max_length=50, null=True, blank=True)
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def carrier_name(self) -> str:
|
|
19
|
+
return "allied_express_local"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SETTINGS = AlliedExpressLocalSettings
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from karrio.server.providers.models.carrier import Carrier
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AmazonShippingSettings(Carrier):
|
|
6
|
+
CARRIER_NAME = "amazon_shipping"
|
|
7
|
+
|
|
8
|
+
class Meta:
|
|
9
|
+
db_table = "amazon_shipping-settings"
|
|
10
|
+
verbose_name = "Amazon Shipping Settings"
|
|
11
|
+
verbose_name_plural = "Amazon Shipping Settings"
|
|
12
|
+
|
|
13
|
+
seller_id = models.CharField(max_length=50)
|
|
14
|
+
developer_id = models.CharField(max_length=50)
|
|
15
|
+
mws_auth_token = models.CharField(max_length=50)
|
|
16
|
+
aws_region = models.CharField(max_length=50, default="us-east-1")
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def carrier_name(self) -> str:
|
|
20
|
+
return self.CARRIER_NAME
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def x_amz_access_token(self) -> str:
|
|
24
|
+
return "" # Setup the access token here.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
SETTINGS = AmazonShippingSettings
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from karrio.server.providers.models.carrier import Carrier, COUNTRIES
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AramexSettings(Carrier):
|
|
6
|
+
class Meta:
|
|
7
|
+
db_table = "aramex-settings"
|
|
8
|
+
verbose_name = "Aramex Settings"
|
|
9
|
+
verbose_name_plural = "Aramex Settings"
|
|
10
|
+
|
|
11
|
+
username = models.CharField(max_length=200)
|
|
12
|
+
password = models.CharField(max_length=200)
|
|
13
|
+
account_pin = models.CharField(max_length=200)
|
|
14
|
+
account_entity = models.CharField(max_length=200)
|
|
15
|
+
account_number = models.CharField(max_length=200)
|
|
16
|
+
account_country_code = models.CharField(
|
|
17
|
+
max_length=3, blank=True, null=True, choices=COUNTRIES
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def carrier_name(self) -> str:
|
|
22
|
+
return "aramex"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
SETTINGS = AramexSettings
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import django.db.models as models
|
|
2
|
+
import karrio.server.providers.models.carrier as providers
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AsendiaUSSettings(providers.Carrier):
|
|
6
|
+
class Meta:
|
|
7
|
+
db_table = "asendia-us-settings"
|
|
8
|
+
verbose_name = "Asendia US Settings"
|
|
9
|
+
verbose_name_plural = "Asendia US Settings"
|
|
10
|
+
|
|
11
|
+
username = models.CharField(max_length=100)
|
|
12
|
+
password = models.CharField(max_length=100)
|
|
13
|
+
api_key = models.CharField(max_length=100)
|
|
14
|
+
account_number = models.CharField(max_length=100, blank=True)
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def carrier_name(self) -> str:
|
|
18
|
+
return "asendia_us"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
SETTINGS = AsendiaUSSettings
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from karrio.server.providers.models.carrier import Carrier
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AustraliaPostSettings(Carrier):
|
|
6
|
+
class Meta:
|
|
7
|
+
db_table = "australia-post-settings"
|
|
8
|
+
verbose_name = "Australia Post Settings"
|
|
9
|
+
verbose_name_plural = "Australia Post Settings"
|
|
10
|
+
|
|
11
|
+
api_key = models.CharField(max_length=200)
|
|
12
|
+
password = models.CharField(max_length=200)
|
|
13
|
+
account_number = models.CharField(max_length=200)
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def carrier_name(self) -> str:
|
|
17
|
+
return "australiapost"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
SETTINGS = AustraliaPostSettings
|