diff --git a/delivery_schenker/README.rst b/delivery_schenker/README.rst new file mode 100644 index 0000000000..198809f4e1 --- /dev/null +++ b/delivery_schenker/README.rst @@ -0,0 +1,191 @@ +================= +Delivery Schenker +================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:066cbe8cb2e06129b8fe498984627ea925b84a1b2fbbf5963a15f2595ef7de80 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdelivery--carrier-lightgray.png?logo=github + :target: https://github.com/OCA/delivery-carrier/tree/18.0/delivery_schenker + :alt: OCA/delivery-carrier +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/delivery-carrier-18-0/delivery-carrier-18-0-delivery_schenker + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/delivery-carrier&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module links the `DB Schenker `__ +booking and tracking APIs with Odoo delivery system. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +This module depends on the zeep python library and the +OCA/delivery-carrier delivery_package_number and delivery_state modules. + +The Schenker API doesn't provide delivery rating methods, so OCA's +delivery_price_method is advised in order to use this carrier in a sales +workflow. + +Configuration +============= + +To configure a Schenker delivery method: + +1. Go to *Inventory > Configuration > Delivery > Shipping methods* and + create a new one. +2. Choose *DB Schenker* as provider. +3. Configure the service parameters according to your contract + considerations. +4. Choose a delivery product and a default packaging. This is mandatory + for the booking request as it needs the packaging code. + +To make tests, set the carrier environment to test from the smart +button. Don't forget to set it to production once you're ready to use +the delivery method! + +Usage +===== + +These are the operations possible with this module: + +Place shipping bookings +----------------------- + +1. When the picking is validated, the shipping will be booked at + Schenker. +2. With the response, we'll receive the delivery tracking number and the + pdf label in a chatter message and it will be kept as attachment to + the document. +3. You can manage packages number either with the proper Odoo workflows + or with the package number field available in the *Additional Info* + tab. You'll get as many labels as declared packages. + +Cancel bookings +--------------- + +1. As in other carriers, we can cancel the shipping after the picking is + done. To do so, go to *Additional Info* tab and click on the *Cancel* + action on the side of the tracking number. +2. We can generate a new shipping if necessary. + +Get labels +---------- + +1. If by chance we delete the generated labels, we can obtain them again + hitting the *Schenker Label* buttons in the header of the picking + form. + +Tracking +-------- + +1. The module is integrated with delivery_state to be able to get the + tracking info directly from the DB Schenker API. +2. To do so, go to a picking shipped with Schenker. In the *Additional + Info* tab you'll find an action button to *Update tracking state* so + the state will be updated from the Schenker API. + +Debugging +--------- + +The API calls and responses are tracked in two special fields in the +picking that can be viewed by technical users. You can also log them in +as ir.logging records setting the carrier debug on from the smart +button. + +Known issues / Roadmap +====================== + +- There's no dummy access key to test API calls so no tests can be + performed. +- The test booking and shipping APIs databases aren't connected so it + isn't possible to perform trackings on test mode. +- Only land shipping is implemented, although the module is prepared + for extend to air and ocean just considering the mandatory request + fields for those methods. Some additional adaptations could be needed + (e.g.: origin and destination airport, port) anyway. +- Only volume is supported as a measure unit and with the limitations + of Odoo itself. To enjoy a full fledged volume support, install and + configure the OCA’s stock_quant_package_dimension module and its + dependencies. The connector is ready to make use of their volume + computations. +- It’d be needed to extend the method to support Schenker measure units + such as loading pieces or pallet space. +- Some more booking features aren’t yet supported although can be + extended in the future. Some of those, although the complete list + would be really extensive: + + - Dangerous goods. + - Driver pre-advise. + - Transport temperature. + - Customs clearance. + - Cargo insurance. + - Cash on delivery. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Tecnativa +* Studio73 + +Contributors +------------ + +- `Tecnativa `__: + + - David Vidal + +- `Studio73 `__: + + - Ethan Hildick + +- Michael Tietz (MT Software) + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/delivery-carrier `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/delivery_schenker/__init__.py b/delivery_schenker/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/delivery_schenker/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/delivery_schenker/__manifest__.py b/delivery_schenker/__manifest__.py new file mode 100644 index 0000000000..7182da26ca --- /dev/null +++ b/delivery_schenker/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2021 Tecnativa - David Vidal +# Copyright 2021 Studio73 - Ethan Hildick +# Copyright 2023 Studio73 - Ferran Mora +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Delivery Schenker", + "summary": "Delivery Carrier implementation for DB Schenker API", + "version": "18.0.1.0.0", + "category": "Stock", + "website": "https://github.com/OCA/delivery-carrier", + "author": "Tecnativa, Studio73, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": ["delivery_package_number", "delivery_state"], + "external_dependencies": {"python": ["zeep"]}, + "data": [ + "views/delivery_schenker_view.xml", + "views/stock_picking_views.xml", + "data/delivery_schenker_data.xml", + ], +} diff --git a/delivery_schenker/api/fat_bookingWebServiceV1_1.wsdl b/delivery_schenker/api/fat_bookingWebServiceV1_1.wsdl new file mode 100644 index 0000000000..79053f4181 --- /dev/null +++ b/delivery_schenker/api/fat_bookingWebServiceV1_1.wsdl @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Booking Web Service to create Land, Ocean and Air bookings + +Booking Web Service operation to create Land bookings + + + + + + + + +Booking Web Service operation to create Air bookings + + + + + + + + +Booking Web Service operation to create Ocean LCL bookings + + + + + + + + +Booking Web Service operation to create Ocean FCL bookings + + + + + + + + +Booking Web Service operation to get a barcode based on a booking id + + + + + + + + +Booking Web Service operation to cancel a booking by booking id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/api/fat_trackingWebServiceV2.wsdl b/delivery_schenker/api/fat_trackingWebServiceV2.wsdl new file mode 100644 index 0000000000..50d927f267 --- /dev/null +++ b/delivery_schenker/api/fat_trackingWebServiceV2.wsdl @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/api/prod_bookingWebServiceV1_1.wsdl b/delivery_schenker/api/prod_bookingWebServiceV1_1.wsdl new file mode 100644 index 0000000000..3f7ccc7a02 --- /dev/null +++ b/delivery_schenker/api/prod_bookingWebServiceV1_1.wsdl @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Booking Web Service to create Land, Ocean and Air bookings + +Booking Web Service operation to create Land bookings + + + + + + + + +Booking Web Service operation to create Air bookings + + + + + + + + +Booking Web Service operation to create Ocean LCL bookings + + + + + + + + +Booking Web Service operation to create Ocean FCL bookings + + + + + + + + +Booking Web Service operation to get a barcode based on a booking id + + + + + + + + +Booking Web Service operation to cancel a booking by booking id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/api/prod_trackingWebServiceV2.wsdl b/delivery_schenker/api/prod_trackingWebServiceV2.wsdl new file mode 100644 index 0000000000..0e398d0088 --- /dev/null +++ b/delivery_schenker/api/prod_trackingWebServiceV2.wsdl @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/data/delivery_schenker_data.xml b/delivery_schenker/data/delivery_schenker_data.xml new file mode 100644 index 0000000000..d4a72c3f84 --- /dev/null +++ b/delivery_schenker/data/delivery_schenker_data.xml @@ -0,0 +1,119 @@ + + + + + CI + (Schenker) Canister + schenker + + + CT + (Schenker) Carton + schenker + + + CS + (Schenker) Case + schenker + + + CO + (Schenker) Colli + schenker + + + CH + (Schenker) Crate + schenker + + + GP + (Schenker) Skeleton box pallet + schenker + + + NE + (Schenker) Unpacked Skid + schenker + + + BG + (Schenker) Bag + schenker + + + BL + (Schenker) Bale + schenker + + + DR + (Schenker) Barrel + schenker + + + BX + (Schenker) Box + schenker + + + BY + (Schenker) Bundle + schenker + + + TR + (Schenker) Drum + schenker + + + EP + (Schenker) Europallet + schenker + + + FR + (Schenker) Frame + schenker + + + HO + (Schenker) Hobbock + schenker + + + OP + (Schenker) One-way pallet + schenker + + + PK + (Schenker) Package + schenker + + + XP + (Schenker) Pallet + schenker + + + PZ + (Schenker) Pipe + schenker + + + RO + (Schenker) Roll + schenker + + + SK + (Schenker) Sack + schenker + + + ZZ + (Schenker) Other + schenker + + diff --git a/delivery_schenker/i18n/delivery_schenker.pot b/delivery_schenker/i18n/delivery_schenker.pot new file mode 100644 index 0000000000..96c035435b --- /dev/null +++ b/delivery_schenker/i18n/delivery_schenker.pot @@ -0,0 +1,653 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * delivery_schenker +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_barcode_format__a4 +msgid "A4" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_barcode_format__a6 +msgid "A6" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_access_key +msgid "Access Key" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__a2a +msgid "Aiport-to-airport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__air +msgid "Air" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_air +msgid "Air service" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_air +msgid "" +"Air shipping product options. Depending on your customer account, some " +"services could not be available" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__a2d +msgid "Airport-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_mail +msgid "Barcode Copy Email" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_format +msgid "Barcode Format" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_separated +msgid "Barcode Separated" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_start_pos +msgid "Barcode Start Position" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_booking_type +msgid "Booking Type" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__package_carrier_type +msgid "Carrier" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_booking_type +msgid "Choose Schenker booking type. Only land is currently supported" +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Connection" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__71 +msgid "DB SCHENKERdirect" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__b +msgid "DB SCHENKERjetcargo business" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__e +msgid "DB SCHENKERjetcargo economy" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__f +msgid "DB SCHENKERjetcargo first" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__s +msgid "DB SCHENKERjetcargo special" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__eagd +msgid "DB SCHENKERjetexpress gold" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__easv +msgid "DB SCHENKERjetexpress silver" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ecpa +msgid "DB SCHENKERparcel" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ectn +msgid "DB SCHENKERspeed" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect1 +msgid "DB SCHENKERspeed 10" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect2 +msgid "DB SCHENKERspeed 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect8 +msgid "DB SCHENKERspeed 8" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__40 +msgid "DB SCHENKERsystem classic" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__sysd +msgid "DB SCHENKERsystem domestic" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__schx +msgid "DB SCHENKERsystem fix" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__42 +msgid "DB SCHENKERsystem fixday" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__schs +msgid "DB SCHENKERsystem international" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__41 +msgid "DB SCHENKERsystem speed" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__scht +msgid "DB SCHENKERtop" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__sch2 +msgid "DB SCHENKERtop 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__delivery_type__schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__product_packaging__package_carrier_type__schenker +msgid "DB Schenker" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__43 +msgid "DBSchenker System" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__44 +msgid "DBSchenker System Premium" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__con +msgid "DBSchenkerconcepts" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__dir +msgid "DBSchenkerdirects" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__pal +msgid "DBSchenkerpallets" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__lpa +msgid "DBSchenkerparcel Logistics Parcel" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__pri +msgid "DBSchenkerprivpark" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_incoterm_id +msgid "Default Incoterm" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_default_packaging_id +msgid "Default Package Type" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_product_packaging__schenker_stackable +msgid "Define if the package is stackable by default" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_indoor_delivery +msgid "Defines if indoor delivery is required" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_express +msgid "Defines if shipment is express" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_food_related +msgid "Defines if shipment is food related" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_pharmaceuticals +msgid "Defines if shipment is pharmaceutical" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_heated_transport +msgid "Defines if shipment is required heated transport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_home_delivery +msgid "Defines if shipment is required home delivery" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_own_pickup +msgid "Defines if shipment is required own pickup" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_type +msgid "" +"Defines service type: D2D, D2P, P2D, P2P, D2A, A2D, A2A. Depending on the " +"Transport mode the service will be validated. For instance if the transport " +"mode is AIR, the service type A2A (AirportToAirport)" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__display_name +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__display_name +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking__display_name +msgid "Display Name" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2a +msgid "Door-to-airport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2d +msgid "Door-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2p +msgid "Door-to-port" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/schenker_request.py:0 +#, python-format +msgid "" +"Error in the request to the Schenker API. This is the thrown message:\n" +"\n" +"[%s]\n" +"%s - %s" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_express +msgid "Express" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_food_related +msgid "Food Related" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_separated +msgid "For A4 define if the labels shall be printed on separate pages" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_start_pos +msgid "For A4 format you can define the starting position" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_group_id +msgid "Group" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_heated_transport +msgid "Heated Transport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_home_delivery +msgid "Home Delivery" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__id +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__id +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking__id +msgid "ID" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_default_packaging_id +msgid "" +"If not delivery package or the package doesn't have defined the packagingit " +"will default to this type" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_indoor_delivery +msgid "Indoor Delivery" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_incoterm_id +msgid "It will be overriden by the sale order one if it's specified." +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Label" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__land +msgid "Land" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_land +msgid "Land service" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_land +msgid "" +"Land shipping product options. Depending on your customer account, some " +"services could not be available" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier____last_update +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging____last_update +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking____last_update +msgid "Last Modified on" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__loading_meters +msgid "Loading meters" +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Logistics" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_measure_unit +msgid "Measure Unit" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__ocean_fcl +msgid "Ocean FCL" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__ocean_lcl +msgid "Ocean LCL" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Only land shipping is currently supported" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Only volume is currently supported" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_mail +msgid "Optional: send a barcode copy to this email address" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_own_pickup +msgid "Own Pickup" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__pallet_space +msgid "Pallet space" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_pharmaceuticals +msgid "Pharmaceuticals" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__pieces +msgid "Pieces" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__p2d +msgid "Port-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_product_packaging +msgid "Product Packaging" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__delivery_type +msgid "Provider" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ecsp +msgid "SCHENKERsystem-plus" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "" +"Schenker API doesn't provide methods to compute delivery rates, so you " +"should relay on another price method instead or override this one in your " +"custom code." +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_access_key +msgid "Schenker Access Key" +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Schenker Configuration" +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_picking_withcarrier_out_form +msgid "Schenker Label" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Schenker Shipping barcode document" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/stock_picking.py:0 +#, python-format +msgid "Schenker label for %s" +msgstr "" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Service" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_type +msgid "Service Type" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_delivery_carrier +msgid "Shipping Methods" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__schenker_stackable +msgid "Stackable" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_measure_unit +msgid "The proper request will be formed accordingly from the picking" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_user +msgid "User" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__volume +msgid "Volume" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auco +msgid "austrocargo" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc0 +msgid "austroexpress PUNKT 10" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc2 +msgid "austroexpress PUNKT 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__aucc +msgid "austroexpress PUNKT 17" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc8 +msgid "austroexpress PUNKT 8" +msgstr "" + +#. module: delivery_schenker +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_01 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_02 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_03 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_04 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_05 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_06 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_07 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_08 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_09 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_10 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_11 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_12 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_13 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_14 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_15 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_16 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_17 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_18 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_19 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_20 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_21 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_22 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_23 +msgid "kg" +msgstr "" + +#. module: delivery_schenker +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_01 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_02 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_03 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_04 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_05 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_06 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_07 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_08 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_09 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_10 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_11 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_12 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_13 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_14 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_15 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_16 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_17 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_18 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_19 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_20 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_21 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_22 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_23 +msgid "m³" +msgstr "" diff --git a/delivery_schenker/i18n/es.po b/delivery_schenker/i18n/es.po new file mode 100644 index 0000000000..25517aecdf --- /dev/null +++ b/delivery_schenker/i18n/es.po @@ -0,0 +1,676 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * delivery_schenker +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-12-14 15:46+0000\n" +"PO-Revision-Date: 2021-12-14 15:46+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_barcode_format__a4 +msgid "A4" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_barcode_format__a6 +msgid "A6" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_access_key +msgid "Access Key" +msgstr "Clave de acceso" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__a2a +msgid "Aiport-to-airport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__air +msgid "Air" +msgstr "Aéreo" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_air +msgid "Air service" +msgstr "Servicio aéreo" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_air +msgid "" +"Air shipping product options. Depending on your customer account, some " +"services could not be available" +msgstr "" +"Opciones de productos de envío aéreo. Dependiendo de tu cuenta de cliente, " +"algunos servicios podrían no estar disponibles." + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__a2d +msgid "Airport-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_mail +msgid "Barcode Copy Email" +msgstr "Enviar etiqueta por correo" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_format +msgid "Barcode Format" +msgstr "Formato de etiqueta" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_separated +msgid "Barcode Separated" +msgstr "Separar etiquetas" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_start_pos +msgid "Barcode Start Position" +msgstr "Primera posición de etiquetas" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_booking_type +msgid "Booking Type" +msgstr "Tipo de envío" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__package_carrier_type +msgid "Carrier" +msgstr "Transportista" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_booking_type +msgid "Choose Schenker booking type. Only land is currently supported" +msgstr "" +"Elige tipo de envío Schenker. Actualmente solo está soportado los envíos " +"terrestres." + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Connection" +msgstr "Conexión" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__71 +msgid "DB SCHENKERdirect" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__b +msgid "DB SCHENKERjetcargo business" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__e +msgid "DB SCHENKERjetcargo economy" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__f +msgid "DB SCHENKERjetcargo first" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__s +msgid "DB SCHENKERjetcargo special" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__eagd +msgid "DB SCHENKERjetexpress gold" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_air__easv +msgid "DB SCHENKERjetexpress silver" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ecpa +msgid "DB SCHENKERparcel" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ectn +msgid "DB SCHENKERspeed" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect1 +msgid "DB SCHENKERspeed 10" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect2 +msgid "DB SCHENKERspeed 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ect8 +msgid "DB SCHENKERspeed 8" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__40 +msgid "DB SCHENKERsystem classic" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__sysd +msgid "DB SCHENKERsystem domestic" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__schx +msgid "DB SCHENKERsystem fix" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__42 +msgid "DB SCHENKERsystem fixday" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__schs +msgid "DB SCHENKERsystem international" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__41 +msgid "DB SCHENKERsystem speed" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__scht +msgid "DB SCHENKERtop" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__sch2 +msgid "DB SCHENKERtop 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__delivery_type__schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__product_packaging__package_carrier_type__schenker +msgid "DB Schenker" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__43 +msgid "DBSchenker System" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__44 +msgid "DBSchenker System Premium" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__con +msgid "DBSchenkerconcepts" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__dir +msgid "DBSchenkerdirects" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__pal +msgid "DBSchenkerpallets" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__lpa +msgid "DBSchenkerparcel Logistics Parcel" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__pri +msgid "DBSchenkerprivpark" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_incoterm_id +msgid "Default Incoterm" +msgstr "Incoterm por defecto" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_default_packaging_id +msgid "Default Package Type" +msgstr "Tipo de empaquetado por defecto" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_product_packaging__schenker_stackable +msgid "Define if the package is stackable by default" +msgstr "Define si el paquete es apilable por defecto" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_indoor_delivery +msgid "Defines if indoor delivery is required" +msgstr "Define si es necesaria la entrega a interiores" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_express +msgid "Defines if shipment is express" +msgstr "Define si el envío es exprés" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_food_related +msgid "Defines if shipment is food related" +msgstr "Define si el envío está relacionado con la comida" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_pharmaceuticals +msgid "Defines if shipment is pharmaceutical" +msgstr "Define si el envío es farmacéutico" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_heated_transport +msgid "Defines if shipment is required heated transport" +msgstr "Define si el envío requiere transporte calentado" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_home_delivery +msgid "Defines if shipment is required home delivery" +msgstr "Define si el envío require la entrega a domicilio" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_own_pickup +msgid "Defines if shipment is required own pickup" +msgstr "Define si el envío require recogida propia" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_type +msgid "" +"Defines service type: D2D, D2P, P2D, P2P, D2A, A2D, A2A. Depending on the " +"Transport mode the service will be validated. For instance if the transport " +"mode is AIR, the service type A2A (AirportToAirport)" +msgstr "" +"Define los tipos de servicio: D2D, D2P, P2D, P2P, D2A, A2D, A2A. Depende del " +"tipo de servicio elegido será validado. Por ejemplo si el transporte es " +"Aéreo, un tipo de de servicio correcto sería A2A (AirportToAirport)" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__display_name +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__display_name +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2a +msgid "Door-to-airport" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2d +msgid "Door-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__d2p +msgid "Door-to-port" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/schenker_request.py:0 +#, python-format +msgid "" +"Error in the request to the Schenker API. This is the thrown message:\n" +"\n" +"[%s]\n" +"%s - %s" +msgstr "" +"Error en el pedido contra la API Schenker. Este es el mensaje devuelto:\n" +"\n" +"[%s]\n" +"%s - %s" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_express +msgid "Express" +msgstr "Exprés" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_food_related +msgid "Food Related" +msgstr "Envío relacionado con alimientos" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_separated +msgid "For A4 define if the labels shall be printed on separate pages" +msgstr "" +"Para las etiquetas A4, define si se deben imprimir en páginas por separado" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_a4_start_pos +msgid "For A4 format you can define the starting position" +msgstr "Para las etiquetas A4, define la primera posición" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_group_id +msgid "Group" +msgstr "Grupo" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_heated_transport +msgid "Heated Transport" +msgstr "Transporte calentado" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_home_delivery +msgid "Home Delivery" +msgstr "Envío a domicilio" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__id +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__id +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking__id +msgid "ID" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_default_packaging_id +msgid "" +"If not delivery package or the package doesn't have defined the packagingit " +"will default to this type" +msgstr "" +"Si el envío no es un paquete o el paquete no tiene definido el empaquetado " +"usará este por defecto" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_indoor_delivery +msgid "Indoor Delivery" +msgstr "Entrega a interiores" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_incoterm_id +msgid "It will be overriden by the sale order one if it's specified." +msgstr "" +"Indica el incoterm, será sobreescrito por el incoterm del pedido de venta si " +"ese está establecido" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Label" +msgstr "Etiqueta" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__land +msgid "Land" +msgstr "Terrestre" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_land +msgid "Land service" +msgstr "Servicio terrestre" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_service_land +msgid "" +"Land shipping product options. Depending on your customer account, some " +"services could not be available" +msgstr "" +"Opciones de productos de envío terrestre. Dependiendo de tu cuenta de " +"cliente, algunos servicios podrían no estar disponibles." + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier____last_update +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging____last_update +#: model:ir.model.fields,field_description:delivery_schenker.field_stock_picking____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__loading_meters +msgid "Loading meters" +msgstr "Metros de carga" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Logistics" +msgstr "Datos logísticos" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_measure_unit +msgid "Measure Unit" +msgstr "Unidad de medida" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__ocean_fcl +msgid "Ocean FCL" +msgstr "Marítimo FCL" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_booking_type__ocean_lcl +msgid "Ocean LCL" +msgstr "Marítimo LCL" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Only land shipping is currently supported" +msgstr "Actualmente solo los envíos terretres están soportados" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Only volume is currently supported" +msgstr "Actualmente solo el volumen está soportado" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_barcode_mail +msgid "Optional: send a barcode copy to this email address" +msgstr "Opcional: Enviar una cópia de la etiqueta a este correo" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_own_pickup +msgid "Own Pickup" +msgstr "Recogida propia" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__pallet_space +msgid "Pallet space" +msgstr "Espacio palet" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_pharmaceuticals +msgid "Pharmaceuticals" +msgstr "Farmacéutico" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__pieces +msgid "Pieces" +msgstr "Bultos" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_type__p2d +msgid "Port-to-door" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_product_packaging +msgid "Product Packaging" +msgstr "Empaquetado de producto" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__delivery_type +msgid "Provider" +msgstr "Proveedor" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__ecsp +msgid "SCHENKERsystem-plus" +msgstr "" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "" +"Schenker API doesn't provide methods to compute delivery rates, so you " +"should relay on another price method instead or override this one in your " +"custom code." +msgstr "" +"API Schenker no provee ninguna forma de calcular las tarifas de envío, porlo " +"tanto se deberia usar otro método o sobreescribir este en código " +"personalizado." + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_access_key +msgid "Schenker Access Key" +msgstr "Clave de acceso Schenker" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Schenker Configuration" +msgstr "Configuración Schenker" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_picking_withcarrier_out_form +msgid "Schenker Label" +msgstr "Etiqueta Schenker" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/delivery_carrier.py:0 +#, python-format +msgid "Schenker Shipping barcode document" +msgstr "Etiqueta de envío Schenker" + +#. module: delivery_schenker +#: code:addons/delivery_schenker/models/stock_picking.py:0 +#, python-format +msgid "Schenker label for %s" +msgstr "Etiqueta Schenker para envío %s" + +#. module: delivery_schenker +#: model_terms:ir.ui.view,arch_db:delivery_schenker.view_delivery_carrier_form +msgid "Service" +msgstr "Servicio" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_service_type +msgid "Service Type" +msgstr "Tipo de servicio" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_delivery_carrier +msgid "Shipping Methods" +msgstr "Métodos de envío" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_product_packaging__schenker_stackable +msgid "Stackable" +msgstr "Apilable" + +#. module: delivery_schenker +#: model:ir.model.fields,help:delivery_schenker.field_delivery_carrier__schenker_measure_unit +msgid "The proper request will be formed accordingly from the picking" +msgstr "La petición apropiada será creada a partir del albarán" + +#. module: delivery_schenker +#: model:ir.model,name:delivery_schenker.model_stock_picking +msgid "Transfer" +msgstr "Albarán" + +#. module: delivery_schenker +#: model:ir.model.fields,field_description:delivery_schenker.field_delivery_carrier__schenker_user +msgid "User" +msgstr "Usuario" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_measure_unit__volume +msgid "Volume" +msgstr "Volumen" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auco +msgid "austrocargo" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc0 +msgid "austroexpress PUNKT 10" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc2 +msgid "austroexpress PUNKT 12" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__aucc +msgid "austroexpress PUNKT 17" +msgstr "" + +#. module: delivery_schenker +#: model:ir.model.fields.selection,name:delivery_schenker.selection__delivery_carrier__schenker_service_land__auc8 +msgid "austroexpress PUNKT 8" +msgstr "" + +#. module: delivery_schenker +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_01 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_02 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_03 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_04 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_05 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_06 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_07 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_08 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_09 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_10 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_11 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_12 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_13 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_14 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_15 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_16 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_17 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_18 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_19 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_20 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_21 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_22 +#: model:product.packaging,weight_uom_name:delivery_schenker.schenker_packaging_23 +msgid "kg" +msgstr "" + +#. module: delivery_schenker +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_01 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_02 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_03 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_04 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_05 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_06 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_07 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_08 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_09 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_10 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_11 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_12 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_13 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_14 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_15 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_16 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_17 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_18 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_19 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_20 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_21 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_22 +#: model:product.packaging,volume_uom_name:delivery_schenker.schenker_packaging_23 +msgid "m³" +msgstr "" diff --git a/delivery_schenker/models/__init__.py b/delivery_schenker/models/__init__.py new file mode 100644 index 0000000000..b575f6f0e2 --- /dev/null +++ b/delivery_schenker/models/__init__.py @@ -0,0 +1,4 @@ +from . import delivery_carrier +from . import schenker_request +from . import stock_package_type +from . import stock_picking diff --git a/delivery_schenker/models/delivery_carrier.py b/delivery_schenker/models/delivery_carrier.py new file mode 100644 index 0000000000..d223d95012 --- /dev/null +++ b/delivery_schenker/models/delivery_carrier.py @@ -0,0 +1,595 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from lxml import etree + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + +from .schenker_request import SchenkerRequest + +SCHENKER_STATUS_CODES = { + "ENT": ("Booked", "shipping_recorded_in_carrier"), + "COL": ("Collected", "shipping_recorded_in_carrier"), + "DET": ("Delivered to terminal by shipper", "in_transit"), + "ENM": ("Arrived", "in_transit"), + "MAN": ("Departed", "in_transit"), + "DIS": ("To Consignee's Disposal", "warehouse_delivered"), + "DOT": ("Out for Delivery", "in_transit"), + "PUP": ("Picked up by consignee", "customer_delivered"), + "DLV": ("Delivered", "customer_delivered"), + "NDL": ("Not delivered", "canceled_shipment"), +} + + +class DeliveryCarrier(models.Model): + _inherit = "delivery.carrier" + + delivery_type = fields.Selection( + selection_add=[("schenker", "DB Schenker")], + ondelete={"schenker": "set default"}, + ) + schenker_access_key = fields.Char(string="Access Key", help="Schenker Access Key") + schenker_group_id = fields.Char(string="Group") + schenker_user = fields.Char(string="User") + schenker_booking_type = fields.Selection( + selection=[ + ("land", "Land"), + ("air", "Air"), + ("ocean_fcl", "Ocean FCL"), + ("ocean_lcl", "Ocean LCL"), + ], + default="land", + string="Booking Type", + help="Choose Schenker booking type. Only land is currently supported", + ) + schenker_barcode_format = fields.Selection( + selection=[("A4", "A4"), ("A6", "A6")], default="A6", string="Barcode Format" + ) + schenker_barcode_mail = fields.Char( + string="Barcode Copy Email", + help="Optional: send a barcode copy to this email address", + ) + schenker_barcode_a4_start_pos = fields.Integer( + string="Barcode Start Position", + default=1, + help="For A4 format you can define the starting position", + ) + schenker_barcode_a4_separated = fields.Boolean( + string="Barcode Separated", + default=False, + help="For A4 define if the labels shall be printed on separate pages", + ) + schenker_incoterm_id = fields.Many2one( + comodel_name="account.incoterms", + string="Default Incoterm", + help="It will be overriden by the sale order one if it's specified.", + ) + schenker_service_type = fields.Selection( + string="Service Type", + help="Defines service type: D2D, D2P, P2D, P2P, D2A, A2D, A2A. Depending on " + "the Transport mode the service will be validated. For instance if the " + "transport mode is AIR, the service type A2A (AirportToAirport)", + selection=[ + ("D2D", "Door-to-door"), + ("D2P", "Door-to-port"), + ("P2D", "Port-to-door"), + ("D2A", "Door-to-airport"), + ("A2D", "Airport-to-door"), + ("A2A", "Aiport-to-airport"), + ], + ) + schenker_service_land = fields.Selection( + string="Land service", + help="Land shipping product options. Depending on your customer account, some " + "services could not be available", + selection=[ + ("CON", "DBSchenkerconcepts"), + ("DIR", "DBSchenkerdirects"), + ("LPA", "DBSchenkerparcel Logistics Parcel"), + ("PAL", "DBSchenkerpallets"), + ("PRI", "DBSchenkerprivpark"), + ("auc0", "austroexpress PUNKT 10"), + ("auc2", "austroexpress PUNKT 12"), + ("auc8", "austroexpress PUNKT 8"), + ("aucc", "austroexpress PUNKT 17"), + ("auco", "austrocargo"), + ("ecsp", "SCHENKERsystem-plus"), + ("ect1", "DB SCHENKERspeed 10"), + ("ect2", "DB SCHENKERspeed 12"), + ("sch2", "DB SCHENKERtop 12"), + ("schs", "DB SCHENKERsystem international"), + ("sysd", "DB SCHENKERsystem domestic"), + ("scht", "DB SCHENKERtop"), + ("schx", "DB SCHENKERsystem fix"), + ("ecpa", "DB SCHENKERparcel"), + ("ect8", "DB SCHENKERspeed 8"), + ("ectn", "DB SCHENKERspeed"), + ("40", "DB SCHENKERsystem classic"), + ("41", "DB SCHENKERsystem speed"), + ("42", "DB SCHENKERsystem fixday"), + ("43", "DBSchenker System"), + ("44", "DBSchenker System Premium"), + ("71", "DB SCHENKERdirect"), + ], + ) + schenker_service_air = fields.Selection( + string="Air service", + help="Air shipping product options. Depending on your customer account, some " + "services could not be available", + selection=[ + ("f", "DB SCHENKERjetcargo first"), + ("s", "DB SCHENKERjetcargo special"), + ("b", "DB SCHENKERjetcargo business"), + ("e", "DB SCHENKERjetcargo economy"), + ("eagd", "DB SCHENKERjetexpress gold"), + ("easv", "DB SCHENKERjetexpress silver"), + ], + ) + schenker_indoor_delivery = fields.Boolean( + string="Indoor Delivery", help="Defines if indoor delivery is required" + ) + schenker_express = fields.Boolean( + string="Express", help="Defines if shipment is express" + ) + schenker_food_related = fields.Boolean( + string="Food Related", help="Defines if shipment is food related" + ) + schenker_heated_transport = fields.Boolean( + string="Heated Transport", + help="Defines if shipment is required heated transport", + ) + schenker_home_delivery = fields.Boolean( + string="Home Delivery", help="Defines if shipment is required home delivery" + ) + schenker_own_pickup = fields.Boolean( + string="Own Pickup", help="Defines if shipment is required own pickup" + ) + schenker_pharmaceuticals = fields.Boolean( + string="Pharmaceuticals", help="Defines if shipment is pharmaceutical" + ) + schenker_measure_unit = fields.Selection( + string="Measure Unit", + help="The proper request will be formed accordingly from the picking", + selection=[ + ("VOLUME", "Volume"), + ("LOADING_METERS", "Loading meters"), + ("PIECES", "Pieces"), + ("PALLET_SPACE", "Pallet space"), + ], + default="VOLUME", + ) + schenker_default_package_type_id = fields.Many2one( + comodel_name="stock.package.type", + string="Default Package Type", + domain=[("package_carrier_type", "=", "schenker")], + help="If not delivery package or the package doesn't have defined the packaging" + " it will default to this type", + ) + + def _get_schenker_credentials(self): + """Access key is mandatory for every request while group and user are + optional""" + credentials = { + "prod": self.prod_environment, + "access_key": self.schenker_access_key, + } + if self.schenker_group_id: + credentials["group_id"] = self.schenker_group_id + if self.schenker_user: + credentials["user"] = self.schenker_user + return credentials + + @api.model + def _schenker_log_request(self, schenker_request, picking): + """Helper to write raw request/response to the current picking. If debug + is active in the carrier, those will be logged in the ir.logging as well""" + schenker_last_request = schenker_last_response = False + try: + schenker_last_request = etree.tostring( + schenker_request.history.last_sent["envelope"], + encoding="UTF-8", + pretty_print=True, + ) + schenker_last_response = etree.tostring( + schenker_request.history.last_received["envelope"], + encoding="UTF-8", + pretty_print=True, + ) + # Don't fail hard on this. Sometimes zeep could not be able to keep history + except Exception: + return + # Debug must be active in the carrier + self.log_xml(schenker_last_request, "schenker_request") + self.log_xml(schenker_last_response, "schenker_response") + + def _prepare_schenker_barcode(self): + """Always request the barcode label when generating the booking. We can choose + between two formats: A6 and A4, where an starting position can be set""" + vals = {"barcodeRequest": self.schenker_barcode_format} + if self.schenker_barcode_mail: + vals["barcodeRequestEmail"] = self.schenker_barcode_mail + if self.schenker_barcode_format == "A6": + return vals + # This options only can be informed when the label format is A4 + vals.update( + { + "start_pos": self.schenker_barcode_a4_start_pos, + "separated": self.schenker_barcode_a4_separated, + } + ) + return vals + + def _prepare_schenker_address( + self, + partner, + address_type="CONSIGNEE", + location_type="PHYSICAL", + person_type="COMPANY", + ): + """Generic for any address type. The address from the one receiving the goods. + Keep in mind that every country could have their own mandatory fields rules, + so the request could fail if those fields aren't filled on the contact. An + informative error should raise though. + :param res.partner record + :returns dicts with shipping address formated for Scheneket API + """ + vals = { + "type": address_type, + "name1": partner.name, + "locationType": location_type, # POSTAL or PHYSICAL + "personType": person_type, # PERSON OR COMPANY + "street": partner.street, + "postalCode": partner.zip, + "city": partner.city, + "stateCode": partner.state_id.code, + "stateName": partner.state_id.name, + "countryCode": partner.country_id.code, + "preferredLanguage": self.env["res.lang"]._lang_get(partner.lang).iso_code, + } + # Optional stuff. The API doesn't like falsy or empty request fields + if partner.email: + vals["email"] = partner.email + if partner.mobile: + vals["mobilePhone"] = partner.mobile + if partner.phone: + vals["phone"] = partner.phone + if partner.street2: + vals["street2"] = partner.street2 + return vals + + def _schenker_shipping_address(self, picking): + """Each booking should have at least 2 addresses of types: SHIPPER and CONSIGNEE + Other options are: PICKUP, DELIVERY, NOTIFY, INVOICE and could be hooked to this + method to include them in the booking request. + :param picking record + :returns list of dicts with shipping addresses formated for Scheneket API + """ + shipper_address = ( + picking.picking_type_id.warehouse_id.partner_id + or picking.company_id.partner_id + ) + consignee_address = picking.partner_id + return [ + self._prepare_schenker_address(shipper_address, "SHIPPER"), + self._prepare_schenker_address(consignee_address), + ] + + def _schenker_shipping_product(self): + """Gets the proper shipping product according to the shipping type + :returns string with shipping product code + """ + type_mapping = { + "air": self.schenker_service_air, + "land": self.schenker_service_land, + "ocean_fcl": "fcl", + "ocean_lcl": "lcl", + } + return type_mapping[self.schenker_booking_type] + + def _schenker_metric_system(self): + """ + :returns string with schenker metric system (METRIC or IMPERIAL) + """ + get_param = self.env["ir.config_parameter"].sudo().get_param + product_weight_in_lbs_param = get_param("product.weight_in_lbs", "0") + return "IMPERIAL" if product_weight_in_lbs_param == "1" else "METRIC" + + def _schenker_pickup_dates(self, picking): + """Convert picking dates for schenker api. We're taking the whole delivery + day as picking windows, although a more complex solution could be provided. + :param picking record with picking to send + :returns dict values with the picking dates in iso format + """ + date_from = fields.Datetime.context_timestamp( + self, picking.date_done.replace(hour=0, minute=0, second=0) + ).isoformat() + date_to = fields.Datetime.context_timestamp( + self, picking.date_done.replace(hour=23, minute=59, second=59) + ).isoformat() + return {"pickUpDateFrom": date_from, "pickUpDateTo": date_to} + + def _schenker_shipping_information_package(self, picking, package): + weight = package.shipping_weight or package.weight + # Volume calculations can be unfolded with stock_quant_package_dimension + if hasattr(package, "volume"): + volume = round(package.volume, 2) + else: + volume = sum([q.quantity * q.product_id.volume for q in package.quant_ids]) + return { + # Dangerous goods is not supported + "dgr": False, + "cargoDesc": picking.name + " / " + package.name, + "grossWeight": round(weight, 2), + # Default to 1 if no volume informed + "volume": volume or 0.01, + "packageType": ( + package.package_type_id.shipper_package_code + or self.schenker_default_package_type_id.shipper_package_code + ), + "stackable": ( + package.package_type_id.schenker_stackable + or self.schenker_default_package_type_id.schenker_stackable + ), + "pieces": 1, + } + + def _schenker_shipping_information(self, picking): + """When we don't use delivery packages, we'll deliver everything in one single + shipping info. Otherwise, we'll get the info for each package. + :param picking record with picking to deliver + :returns list of dicts with delivery packages shipping info + """ + if picking.package_level_ids and picking.package_ids: + return [ + self._schenker_shipping_information_package(picking, package) + for package in picking.package_ids + ] + weight = picking.shipping_weight or picking.weight + # Obviously products should be well configured. This parameter is mandatory. + volume = sum( + [ + ml.product_uom_id._compute_quantity(ml.quantity, ml.product_id.uom_id) + * ml.product_id.volume + for ml in picking.move_line_ids + ] + ) + return [ + { + # Dangerous goods is not supported + "dgr": False, + "cargoDesc": picking.name, + # For a more complex solution use packaging properly + "grossWeight": round(weight / picking.number_of_packages, 2), + "volume": round(volume, 2) or 0.01, + "packageType": ( + self.schenker_default_package_type_id.shipper_package_code + ), + "stackable": self.schenker_default_package_type_id.schenker_stackable, + "pieces": picking.number_of_packages, + } + ] + + def _schenker_measures(self, picking, vals): + """Only volume is supported as a pallet calculations structure should be + provided to use the other API options. This hook can be used to communicate + with the API in the future + :param picking record with picking to deliver + :returns dict values for the proper unit key and value + """ + if self.schenker_measure_unit == "VOLUME": + return {"measureUnitVolume": vals["shippingInformation"]["volume"]} + return {} + + def _prepare_schenker_shipping(self, picking): + """Convert picking values for schenker api + :param picking record with picking to send + :returns dict values for the connector + """ + self.ensure_one() + # We'll compose the request via some diferenced parts, like label settings, + # address options, incoterms and so. There are lots of thing to take into + # account to acomplish a properly formed request. + vals = {} + vals.update(self._prepare_schenker_barcode()) + shipping_information = self._schenker_shipping_information(picking) + vals.update( + { + "address": self._schenker_shipping_address(picking), + "incoterm": ( + picking.sale_id.incoterm.code or self.schenker_incoterm_id.code + ), + # A maximum of 35 characters is supported + "incotermLocation": picking.partner_id.display_name[:35], + "productCode": self._schenker_shipping_product(), + "measurementType": self._schenker_metric_system(), + "grossWeight": round(picking.shipping_weight, 2), + "shippingInformation": { + "shipmentPosition": shipping_information, + "grossWeight": round(picking.shipping_weight, 2), + "volume": shipping_information[0]["volume"], + }, + "measureUnit": self.schenker_measure_unit, + # Customs Clearance not supported for now as it needs a full customs + # implementation + "customsClearance": False, + # Defines a business scenario where the Schenker customer sends a + # booking request in the name of his ordering party + "neutralShipping": False, + "pickupDates": self._schenker_pickup_dates(picking), + # Not supported for the moment + "specialCargo": False, + "specialCargoDescription": False, + "serviceType": self.schenker_service_type, + "indoorDelivery": self.schenker_indoor_delivery, + "express": self.schenker_express, + "foodRelated": self.schenker_food_related, + "heatedTransport": self.schenker_heated_transport, + "homeDelivery": self.schenker_home_delivery, + "ownPickup": self.schenker_own_pickup, + "pharmaceuticals": self.schenker_pharmaceuticals, + } + ) + vals.update(self._schenker_measures(picking, vals)) + return vals + + def schenker_send_shipping(self, pickings): + """Send booking request to Schenker + :param pickings: A recordset of pickings + :return list: A list of dictionaries although in practice it's + called one by one and only the first item in the dict is taken. Due + to this design, we have to inject vals in the context to be able to + add them to the message. + """ + schenker_request = SchenkerRequest(**self._get_schenker_credentials()) + result = [] + for picking in pickings: + vals = self._prepare_schenker_shipping(picking) + vals.update({"tracking_number": False, "exact_price": 0}) + try: + response = schenker_request._send_shipping( + vals, self.schenker_booking_type + ) + except Exception as e: + raise (e) + finally: + self._schenker_log_request(schenker_request, picking) + if not response: + result.append(vals) + continue + vals["tracking_number"] = response.get("booking_id") + # We post an extra message in the chatter with the barcode and the + # label because there's clean way to override the one sent by core. + body = _("Schenker Shipping barcode document") + attachment = [] + if response.get("barcode"): + attachment = [ + ( + "schenker_label_{}.pdf".format(response.get("booking_id")), + response.get("barcode"), + ) + ] + picking.message_post(body=body, attachments=attachment) + result.append(vals) + return result + + def schenker_cancel_shipment(self, pickings): + """Cancel the expedition + :param pickings - stock.picking recordset + :returns pdf file + """ + schenker_request = SchenkerRequest(**self._get_schenker_credentials()) + for picking in pickings.filtered("carrier_tracking_ref"): + try: + schenker_request._cancel_shipment(picking.carrier_tracking_ref) + except Exception as e: + raise (e) + finally: + self._schenker_log_request(schenker_request, picking) + return True + + def schenker_get_label(self, reference): + """Generate label for picking + :param picking - stock.picking record + :returns pdf file + """ + self.ensure_one() + if not reference: + return False + schenker_request = SchenkerRequest(**self._get_schenker_credentials()) + format_vals = self.schenker_barcode_format + if format_vals == "A4": + format_vals = { + "start_pos": self.schenker_barcode_a4_start_pos, + "_value_1": self.schenker_barcode_format, + } + label = schenker_request._shipping_label([reference], format_vals) + if not label: + return False + return label + + def schenker_get_tracking_link(self, picking): + """Provide tracking link for the customer""" + return f"https://eschenker.dbschenker.com/app/tracking-public/?refNumber={picking.carrier_tracking_ref}" + + def _prepare_schenker_tracking(self, picking): + self.ensure_one() + return { + "reference": picking.carrier_tracking_ref, + "reference_type": "cu", + "booking_type": self.schenker_booking_type, + } + + def schenker_tracking_state_update(self, picking): + """Tracking state update""" + self.ensure_one() + if not picking.carrier_tracking_ref: + return + schenker_request = SchenkerRequest( + **self._get_schenker_credentials(), service="tracking" + ) + response = schenker_request._get_tracking_states( + **self._prepare_schenker_tracking(picking) + ) + if response.get("shipment"): + shipment = response.get("shipment")[0] + info = shipment.ShipmentInfo.ShipmentBasicInfo + status_event_list = info.StatusEventList.StatusEvent + last_event = SCHENKER_STATUS_CODES.get(info.LastEvent, ("",)) + picking.write( + { + "tracking_state_history": ( + "\n".join( + [ + "{} {} {} - [{}] {}".format( + fields.Datetime.from_string(t.Date).strftime( + "%d/%m/%Y" + ), + t.Time.strftime("%H:%M:%S"), + t.OccurredAt.LocationName, + t.Status, + t.StatusDescription._value_1, + ) + for t in status_event_list + ] + ) + ), + "tracking_state": f"[{info.LastEvent}] {last_event[0]}", + "delivery_state": last_event[1], + } + ) + return + + def schenker_rate_shipment(self, order): + """There's no public API so another price method should be used.""" + return { + "success": True, + "price": self.product_id.lst_price, + "error_message": _( + "Schenker API doesn't provide methods to compute delivery " + "rates, so you should relay on another price method instead or " + "override this one in your custom code." + ), + "warning_message": _( + "Schenker API doesn't provide methods to compute delivery " + "rates, so you should relay on another price method instead or " + "override this one in your custom code." + ), + } + + # UX Control over not implemented features. + + @api.onchange("schenker_booking_type") + def onchange_schenker_booking_type(self): + """Avoid by UX that the user could choose another shipping method. In + the future, this can be removed as long as those method have the proper + support""" + if self.schenker_booking_type != "land": + raise UserError(_("Only land shipping is currently supported")) + + @api.onchange("schenker_measure_unit") + def onchange_schenker_measure_unit(self): + """Avoid by UX that the user could choose another measure unit. Proper pallet + calculation structure should be provided to use the other API options. A hook + method is provided though.""" + if self.schenker_measure_unit != "VOLUME": + raise UserError(_("Only volume is currently supported")) diff --git a/delivery_schenker/models/schenker_request.py b/delivery_schenker/models/schenker_request.py new file mode 100644 index 0000000000..ef992d0ba6 --- /dev/null +++ b/delivery_schenker/models/schenker_request.py @@ -0,0 +1,196 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import logging +from xml.etree import ElementTree as ET + +from zeep import Client, Settings +from zeep.exceptions import Fault +from zeep.plugins import HistoryPlugin + +from odoo import _ +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + +SCHENKER_API_URL = { + "test": "https://eschenker-fat.dbschenker.com", + "prod": "https://eschenker.dbschenker.com", +} +SCHENKER_API_SERVICE = { + "booking": "/webservice/bookingWebServiceV1_1?wsdl", + "tracking": "/webservice/trackingWebServiceV2?wsdl", +} + + +class SchenkerRequest: + """Interface between Schenker SOAP API and Odoo recordset + Abstract Schenker API Operations to connect them with Odoo + + Not all the features are implemented, but could be easily extended with + the provided API. We leave the operations empty for future. + """ + + def __init__( + self, access_key=None, group_id=None, user=None, prod=False, service="booking" + ): + self.access_key = access_key or "" + self.group_id = group_id or "" + self.user = user or "" + self.service = service + api_env = "prod" if prod else "test" + self.history = HistoryPlugin(maxlen=10) + settings = Settings(strict=False, xml_huge_tree=True) + self.client = Client( + wsdl=SCHENKER_API_URL[api_env] + SCHENKER_API_SERVICE[service], + settings=settings, + plugins=[self.history], + ) + + def _process_reply(self, service, vals=None, send_as_kw=False): + """Schenker API returns error petitions as server exceptions wich makes zeep to + raise a Fault exception as well. To catch the error info we need to make a + raw_response request and the extract the error codes from the response.""" + try: + if not send_as_kw: + response = service(vals) + else: + response = service(**vals) + except Fault as e: + with self.client.settings(raw_response=True): + if not send_as_kw: + response = service(vals) + else: + response = service(**vals) + try: + root = ET.fromstring(response.text) + error_text = next(root.iter("faultstring")).text + error_message = next(root.iter("message")).text + error_code = next(root.iter("code")).text + raise ValidationError( + _( + "Error in the request to the Schenker API. This is the " + "thrown message:\n\n" + "[%(error_text)s]\n" + "%(error_code)s - %(error_message)s" + ) + % { + "error_text": error_text, + "error_code": error_code, + "error_message": error_message, + } + ) from e + except ValidationError: + raise + # If we can't get the proper exception, fallback to the first + # exception error traceback + except Exception as exc: + raise Fault(e) from exc + return response + + # Booking API methods + + def _shipping_type_method(self, method): + """Map shipping method with API method. Note that currently only land + is supported. Default to land to ensure a method is provided. + :params string with shipping method + :returns string with the mapped key value for the proper method + """ + method_map = { + "land": "getBookingRequestLand", + "air": "getBookingRequestAir", + "ocean_fcl": "getBookingRequestOceanFCL", + "ocean_lcl": "getBookingRequestOceanLCL", + } + return method_map.get("method", "getBookingRequestLand") + + def _shipping_api_credentials(self): + """Each API has a different credentials SOAP declaration""" + credentials = {"applicationArea": {"accessKey": self.access_key}} + if self.user: + credentials["applicationArea"]["userId"] = self.user + if self.group_id: + credentials["applicationArea"]["groupId"] = self.group_id + return credentials + + def _scheneker_shipping_api_wrapper(self, method=False): + """Aside from a different API method, each one has its own wrapper""" + booking_wrapper_map = { + "land": "bookingLand", + "air": "bookingAir", + "ocean_fcl": "bookingOceanFCL", + "ocean_lcl": "bookingOceanLCL", + } + return booking_wrapper_map.get(method, "land") + + def _send_shipping(self, picking_vals, method=False): + """Create new shipment + :params vals dict of needed values + :returns dict with Schenker response containing the shipping code and label + """ + vals = self._shipping_api_credentials() + method_wrapper = self._scheneker_shipping_api_wrapper(method) + vals[method_wrapper] = picking_vals + # From the Schenker docs: + # Defines if booking shall be submitted. If false, the booking can be edited + # in the frontend and MUST be submitted manually. + vals[method_wrapper].update({"submitBooking": True}) + response = self._process_reply( + self.client.service[self._shipping_type_method(method)], vals + ) + return {"booking_id": response.bookingId, "barcode": response.barcodeDocument} + + def _shipping_label(self, reference_list=None, label_format="A6"): + """Get shipping label for the given ref + :param list reference -- shipping reference list + :returns: base64 with pdf labels + """ + reference_list = reference_list or [] + vals = dict( + **self._shipping_api_credentials(), + **{"barcodeRequest": {"format": label_format}}, + ) + vals["barcodeRequest"].update({"bookingId": reference_list}) + label = self._process_reply( + self.client.service.getBookingBarcodeRequest, vals + ).document + return label + + def _cancel_shipment(self, reference=False): + """Cancel de expedition for the given ref + :param str reference -- booking reference string + :returns: bool True if success + """ + vals = self._shipping_api_credentials() + vals.update({"cancelRequest": {"bookingId": reference}}) + response = self._process_reply( + self.client.service.getBookingCancelRequest, vals + ) + # TODO: Inspect typical response as we don't want to return a zeep object. + # Anyway, it's going to fail if the booking can't be cancelled. So either we + # receive an exception error or the booking is cancelled. + return bool(response) + + # Tracking API methods + + def _tracking_api_credentials(self): + """Each API has a different credentials SOAP declaration""" + return {"AccessKey": self.access_key, "in": {}} + + def _get_tracking_states( + self, reference=False, reference_type="cu", booking_type="land" + ): + if not reference: + return {} + vals = self._tracking_api_credentials() + vals["in"].update( + { + "referenceNumber": reference, + "referenceType": reference_type, + "transportNature": "exp" if booking_type == "land" else "int", + } + ) + response = self._process_reply( + self.client.service.getPublicShipmentDetails, vals, send_as_kw=True + ) + return {"shipment": response.Shipment} diff --git a/delivery_schenker/models/stock_package_type.py b/delivery_schenker/models/stock_package_type.py new file mode 100644 index 0000000000..e06e9fc24c --- /dev/null +++ b/delivery_schenker/models/stock_package_type.py @@ -0,0 +1,13 @@ +# Copyright 2021 Tecnativa - David Vidal +# Copyright 2023 Studio73 - Ferran Mora +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class StockPackageType(models.Model): + _inherit = "stock.package.type" + + package_carrier_type = fields.Selection(selection_add=[("schenker", "DB Schenker")]) + schenker_stackable = fields.Boolean( + string="Stackable", help="Define if the package is stackable by default" + ) diff --git a/delivery_schenker/models/stock_picking.py b/delivery_schenker/models/stock_picking.py new file mode 100644 index 0000000000..66c9cf2495 --- /dev/null +++ b/delivery_schenker/models/stock_picking.py @@ -0,0 +1,21 @@ +# Copyright 2021 Studio73 - Ethan Hildick +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, models + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + def schenker_get_label(self): + self.ensure_one() + tracking_ref = self.carrier_tracking_ref + if self.delivery_type != "schenker" or not tracking_ref: + return + label = self.carrier_id.schenker_get_label(tracking_ref) + label_name = f"schenker_label_{tracking_ref}.pdf" + self.message_post( + body=(_("Schenker label for %s") % tracking_ref), + attachments=[(label_name, label)], + ) + return label diff --git a/delivery_schenker/pyproject.toml b/delivery_schenker/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/delivery_schenker/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/delivery_schenker/readme/CONFIGURE.md b/delivery_schenker/readme/CONFIGURE.md new file mode 100644 index 0000000000..c9577903fe --- /dev/null +++ b/delivery_schenker/readme/CONFIGURE.md @@ -0,0 +1,13 @@ +To configure a Schenker delivery method: + +1. Go to *Inventory \> Configuration \> Delivery \> Shipping methods* + and create a new one. +2. Choose *DB Schenker* as provider. +3. Configure the service parameters according to your contract + considerations. +4. Choose a delivery product and a default packaging. This is mandatory + for the booking request as it needs the packaging code. + +To make tests, set the carrier environment to test from the smart +button. Don't forget to set it to production once you're ready to use +the delivery method! diff --git a/delivery_schenker/readme/CONTRIBUTORS.md b/delivery_schenker/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..c177d28a7a --- /dev/null +++ b/delivery_schenker/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +- [Tecnativa](https://www.tecnativa.com): + - David Vidal +- [Studio73](https://www.studio73.es): + - Ethan Hildick +- Michael Tietz (MT Software) \<\> diff --git a/delivery_schenker/readme/DESCRIPTION.md b/delivery_schenker/readme/DESCRIPTION.md new file mode 100644 index 0000000000..b22adbb0de --- /dev/null +++ b/delivery_schenker/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module links the [DB Schenker](https://www.dbschenker.com) booking +and tracking APIs with Odoo delivery system. diff --git a/delivery_schenker/readme/INSTALL.md b/delivery_schenker/readme/INSTALL.md new file mode 100644 index 0000000000..a201b145a3 --- /dev/null +++ b/delivery_schenker/readme/INSTALL.md @@ -0,0 +1,6 @@ +This module depends on the zeep python library and the +OCA/delivery-carrier delivery_package_number and delivery_state modules. + +The Schenker API doesn't provide delivery rating methods, so OCA's +delivery_price_method is advised in order to use this carrier in a sales +workflow. diff --git a/delivery_schenker/readme/ROADMAP.md b/delivery_schenker/readme/ROADMAP.md new file mode 100644 index 0000000000..ed6ed137a7 --- /dev/null +++ b/delivery_schenker/readme/ROADMAP.md @@ -0,0 +1,24 @@ +- There's no dummy access key to test API calls so no tests can be + performed. +- The test booking and shipping APIs databases aren't connected so it + isn't possible to perform trackings on test mode. +- Only land shipping is implemented, although the module is prepared for + extend to air and ocean just considering the mandatory request fields + for those methods. Some additional adaptations could be needed (e.g.: + origin and destination airport, port) anyway. +- Only volume is supported as a measure unit and with the limitations of + Odoo itself. To enjoy a full fledged volume support, install and + configure the OCA’s stock_quant_package_dimension module and its + dependencies. The connector is ready to make use of their volume + computations. +- It’d be needed to extend the method to support Schenker measure units + such as loading pieces or pallet space. +- Some more booking features aren’t yet supported although can be + extended in the future. Some of those, although the complete list + would be really extensive: + - Dangerous goods. + - Driver pre-advise. + - Transport temperature. + - Customs clearance. + - Cargo insurance. + - Cash on delivery. diff --git a/delivery_schenker/readme/USAGE.md b/delivery_schenker/readme/USAGE.md new file mode 100644 index 0000000000..6827d43fed --- /dev/null +++ b/delivery_schenker/readme/USAGE.md @@ -0,0 +1,40 @@ +These are the operations possible with this module: + +## Place shipping bookings + +1. When the picking is validated, the shipping will be booked at + Schenker. +2. With the response, we'll receive the delivery tracking number and + the pdf label in a chatter message and it will be kept as attachment + to the document. +3. You can manage packages number either with the proper Odoo workflows + or with the package number field available in the *Additional Info* + tab. You'll get as many labels as declared packages. + +## Cancel bookings + +1. As in other carriers, we can cancel the shipping after the picking + is done. To do so, go to *Additional Info* tab and click on the + *Cancel* action on the side of the tracking number. +2. We can generate a new shipping if necessary. + +## Get labels + +1. If by chance we delete the generated labels, we can obtain them + again hitting the *Schenker Label* buttons in the header of the + picking form. + +## Tracking + +1. The module is integrated with delivery_state to be able to get the + tracking info directly from the DB Schenker API. +2. To do so, go to a picking shipped with Schenker. In the *Additional + Info* tab you'll find an action button to *Update tracking state* so + the state will be updated from the Schenker API. + +## Debugging + +The API calls and responses are tracked in two special fields in the +picking that can be viewed by technical users. You can also log them in +as ir.logging records setting the carrier debug on from the smart +button. diff --git a/delivery_schenker/static/description/icon.png b/delivery_schenker/static/description/icon.png new file mode 100644 index 0000000000..e3b8b0ff97 Binary files /dev/null and b/delivery_schenker/static/description/icon.png differ diff --git a/delivery_schenker/static/description/icon.svg b/delivery_schenker/static/description/icon.svg new file mode 100644 index 0000000000..bbca8a0869 --- /dev/null +++ b/delivery_schenker/static/description/icon.svg @@ -0,0 +1,528 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/static/description/index.html b/delivery_schenker/static/description/index.html new file mode 100644 index 0000000000..f53657d3f8 --- /dev/null +++ b/delivery_schenker/static/description/index.html @@ -0,0 +1,550 @@ + + + + + +Delivery Schenker + + + +
+

Delivery Schenker

+ + +

Beta License: AGPL-3 OCA/delivery-carrier Translate me on Weblate Try me on Runboat

+

This module links the DB Schenker +booking and tracking APIs with Odoo delivery system.

+

Table of contents

+ +
+

Installation

+

This module depends on the zeep python library and the +OCA/delivery-carrier delivery_package_number and delivery_state modules.

+

The Schenker API doesn’t provide delivery rating methods, so OCA’s +delivery_price_method is advised in order to use this carrier in a sales +workflow.

+
+
+

Configuration

+

To configure a Schenker delivery method:

+
    +
  1. Go to Inventory > Configuration > Delivery > Shipping methods and +create a new one.
  2. +
  3. Choose DB Schenker as provider.
  4. +
  5. Configure the service parameters according to your contract +considerations.
  6. +
  7. Choose a delivery product and a default packaging. This is mandatory +for the booking request as it needs the packaging code.
  8. +
+

To make tests, set the carrier environment to test from the smart +button. Don’t forget to set it to production once you’re ready to use +the delivery method!

+
+
+

Usage

+

These are the operations possible with this module:

+
+

Place shipping bookings

+
    +
  1. When the picking is validated, the shipping will be booked at +Schenker.
  2. +
  3. With the response, we’ll receive the delivery tracking number and the +pdf label in a chatter message and it will be kept as attachment to +the document.
  4. +
  5. You can manage packages number either with the proper Odoo workflows +or with the package number field available in the Additional Info +tab. You’ll get as many labels as declared packages.
  6. +
+
+
+

Cancel bookings

+
    +
  1. As in other carriers, we can cancel the shipping after the picking is +done. To do so, go to Additional Info tab and click on the Cancel +action on the side of the tracking number.
  2. +
  3. We can generate a new shipping if necessary.
  4. +
+
+
+

Get labels

+
    +
  1. If by chance we delete the generated labels, we can obtain them again +hitting the Schenker Label buttons in the header of the picking +form.
  2. +
+
+
+

Tracking

+
    +
  1. The module is integrated with delivery_state to be able to get the +tracking info directly from the DB Schenker API.
  2. +
  3. To do so, go to a picking shipped with Schenker. In the Additional +Info tab you’ll find an action button to Update tracking state so +the state will be updated from the Schenker API.
  4. +
+
+
+

Debugging

+

The API calls and responses are tracked in two special fields in the +picking that can be viewed by technical users. You can also log them in +as ir.logging records setting the carrier debug on from the smart +button.

+
+
+
+

Known issues / Roadmap

+
    +
  • There’s no dummy access key to test API calls so no tests can be +performed.
  • +
  • The test booking and shipping APIs databases aren’t connected so it +isn’t possible to perform trackings on test mode.
  • +
  • Only land shipping is implemented, although the module is prepared +for extend to air and ocean just considering the mandatory request +fields for those methods. Some additional adaptations could be needed +(e.g.: origin and destination airport, port) anyway.
  • +
  • Only volume is supported as a measure unit and with the limitations +of Odoo itself. To enjoy a full fledged volume support, install and +configure the OCA’s stock_quant_package_dimension module and its +dependencies. The connector is ready to make use of their volume +computations.
  • +
  • It’d be needed to extend the method to support Schenker measure units +such as loading pieces or pallet space.
  • +
  • Some more booking features aren’t yet supported although can be +extended in the future. Some of those, although the complete list +would be really extensive:
      +
    • Dangerous goods.
    • +
    • Driver pre-advise.
    • +
    • Transport temperature.
    • +
    • Customs clearance.
    • +
    • Cargo insurance.
    • +
    • Cash on delivery.
    • +
    +
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
  • Studio73
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/delivery-carrier project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/delivery_schenker/tests/__init__.py b/delivery_schenker/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/delivery_schenker/views/delivery_schenker_view.xml b/delivery_schenker/views/delivery_schenker_view.xml new file mode 100644 index 0000000000..c2b557efeb --- /dev/null +++ b/delivery_schenker/views/delivery_schenker_view.xml @@ -0,0 +1,81 @@ + + + + + delivery.carrier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/delivery_schenker/views/stock_picking_views.xml b/delivery_schenker/views/stock_picking_views.xml new file mode 100644 index 0000000000..06755747c1 --- /dev/null +++ b/delivery_schenker/views/stock_picking_views.xml @@ -0,0 +1,21 @@ + + + + stock.picking + + + +