click_and_drop_api 3.0.3__tar.gz → 3.0.4__tar.gz
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.
- {click_and_drop_api-3.0.3/click_and_drop_api.egg-info → click_and_drop_api-3.0.4}/PKG-INFO +1 -1
- click_and_drop_api-3.0.4/click_and_drop_api/examples/mock-label.pdf +0 -0
- click_and_drop_api-3.0.4/click_and_drop_api/examples/mock-manifest.pdf +0 -0
- click_and_drop_api-3.0.4/click_and_drop_api/examples/oba_full_workflow.py +138 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/api.py +10 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/base.py +185 -2
- click_and_drop_api-3.0.4/click_and_drop_api/simple/compatibility.py +8 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/mock.py +48 -2
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/types.py +13 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4/click_and_drop_api.egg-info}/PKG-INFO +1 -1
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/SOURCES.txt +6 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/pyproject.toml +4 -1
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_mock_api.py +15 -0
- click_and_drop_api-3.0.4/test/test_mock_api_manifest.py +51 -0
- click_and_drop_api-3.0.4/test/test_mock_api_update_orders.py +207 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/LICENSE +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/MANIFEST.in +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/README.md +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/labels_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/manifests_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/orders_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/version_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api_client.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/configuration.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/__main__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/check_oba.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/create_order.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/generate_label.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/package_size_and_cost.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/shipping_countries.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_order.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_specific_orders.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_version.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/exceptions.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/address_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/billing_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_label_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_orders_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_packages_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/delete_orders_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/deleted_order_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/dimensions_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/failed_order_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_details_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_info_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_line_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_orders_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_postal_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_shipping_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_tag_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_version_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/importer.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/label_generation_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_eligible_orders_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_errors_error_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_errors_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_error_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_field_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_update_error.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/postage_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/product_item_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/recipient_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/sender_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/shipment_package_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/tag_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_order_status_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_order_status_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_orders_status_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/updated_order_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/py.typed +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/rest.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/addresses.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/errors.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/__init__.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/db.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/documents.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/format_dimensions.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/large_letter.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/large_parcel.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/letter.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/medium_parcel.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_letter-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_letter-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_parcel-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_parcel-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/letter-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/letter-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/medium_parcel-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/medium_parcel-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/small_parcel-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/small_parcel-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/documents-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/large_letter-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/large_letter-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/letter-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/letter-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/parcel-DE.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/parcel-GB.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba_parser.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/package_shipping_option.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/parcel.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/parser.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/small_parcel.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping_test_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/dependency_links.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/requires.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/top_level.txt +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/setup.cfg +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/setup.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_address_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_billing_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_choose_size_by_weight.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_label_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_orders_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_packages_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_delete_orders_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_deleted_order_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_dimensions_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_failed_order_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_details_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_info_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_line_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_orders_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_postal_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_shipping_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_tag_details_result.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_version_resource.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_importer.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_label_generation_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_labels_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_eligible_orders_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_errors_error_details_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_errors_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_orders_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifests_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_oba_parser.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_error_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_error_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_field_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_update_error.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_orders_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_parcel_constraints.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_parcel_weights.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_postage_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_product_item_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_recipient_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_sender_details_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipment_package_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipping_option_model.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipping_options.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_simple_create_api.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_tag_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_order_status_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_order_status_response.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_orders_status_request.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_updated_order_info.py +0 -0
- {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_version_api.py +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Full OBA workflow: create a cheap domestic order, generate a label,
|
|
3
|
+
apply postage via manifest, and mark the order as despatched.
|
|
4
|
+
|
|
5
|
+
Steps performed:
|
|
6
|
+
1. Verify the account is OBA (required for label generation and OBA services)
|
|
7
|
+
2. Pick the cheapest domestic OBA service
|
|
8
|
+
3. Create the order (with label generation requested at creation time)
|
|
9
|
+
4. Save the label PDF to disk
|
|
10
|
+
5. Manifest eligible orders (applies postage)
|
|
11
|
+
6. Set the order status to "despatched"
|
|
12
|
+
|
|
13
|
+
Note: Label generation is only available for OBA customers.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from datetime import datetime, UTC
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from click_and_drop_api.simple import (
|
|
22
|
+
ClickAndDrop,
|
|
23
|
+
CreateOrder,
|
|
24
|
+
LabelGeneration,
|
|
25
|
+
RecipientDetails,
|
|
26
|
+
Address,
|
|
27
|
+
db,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
# Configuration
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
API_KEY = os.environ["API_KEY"]
|
|
35
|
+
REFERENCE = "oba-workflow-{now}".format(now=datetime.now(UTC).strftime("%Y%m%d%H%M%S"))
|
|
36
|
+
WEIGHT_GRAMS = 100
|
|
37
|
+
|
|
38
|
+
api = ClickAndDrop(API_KEY)
|
|
39
|
+
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
# Step 1: verify OBA
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
print("Checking account type…")
|
|
45
|
+
if not api.is_oba():
|
|
46
|
+
print("ERROR: This account is not OBA. Label generation requires an OBA account.")
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
print("Account is OBA.")
|
|
49
|
+
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
# Step 2: pick cheapest domestic OBA service
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
cheapest = db.filter(is_oba=True, international=False).any_or_none
|
|
55
|
+
if cheapest is None:
|
|
56
|
+
print("ERROR: No domestic OBA service found in the shipping database.")
|
|
57
|
+
sys.exit(1)
|
|
58
|
+
|
|
59
|
+
print(
|
|
60
|
+
f"Using service: {cheapest.brand} {cheapest.service_code}"
|
|
61
|
+
f" ({cheapest.delivery_speed}) — £{cheapest.gross}"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
# Step 3: create the order, requesting a label in the response
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
order = CreateOrder(
|
|
69
|
+
order_reference=REFERENCE,
|
|
70
|
+
recipient=RecipientDetails(
|
|
71
|
+
address=Address(
|
|
72
|
+
full_name="Nicco Kunzmann",
|
|
73
|
+
address_line1="1 Test Street",
|
|
74
|
+
city="London",
|
|
75
|
+
postcode="SW1A 1AA",
|
|
76
|
+
country_code="GB",
|
|
77
|
+
)
|
|
78
|
+
),
|
|
79
|
+
order_date=datetime.now(UTC),
|
|
80
|
+
subtotal=1.00,
|
|
81
|
+
shipping_cost_charged=float(cheapest.gross),
|
|
82
|
+
total=1.00 + float(cheapest.gross),
|
|
83
|
+
currency_code="GBP",
|
|
84
|
+
postage_details=cheapest.as_postage_details(),
|
|
85
|
+
packages=[cheapest.as_package_request(weight_in_grams=WEIGHT_GRAMS)],
|
|
86
|
+
label=LabelGeneration(
|
|
87
|
+
include_label_in_response=True,
|
|
88
|
+
include_cn=False,
|
|
89
|
+
include_returns_label=False,
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
print(f"Creating order {REFERENCE!r}…")
|
|
94
|
+
response = api.create_order(order)
|
|
95
|
+
|
|
96
|
+
if response.errors_count or not response.created_orders:
|
|
97
|
+
print(f"ERROR: Order creation failed: {response.failed_orders}")
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
created = response.created_orders[0]
|
|
101
|
+
order_id = created.order_identifier
|
|
102
|
+
print(f"Order created: id={order_id}, reference={created.order_reference}")
|
|
103
|
+
|
|
104
|
+
# ---------------------------------------------------------------------------
|
|
105
|
+
# Step 4: save label PDF
|
|
106
|
+
# ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
print("Fetching label…")
|
|
109
|
+
label_pdf = api.get_label(order_id, "postageLabel", include_returns_label=False)
|
|
110
|
+
label_path = Path(__file__).parent / "label.pdf"
|
|
111
|
+
label_path.write_bytes(label_pdf)
|
|
112
|
+
print(f"Label saved to {label_path}")
|
|
113
|
+
|
|
114
|
+
# ---------------------------------------------------------------------------
|
|
115
|
+
# Step 5: manifest (applies postage)
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
print("Manifesting eligible orders…")
|
|
119
|
+
manifest = api.manifest_orders()
|
|
120
|
+
print(f"Manifest number: {manifest.manifest_number}")
|
|
121
|
+
if manifest.pdf is not None:
|
|
122
|
+
manifest_path = Path(__file__).parent / "manifest.pdf"
|
|
123
|
+
manifest_path.write_bytes(manifest.pdf)
|
|
124
|
+
print(f"Manifest PDF saved to {manifest_path}")
|
|
125
|
+
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
# Step 6: mark as despatched
|
|
128
|
+
# ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
print(f"Setting order {order_id} to 'despatched'…")
|
|
131
|
+
update = api.update_orders([order_id], status="despatched")
|
|
132
|
+
|
|
133
|
+
if update.errors:
|
|
134
|
+
print(f"WARNING: status update errors: {update.errors}")
|
|
135
|
+
else:
|
|
136
|
+
print("Order marked as despatched.")
|
|
137
|
+
|
|
138
|
+
print("Done.")
|
|
@@ -170,5 +170,15 @@ class ClickAndDrop(AbstractClickAndDrop):
|
|
|
170
170
|
include_cn=include_cn,
|
|
171
171
|
)
|
|
172
172
|
|
|
173
|
+
def _set_order_status(
|
|
174
|
+
self, request: click_and_drop_api.UpdateOrdersStatusRequest
|
|
175
|
+
) -> click_and_drop_api.UpdateOrderStatusResponse:
|
|
176
|
+
return self._orders_api.update_orders_status_async(request)
|
|
177
|
+
|
|
178
|
+
def _manifest_orders(
|
|
179
|
+
self, request: click_and_drop_api.ManifestEligibleOrdersRequest
|
|
180
|
+
) -> click_and_drop_api.ManifestOrdersResponse:
|
|
181
|
+
return self._manifests_api.manifest_eligible_async(request)
|
|
182
|
+
|
|
173
183
|
|
|
174
184
|
__all__ = ["ClickAndDrop"]
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
|
+
import os
|
|
6
7
|
from typing import Literal, Optional, Union
|
|
8
|
+
from click_and_drop_api.simple.compatibility import Self
|
|
7
9
|
|
|
8
10
|
import click_and_drop_api
|
|
9
11
|
|
|
@@ -12,7 +14,17 @@ from datetime import datetime, timezone
|
|
|
12
14
|
|
|
13
15
|
from click_and_drop_api.exceptions import ApiException
|
|
14
16
|
from click_and_drop_api.models.create_order_response import CreateOrderResponse
|
|
17
|
+
from click_and_drop_api.models.manifest_eligible_orders_request import (
|
|
18
|
+
ManifestEligibleOrdersRequest,
|
|
19
|
+
)
|
|
20
|
+
from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
|
|
15
21
|
from click_and_drop_api.models.order_field_response import OrderFieldResponse
|
|
22
|
+
from click_and_drop_api.models.update_order_status_response import (
|
|
23
|
+
UpdateOrderStatusResponse,
|
|
24
|
+
)
|
|
25
|
+
from click_and_drop_api.models.update_orders_status_request import (
|
|
26
|
+
UpdateOrdersStatusRequest,
|
|
27
|
+
)
|
|
16
28
|
from click_and_drop_api.simple import (
|
|
17
29
|
Address,
|
|
18
30
|
CreateOrder,
|
|
@@ -22,11 +34,17 @@ from click_and_drop_api.simple import (
|
|
|
22
34
|
)
|
|
23
35
|
from click_and_drop_api.simple.shipping_test_result import ShippingTestResult
|
|
24
36
|
from click_and_drop_api.simple.addresses import get_address, get_all_country_codes
|
|
37
|
+
from .types import ManifestedOrders, UpdateOrderStatus
|
|
25
38
|
|
|
26
39
|
|
|
27
40
|
class AbstractClickAndDrop(ABC):
|
|
28
41
|
"""Common interface shared by ClickAndDrop and MockClickAndDrop."""
|
|
29
42
|
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_env(cls, api_env_var: str = "API_KEY") -> Self:
|
|
45
|
+
api_key = os.environ[api_env_var]
|
|
46
|
+
return cls(api_key)
|
|
47
|
+
|
|
30
48
|
max_order_count: int = 100
|
|
31
49
|
|
|
32
50
|
@property
|
|
@@ -52,7 +70,7 @@ class AbstractClickAndDrop(ABC):
|
|
|
52
70
|
Parameters:
|
|
53
71
|
orders: One or more :class:`~click_and_drop_api.simple.types.CreateOrder` instances.
|
|
54
72
|
Returns:
|
|
55
|
-
A :class:`~click_and_drop_api.CreateOrdersResponse` instance containing created and failed orders.
|
|
73
|
+
A :class:`~click_and_drop_api.models.create_orders_response.CreateOrdersResponse` instance containing created and failed orders.
|
|
56
74
|
|
|
57
75
|
https://api.parcel.royalmail.com/#tag/Orders/operation/CreateOrdersAsync
|
|
58
76
|
"""
|
|
@@ -223,7 +241,7 @@ class AbstractClickAndDrop(ABC):
|
|
|
223
241
|
address for every country.
|
|
224
242
|
|
|
225
243
|
Returns:
|
|
226
|
-
:class
|
|
244
|
+
:class:`~click_and_drop_api.simple.shipping_test_result.ShippingTestResult` with ``success=True/False`` and a message.
|
|
227
245
|
|
|
228
246
|
Note:
|
|
229
247
|
This method only seems to work for OBA accounts
|
|
@@ -316,6 +334,171 @@ class AbstractClickAndDrop(ABC):
|
|
|
316
334
|
postage_details=PostageDetails(service_code=service_code),
|
|
317
335
|
)
|
|
318
336
|
|
|
337
|
+
def update_order_status(
|
|
338
|
+
self, updates: list[UpdateOrderStatus]
|
|
339
|
+
) -> UpdateOrderStatusResponse:
|
|
340
|
+
"""Set the status of an order.
|
|
341
|
+
|
|
342
|
+
Parameters:
|
|
343
|
+
requests: A list of UpdateOrdersStatusRequest instances.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
A :class:`~click_and_drop_api.models.set_order_status_resource.SetOrderStatusResource` instance containing the updated order information.
|
|
347
|
+
"""
|
|
348
|
+
result = UpdateOrderStatusResponse(updated_orders=[], errors=[])
|
|
349
|
+
for i in range(0, len(updates), self.max_order_count):
|
|
350
|
+
request = UpdateOrdersStatusRequest(
|
|
351
|
+
items=updates[i : i + self.max_order_count]
|
|
352
|
+
)
|
|
353
|
+
response = self._set_order_status(request)
|
|
354
|
+
result.updated_orders.extend(response.updated_orders)
|
|
355
|
+
result.errors.extend(response.errors)
|
|
356
|
+
return result
|
|
357
|
+
|
|
358
|
+
def update_orders(
|
|
359
|
+
self,
|
|
360
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
361
|
+
status: Literal["new", "despatchedByOtherCourier", "despatched"] | None = None,
|
|
362
|
+
tracking_number: str | None = None,
|
|
363
|
+
despatch_date: datetime | None = None,
|
|
364
|
+
shipping_carrier: str | None = None,
|
|
365
|
+
shipping_service: str | None = None,
|
|
366
|
+
):
|
|
367
|
+
"""Update the status of multiple orders."""
|
|
368
|
+
return self.update_order_status(
|
|
369
|
+
self._get_orders_update_request(
|
|
370
|
+
order_identifiers,
|
|
371
|
+
status=status,
|
|
372
|
+
tracking_number=tracking_number,
|
|
373
|
+
despatch_date=despatch_date,
|
|
374
|
+
shipping_carrier=shipping_carrier,
|
|
375
|
+
shipping_service=shipping_service,
|
|
376
|
+
)
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
def set_order_status(
|
|
380
|
+
self,
|
|
381
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
382
|
+
status: Literal["new", "despatchedByOtherCourier", "despatched"],
|
|
383
|
+
) -> UpdateOrderStatusResponse:
|
|
384
|
+
"""Set the status of orders."""
|
|
385
|
+
return self.update_order_status(
|
|
386
|
+
self._get_orders_update_request(order_identifiers, status=status)
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
def set_order_tracking_number(
|
|
390
|
+
self, order_identifiers: list[Union[str, int]] | str | int, tracking_number: str
|
|
391
|
+
) -> UpdateOrderStatusResponse:
|
|
392
|
+
"""Set the tracking number of a orders."""
|
|
393
|
+
return self.update_order_status(
|
|
394
|
+
self._get_orders_update_request(
|
|
395
|
+
order_identifiers, tracking_number=tracking_number
|
|
396
|
+
)
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
def set_order_despatch_date(
|
|
400
|
+
self,
|
|
401
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
402
|
+
despatch_date: datetime,
|
|
403
|
+
) -> UpdateOrderStatusResponse:
|
|
404
|
+
"""Set the despatch date of a orders."""
|
|
405
|
+
return self.update_order_status(
|
|
406
|
+
self._get_orders_update_request(
|
|
407
|
+
order_identifiers, despatch_date=despatch_date
|
|
408
|
+
)
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
def set_order_shipping_carrier(
|
|
412
|
+
self,
|
|
413
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
414
|
+
shipping_carrier: str,
|
|
415
|
+
) -> UpdateOrderStatusResponse:
|
|
416
|
+
"""Set the shipping carrier of a orders."""
|
|
417
|
+
return self.update_order_status(
|
|
418
|
+
self._get_orders_update_request(
|
|
419
|
+
order_identifiers, shipping_carrier=shipping_carrier
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def set_order_shipping_service(
|
|
424
|
+
self,
|
|
425
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
426
|
+
shipping_service: str,
|
|
427
|
+
) -> UpdateOrderStatusResponse:
|
|
428
|
+
"""Set the shipping service of a orders."""
|
|
429
|
+
return self.update_order_status(
|
|
430
|
+
self._get_orders_update_request(
|
|
431
|
+
order_identifiers, shipping_service=shipping_service
|
|
432
|
+
)
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
def _get_orders_update_request(
|
|
436
|
+
self,
|
|
437
|
+
order_identifiers: list[Union[str, int]] | str | int,
|
|
438
|
+
status: str | None = None,
|
|
439
|
+
tracking_number: str | None = None,
|
|
440
|
+
despatch_date: datetime | None = None,
|
|
441
|
+
shipping_carrier: str | None = None,
|
|
442
|
+
shipping_service: str | None = None,
|
|
443
|
+
) -> list[UpdateOrderStatus]:
|
|
444
|
+
"""Get a list of UpdateOrderStatus for the given order identifiers and attributes."""
|
|
445
|
+
if not isinstance(order_identifiers, list):
|
|
446
|
+
order_identifiers = [order_identifiers]
|
|
447
|
+
result = []
|
|
448
|
+
for identifier in order_identifiers:
|
|
449
|
+
order_id = identifier if isinstance(identifier, int) else None
|
|
450
|
+
order_ref = identifier if isinstance(identifier, str) else None
|
|
451
|
+
result.append(
|
|
452
|
+
UpdateOrderStatus(
|
|
453
|
+
order_identifier=order_id,
|
|
454
|
+
order_reference=order_ref,
|
|
455
|
+
status=status,
|
|
456
|
+
tracking_number=tracking_number,
|
|
457
|
+
despatch_date=despatch_date,
|
|
458
|
+
shipping_carrier=shipping_carrier,
|
|
459
|
+
shipping_service=shipping_service,
|
|
460
|
+
)
|
|
461
|
+
)
|
|
462
|
+
return result
|
|
463
|
+
|
|
464
|
+
@abstractmethod
|
|
465
|
+
def _set_order_status(
|
|
466
|
+
self, request: UpdateOrdersStatusRequest
|
|
467
|
+
) -> UpdateOrderStatusResponse:
|
|
468
|
+
"""Set the status of an order."""
|
|
469
|
+
|
|
470
|
+
@abstractmethod
|
|
471
|
+
def _manifest_orders(
|
|
472
|
+
self, request: ManifestEligibleOrdersRequest
|
|
473
|
+
) -> ManifestOrdersResponse:
|
|
474
|
+
"""Manifest eligible orders."""
|
|
475
|
+
|
|
476
|
+
def manifest_orders(self, carrier_name: str | None = None) -> ManifestedOrders:
|
|
477
|
+
"""Manifest all eligible orders, applying postage.
|
|
478
|
+
|
|
479
|
+
Manifests all orders in ``Label Generated`` and ``Despatched`` statuses
|
|
480
|
+
and returns manifest paperwork where possible.
|
|
481
|
+
|
|
482
|
+
Parameters:
|
|
483
|
+
carrier_name:
|
|
484
|
+
Required when the account has multiple carriers or postage
|
|
485
|
+
location numbers. Must match the carrier name configured in the
|
|
486
|
+
account settings. Pass ``None`` for single-carrier accounts.
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
A :class:`~click_and_drop_api.models.manifest_orders_response.ManifestOrdersResponse`
|
|
490
|
+
containing the manifest number and an optional base64-encoded PDF.
|
|
491
|
+
|
|
492
|
+
https://api.parcel.royalmail.com/#tag/Manifests/operation/ManifestEligibleAsync
|
|
493
|
+
"""
|
|
494
|
+
response = self._manifest_orders(
|
|
495
|
+
ManifestEligibleOrdersRequest(carrier_name=carrier_name)
|
|
496
|
+
)
|
|
497
|
+
return ManifestedOrders(
|
|
498
|
+
manifest_number=response.manifest_number,
|
|
499
|
+
document_pdf=response.document_pdf,
|
|
500
|
+
)
|
|
501
|
+
|
|
319
502
|
|
|
320
503
|
__all__ = [
|
|
321
504
|
"AbstractClickAndDrop",
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import base64
|
|
6
|
+
from importlib.resources import files
|
|
5
7
|
from datetime import datetime, timezone
|
|
6
8
|
from typing import Literal, Optional, Union
|
|
7
9
|
|
|
@@ -26,7 +28,7 @@ class MockClickAndDrop(AbstractClickAndDrop):
|
|
|
26
28
|
assert response.success_count == 1
|
|
27
29
|
"""
|
|
28
30
|
|
|
29
|
-
def __init__(self, key: str = _MOCK_KEY):
|
|
31
|
+
def __init__(self, key: str = _MOCK_KEY, is_oba: bool = True):
|
|
30
32
|
if not isinstance(key, str):
|
|
31
33
|
raise TypeError(f"Expected str, got {key}.")
|
|
32
34
|
key = key.strip()
|
|
@@ -35,8 +37,13 @@ class MockClickAndDrop(AbstractClickAndDrop):
|
|
|
35
37
|
if "".join(key.split()) != key:
|
|
36
38
|
raise ValueError(f"Expected no whitespace in {key!r}.")
|
|
37
39
|
self._key = key
|
|
40
|
+
self._is_oba = is_oba
|
|
38
41
|
self._orders: dict[int, click_and_drop_api.GetOrderInfoResource] = {}
|
|
39
42
|
self._next_id = 1
|
|
43
|
+
self._next_manifest_id = 1
|
|
44
|
+
|
|
45
|
+
def is_oba(self) -> bool:
|
|
46
|
+
return self._is_oba
|
|
40
47
|
|
|
41
48
|
@property
|
|
42
49
|
def key(self) -> str:
|
|
@@ -135,7 +142,46 @@ class MockClickAndDrop(AbstractClickAndDrop):
|
|
|
135
142
|
include_returns_label: Optional[bool] = None,
|
|
136
143
|
include_cn: Optional[bool] = None,
|
|
137
144
|
) -> bytearray:
|
|
138
|
-
|
|
145
|
+
data = (
|
|
146
|
+
files("click_and_drop_api.examples").joinpath("mock-label.pdf").read_bytes()
|
|
147
|
+
)
|
|
148
|
+
return bytearray(data)
|
|
149
|
+
|
|
150
|
+
def _manifest_orders(
|
|
151
|
+
self, request: click_and_drop_api.ManifestEligibleOrdersRequest
|
|
152
|
+
) -> click_and_drop_api.ManifestOrdersResponse:
|
|
153
|
+
manifest_id = self._next_manifest_id
|
|
154
|
+
self._next_manifest_id += 1
|
|
155
|
+
data = (
|
|
156
|
+
files("click_and_drop_api.examples")
|
|
157
|
+
.joinpath("mock-manifest.pdf")
|
|
158
|
+
.read_bytes()
|
|
159
|
+
)
|
|
160
|
+
return click_and_drop_api.ManifestOrdersResponse(
|
|
161
|
+
manifest_number=manifest_id,
|
|
162
|
+
document_pdf=base64.b64encode(data).decode(),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def _set_order_status(
|
|
166
|
+
self, request: click_and_drop_api.UpdateOrdersStatusRequest
|
|
167
|
+
) -> click_and_drop_api.UpdateOrderStatusResponse:
|
|
168
|
+
# For simplicity, this mock does not actually update the orders.
|
|
169
|
+
# It just returns a successful response for all items in the request.
|
|
170
|
+
created = []
|
|
171
|
+
errors = []
|
|
172
|
+
for item in request.items or []:
|
|
173
|
+
created.append(
|
|
174
|
+
click_and_drop_api.UpdatedOrderInfo(
|
|
175
|
+
order_identifier=item.order_identifier,
|
|
176
|
+
order_reference=item.order_reference,
|
|
177
|
+
status=item.status,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return click_and_drop_api.UpdateOrderStatusResponse(
|
|
182
|
+
updated_orders=created,
|
|
183
|
+
errors=errors,
|
|
184
|
+
)
|
|
139
185
|
|
|
140
186
|
|
|
141
187
|
__all__ = ["MockClickAndDrop"]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Renamed types for nicer reading"""
|
|
2
2
|
|
|
3
|
+
import base64
|
|
4
|
+
|
|
3
5
|
from click_and_drop_api.models.address_request import AddressRequest as Address
|
|
4
6
|
from click_and_drop_api.models.billing_details_request import (
|
|
5
7
|
BillingDetailsRequest as BillingDetails,
|
|
@@ -20,6 +22,7 @@ from click_and_drop_api.models.manifest_details_response import (
|
|
|
20
22
|
from click_and_drop_api.models.manifest_eligible_orders_request import (
|
|
21
23
|
ManifestEligibleOrdersRequest as ManifestEligibleOrders,
|
|
22
24
|
)
|
|
25
|
+
from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
|
|
23
26
|
from click_and_drop_api.models.postage_details_request import (
|
|
24
27
|
PostageDetailsRequest as PostageDetails,
|
|
25
28
|
)
|
|
@@ -47,9 +50,19 @@ from click_and_drop_api.models.update_orders_status_request import (
|
|
|
47
50
|
)
|
|
48
51
|
|
|
49
52
|
|
|
53
|
+
class ManifestedOrders(ManifestOrdersResponse):
|
|
54
|
+
@property
|
|
55
|
+
def pdf(self) -> bytearray | None:
|
|
56
|
+
"""Return the PDF content of the manifest as a bytearray, or None if unavailable."""
|
|
57
|
+
if self.document_pdf is None:
|
|
58
|
+
return None
|
|
59
|
+
return bytearray(base64.b64decode(self.document_pdf))
|
|
60
|
+
|
|
61
|
+
|
|
50
62
|
__all__ = [
|
|
51
63
|
"CreateOrder",
|
|
52
64
|
"RecipientDetails",
|
|
65
|
+
"ManifestedOrders",
|
|
53
66
|
"Address",
|
|
54
67
|
"PostageDetails",
|
|
55
68
|
"ShipmentPackage",
|
{click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/SOURCES.txt
RENAMED
|
@@ -26,6 +26,9 @@ click_and_drop_api/examples/__main__.py
|
|
|
26
26
|
click_and_drop_api/examples/check_oba.py
|
|
27
27
|
click_and_drop_api/examples/create_order.py
|
|
28
28
|
click_and_drop_api/examples/generate_label.py
|
|
29
|
+
click_and_drop_api/examples/mock-label.pdf
|
|
30
|
+
click_and_drop_api/examples/mock-manifest.pdf
|
|
31
|
+
click_and_drop_api/examples/oba_full_workflow.py
|
|
29
32
|
click_and_drop_api/examples/package_size_and_cost.py
|
|
30
33
|
click_and_drop_api/examples/shipping_countries.py
|
|
31
34
|
click_and_drop_api/examples/view_order.py
|
|
@@ -80,6 +83,7 @@ click_and_drop_api/simple/__init__.py
|
|
|
80
83
|
click_and_drop_api/simple/addresses.py
|
|
81
84
|
click_and_drop_api/simple/api.py
|
|
82
85
|
click_and_drop_api/simple/base.py
|
|
86
|
+
click_and_drop_api/simple/compatibility.py
|
|
83
87
|
click_and_drop_api/simple/errors.py
|
|
84
88
|
click_and_drop_api/simple/mock.py
|
|
85
89
|
click_and_drop_api/simple/shipping_test_result.py
|
|
@@ -148,6 +152,8 @@ test/test_manifest_errors_response.py
|
|
|
148
152
|
test/test_manifest_orders_response.py
|
|
149
153
|
test/test_manifests_api.py
|
|
150
154
|
test/test_mock_api.py
|
|
155
|
+
test/test_mock_api_manifest.py
|
|
156
|
+
test/test_mock_api_update_orders.py
|
|
151
157
|
test/test_oba_parser.py
|
|
152
158
|
test/test_order_error_info.py
|
|
153
159
|
test/test_order_error_response.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "click_and_drop_api"
|
|
3
|
-
version = "3.0.
|
|
3
|
+
version = "3.0.4"
|
|
4
4
|
description = "ChannelShipper & Royal Mail Public API"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Nicco Kunzmann", email = "niccokunzmann@rambler.ru"},
|
|
@@ -73,6 +73,9 @@ cli = [
|
|
|
73
73
|
"tox",
|
|
74
74
|
]
|
|
75
75
|
|
|
76
|
+
[tool.setuptools.package-data]
|
|
77
|
+
"click_and_drop_api.examples" = ["*.pdf"]
|
|
78
|
+
|
|
76
79
|
[build-system]
|
|
77
80
|
requires = ["setuptools"]
|
|
78
81
|
build-backend = "setuptools.build_meta"
|
|
@@ -260,6 +260,21 @@ def test_test_shipping_multiple_calls_stay_clean(api):
|
|
|
260
260
|
assert len(api._orders) == 0
|
|
261
261
|
|
|
262
262
|
|
|
263
|
+
# --- is_oba ---
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def test_is_oba_default_is_true():
|
|
267
|
+
assert MockClickAndDrop().is_oba() is True
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def test_is_oba_true():
|
|
271
|
+
assert MockClickAndDrop(is_oba=True).is_oba() is True
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def test_is_oba_false():
|
|
275
|
+
assert MockClickAndDrop(is_oba=False).is_oba() is False
|
|
276
|
+
|
|
277
|
+
|
|
263
278
|
# --- format_fields_for_error_message ---
|
|
264
279
|
|
|
265
280
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Tests for manifest_orders."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
|
|
6
|
+
from click_and_drop_api.simple.mock import MockClickAndDrop
|
|
7
|
+
from click_and_drop_api.simple.types import ManifestedOrders
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def api() -> MockClickAndDrop:
|
|
12
|
+
return MockClickAndDrop()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_manifest_orders_returns_response(api: MockClickAndDrop) -> None:
|
|
16
|
+
result = api.manifest_orders()
|
|
17
|
+
assert isinstance(result, ManifestOrdersResponse)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_manifest_orders_has_manifest_number(api: MockClickAndDrop) -> None:
|
|
21
|
+
result = api.manifest_orders()
|
|
22
|
+
assert result.manifest_number is not None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_manifest_orders_with_carrier_name(api: MockClickAndDrop) -> None:
|
|
26
|
+
result = api.manifest_orders(carrier_name="Royal Mail")
|
|
27
|
+
assert isinstance(result, ManifestOrdersResponse)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_manifest_orders_increments_manifest_number(api: MockClickAndDrop) -> None:
|
|
31
|
+
r1 = api.manifest_orders()
|
|
32
|
+
r2 = api.manifest_orders()
|
|
33
|
+
assert r2.manifest_number != r1.manifest_number
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# --- .pdf property ---
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_manifest_orders_pdf_returns_bytearray(api: MockClickAndDrop) -> None:
|
|
40
|
+
result: ManifestedOrders = api.manifest_orders()
|
|
41
|
+
assert isinstance(result.pdf, bytearray)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_manifest_orders_pdf_starts_with_pdf_header(api: MockClickAndDrop) -> None:
|
|
45
|
+
result: ManifestedOrders = api.manifest_orders()
|
|
46
|
+
assert result.pdf[:4] == bytearray(b"%PDF")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_manifest_orders_pdf_none_when_no_document() -> None:
|
|
50
|
+
result = ManifestedOrders(manifest_number=1, document_pdf=None)
|
|
51
|
+
assert result.pdf is None
|