From 97e4ee718343c1963c1a27b38bd3099098e5c5fe Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 21 Sep 2022 00:25:51 +0000 Subject: [PATCH] [IMP] delivery_purolator: rework packaging, support packaging codes, tests --- .../data/delivery_purolator_data.xml | 18 ++++++-- .../data/delivery_purolator_demo.xml | 4 +- .../models/delivery_purolator.py | 8 ++-- .../models/purolator_services.py | 41 +++++++++++++++++-- delivery_purolator/tests/test_purolator.py | 4 ++ 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/delivery_purolator/data/delivery_purolator_data.xml b/delivery_purolator/data/delivery_purolator_data.xml index 503d26de..527dd1c0 100644 --- a/delivery_purolator/data/delivery_purolator_data.xml +++ b/delivery_purolator/data/delivery_purolator_data.xml @@ -2,9 +2,21 @@ - - Purolator Customer Packaging - CustomerPackaging + + Purolator Default + + purolator + + + + Purolator LargePackage + LargePackage + purolator + + + + Purolator FlatPackage + FlatPackage purolator diff --git a/delivery_purolator/data/delivery_purolator_demo.xml b/delivery_purolator/data/delivery_purolator_demo.xml index 7388c15d..ede6dd63 100644 --- a/delivery_purolator/data/delivery_purolator_demo.xml +++ b/delivery_purolator/data/delivery_purolator_demo.xml @@ -20,7 +20,7 @@ purolator PurolatorExpress - + @@ -39,7 +39,7 @@ purolator PurolatorGround - + diff --git a/delivery_purolator/models/delivery_purolator.py b/delivery_purolator/models/delivery_purolator.py index 4aab75b9..758b2ece 100644 --- a/delivery_purolator/models/delivery_purolator.py +++ b/delivery_purolator/models/delivery_purolator.py @@ -1,3 +1,4 @@ +from base64 import b64decode from odoo import fields, models, _ from odoo.exceptions import UserError from .purolator_services import PurolatorClient @@ -253,7 +254,8 @@ class ProviderPurolator(models.Model): def _purolator_fill_address(self, addr, partner): - addr.Name = partner.name if not partner.is_company else '' + # known to not work without a name + addr.Name = partner.name addr.Company = partner.name if partner.is_company else (partner.company_name or '') addr.Department = '' addr.StreetNumber, addr.StreetName, addr.StreetType = self._purolator_address_street(partner) @@ -318,13 +320,13 @@ class ProviderPurolator(models.Model): p.carrier_tracking_ref = pin doc_res = service.document_by_pin(pin, output_type=self.purolator_label_file_type) for n, blob in enumerate(self._purolator_extract_doc_blobs(doc_res), 1): - document_blobs.append(('PuroPackage-%s-%s.%s' % (pin, n, self.purolator_label_file_type), blob)) + document_blobs.append(('PuroPackage-%s-%s.%s' % (pin, n, self.purolator_label_file_type), b64decode(blob))) else: # retrieve shipment_pin document(s) doc_res = service.document_by_pin(shipment_pin, output_type=self.purolator_label_file_type) # _logger.info('purolator service.document_by_pin for pin %s resulted in %s' % (shipment_pin, doc_res)) for n, blob in enumerate(self._purolator_extract_doc_blobs(doc_res), 1): - document_blobs.append(('PuroShipment-%s-%s.%s' % (shipment_pin, n, self.purolator_label_file_type), blob)) + document_blobs.append(('PuroShipment-%s-%s.%s' % (shipment_pin, n, self.purolator_label_file_type), b64decode(blob))) if document_blobs: logmessage = _("Shipment created in Purolator
Tracking Number/PIN : %s") % (shipment_pin) diff --git a/delivery_purolator/models/purolator_services.py b/delivery_purolator/models/purolator_services.py index 109ba771..a36f4b97 100644 --- a/delivery_purolator/models/purolator_services.py +++ b/delivery_purolator/models/purolator_services.py @@ -7,6 +7,15 @@ from zeep.transports import Transport from odoo.exceptions import UserError +PUROLATOR_PIECE_SPECIAL_HANDLING_TYPE = [ + # 'AdditionalHandling', # unknown if this is "SpecialHandling" + 'FlatPackage', + 'LargePackage', + # 'Oversized', # unknown if this is "SpecialHandling" + # 'ResidentialAreaHeavyweight', # unknown if this is "SpecialHandling" +] + + class PurolatorClient(object): # clients and factories @@ -151,9 +160,23 @@ class PurolatorClient(object): shipment.PaymentInformation = factory.PaymentInformation() return shipment + def _add_piece_code(self, factory, piece, code): + # note that we ONLY support special handling type + if not piece.Options: + piece.Options = factory.ArrayOfOptionIDValuePair() + piece.Options.OptionIDValuePair.append(factory.OptionIDValuePair( + ID='SpecialHandling', + Value='true', + )) + piece.Options.OptionIDValuePair.append(factory.OptionIDValuePair( + ID='SpecialHandlingType', + Value=code, + )) + def estimate_shipment_add_sale_order_packages(self, shipment, carrier, order): # this could be a non-purolator package type as returned by the search functions package_type = carrier.get_package_type_for_order(order) + package_type_codes = [t.strip() for t in (package_type.shipper_package_code or '').split(',') if t.strip() in PUROLATOR_PIECE_SPECIAL_HANDLING_TYPE] shipment.PackageInformation.ServiceID = carrier.purolator_service_type weight = carrier.purolator_convert_weight(order._get_estimated_weight()) package_type_max_weight = 0.0 @@ -190,6 +213,9 @@ class PurolatorClient(object): 'DimensionUnit': 'in', }, ) + for package_code in package_type_codes: + self._add_piece_code(self.estimating_factory, p, package_code) + shipment.PackageInformation.PiecesInformation.Piece.append(p) shipment.PackageInformation.TotalWeight.Value = str(weight) shipment.PackageInformation.TotalWeight.WeightUnit = 'lb' @@ -215,6 +241,7 @@ class PurolatorClient(object): package_weight = 1.0 total_weight_value += package_weight package_type = carrier.purolator_default_package_type_id + package_type_codes = [t.strip() for t in (package_type.shipper_package_code or '').split(',') if t.strip() in PUROLATOR_PIECE_SPECIAL_HANDLING_TYPE] p = factory.Piece( Weight={ 'Value': str(package_weight), @@ -233,6 +260,9 @@ class PurolatorClient(object): 'DimensionUnit': 'in', }, ) + for package_code in package_type_codes: + self._add_piece_code(factory, p, package_code) + shipment.PackageInformation.PiecesInformation.Piece.append(p) else: for package in packages: @@ -240,6 +270,11 @@ class PurolatorClient(object): if package_weight < 1.0: package_weight = 1.0 package_type = package.package_type_id + package_type_code = package_type.shipper_package_code or '' + if package_type.package_carrier_type != 'purolator': + package_type_code = carrier.purolator_default_package_type_id.shipper_package_code or '' + package_type_codes = [t.strip() for t in package_type_code.split(',') if t.strip() in PUROLATOR_PIECE_SPECIAL_HANDLING_TYPE] + total_weight_value += package_weight p = factory.Piece( Weight={ @@ -259,9 +294,9 @@ class PurolatorClient(object): 'DimensionUnit': 'in', }, ) - # TODO p.Options.OptionIDValuePair (ID='SpecialHandling', Value='true') - # can we do per-package signature requirements? - # Packaging specific codes? + for package_code in package_type_codes: + self._add_piece_code(factory, p, package_code) + shipment.PackageInformation.PiecesInformation.Piece.append(p) shipment.PackageInformation.TotalWeight.Value = str(total_weight_value) diff --git a/delivery_purolator/tests/test_purolator.py b/delivery_purolator/tests/test_purolator.py index 47d39f44..c316dd26 100644 --- a/delivery_purolator/tests/test_purolator.py +++ b/delivery_purolator/tests/test_purolator.py @@ -53,6 +53,10 @@ class TestPurolator(TransactionCase): 'price_unit': self.storage_box.lst_price, })], }) + + # reconfigure this method so that we can set its default package to one that needs a service code + self.delivery_carrier_ground = self.env.ref('delivery_purolator.purolator_ground') + self.delivery_carrier_ground.purolator_default_package_type_id = self.env.ref('delivery_purolator.purolator_packaging_large_package') def _so_pick_shipping(self): # Regular Update Shipping functionality