karrio-server-pricing 2025.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. karrio/server/pricing/__init__.py +1 -0
  2. karrio/server/pricing/admin.py +55 -0
  3. karrio/server/pricing/apps.py +12 -0
  4. karrio/server/pricing/migrations/0001_initial.py +974 -0
  5. karrio/server/pricing/migrations/0002_auto_20201127_0721.py +855 -0
  6. karrio/server/pricing/migrations/0003_auto_20201230_0820.py +939 -0
  7. karrio/server/pricing/migrations/0004_auto_20201231_1402.py +940 -0
  8. karrio/server/pricing/migrations/0005_auto_20210204_1725.py +923 -0
  9. karrio/server/pricing/migrations/0006_auto_20210217_1109.py +1224 -0
  10. karrio/server/pricing/migrations/0007_auto_20210218_1202.py +955 -0
  11. karrio/server/pricing/migrations/0008_auto_20210418_0504.py +1010 -0
  12. karrio/server/pricing/migrations/0009_auto_20210603_2149.py +1043 -0
  13. karrio/server/pricing/migrations/0010_auto_20210612_1608.py +1070 -0
  14. karrio/server/pricing/migrations/0011_auto_20210615_1601.py +1109 -0
  15. karrio/server/pricing/migrations/0012_surcharge_carrier_accounts.py +23 -0
  16. karrio/server/pricing/migrations/0013_alter_surcharge_services.py +1086 -0
  17. karrio/server/pricing/migrations/0014_auto_20211013_1520.py +12 -0
  18. karrio/server/pricing/migrations/0015_auto_20211204_1350.py +1124 -0
  19. karrio/server/pricing/migrations/0016_auto_20211220_1500.py +1126 -0
  20. karrio/server/pricing/migrations/0017_alter_surcharge_services.py +1093 -0
  21. karrio/server/pricing/migrations/0018_alter_surcharge_services.py +1100 -0
  22. karrio/server/pricing/migrations/0019_alter_surcharge_services.py +1093 -0
  23. karrio/server/pricing/migrations/0020_auto_20220412_1215.py +3175 -0
  24. karrio/server/pricing/migrations/0021_auto_20220413_0959.py +3179 -0
  25. karrio/server/pricing/migrations/0022_alter_surcharge_services.py +3144 -0
  26. karrio/server/pricing/migrations/0023_auto_20220504_1335.py +3175 -0
  27. karrio/server/pricing/migrations/0024_auto_20220808_0803.py +3180 -0
  28. karrio/server/pricing/migrations/0025_alter_surcharge_carriers.py +51 -0
  29. karrio/server/pricing/migrations/0026_auto_20220828_0158.py +3199 -0
  30. karrio/server/pricing/migrations/0027_alter_surcharge_services.py +3170 -0
  31. karrio/server/pricing/migrations/0028_surcharge_markup_carriers_surcharge_markup_services.py +3016 -0
  32. karrio/server/pricing/migrations/0029_alter_surcharge_services.py +2939 -0
  33. karrio/server/pricing/migrations/0030_alter_surcharge_services.py +2940 -0
  34. karrio/server/pricing/migrations/0031_alter_surcharge_carriers.py +52 -0
  35. karrio/server/pricing/migrations/0032_alter_surcharge_services.py +2963 -0
  36. karrio/server/pricing/migrations/0033_alter_surcharge_services.py +2964 -0
  37. karrio/server/pricing/migrations/0034_alter_surcharge_carriers_alter_surcharge_services.py +3009 -0
  38. karrio/server/pricing/migrations/0035_alter_surcharge_carriers.py +56 -0
  39. karrio/server/pricing/migrations/0036_alter_surcharge_carriers_alter_surcharge_services.py +3022 -0
  40. karrio/server/pricing/migrations/0037_alter_surcharge_carriers_alter_surcharge_services.py +3078 -0
  41. karrio/server/pricing/migrations/0038_alter_surcharge_carriers_alter_surcharge_services.py +3093 -0
  42. karrio/server/pricing/migrations/0039_alter_surcharge_carriers_alter_surcharge_services.py +3095 -0
  43. karrio/server/pricing/migrations/0040_alter_surcharge_services.py +3058 -0
  44. karrio/server/pricing/migrations/0041_alter_surcharge_services.py +3061 -0
  45. karrio/server/pricing/migrations/0042_alter_surcharge_carriers_alter_surcharge_services.py +3128 -0
  46. karrio/server/pricing/migrations/0043_alter_surcharge_services.py +3090 -0
  47. karrio/server/pricing/migrations/0044_alter_surcharge_carriers.py +62 -0
  48. karrio/server/pricing/migrations/0045_alter_surcharge_carriers.py +63 -0
  49. karrio/server/pricing/migrations/0046_alter_surcharge_services.py +3100 -0
  50. karrio/server/pricing/migrations/0047_alter_surcharge_services.py +3171 -0
  51. karrio/server/pricing/migrations/0048_alter_surcharge_services.py +3195 -0
  52. karrio/server/pricing/migrations/0049_alter_surcharge_carriers_alter_surcharge_services.py +3246 -0
  53. karrio/server/pricing/migrations/0050_alter_surcharge_carriers.py +64 -0
  54. karrio/server/pricing/migrations/0051_alter_surcharge_carriers_alter_surcharge_services.py +2956 -0
  55. karrio/server/pricing/migrations/0052_alter_surcharge_carriers_alter_surcharge_services.py +3547 -0
  56. karrio/server/pricing/migrations/0053_alter_surcharge_carriers_alter_surcharge_services.py +3561 -0
  57. karrio/server/pricing/migrations/0054_alter_surcharge_services.py +3409 -0
  58. karrio/server/pricing/migrations/0055_alter_surcharge_services.py +3455 -0
  59. karrio/server/pricing/migrations/0056_alter_surcharge_carriers_alter_surcharge_services.py +3609 -0
  60. karrio/server/pricing/migrations/0057_alter_surcharge_carriers_alter_surcharge_services.py +4384 -0
  61. karrio/server/pricing/migrations/0058_alter_surcharge_services.py +4321 -0
  62. karrio/server/pricing/migrations/0059_alter_surcharge_carriers_alter_surcharge_services.py +4892 -0
  63. karrio/server/pricing/migrations/0060_alter_surcharge_services.py +4894 -0
  64. karrio/server/pricing/migrations/0061_alter_surcharge_services.py +4888 -0
  65. karrio/server/pricing/migrations/0062_alter_surcharge_carriers_alter_surcharge_services.py +4704 -0
  66. karrio/server/pricing/migrations/0063_alter_surcharge_carriers_alter_surcharge_services.py +34 -0
  67. karrio/server/pricing/migrations/0064_alter_surcharge_carriers_alter_surcharge_services.py +4669 -0
  68. karrio/server/pricing/migrations/0065_fix_surcharge_type_enum.py +36 -0
  69. karrio/server/pricing/migrations/0066_alter_surcharge_carriers_alter_surcharge_services_and_more.py +4712 -0
  70. karrio/server/pricing/migrations/0067_alter_surcharge_carriers_alter_surcharge_services.py +24 -0
  71. karrio/server/pricing/migrations/0068_alter_surcharge_carriers_alter_surcharge_services.py +24 -0
  72. karrio/server/pricing/migrations/0069_alter_surcharge_carriers_alter_surcharge_services.py +4707 -0
  73. karrio/server/pricing/migrations/0070_alter_surcharge_carriers_alter_surcharge_services.py +34 -0
  74. karrio/server/pricing/migrations/0071_alter_surcharge_carriers_alter_surcharge_services.py +4707 -0
  75. karrio/server/pricing/migrations/0072_alter_surcharge_carriers_alter_surcharge_services.py +24 -0
  76. karrio/server/pricing/migrations/__init__.py +0 -0
  77. karrio/server/pricing/models.py +153 -0
  78. karrio/server/pricing/serializers.py +18 -0
  79. karrio/server/pricing/signals.py +33 -0
  80. karrio/server/pricing/tests.py +301 -0
  81. karrio/server/pricing/views.py +3 -0
  82. karrio_server_pricing-2025.5.dist-info/METADATA +27 -0
  83. karrio_server_pricing-2025.5.dist-info/RECORD +85 -0
  84. karrio_server_pricing-2025.5.dist-info/WHEEL +5 -0
  85. karrio_server_pricing-2025.5.dist-info/top_level.txt +2 -0
@@ -0,0 +1,24 @@
1
+ # Generated by Django 5.2.7 on 2025-11-19 19:09
2
+
3
+ import karrio.server.core.fields
4
+ from django.db import migrations
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('pricing', '0071_alter_surcharge_carriers_alter_surcharge_services'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name='surcharge',
16
+ name='carriers',
17
+ field=karrio.server.core.fields.MultiChoiceField(blank=True, choices=[('australiapost', 'australiapost'), ('canadapost', 'canadapost'), ('dhl_express', 'dhl_express'), ('dhl_parcel_de', 'dhl_parcel_de'), ('dhl_poland', 'dhl_poland'), ('dhl_universal', 'dhl_universal'), ('dpd', 'dpd'), ('fedex', 'fedex'), ('generic', 'generic'), ('landmark', 'landmark'), ('laposte', 'laposte'), ('purolator', 'purolator'), ('seko', 'seko'), ('sendle', 'sendle'), ('ups', 'ups'), ('usps', 'usps'), ('usps_international', 'usps_international')], help_text='\n The list of carriers you want to apply the surcharge to.\n <br/>\n Note that by default, the surcharge is applied to all carriers\n ', null=True),
18
+ ),
19
+ migrations.AlterField(
20
+ model_name='surcharge',
21
+ name='services',
22
+ field=karrio.server.core.fields.MultiChoiceField(blank=True, choices=[('australiapost_parcel_post', 'australiapost_parcel_post'), ('australiapost_express_post', 'australiapost_express_post'), ('australiapost_parcel_post_signature', 'australiapost_parcel_post_signature'), ('australiapost_express_post_signature', 'australiapost_express_post_signature'), ('australiapost_intl_standard_pack_track', 'australiapost_intl_standard_pack_track'), ('australiapost_intl_standard_with_signature', 'australiapost_intl_standard_with_signature'), ('australiapost_intl_express_merch', 'australiapost_intl_express_merch'), ('australiapost_intl_express_docs', 'australiapost_intl_express_docs'), ('australiapost_eparcel_post_returns', 'australiapost_eparcel_post_returns'), ('australiapost_express_eparcel_post_returns', 'australiapost_express_eparcel_post_returns'), ('canadapost_regular_parcel', 'canadapost_regular_parcel'), ('canadapost_expedited_parcel', 'canadapost_expedited_parcel'), ('canadapost_xpresspost', 'canadapost_xpresspost'), ('canadapost_xpresspost_certified', 'canadapost_xpresspost_certified'), ('canadapost_priority', 'canadapost_priority'), ('canadapost_library_books', 'canadapost_library_books'), ('canadapost_expedited_parcel_usa', 'canadapost_expedited_parcel_usa'), ('canadapost_priority_worldwide_envelope_usa', 'canadapost_priority_worldwide_envelope_usa'), ('canadapost_priority_worldwide_pak_usa', 'canadapost_priority_worldwide_pak_usa'), ('canadapost_priority_worldwide_parcel_usa', 'canadapost_priority_worldwide_parcel_usa'), ('canadapost_small_packet_usa_air', 'canadapost_small_packet_usa_air'), ('canadapost_tracked_packet_usa', 'canadapost_tracked_packet_usa'), ('canadapost_tracked_packet_usa_lvm', 'canadapost_tracked_packet_usa_lvm'), ('canadapost_xpresspost_usa', 'canadapost_xpresspost_usa'), ('canadapost_xpresspost_international', 'canadapost_xpresspost_international'), ('canadapost_international_parcel_air', 'canadapost_international_parcel_air'), ('canadapost_international_parcel_surface', 'canadapost_international_parcel_surface'), ('canadapost_priority_worldwide_envelope_intl', 'canadapost_priority_worldwide_envelope_intl'), ('canadapost_priority_worldwide_pak_intl', 'canadapost_priority_worldwide_pak_intl'), ('canadapost_priority_worldwide_parcel_intl', 'canadapost_priority_worldwide_parcel_intl'), ('canadapost_small_packet_international_air', 'canadapost_small_packet_international_air'), ('canadapost_small_packet_international_surface', 'canadapost_small_packet_international_surface'), ('canadapost_tracked_packet_international', 'canadapost_tracked_packet_international'), ('dhl_logistics_services', 'dhl_logistics_services'), ('dhl_domestic_express_12_00', 'dhl_domestic_express_12_00'), ('dhl_express_choice', 'dhl_express_choice'), ('dhl_express_choice_nondoc', 'dhl_express_choice_nondoc'), ('dhl_jetline', 'dhl_jetline'), ('dhl_sprintline', 'dhl_sprintline'), ('dhl_air_capacity_sales', 'dhl_air_capacity_sales'), ('dhl_express_easy', 'dhl_express_easy'), ('dhl_express_easy_nondoc', 'dhl_express_easy_nondoc'), ('dhl_parcel_product', 'dhl_parcel_product'), ('dhl_accounting', 'dhl_accounting'), ('dhl_breakbulk_express', 'dhl_breakbulk_express'), ('dhl_medical_express', 'dhl_medical_express'), ('dhl_express_worldwide_doc', 'dhl_express_worldwide_doc'), ('dhl_express_9_00_nondoc', 'dhl_express_9_00_nondoc'), ('dhl_freight_worldwide_nondoc', 'dhl_freight_worldwide_nondoc'), ('dhl_economy_select_domestic', 'dhl_economy_select_domestic'), ('dhl_economy_select_nondoc', 'dhl_economy_select_nondoc'), ('dhl_express_domestic_9_00', 'dhl_express_domestic_9_00'), ('dhl_jumbo_box_nondoc', 'dhl_jumbo_box_nondoc'), ('dhl_express_9_00', 'dhl_express_9_00'), ('dhl_express_10_30', 'dhl_express_10_30'), ('dhl_express_10_30_nondoc', 'dhl_express_10_30_nondoc'), ('dhl_express_domestic', 'dhl_express_domestic'), ('dhl_express_domestic_10_30', 'dhl_express_domestic_10_30'), ('dhl_express_worldwide_nondoc', 'dhl_express_worldwide_nondoc'), ('dhl_medical_express_nondoc', 'dhl_medical_express_nondoc'), ('dhl_globalmail', 'dhl_globalmail'), ('dhl_same_day', 'dhl_same_day'), ('dhl_express_12_00', 'dhl_express_12_00'), ('dhl_express_worldwide', 'dhl_express_worldwide'), ('dhl_parcel_product_nondoc', 'dhl_parcel_product_nondoc'), ('dhl_economy_select', 'dhl_economy_select'), ('dhl_express_envelope', 'dhl_express_envelope'), ('dhl_express_12_00_nondoc', 'dhl_express_12_00_nondoc'), ('dhl_destination_charges', 'dhl_destination_charges'), ('dhl_express_all', 'dhl_express_all'), ('dhl_parcel_de_paket', 'dhl_parcel_de_paket'), ('dhl_parcel_de_warenpost', 'dhl_parcel_de_warenpost'), ('dhl_parcel_de_europaket', 'dhl_parcel_de_europaket'), ('dhl_parcel_de_paket_international', 'dhl_parcel_de_paket_international'), ('dhl_parcel_de_warenpost_international', 'dhl_parcel_de_warenpost_international'), ('dhl_poland_premium', 'dhl_poland_premium'), ('dhl_poland_polska', 'dhl_poland_polska'), ('dhl_poland_09', 'dhl_poland_09'), ('dhl_poland_12', 'dhl_poland_12'), ('dhl_poland_connect', 'dhl_poland_connect'), ('dhl_poland_international', 'dhl_poland_international'), ('dpd_cl', 'dpd_cl'), ('dpd_express_10h', 'dpd_express_10h'), ('dpd_express_12h', 'dpd_express_12h'), ('dpd_express_18h_guarantee', 'dpd_express_18h_guarantee'), ('dpd_express_b2b_predict', 'dpd_express_b2b_predict'), ('fedex_international_priority_express', 'fedex_international_priority_express'), ('fedex_international_first', 'fedex_international_first'), ('fedex_international_priority', 'fedex_international_priority'), ('fedex_international_economy', 'fedex_international_economy'), ('fedex_ground', 'fedex_ground'), ('fedex_cargo_mail', 'fedex_cargo_mail'), ('fedex_cargo_international_premium', 'fedex_cargo_international_premium'), ('fedex_first_overnight', 'fedex_first_overnight'), ('fedex_first_overnight_freight', 'fedex_first_overnight_freight'), ('fedex_1_day_freight', 'fedex_1_day_freight'), ('fedex_2_day_freight', 'fedex_2_day_freight'), ('fedex_3_day_freight', 'fedex_3_day_freight'), ('fedex_international_priority_freight', 'fedex_international_priority_freight'), ('fedex_international_economy_freight', 'fedex_international_economy_freight'), ('fedex_cargo_airport_to_airport', 'fedex_cargo_airport_to_airport'), ('fedex_international_priority_distribution', 'fedex_international_priority_distribution'), ('fedex_ip_direct_distribution_freight', 'fedex_ip_direct_distribution_freight'), ('fedex_intl_ground_distribution', 'fedex_intl_ground_distribution'), ('fedex_ground_home_delivery', 'fedex_ground_home_delivery'), ('fedex_smart_post', 'fedex_smart_post'), ('fedex_priority_overnight', 'fedex_priority_overnight'), ('fedex_standard_overnight', 'fedex_standard_overnight'), ('fedex_2_day', 'fedex_2_day'), ('fedex_2_day_am', 'fedex_2_day_am'), ('fedex_express_saver', 'fedex_express_saver'), ('fedex_same_day', 'fedex_same_day'), ('fedex_same_day_city', 'fedex_same_day_city'), ('fedex_one_day_freight', 'fedex_one_day_freight'), ('fedex_international_economy_distribution', 'fedex_international_economy_distribution'), ('fedex_international_connect_plus', 'fedex_international_connect_plus'), ('fedex_international_distribution_freight', 'fedex_international_distribution_freight'), ('fedex_regional_economy', 'fedex_regional_economy'), ('fedex_next_day_freight', 'fedex_next_day_freight'), ('fedex_next_day', 'fedex_next_day'), ('fedex_next_day_10am', 'fedex_next_day_10am'), ('fedex_next_day_12pm', 'fedex_next_day_12pm'), ('fedex_next_day_end_of_day', 'fedex_next_day_end_of_day'), ('fedex_distance_deferred', 'fedex_distance_deferred'), ('standard_service', 'standard_service'), ('landmark_maxipak_scan_ddp', 'landmark_maxipak_scan_ddp'), ('landmark_maxipak_scan_ddu', 'landmark_maxipak_scan_ddu'), ('landmark_minipak_scan_ddp', 'landmark_minipak_scan_ddp'), ('landmark_minipak_scan_ddu', 'landmark_minipak_scan_ddu'), ('landmark_maxipak_scan_ddp_pudo', 'landmark_maxipak_scan_ddp_pudo'), ('landmark_maxipak_scan_premium_ups_express_ddp', 'landmark_maxipak_scan_premium_ups_express_ddp'), ('landmark_maxipak_scan_premium_ups_express_ddu', 'landmark_maxipak_scan_premium_ups_express_ddu'), ('landmark_maxipak_scan_premium_ups_standard_ddp', 'landmark_maxipak_scan_premium_ups_standard_ddp'), ('landmark_maxipak_scan_premium_ups_standard_ddu', 'landmark_maxipak_scan_premium_ups_standard_ddu'), ('purolator_express_9_am', 'purolator_express_9_am'), ('purolator_express_us', 'purolator_express_us'), ('purolator_express_10_30_am', 'purolator_express_10_30_am'), ('purolator_express_us_9_am', 'purolator_express_us_9_am'), ('purolator_express_12_pm', 'purolator_express_12_pm'), ('purolator_express_us_10_30_am', 'purolator_express_us_10_30_am'), ('purolator_express', 'purolator_express'), ('purolator_express_us_12_00', 'purolator_express_us_12_00'), ('purolator_express_evening', 'purolator_express_evening'), ('purolator_express_envelope_us', 'purolator_express_envelope_us'), ('purolator_express_envelope_9_am', 'purolator_express_envelope_9_am'), ('purolator_express_us_envelope_9_am', 'purolator_express_us_envelope_9_am'), ('purolator_express_envelope_10_30_am', 'purolator_express_envelope_10_30_am'), ('purolator_express_us_envelope_10_30_am', 'purolator_express_us_envelope_10_30_am'), ('purolator_express_envelope_12_pm', 'purolator_express_envelope_12_pm'), ('purolator_express_us_envelope_12_00', 'purolator_express_us_envelope_12_00'), ('purolator_express_envelope', 'purolator_express_envelope'), ('purolator_express_pack_us', 'purolator_express_pack_us'), ('purolator_express_envelope_evening', 'purolator_express_envelope_evening'), ('purolator_express_us_pack_9_am', 'purolator_express_us_pack_9_am'), ('purolator_express_pack_9_am', 'purolator_express_pack_9_am'), ('purolator_express_us_pack_10_30_am', 'purolator_express_us_pack_10_30_am'), ('purolator_express_pack10_30_am', 'purolator_express_pack10_30_am'), ('purolator_express_us_pack_12_00', 'purolator_express_us_pack_12_00'), ('purolator_express_pack_12_pm', 'purolator_express_pack_12_pm'), ('purolator_express_box_us', 'purolator_express_box_us'), ('purolator_express_pack', 'purolator_express_pack'), ('purolator_express_us_box_9_am', 'purolator_express_us_box_9_am'), ('purolator_express_pack_evening', 'purolator_express_pack_evening'), ('purolator_express_us_box_10_30_am', 'purolator_express_us_box_10_30_am'), ('purolator_express_box_9_am', 'purolator_express_box_9_am'), ('purolator_express_us_box_12_00', 'purolator_express_us_box_12_00'), ('purolator_express_box_10_30_am', 'purolator_express_box_10_30_am'), ('purolator_ground_us', 'purolator_ground_us'), ('purolator_express_box_12_pm', 'purolator_express_box_12_pm'), ('purolator_express_international', 'purolator_express_international'), ('purolator_express_box', 'purolator_express_box'), ('purolator_express_international_9_am', 'purolator_express_international_9_am'), ('purolator_express_box_evening', 'purolator_express_box_evening'), ('purolator_express_international_10_30_am', 'purolator_express_international_10_30_am'), ('purolator_ground', 'purolator_ground'), ('purolator_express_international_12_00', 'purolator_express_international_12_00'), ('purolator_ground_9_am', 'purolator_ground_9_am'), ('purolator_express_envelope_international', 'purolator_express_envelope_international'), ('purolator_ground_10_30_am', 'purolator_ground_10_30_am'), ('purolator_express_international_envelope_9_am', 'purolator_express_international_envelope_9_am'), ('purolator_ground_evening', 'purolator_ground_evening'), ('purolator_express_international_envelope_10_30_am', 'purolator_express_international_envelope_10_30_am'), ('purolator_quick_ship', 'purolator_quick_ship'), ('purolator_express_international_envelope_12_00', 'purolator_express_international_envelope_12_00'), ('purolator_quick_ship_envelope', 'purolator_quick_ship_envelope'), ('purolator_express_pack_international', 'purolator_express_pack_international'), ('purolator_quick_ship_pack', 'purolator_quick_ship_pack'), ('purolator_express_international_pack_9_am', 'purolator_express_international_pack_9_am'), ('purolator_quick_ship_box', 'purolator_quick_ship_box'), ('purolator_express_international_pack_10_30_am', 'purolator_express_international_pack_10_30_am'), ('purolator_express_international_pack_12_00', 'purolator_express_international_pack_12_00'), ('purolator_express_box_international', 'purolator_express_box_international'), ('purolator_express_international_box_9_am', 'purolator_express_international_box_9_am'), ('purolator_express_international_box_10_30_am', 'purolator_express_international_box_10_30_am'), ('purolator_express_international_box_12_00', 'purolator_express_international_box_12_00'), ('seko_ecommerce_standard_tracked', 'seko_ecommerce_standard_tracked'), ('seko_ecommerce_express_tracked', 'seko_ecommerce_express_tracked'), ('seko_domestic_express', 'seko_domestic_express'), ('seko_domestic_standard', 'seko_domestic_standard'), ('seko_domestic_large_parcel', 'seko_domestic_large_parcel'), ('sendle_standard_pickup', 'sendle_standard_pickup'), ('sendle_standard_dropoff', 'sendle_standard_dropoff'), ('sendle_express_pickup', 'sendle_express_pickup'), ('ups_standard', 'ups_standard'), ('ups_worldwide_express', 'ups_worldwide_express'), ('ups_worldwide_expedited', 'ups_worldwide_expedited'), ('ups_worldwide_express_plus', 'ups_worldwide_express_plus'), ('ups_worldwide_saver', 'ups_worldwide_saver'), ('ups_2nd_day_air', 'ups_2nd_day_air'), ('ups_2nd_day_air_am', 'ups_2nd_day_air_am'), ('ups_3_day_select', 'ups_3_day_select'), ('ups_ground', 'ups_ground'), ('ups_next_day_air', 'ups_next_day_air'), ('ups_next_day_air_early', 'ups_next_day_air_early'), ('ups_next_day_air_saver', 'ups_next_day_air_saver'), ('ups_expedited_ca', 'ups_expedited_ca'), ('ups_express_saver_ca', 'ups_express_saver_ca'), ('ups_3_day_select_ca_us', 'ups_3_day_select_ca_us'), ('ups_access_point_economy_ca', 'ups_access_point_economy_ca'), ('ups_express_ca', 'ups_express_ca'), ('ups_express_early_ca', 'ups_express_early_ca'), ('ups_express_saver_intl_ca', 'ups_express_saver_intl_ca'), ('ups_standard_ca', 'ups_standard_ca'), ('ups_worldwide_expedited_ca', 'ups_worldwide_expedited_ca'), ('ups_worldwide_express_ca', 'ups_worldwide_express_ca'), ('ups_worldwide_express_plus_ca', 'ups_worldwide_express_plus_ca'), ('ups_express_early_ca_us', 'ups_express_early_ca_us'), ('ups_access_point_economy_eu', 'ups_access_point_economy_eu'), ('ups_expedited_eu', 'ups_expedited_eu'), ('ups_express_eu', 'ups_express_eu'), ('ups_standard_eu', 'ups_standard_eu'), ('ups_worldwide_express_plus_eu', 'ups_worldwide_express_plus_eu'), ('ups_worldwide_saver_eu', 'ups_worldwide_saver_eu'), ('ups_access_point_economy_mx', 'ups_access_point_economy_mx'), ('ups_expedited_mx', 'ups_expedited_mx'), ('ups_express_mx', 'ups_express_mx'), ('ups_standard_mx', 'ups_standard_mx'), ('ups_worldwide_express_plus_mx', 'ups_worldwide_express_plus_mx'), ('ups_worldwide_saver_mx', 'ups_worldwide_saver_mx'), ('ups_access_point_economy_pl', 'ups_access_point_economy_pl'), ('ups_today_dedicated_courrier_pl', 'ups_today_dedicated_courrier_pl'), ('ups_today_express_pl', 'ups_today_express_pl'), ('ups_today_express_saver_pl', 'ups_today_express_saver_pl'), ('ups_today_standard_pl', 'ups_today_standard_pl'), ('ups_expedited_pl', 'ups_expedited_pl'), ('ups_express_pl', 'ups_express_pl'), ('ups_express_plus_pl', 'ups_express_plus_pl'), ('ups_express_saver_pl', 'ups_express_saver_pl'), ('ups_standard_pl', 'ups_standard_pl'), ('ups_2nd_day_air_pr', 'ups_2nd_day_air_pr'), ('ups_ground_pr', 'ups_ground_pr'), ('ups_next_day_air_pr', 'ups_next_day_air_pr'), ('ups_next_day_air_early_pr', 'ups_next_day_air_early_pr'), ('ups_worldwide_expedited_pr', 'ups_worldwide_expedited_pr'), ('ups_worldwide_express_pr', 'ups_worldwide_express_pr'), ('ups_worldwide_express_plus_pr', 'ups_worldwide_express_plus_pr'), ('ups_worldwide_saver_pr', 'ups_worldwide_saver_pr'), ('ups_express_12_00_de', 'ups_express_12_00_de'), ('ups_worldwide_express_freight', 'ups_worldwide_express_freight'), ('ups_worldwide_express_freight_midday', 'ups_worldwide_express_freight_midday'), ('ups_worldwide_economy_ddu', 'ups_worldwide_economy_ddu'), ('ups_worldwide_economy_ddp', 'ups_worldwide_economy_ddp'), ('usps_parcel_select_lightweight', 'usps_parcel_select_lightweight'), ('usps_parcel_select', 'usps_parcel_select'), ('usps_priority_mail_express', 'usps_priority_mail_express'), ('usps_priority_mail', 'usps_priority_mail'), ('usps_library_mail', 'usps_library_mail'), ('usps_media_mail', 'usps_media_mail'), ('usps_bound_printed_matter', 'usps_bound_printed_matter'), ('usps_connect_local', 'usps_connect_local'), ('usps_connect_mail', 'usps_connect_mail'), ('usps_connect_next_day', 'usps_connect_next_day'), ('usps_connect_regional', 'usps_connect_regional'), ('usps_connect_same_day', 'usps_connect_same_day'), ('usps_ground_advantage', 'usps_ground_advantage'), ('usps_domestic_matter_for_the_blind', 'usps_domestic_matter_for_the_blind'), ('usps_all', 'usps_all'), ('usps_first_class_package_international_service', 'usps_first_class_package_international_service'), ('usps_priority_mail_international', 'usps_priority_mail_international'), ('usps_priority_mail_express_international', 'usps_priority_mail_express_international'), ('usps_global_express_guaranteed', 'usps_global_express_guaranteed'), ('usps_all', 'usps_all')], help_text='\n The list of services you want to apply the surcharge to.\n <br/>\n Note that by default, the surcharge is applied to all services\n ', null=True),
23
+ ),
24
+ ]
File without changes
@@ -0,0 +1,153 @@
1
+ import typing
2
+ import functools
3
+ import django.db.models as models
4
+ import django.core.validators as validators
5
+
6
+ import karrio.lib as lib
7
+ import karrio.core.models as karrio
8
+ import karrio.server.core.models as core
9
+ import karrio.server.core.fields as fields
10
+ import karrio.server.core.datatypes as datatypes
11
+ import karrio.server.providers.models as providers
12
+ import karrio.server.pricing.serializers as serializers
13
+ from karrio.server.core.logging import logger
14
+
15
+
16
+ @core.register_model
17
+ class Surcharge(core.ControlledAccessModel, core.Entity):
18
+ class Meta:
19
+ db_table = "surcharge"
20
+ verbose_name = "Markup"
21
+ verbose_name_plural = "Markups"
22
+
23
+ CONTEXT_RELATIONS = ["carrier_accounts"]
24
+
25
+ id = models.CharField(
26
+ max_length=50,
27
+ primary_key=True,
28
+ default=functools.partial(core.uuid, prefix="chrg_"),
29
+ editable=False,
30
+ )
31
+ active = models.BooleanField(default=True)
32
+
33
+ name = models.CharField(
34
+ max_length=100,
35
+ unique=True,
36
+ help_text="The surcharge name (label) that will appear in the rate (quote)",
37
+ )
38
+ amount = models.FloatField(
39
+ validators=[validators.MinValueValidator(0.1)],
40
+ default=0.0,
41
+ help_text="""
42
+ The surcharge amount or percentage to add to the quote
43
+ """,
44
+ )
45
+ surcharge_type = models.CharField(
46
+ max_length=25,
47
+ choices=serializers.SURCHAGE_TYPE,
48
+ default=serializers.SURCHAGE_TYPE[0][0],
49
+ help_text="""
50
+ Determine whether the surcharge is in percentage or net amount
51
+ <br/><br/>
52
+ For <strong>AMOUNT</strong>: rate ($22) and amount (1) will result in a new total_charge of ($23)
53
+ <br/>
54
+ For <strong>PERCENTAGE</strong>: rate ($22) and amount (5) will result in a new total_charge of ($23.10)
55
+ """,
56
+ )
57
+ carriers = fields.MultiChoiceField(
58
+ choices=serializers.CARRIERS,
59
+ null=True,
60
+ blank=True,
61
+ help_text="""
62
+ The list of carriers you want to apply the surcharge to.
63
+ <br/>
64
+ Note that by default, the surcharge is applied to all carriers
65
+ """,
66
+ )
67
+ carrier_accounts = models.ManyToManyField(
68
+ providers.Carrier,
69
+ blank=True,
70
+ help_text="""
71
+ The list of carrier accounts you want to apply the surcharge to.
72
+ <br/>
73
+ Note that by default, the surcharge is applied to all carrier accounts
74
+ """,
75
+ )
76
+ services = fields.MultiChoiceField(
77
+ choices=serializers.SERVICES,
78
+ null=True,
79
+ blank=True,
80
+ help_text="""
81
+ The list of services you want to apply the surcharge to.
82
+ <br/>
83
+ Note that by default, the surcharge is applied to all services
84
+ """,
85
+ )
86
+
87
+ @property
88
+ def object_type(self):
89
+ return "surcharge"
90
+
91
+ def __str__(self):
92
+ type_ = "$" if self.surcharge_type == "AMOUNT" else "%"
93
+ return f"{self.id} ({self.amount} {type_})"
94
+
95
+ def apply_charge(self, response: datatypes.RateResponse) -> datatypes.RateResponse:
96
+ def apply(rate: datatypes.Rate) -> datatypes.Rate:
97
+ applicable = []
98
+ carrier_ids = [c.carrier_id for c in self.carrier_accounts.all()]
99
+ charges = getattr(rate, "extra_charges", None) or []
100
+
101
+ if any(self.carriers or []):
102
+ # For custom carriers (ext="generic"), check if "generic" is in the addon's carrier list
103
+ # since rate.carrier_name contains custom_carrier_name but users select "generic"
104
+ if (
105
+ rate.meta
106
+ and rate.meta.get("ext") == "generic"
107
+ and "generic" in self.carriers
108
+ ):
109
+ applicable.append(True)
110
+ else:
111
+ applicable.append(rate.carrier_name in self.carriers)
112
+
113
+ if any(carrier_ids):
114
+ applicable.append(rate.carrier_id in carrier_ids)
115
+
116
+ if any(self.services or []):
117
+ applicable.append(rate.service in self.services)
118
+
119
+ if any(applicable) and all(applicable):
120
+ logger.debug("Applying broker surcharge to rate", rate_id=rate.id, surcharge_id=self.id)
121
+
122
+ amount = lib.to_decimal(
123
+ self.amount
124
+ if self.surcharge_type == "AMOUNT"
125
+ else (rate.total_charge * (typing.cast(float, self.amount) / 100))
126
+ )
127
+ total_charge = lib.to_decimal(rate.total_charge + amount)
128
+ extra_charges = rate.extra_charges + [
129
+ karrio.ChargeDetails(
130
+ name=typing.cast(str, self.name),
131
+ amount=amount,
132
+ currency=rate.currency,
133
+ id=self.id,
134
+ )
135
+ ]
136
+
137
+ return datatypes.Rate(
138
+ **{
139
+ **lib.to_dict(rate),
140
+ "total_charge": total_charge,
141
+ "extra_charges": extra_charges,
142
+ }
143
+ )
144
+
145
+ return rate
146
+
147
+ return datatypes.RateResponse(
148
+ messages=response.messages,
149
+ rates=sorted(
150
+ [apply(rate) for rate in response.rates],
151
+ key=lambda rate: rate.total_charge,
152
+ ),
153
+ )
@@ -0,0 +1,18 @@
1
+ import enum
2
+ import karrio.server.core.dataunits as dataunits
3
+ from karrio.server.core.serializers import (
4
+ CARRIERS,
5
+ )
6
+
7
+
8
+ class SurchargeType(enum.Enum):
9
+ AMOUNT = "AMOUNT"
10
+ PERCENTAGE = "PERCENTAGE"
11
+
12
+
13
+ CARRIER_SERVICES = [
14
+ dataunits.REFERENCE_MODELS["services"][name]
15
+ for name in sorted(dataunits.REFERENCE_MODELS["services"].keys())
16
+ ]
17
+ SERVICES = [(code, code) for services in CARRIER_SERVICES for code in services]
18
+ SURCHAGE_TYPE = [(c.name, c.name) for c in list(SurchargeType)]
@@ -0,0 +1,33 @@
1
+ import functools
2
+ import importlib
3
+ from django.db.models import Q
4
+
5
+ from karrio.server.serializers import Context
6
+ from karrio.server.core.gateway import Rates
7
+ from karrio.server.core.logging import logger
8
+ import karrio.server.pricing.models as models
9
+
10
+
11
+ def register_rate_post_processing(*args, **kwargs):
12
+ Rates.post_process_functions += [apply_custom_surcharges]
13
+ logger.info("Signal registration complete", module="karrio.pricing")
14
+
15
+
16
+ def apply_custom_surcharges(context: Context, result):
17
+ _filters = tuple()
18
+
19
+ if importlib.util.find_spec("karrio.server.orgs") is not None:
20
+ _filters += (
21
+ Q(active=True, org__id=getattr(context.org, "id", None))
22
+ | Q(active=True, org=None),
23
+ )
24
+ else:
25
+ _filters += (Q(active=True),)
26
+
27
+ charges = models.Surcharge.objects.filter(*_filters)
28
+
29
+ return functools.reduce(
30
+ lambda cummulated_result, charge: charge.apply_charge(cummulated_result),
31
+ charges,
32
+ result,
33
+ )
@@ -0,0 +1,301 @@
1
+ import json
2
+ import logging
3
+ from unittest.mock import patch, ANY
4
+ from django.urls import reverse
5
+ from rest_framework import status
6
+ from karrio.core.models import RateDetails, ChargeDetails
7
+ from karrio.server.core.tests import APITestCase
8
+ import karrio.server.pricing.models as models
9
+
10
+ logging.disable(logging.CRITICAL)
11
+
12
+
13
+ class TestPricing(APITestCase):
14
+ def setUp(self) -> None:
15
+ super().setUp()
16
+
17
+ self.charge: models.Surcharge = models.Surcharge.objects.create(
18
+ **{
19
+ "amount": 1.0,
20
+ "name": "brokerage",
21
+ "carriers": ["canadapost"],
22
+ "services": ["canadapost_priority", "canadapost_regular_parcel"],
23
+ }
24
+ )
25
+
26
+ def test_apply_surcharge_amount_to_shipment_rates(self):
27
+ url = reverse("karrio.server.proxy:shipment-rates")
28
+ data = RATING_DATA
29
+
30
+ with patch("karrio.server.core.gateway.utils.identity") as mock:
31
+ mock.return_value = RETURNED_VALUE
32
+ response = self.client.post(f"{url}", data)
33
+ response_data = json.loads(response.content)
34
+
35
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
36
+ self.assertDictEqual(response_data, RATING_RESPONSE)
37
+
38
+ def test_apply_surcharge_percentage_to_shipment_rates(self):
39
+ self.charge.amount = 2.0
40
+ self.charge.surcharge_type = "PERCENTAGE"
41
+ self.charge.save()
42
+ url = reverse("karrio.server.proxy:shipment-rates")
43
+ data = RATING_DATA
44
+
45
+ with patch("karrio.server.core.gateway.utils.identity") as mock:
46
+ mock.return_value = RETURNED_VALUE
47
+ response = self.client.post(f"{url}", data)
48
+ response_data = json.loads(response.content)
49
+
50
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
51
+ self.assertDictEqual(response_data, RATING_WITH_PERCENTAGE_RESPONSE)
52
+
53
+
54
+ RATING_DATA = {
55
+ "shipper": {
56
+ "postal_code": "V6M2V9",
57
+ "city": "Vancouver",
58
+ "country_code": "CA",
59
+ "state_code": "BC",
60
+ "residential": True,
61
+ "address_line1": "5840 Oak St",
62
+ },
63
+ "recipient": {
64
+ "postal_code": "E1C4Z8",
65
+ "city": "Moncton",
66
+ "country_code": "CA",
67
+ "state_code": "NB",
68
+ "residential": False,
69
+ "address_line1": "125 Church St",
70
+ },
71
+ "parcels": [
72
+ {
73
+ "weight": 1,
74
+ "weight_unit": "KG",
75
+ "packagePreset": "canadapost_corrugated_small_box",
76
+ }
77
+ ],
78
+ "services": [],
79
+ "carrier_ids": ["canadapost"],
80
+ }
81
+
82
+ RETURNED_VALUE = (
83
+ [
84
+ RateDetails(
85
+ carrier_id="canadapost",
86
+ carrier_name="canadapost",
87
+ currency="CAD",
88
+ transit_days=7,
89
+ service="canadapost_expedited_parcel",
90
+ total_charge=32.99,
91
+ extra_charges=[
92
+ ChargeDetails(amount=29.64, currency="CAD", name="Base charge"),
93
+ ChargeDetails(amount=1.24, currency="CAD", name="Fuel surcharge"),
94
+ ChargeDetails(amount=-2.19, currency="CAD", name="SMB Savings"),
95
+ ChargeDetails(amount=4.3, currency="CAD", name="Duty and taxes"),
96
+ ChargeDetails(amount=-0.95, currency="CAD", name="Discount"),
97
+ ],
98
+ ),
99
+ RateDetails(
100
+ carrier_id="canadapost",
101
+ carrier_name="canadapost",
102
+ currency="CAD",
103
+ transit_days=2,
104
+ service="canadapost_xpresspost",
105
+ total_charge=85.65,
106
+ extra_charges=[
107
+ ChargeDetails(amount=75.82, currency="CAD", name="Base charge"),
108
+ ChargeDetails(amount=3.21, currency="CAD", name="Fuel surcharge"),
109
+ ChargeDetails(amount=-4.55, currency="CAD", name="SMB Savings"),
110
+ ChargeDetails(amount=4.3, currency="CAD", name="Duty and taxes"),
111
+ ChargeDetails(amount=11.17, currency="CAD", name="Discount"),
112
+ ],
113
+ ),
114
+ RateDetails(
115
+ carrier_id="canadapost",
116
+ carrier_name="canadapost",
117
+ currency="CAD",
118
+ transit_days=2,
119
+ service="canadapost_priority",
120
+ total_charge=113.93,
121
+ extra_charges=[
122
+ ChargeDetails(amount=101.83, currency="CAD", name="Base charge"),
123
+ ChargeDetails(amount=4.27, currency="CAD", name="Fuel surcharge"),
124
+ ChargeDetails(amount=-7.03, currency="CAD", name="SMB Savings"),
125
+ ChargeDetails(amount=14.86, currency="CAD", name="Duties and taxes"),
126
+ ChargeDetails(amount=-2.76, currency="CAD", name="Discount"),
127
+ ],
128
+ ),
129
+ ],
130
+ [],
131
+ )
132
+
133
+ RATING_RESPONSE = {
134
+ "messages": [],
135
+ "rates": [
136
+ {
137
+ "id": ANY,
138
+ "object_type": "rate",
139
+ "carrier_name": "canadapost",
140
+ "carrier_id": "canadapost",
141
+ "currency": "CAD",
142
+ "estimated_delivery": ANY,
143
+ "service": "canadapost_expedited_parcel",
144
+ "total_charge": 32.99,
145
+ "transit_days": 7,
146
+ "extra_charges": [
147
+ {"name": "Base charge", "amount": 29.64, "currency": "CAD", "id": None},
148
+ {"name": "Fuel surcharge", "amount": 1.24, "currency": "CAD", "id": None},
149
+ {"name": "SMB Savings", "amount": -2.19, "currency": "CAD", "id": None},
150
+ {"name": "Duty and taxes", "amount": 4.3, "currency": "CAD", "id": None},
151
+ {"name": "Discount", "amount": -0.95, "currency": "CAD", "id": None},
152
+ ],
153
+ "meta": {
154
+ "ext": "canadapost",
155
+ "carrier": "canadapost",
156
+ "rate_provider": "canadapost",
157
+ "service_name": "CANADAPOST EXPEDITED PARCEL",
158
+ "carrier_connection_id": ANY,
159
+ },
160
+ "test_mode": True,
161
+ },
162
+ {
163
+ "id": ANY,
164
+ "object_type": "rate",
165
+ "carrier_name": "canadapost",
166
+ "carrier_id": "canadapost",
167
+ "currency": "CAD",
168
+ "estimated_delivery": ANY,
169
+ "service": "canadapost_xpresspost",
170
+ "total_charge": 85.65,
171
+ "transit_days": 2,
172
+ "extra_charges": [
173
+ {"name": "Base charge", "amount": 75.82, "currency": "CAD", "id": None},
174
+ {"name": "Fuel surcharge", "amount": 3.21, "currency": "CAD", "id": None},
175
+ {"name": "SMB Savings", "amount": -4.55, "currency": "CAD", "id": None},
176
+ {"name": "Duty and taxes", "amount": 4.3, "currency": "CAD", "id": None},
177
+ {"name": "Discount", "amount": 11.17, "currency": "CAD", "id": None},
178
+ ],
179
+ "meta": {
180
+ "ext": "canadapost",
181
+ "carrier": "canadapost",
182
+ "rate_provider": "canadapost",
183
+ "service_name": "CANADAPOST XPRESSPOST",
184
+ "carrier_connection_id": ANY,
185
+ },
186
+ "test_mode": True,
187
+ },
188
+ {
189
+ "id": ANY,
190
+ "object_type": "rate",
191
+ "carrier_name": "canadapost",
192
+ "carrier_id": "canadapost",
193
+ "currency": "CAD",
194
+ "estimated_delivery": ANY,
195
+ "service": "canadapost_priority",
196
+ "total_charge": 114.93,
197
+ "transit_days": 2,
198
+ "extra_charges": [
199
+ {"name": "Base charge", "amount": 101.83, "currency": "CAD", "id": None},
200
+ {"name": "Fuel surcharge", "amount": 4.27, "currency": "CAD", "id": None},
201
+ {"name": "SMB Savings", "amount": -7.03, "currency": "CAD", "id": None},
202
+ {"name": "Duties and taxes", "amount": 14.86, "currency": "CAD", "id": None},
203
+ {"name": "Discount", "amount": -2.76, "currency": "CAD", "id": None},
204
+ {"name": "brokerage", "amount": 1.0, "currency": "CAD", "id": ANY},
205
+ ],
206
+ "meta": {
207
+ "ext": "canadapost",
208
+ "carrier": "canadapost",
209
+ "carrier_connection_id": ANY,
210
+ "rate_provider": "canadapost",
211
+ "service_name": "CANADAPOST PRIORITY",
212
+ },
213
+ "test_mode": True,
214
+ },
215
+ ],
216
+ }
217
+
218
+ RATING_WITH_PERCENTAGE_RESPONSE = {
219
+ "messages": [],
220
+ "rates": [
221
+ {
222
+ "id": ANY,
223
+ "object_type": "rate",
224
+ "carrier_name": "canadapost",
225
+ "carrier_id": "canadapost",
226
+ "currency": "CAD",
227
+ "estimated_delivery": ANY,
228
+ "service": "canadapost_expedited_parcel",
229
+ "total_charge": 32.99,
230
+ "transit_days": 7,
231
+ "extra_charges": [
232
+ {"name": "Base charge", "amount": 29.64, "currency": "CAD", "id": None},
233
+ {"name": "Fuel surcharge", "amount": 1.24, "currency": "CAD", "id": None},
234
+ {"name": "SMB Savings", "amount": -2.19, "currency": "CAD", "id": None},
235
+ {"name": "Duty and taxes", "amount": 4.3, "currency": "CAD", "id": None},
236
+ {"name": "Discount", "amount": -0.95, "currency": "CAD", "id": None},
237
+ ],
238
+ "meta": {
239
+ "ext": "canadapost",
240
+ "carrier": "canadapost",
241
+ "rate_provider": "canadapost",
242
+ "service_name": "CANADAPOST EXPEDITED PARCEL",
243
+ "carrier_connection_id": ANY,
244
+ },
245
+ "test_mode": True,
246
+ },
247
+ {
248
+ "id": ANY,
249
+ "object_type": "rate",
250
+ "carrier_name": "canadapost",
251
+ "carrier_id": "canadapost",
252
+ "currency": "CAD",
253
+ "estimated_delivery": ANY,
254
+ "service": "canadapost_xpresspost",
255
+ "total_charge": 85.65,
256
+ "transit_days": 2,
257
+ "extra_charges": [
258
+ {"name": "Base charge", "amount": 75.82, "currency": "CAD", "id": None},
259
+ {"name": "Fuel surcharge", "amount": 3.21, "currency": "CAD", "id": None},
260
+ {"name": "SMB Savings", "amount": -4.55, "currency": "CAD", "id": None},
261
+ {"name": "Duty and taxes", "amount": 4.3, "currency": "CAD", "id": None},
262
+ {"name": "Discount", "amount": 11.17, "currency": "CAD", "id": None},
263
+ ],
264
+ "meta": {
265
+ "ext": "canadapost",
266
+ "carrier": "canadapost",
267
+ "rate_provider": "canadapost",
268
+ "service_name": "CANADAPOST XPRESSPOST",
269
+ "carrier_connection_id": ANY,
270
+ },
271
+ "test_mode": True,
272
+ },
273
+ {
274
+ "id": ANY,
275
+ "object_type": "rate",
276
+ "carrier_name": "canadapost",
277
+ "carrier_id": "canadapost",
278
+ "currency": "CAD",
279
+ "estimated_delivery": ANY,
280
+ "service": "canadapost_priority",
281
+ "total_charge": 116.21,
282
+ "transit_days": 2,
283
+ "extra_charges": [
284
+ {"name": "Base charge", "amount": 101.83, "currency": "CAD", "id": None},
285
+ {"name": "Fuel surcharge", "amount": 4.27, "currency": "CAD", "id": None},
286
+ {"name": "SMB Savings", "amount": -7.03, "currency": "CAD", "id": None},
287
+ {"name": "Duties and taxes", "amount": 14.86, "currency": "CAD", "id": None},
288
+ {"name": "Discount", "amount": -2.76, "currency": "CAD", "id": None},
289
+ {"name": "brokerage", "amount": 2.28, "currency": "CAD", "id": ANY},
290
+ ],
291
+ "meta": {
292
+ "ext": "canadapost",
293
+ "carrier": "canadapost",
294
+ "carrier_connection_id": ANY,
295
+ "rate_provider": "canadapost",
296
+ "service_name": "CANADAPOST PRIORITY",
297
+ },
298
+ "test_mode": True,
299
+ },
300
+ ],
301
+ }
@@ -0,0 +1,3 @@
1
+ from django.shortcuts import render
2
+
3
+ # Create your views here.
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: karrio_server_pricing
3
+ Version: 2025.5
4
+ Summary: Multi-carrier shipping API Pricing panel
5
+ Author-email: karrio <hello@karrio.io>
6
+ License-Expression: LGPL-3.0
7
+ Project-URL: Homepage, https://github.com/karrioapi/karrio
8
+ Classifier: Programming Language :: Python :: 3
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: karrio_server_core
12
+
13
+ # karrio.server.pricing
14
+
15
+ This package is a module of the [karrio](https://pypi.org/project/karrio.server) universal shipping API.
16
+
17
+ ## Requirements
18
+
19
+ `Python 3.11+`
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pip install karrio.server.pricing
25
+ ```
26
+
27
+ Check the [karrio docs](https://docs.karrio.io) to get started.