From 0d5c6f7ececcfc91ebc35f3d4fce4a3209de49f9 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Thu, 29 Oct 2020 11:43:43 -0700 Subject: [PATCH 01/14] [MOV] delivery_gso: from hibou-suite-enterprise:11.0 --- delivery_gso/__init__.py | 1 + delivery_gso/__manifest__.py | 25 ++ delivery_gso/models/__init__.py | 1 + delivery_gso/models/delivery_gso.py | 321 +++++++++++++++++++++++ delivery_gso/models/requests_gso.py | 47 ++++ delivery_gso/views/delivery_gso_view.xml | 28 ++ 6 files changed, 423 insertions(+) create mode 100644 delivery_gso/__init__.py create mode 100644 delivery_gso/__manifest__.py create mode 100644 delivery_gso/models/__init__.py create mode 100644 delivery_gso/models/delivery_gso.py create mode 100644 delivery_gso/models/requests_gso.py create mode 100644 delivery_gso/views/delivery_gso_view.xml diff --git a/delivery_gso/__init__.py b/delivery_gso/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/delivery_gso/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py new file mode 100644 index 00000000..3f94b3c9 --- /dev/null +++ b/delivery_gso/__manifest__.py @@ -0,0 +1,25 @@ +{ + 'name': 'Golden State Overnight (gso.com) Shipping', + 'summary': 'Send your shippings through gso.com and track them online.', + 'version': '11.0.1.0.0', + 'author': "Hibou Corp.", + 'category': 'Warehouse', + 'license': 'AGPL-3', + 'images': [], + 'website': "https://hibou.io", + 'description': """ +Golden State Overnight (gso.com) Shipping +========================== +* Provides estimates on shipping costs through gso.com. +* Send your shippings through gso.com and allows tracking of packages. +""", + 'depends': [ + 'delivery_hibou', + ], + 'demo': [], + 'data': [ + 'views/delivery_gso_view.xml', + ], + 'auto_install': False, + 'installable': True, +} diff --git a/delivery_gso/models/__init__.py b/delivery_gso/models/__init__.py new file mode 100644 index 00000000..943392d3 --- /dev/null +++ b/delivery_gso/models/__init__.py @@ -0,0 +1 @@ +from . import delivery_gso diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py new file mode 100644 index 00000000..84bb6477 --- /dev/null +++ b/delivery_gso/models/delivery_gso.py @@ -0,0 +1,321 @@ +import pytz +from math import ceil +from requests import HTTPError +from hashlib import sha1 + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError, UserError + +from .requests_gso import GSORequest + +GSO_TZ = 'PST8PDT' + + +class ProductPackaging(models.Model): + _inherit = 'product.packaging' + + package_carrier_type = fields.Selection(selection_add=[('gso', 'gso.com')]) + + +class ProviderGSO(models.Model): + _inherit = 'delivery.carrier' + + delivery_type = fields.Selection(selection_add=[('gso', 'gso.com')]) + gso_username = fields.Char(string='gso.com Username', groups='base.group_system') + gso_password = fields.Char(string='gso.com Password', groups='base.group_system') + gso_account_number = fields.Char(string='gso.com Account Number', groups='base.group_system') + gso_default_packaging_id = fields.Many2one('product.packaging', string='Default Package Type') + # For service type, SAM, SPM, and SEV require authorized accounts. + gso_service_type = fields.Selection([('PDS', 'Priority Overnight'), + ('EPS', 'Early Priority Overnight'), + ('NPS', 'Noon Priority Overnight'), + ('SDS', 'Saturday Delivery'), + ('ESS', 'Early Saturday Delivery'), + ('CPS', 'GSO Ground'), + ('SAM', 'AM Select (8A-12P) Delivery Window'), + ('SPM', 'PM Select (12P-4P) Delivery Window'), + ('SEV', 'Evening Select (4P-8P) Delivery Window'), + ], + string="Service Type", default="CPS", help="Service Type determines speed of delivery") + gso_image_type = fields.Selection([('NO_LABEL', 'No Label'), + ('PAPER_LABEL', 'Paper Label'), + ('ZPL_SHORT_LABEL', 'Short Label'), + ('ZPL_LONG_LABEL', 'Long label'), + ], + string="Image Type", default="ZPL_SHORT_LABEL", help="Image Type is the type of Label to use") + + def _get_gso_service(self): + return GSORequest(self.prod_environment, + self.gso_username, + self.gso_password, + self.gso_account_number) + + def _gso_make_ship_address(self, partner): + # Addresses look like + # { + # 'ShipToCompany': '', + # 'ShipToAttention': '', + # 'ShipToPhone': '', + # 'ShipToEmail': '', + # 'DeliveryAddress1': '', + # 'DeliveryAddress2': '', + # 'DeliveryCity': '', + # 'DeliveryState': '', + # 'DeliveryZip': '', + # } + address = {} + # ShipToCompany is required. ShipToAttention which is a person is not. + if partner.name and not partner.parent_id: + address['ShipToCompany'] = partner.name + if partner.name and partner.parent_id: + address['ShipToCompany'] = partner.parent_id.name # or partner.parent_id.id.name ?? + address['ShipToAttention'] = partner.name + + if partner.phone: + address['ShipToPhone'] = partner.phone + if partner.email: + address['ShipToEmail'] = partner.email + if partner.street: + address['DeliveryAddress1'] = partner.street + if partner.street2: + address['DeliveryAddress2'] = partner.street2 + if partner.city: + address['DeliveryCity'] = partner.city + if partner.state_id: + address['DeliveryState'] = partner.state_id.code + if partner.zip: + address['DeliveryZip'] = partner.zip + + return address + + def _gso_make_shipper_address(self, warehouse, company): + # Addresses look like + # { + # 'ShipperCompany': '', + # 'ShipperContact': '', + # 'ShipperPhone': '', + # 'ShipperEmail': '', + # 'PickupAddress1': '', + # 'PickupAddress2': '', + # 'PickupCity': '', + # 'PickupState': '', + # 'PickupZip': '', + # } + address = {} + if company.name and not company.parent_id: + address['ShipperCompany'] = company.name + if company.name and company.parent_id: + address['ShipperCompany'] = company.parent_id.name + address['ShipperContact'] = company.name + + if warehouse.phone: + address['ShipperPhone'] = warehouse.phone + if warehouse.email: + address['ShipperEmail'] = warehouse.email + if warehouse.street: + address['PickupAddress1'] = warehouse.street + if warehouse.street2: + address['PickupAddress2'] = warehouse.street2 + if warehouse.city: + address['PickupCity'] = warehouse.city + if warehouse.state_id: + address['PickupState'] = warehouse.state_id.code + if warehouse.zip: + address['PickupZip'] = warehouse.zip + + return address + + def _gso_create_tracking_number(self, identifier): + # Override for a more 'customized' tracking number + # Expects a self.sudo() + if not identifier: + identifier = fields.Datetime.now() # string in Odoo 11 + salt = self.env['ir.config_parameter'].sudo().get_param('database.secret') + sha = sha1((identifier + salt).encode()).hexdigest() + return sha[:20] + + def _gso_get_package_dimensions(self, package=None): + if not package: + package_type = self.gso_default_packaging_id + else: + package_type = package.packaging_id + return {'Length': package_type.length, 'Width': package_type.width, 'Height': package_type.height} + + def _gso_convert_weight(self, weight_in_kg): + # m(lb) = m(kg) / 0.45359237 + weight_in_lb = weight_in_kg / 0.45359237 + # If less than 8 oz... + if weight_in_lb < 0.5: + return 0 + else: + # Round up to nearest lb + return int(ceil(weight_in_lb)) + + def gso_send_shipping(self, pickings): + res = [] + sudoself = self.sudo() + service = sudoself._get_gso_service() + + for picking in pickings: + company = self.get_shipper_company(picking=picking) + from_ = self.get_shipper_warehouse(picking=picking) + to = self.get_recipient(picking=picking) + address_type = 'B' if bool(to.company or to.parent_id.company) else 'R' + + request_body = { + 'AccountNumber': sudoself.gso_account_number, + 'Shipment': { + 'ServiceCode': sudoself.gso_service_type, + 'ShipmentLabelType': sudoself.gso_image_type, + 'SignatureCode': 'SIG_NOT_REQD', + 'DeliveryAddressType': address_type, + # 'ShipDate': fields.Date.today(), # safer not to send in case you want to ship on a weekend + }, + } + request_body['Shipment'].update(self._gso_make_shipper_address(from_, company)) + request_body['Shipment'].update(self._gso_make_ship_address(to)) + + # Automatic insurance at $100.0 + insurance_value = sudoself.get_insurance_value(picking=picking) + if insurance_value: + request_body['Shipment']['SignatureCode'] = 'SIG_REQD' + if insurance_value > 100.0: + # Documentation says to set DeclaredValue ONLY if over $100.00 + request_body['Shipment']['DeclaredValue'] = insurance_value + + cost = 0.0 + labels = { + 'thermal': [], + 'paper': [], + } + if picking.package_ids: + # Every package will be a transaction + for package in picking.package_ids: + request_body['Shipment']['Weight'] = self._gso_convert_weight(package.shipping_weight) + request_body['Shipment'].update(self._gso_get_package_dimensions(package)) + request_body['Shipment']['ShipmentReference'] = package.name + request_body['Shipment']['TrackingNumber'] = self._gso_create_tracking_number(package.name) + try: + response = service.post_shipment(request_body) + + if response.get('ThermalLabel'): + labels['thermal'].append((response['TrackingNumber'], response['ThermalLabel'])) + elif response.get('PaperLabel'): + labels['paper'].append((response['TrackingNumber'], response['PaperLabel'])) + + if response.get('ShipmentCharges', {}).get('TotalCharge'): + cost += response['ShipmentCharges']['TotalCharge'] + except HTTPError as e: + raise ValidationError(e) + else: + request_body['Shipment']['Weight'] = self._gso_convert_weight(picking.shipping_weight) + request_body['Shipment'].update(self._gso_get_package_dimensions()) + request_body['Shipment']['ShipmentReference'] = picking.name + request_body['Shipment']['TrackingNumber'] = self._gso_create_tracking_number(picking.name) + try: + response = service.post_shipment(request_body) + + if response.get('ThermalLabel'): + labels['thermal'].append((response['TrackingNumber'], response['ThermalLabel'])) + elif response.get('PaperLabel'): + labels['paper'].append((response['TrackingNumber'], response['PaperLabel'])) + + if response.get('ShipmentCharges', {}).get('TotalCharge'): + cost += response['ShipmentCharges']['TotalCharge'] + except HTTPError as e: + raise ValidationError(e) + + # Handle results + trackings = [l[0] for l in labels['thermal']] + [l(0) for l in labels['paper']] + carrier_tracking_ref = ','.join(trackings) + + logmessage = _("Shipment created into GSO
" + "Tracking Numbers: %s") % (carrier_tracking_ref, ) + attachments = [] + if labels['thermal']: + attachments += [('LabelGSO-%s.zpl' % (l[0], ), l[1]) for l in labels['thermal']] + if labels['paper']: + attachments += [('LabelGSO-%s.pdf' % (l[0], ), l[1]) for l in labels['thermal']] + picking.message_post(body=logmessage, attachments=attachments) + shipping_data = {'exact_price': cost, + 'tracking_number': carrier_tracking_ref} + res.append(shipping_data) + return res + + def gso_cancel_shipment(self, picking): + sudoself = self.sudo() + service = sudoself._get_gso_service() + try: + request_body = { + 'AccountNumber': sudoself.gso_account_number, + } + for tracking in picking.carrier_tracking_ref.split(','): + request_body['TrackingNumber'] = tracking + _ = service.delete_shipment(request_body) + except HTTPError as e: + raise ValidationError(e) + picking.message_post(body=(_('Shipment N° %s has been cancelled') % (picking.carrier_tracking_ref, ))) + picking.write({'carrier_tracking_ref': '', 'carrier_price': 0.0}) + + def gso_rate_shipment(self, order): + sudoself = self.sudo() + service = sudoself._get_gso_service() + from_ = sudoself.get_shipper_warehouse(order=order) + to = sudoself.get_recipient(order=order) + address_type = 'B' if bool(to.company or to.parent_id.company) else 'R' + + est_weight_value = self._gso_convert_weight( + sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) + + date_planned = None + if self.env.context.get('date_planned'): + date_planned = self.env.context.get('date_planned') + + ship_date_utc = fields.Datetime.from_string(date_planned if date_planned else fields.Datetime.now()) + ship_date_utc = ship_date_utc.replace(tzinfo=pytz.utc) + ship_date_gso = ship_date_utc.astimezone(pytz.timezone(GSO_TZ)) + ship_date_gso = fields.Datetime.to_string(ship_date_gso) + + request_body = { + 'AccountNumber': sudoself.gso_account_number, + 'OriginZip': from_.zip, + 'DestinationZip': to.zip, + 'ShipDate': ship_date_gso, + 'PackageDimension': self._gso_get_package_dimensions(), + 'PackageWeight': est_weight_value, + 'DeliveryAddressType': address_type, + } + + result = service.get_rates_and_transit_time(request_body) + + delivery = list(filter(lambda d: d['ServiceCode'] == sudoself.gso_service_type, result['DeliveryServiceTypes'])) + if delivery: + delivery = delivery[0] + delivery_date_gso = delivery['DeliveryDate'].replace('T', ' ') + delivery_date_gso = fields.Datetime.from_string(delivery_date_gso) + delivery_date_gso = delivery_date_gso.replace(tzinfo=pytz.timezone(GSO_TZ)) + delivery_date_utc = delivery_date_gso.astimezone(pytz.utc) + delivery_date_utc = fields.Datetime.to_string(delivery_date_utc) + price = delivery.get('ShipmentCharges', {}).get('TotalCharge', 0.0) + return { + 'success': True, + 'price': price, + 'error_message': False, + 'date_delivered': delivery_date_utc, + 'warning_message': _('TotalCharge not found.') if price == 0.0 else False, + } + + raise Exception() + return { + 'success': False, + 'price': 0.0, + 'error_message': _('Delivery Method not found in result'), + 'warning_message': False, + } + + def gso_get_tracking_link(self, pickings): + # No way to get a link specifically as their site only allows POST into tracking form. + res = [] + for _ in pickings: + res.append('https://www.gso.com/Tracking') + return res diff --git a/delivery_gso/models/requests_gso.py b/delivery_gso/models/requests_gso.py new file mode 100644 index 00000000..e5fceb3a --- /dev/null +++ b/delivery_gso/models/requests_gso.py @@ -0,0 +1,47 @@ +import requests +from json import dumps + + +class GSORequest: + + BASE_URL = 'https://api.gso.com/Rest/v1' + + def __init__(self, production, username, password, account_number): + self.username = username + self.password = password + self.account_number = account_number + self.headers = self.make_headers() + self._get_token() + + def make_headers(self): + return { + 'Content-Type': 'application/json', + 'Accept-Encoding': 'gzip', + 'UserName': self.username, + 'PassWord': self.password, + 'AccountNumber': self.account_number, + } + + # Token Lasts 12 hours and should be refreshed accordingly. + # Might need to change to prevent too many calls to the API + def _get_token(self): + endpoint_url = self.BASE_URL + '/token' + response = requests.get(endpoint_url, headers=self.headers) + response.raise_for_status() + self.headers.update({'Token': response.headers['Token']}) + + def call(self, http_method, endpoint_url, payload): + url = self.BASE_URL + endpoint_url + result = requests.request(http_method, url, data=dumps(payload), headers=self.headers) + if result.status_code != 200: + raise requests.exceptions.HTTPError(result.text) + return result.json() + + def post_shipment(self, request_body): + return self.call('POST', '/Shipment', request_body) + + def delete_shipment(self, request_body): + return self.call('DELETE', '/Shipment', request_body) + + def get_rates_and_transit_time(self, request_body): + return self.call('POST', '/RatesAndTransitTimes', request_body) diff --git a/delivery_gso/views/delivery_gso_view.xml b/delivery_gso/views/delivery_gso_view.xml new file mode 100644 index 00000000..ec57d2fe --- /dev/null +++ b/delivery_gso/views/delivery_gso_view.xml @@ -0,0 +1,28 @@ + + + + + delivery.carrier.form.provider.gso + delivery.carrier + + + + + + + + + + + + + + + + + + + + + + From f38017742d292f3d6c3102b4380c9b3fb2586720 Mon Sep 17 00:00:00 2001 From: Connor Christian Date: Thu, 5 Nov 2020 12:46:40 -0500 Subject: [PATCH 02/14] [MIG] delivery_gso: for Odoo 12.0 Fixed warning in manifest by extending underline "===..." --- delivery_gso/__manifest__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index 3f94b3c9..2856bc7a 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -9,7 +9,8 @@ 'website': "https://hibou.io", 'description': """ Golden State Overnight (gso.com) Shipping -========================== +========================================= + * Provides estimates on shipping costs through gso.com. * Send your shippings through gso.com and allows tracking of packages. """, From 849d567867f0107a71ef6c702410b9a1c38be594 Mon Sep 17 00:00:00 2001 From: Connor Christian Date: Thu, 5 Nov 2020 13:05:30 -0500 Subject: [PATCH 03/14] [FIX] delivery_gso: removed outer parenthesis to fix message --- delivery_gso/models/delivery_gso.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 84bb6477..e553445e 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -254,7 +254,7 @@ class ProviderGSO(models.Model): _ = service.delete_shipment(request_body) except HTTPError as e: raise ValidationError(e) - picking.message_post(body=(_('Shipment N° %s has been cancelled') % (picking.carrier_tracking_ref, ))) + picking.message_post(body=_('Shipment N° %s has been cancelled') % (picking.carrier_tracking_ref, )) picking.write({'carrier_tracking_ref': '', 'carrier_price': 0.0}) def gso_rate_shipment(self, order): From de6f698d6a860a92c410863b2ce9f7ad996f42a6 Mon Sep 17 00:00:00 2001 From: Connor Christian Date: Thu, 12 Nov 2020 14:24:55 -0500 Subject: [PATCH 04/14] [MIG] delivery_gso: for Odoo 13.0 --- delivery_gso/models/delivery_gso.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index e553445e..de60b22e 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -160,7 +160,7 @@ class ProviderGSO(models.Model): company = self.get_shipper_company(picking=picking) from_ = self.get_shipper_warehouse(picking=picking) to = self.get_recipient(picking=picking) - address_type = 'B' if bool(to.company or to.parent_id.company) else 'R' + address_type = 'B' if "company" in (to.company_type, to.parent_id.company_type) else 'R' request_body = { 'AccountNumber': sudoself.gso_account_number, @@ -251,7 +251,7 @@ class ProviderGSO(models.Model): } for tracking in picking.carrier_tracking_ref.split(','): request_body['TrackingNumber'] = tracking - _ = service.delete_shipment(request_body) + __ = service.delete_shipment(request_body) except HTTPError as e: raise ValidationError(e) picking.message_post(body=_('Shipment N° %s has been cancelled') % (picking.carrier_tracking_ref, )) @@ -262,7 +262,7 @@ class ProviderGSO(models.Model): service = sudoself._get_gso_service() from_ = sudoself.get_shipper_warehouse(order=order) to = sudoself.get_recipient(order=order) - address_type = 'B' if bool(to.company or to.parent_id.company) else 'R' + address_type = 'B' if "company" in (to.company_type, to.parent_id.company_type) else 'R' est_weight_value = self._gso_convert_weight( sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) From 96f261f9accd88cd2a8f13cd3ab3ce2f13617c2c Mon Sep 17 00:00:00 2001 From: Connor Christian Date: Wed, 18 Nov 2020 13:11:00 -0500 Subject: [PATCH 05/14] [MIG] delivery_gso: for Odoo 14.0 --- delivery_gso/__manifest__.py | 2 +- delivery_gso/models/delivery_gso.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index 2856bc7a..f617443b 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '11.0.1.0.0', + 'version': '14.0.1.0.0', 'author': "Hibou Corp.", 'category': 'Warehouse', 'license': 'AGPL-3', diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index de60b22e..b68c397d 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -20,7 +20,7 @@ class ProductPackaging(models.Model): class ProviderGSO(models.Model): _inherit = 'delivery.carrier' - delivery_type = fields.Selection(selection_add=[('gso', 'gso.com')]) + delivery_type = fields.Selection(selection_add=[('gso', 'gso.com')], ondelete={'gso': 'cascade'}) gso_username = fields.Char(string='gso.com Username', groups='base.group_system') gso_password = fields.Char(string='gso.com Password', groups='base.group_system') gso_account_number = fields.Char(string='gso.com Account Number', groups='base.group_system') @@ -139,7 +139,7 @@ class ProviderGSO(models.Model): package_type = self.gso_default_packaging_id else: package_type = package.packaging_id - return {'Length': package_type.length, 'Width': package_type.width, 'Height': package_type.height} + return {'Length': package_type.packaging_length, 'Width': package_type.width, 'Height': package_type.height} def _gso_convert_weight(self, weight_in_kg): # m(lb) = m(kg) / 0.45359237 From bea73e1a014708c1137ec6c5f5091e5277d527ed Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Tue, 14 Sep 2021 11:42:47 -0500 Subject: [PATCH 06/14] [IMP] delivery_gso: move gso_rate_shipment_multi into 14.0 --- delivery_gso/models/delivery_gso.py | 87 +++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index b68c397d..597a5b59 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -7,6 +7,8 @@ from odoo import api, fields, models, _ from odoo.exceptions import ValidationError, UserError from .requests_gso import GSORequest +import logging +_logger = logging.getLogger(__name__) GSO_TZ = 'PST8PDT' @@ -319,3 +321,88 @@ class ProviderGSO(models.Model): for _ in pickings: res.append('https://www.gso.com/Tracking') return res + + def gso_rate_shipment_multi(self, order=None, picking=None): + sudoself = self.sudo() + service = sudoself._get_gso_service() + from_ = sudoself.get_shipper_warehouse(order=order, picking=picking) + to = sudoself.get_recipient(order=order, picking=picking) + address_type = 'B' if bool(to.is_company or to.parent_id.is_company) else 'R' + + if order: + est_weight_value = self._gso_convert_weight( + sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) + else: + est_weight_value = self._gso_convert_weight(picking.shipping_weight) + + date_planned = fields.Datetime.now() + if self.env.context.get('date_planned'): + date_planned = self.env.context.get('date_planned') + + ship_date_utc = fields.Datetime.from_string(date_planned if date_planned else fields.Datetime.now()) + ship_date_utc = ship_date_utc.replace(tzinfo=pytz.utc) + ship_date_gso = ship_date_utc.astimezone(pytz.timezone(GSO_TZ)) + ship_date_gso = fields.Datetime.to_string(ship_date_gso) + + if picking and picking.package_ids: + package_dimensions = self._gso_get_package_dimensions(package=picking.package_ids[0]) + else: + package_dimensions = self._gso_get_package_dimensions() + + request_body = { + 'AccountNumber': sudoself.gso_account_number, + 'OriginZip': from_.zip, + 'DestinationZip': to.zip, + 'ShipDate': ship_date_gso, + 'PackageDimension': package_dimensions, + 'PackageWeight': est_weight_value, + 'DeliveryAddressType': address_type, + } + + try: + result = service.get_rates_and_transit_time(request_body) + # _logger.warn('GSO result:\n%s' % result) + except HTTPError as e: + _logger.error(e) + return [{ + 'success': False, + 'price': 0.0, + 'error_message': _('GSO web service returned an error.'), + 'warning_message': False, + }] + + # delivery = list(filter(lambda d: d['ServiceCode'] == sudoself.gso_service_type, result['DeliveryServiceTypes'])) + # if delivery: + rates = [] + for delivery in result['DeliveryServiceTypes']: + delivery_date_gso = delivery['DeliveryDate'].replace('T', ' ') + delivery_date_gso = fields.Datetime.from_string(delivery_date_gso) + delivery_date_gso = delivery_date_gso.replace(tzinfo=pytz.timezone(GSO_TZ)) + delivery_date_utc = delivery_date_gso.astimezone(pytz.utc) + delivery_date_utc = fields.Datetime.to_string(delivery_date_utc) + price = delivery.get('ShipmentCharges', {}).get('TotalCharge', 0.0) + + carrier = self.gso_find_delivery_carrier_for_service(delivery['ServiceCode']) + if carrier: + rates.append({ + 'carrier': carrier, + 'success': True, + 'price': price, + 'error_message': False, + 'warning_message': _('TotalCharge not found.') if price == 0.0 else False, + 'date_planned': date_planned, + 'date_delivered': delivery_date_utc, + 'transit_days': False, + 'service_code': delivery['ServiceCode'], + }) + + return rates + + def gso_find_delivery_carrier_for_service(self, service_code): + if self.gso_service_type == service_code: + return self + # arbitrary decision, lets find the same account number + carrier = self.search([('gso_account_number', '=', self.gso_account_number), + ('gso_service_type', '=', service_code) + ], limit=1) + return carrier From 7c19f385b6e442df1188180530f776a246e42f01 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Mon, 20 Sep 2021 08:18:20 -0700 Subject: [PATCH 07/14] [FIX] delivery_gso: paper label handling --- delivery_gso/models/delivery_gso.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 597a5b59..513d398b 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -1,5 +1,6 @@ import pytz from math import ceil +from base64 import b64decode from requests import HTTPError from hashlib import sha1 @@ -13,6 +14,13 @@ _logger = logging.getLogger(__name__) GSO_TZ = 'PST8PDT' +def inline_b64decode(data): + try: + return b64decode(data) + except: + return '' + + class ProductPackaging(models.Model): _inherit = 'product.packaging' @@ -228,7 +236,7 @@ class ProviderGSO(models.Model): raise ValidationError(e) # Handle results - trackings = [l[0] for l in labels['thermal']] + [l(0) for l in labels['paper']] + trackings = [l[0] for l in labels['thermal']] + [l[0] for l in labels['paper']] carrier_tracking_ref = ','.join(trackings) logmessage = _("Shipment created into GSO
" @@ -237,7 +245,8 @@ class ProviderGSO(models.Model): if labels['thermal']: attachments += [('LabelGSO-%s.zpl' % (l[0], ), l[1]) for l in labels['thermal']] if labels['paper']: - attachments += [('LabelGSO-%s.pdf' % (l[0], ), l[1]) for l in labels['thermal']] + # paper labels re-encoded base64 + attachments += [('LabelGSO-%s.png' % (l[0], ), inline_b64decode(l[1])) for l in labels['paper']] picking.message_post(body=logmessage, attachments=attachments) shipping_data = {'exact_price': cost, 'tracking_number': carrier_tracking_ref} From ccfeb6ce73bc766dd857ef44e86c659dface8fa9 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Mon, 20 Sep 2021 17:47:22 -0700 Subject: [PATCH 08/14] [IMP] delivery_gso: mechansims for per-package rating and shipping --- delivery_gso/__init__.py | 2 + delivery_gso/__manifest__.py | 4 +- delivery_gso/models/__init__.py | 2 + delivery_gso/models/delivery_gso.py | 57 ++++++++++++++++++++++------- delivery_gso/models/requests_gso.py | 2 + 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/delivery_gso/__init__.py b/delivery_gso/__init__.py index 0650744f..09434554 100644 --- a/delivery_gso/__init__.py +++ b/delivery_gso/__init__.py @@ -1 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import models diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index f617443b..8dcc7785 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,10 +1,10 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '14.0.1.0.0', + 'version': '14.0.1.1.0', 'author': "Hibou Corp.", 'category': 'Warehouse', - 'license': 'AGPL-3', + 'license': 'OPL-1', 'images': [], 'website': "https://hibou.io", 'description': """ diff --git a/delivery_gso/models/__init__.py b/delivery_gso/models/__init__.py index 943392d3..c9a65a9e 100644 --- a/delivery_gso/models/__init__.py +++ b/delivery_gso/models/__init__.py @@ -1 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import delivery_gso diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 513d398b..3df02556 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + import pytz from math import ceil from base64 import b64decode @@ -198,9 +200,15 @@ class ProviderGSO(models.Model): 'thermal': [], 'paper': [], } - if picking.package_ids: + picking_packages = picking.package_ids + package_carriers = picking_packages.mapped('carrier_id') + if package_carriers: + # only ship ours + picking_packages = picking_packages.filtered(lambda p: p.carrier_id == self and not p.carrier_tracking_ref) + + if picking_packages: # Every package will be a transaction - for package in picking.package_ids: + for package in picking_packages: request_body['Shipment']['Weight'] = self._gso_convert_weight(package.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions(package)) request_body['Shipment']['ShipmentReference'] = package.name @@ -217,7 +225,8 @@ class ProviderGSO(models.Model): cost += response['ShipmentCharges']['TotalCharge'] except HTTPError as e: raise ValidationError(e) - else: + elif not package_carriers: + # ship the whole picking request_body['Shipment']['Weight'] = self._gso_convert_weight(picking.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions()) request_body['Shipment']['ShipmentReference'] = picking.name @@ -234,6 +243,8 @@ class ProviderGSO(models.Model): cost += response['ShipmentCharges']['TotalCharge'] except HTTPError as e: raise ValidationError(e) + else: + continue # Handle results trackings = [l[0] for l in labels['thermal']] + [l[0] for l in labels['paper']] @@ -331,18 +342,32 @@ class ProviderGSO(models.Model): res.append('https://www.gso.com/Tracking') return res - def gso_rate_shipment_multi(self, order=None, picking=None): + def gso_rate_shipment_multi(self, order=None, picking=None, packages=None): + if not packages: + return self._gso_rate_shipment_multi_package(order=order, picking=picking) + else: + rates = [] + for package in packages: + rates += self._gso_rate_shipment_multi_package(order=order, picking=picking, package=package) + return rates + + def _gso_rate_shipment_multi_package(self, order=None, picking=None, package=None): sudoself = self.sudo() - service = sudoself._get_gso_service() + try: + service = sudoself._get_gso_service() + except HTTPError as e: + _logger.error(e) + return [{ + 'success': False, + 'price': 0.0, + 'error_message': _('GSO web service returned an error. ' + str(e)), + 'warning_message': False, + }] + from_ = sudoself.get_shipper_warehouse(order=order, picking=picking) to = sudoself.get_recipient(order=order, picking=picking) address_type = 'B' if bool(to.is_company or to.parent_id.is_company) else 'R' - - if order: - est_weight_value = self._gso_convert_weight( - sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) - else: - est_weight_value = self._gso_convert_weight(picking.shipping_weight) + package_dimensions = self._gso_get_package_dimensions(package=package) date_planned = fields.Datetime.now() if self.env.context.get('date_planned'): @@ -353,10 +378,13 @@ class ProviderGSO(models.Model): ship_date_gso = ship_date_utc.astimezone(pytz.timezone(GSO_TZ)) ship_date_gso = fields.Datetime.to_string(ship_date_gso) - if picking and picking.package_ids: - package_dimensions = self._gso_get_package_dimensions(package=picking.package_ids[0]) + if order: + est_weight_value = self._gso_convert_weight( + sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) + elif not package: + est_weight_value = self._gso_convert_weight(picking.shipping_weight) else: - package_dimensions = self._gso_get_package_dimensions() + est_weight_value = package.shipping_weight or package.weight request_body = { 'AccountNumber': sudoself.gso_account_number, @@ -395,6 +423,7 @@ class ProviderGSO(models.Model): if carrier: rates.append({ 'carrier': carrier, + 'package': package or self.env['stock.quant.package'].browse(), 'success': True, 'price': price, 'error_message': False, diff --git a/delivery_gso/models/requests_gso.py b/delivery_gso/models/requests_gso.py index e5fceb3a..4e512661 100644 --- a/delivery_gso/models/requests_gso.py +++ b/delivery_gso/models/requests_gso.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + import requests from json import dumps From bc2eceb5386d15fdbb861f4d7cd2448ed2479f30 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 6 Oct 2021 08:27:04 -0700 Subject: [PATCH 09/14] [MIG] delivery_gso: for Odoo 15.0 --- delivery_gso/__manifest__.py | 2 +- delivery_gso/models/delivery_gso.py | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index 8dcc7785..e1923d56 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '14.0.1.1.0', + 'version': '15.0.1.0.0', 'author': "Hibou Corp.", 'category': 'Warehouse', 'license': 'OPL-1', diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 3df02556..04f55595 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -23,10 +23,10 @@ def inline_b64decode(data): return '' -class ProductPackaging(models.Model): - _inherit = 'product.packaging' +class StockPackageType(models.Model): + _inherit = 'stock.package.type' - package_carrier_type = fields.Selection(selection_add=[('gso', 'gso.com')]) + package_carrier_type = fields.Selection(selection_add=[('gso', 'gso.com')], ondelete={'gso': 'set default'}) class ProviderGSO(models.Model): @@ -36,7 +36,7 @@ class ProviderGSO(models.Model): gso_username = fields.Char(string='gso.com Username', groups='base.group_system') gso_password = fields.Char(string='gso.com Password', groups='base.group_system') gso_account_number = fields.Char(string='gso.com Account Number', groups='base.group_system') - gso_default_packaging_id = fields.Many2one('product.packaging', string='Default Package Type') + gso_default_packaging_id = fields.Many2one('stock.package.type', string='Default Package Type') # For service type, SAM, SPM, and SEV require authorized accounts. gso_service_type = fields.Selection([('PDS', 'Priority Overnight'), ('EPS', 'Early Priority Overnight'), @@ -151,11 +151,20 @@ class ProviderGSO(models.Model): package_type = self.gso_default_packaging_id else: package_type = package.packaging_id + length_uom = self.env['product.template']._get_length_uom_id_from_ir_config_parameter() + if length_uom.name == 'ft': + return {'Length': round(package_type.packaging_length / 12.0), 'Width': round(package_type.width / 12.0), 'Height': round(package_type.height / 12.0)} + elif length_uom.name == 'mm': + return {'Length': round(package_type.packaging_length * 0.0393701), 'Width': round(package_type.width * 0.0393701), 'Height': round(package_type.height * 0.0393701)} return {'Length': package_type.packaging_length, 'Width': package_type.width, 'Height': package_type.height} - def _gso_convert_weight(self, weight_in_kg): - # m(lb) = m(kg) / 0.45359237 - weight_in_lb = weight_in_kg / 0.45359237 + def _gso_convert_weight(self, weight_in_db): + weight_uom = self.env['product.template']._get_weight_uom_id_from_ir_config_parameter() + if weight_uom.name == 'kg': + weight_in_lb = weight_in_db / 0.45359237 + else: + # assume lbs + weight_in_lb = weight_in_db # If less than 8 oz... if weight_in_lb < 0.5: return 0 From 0816924c8eaef0b21c809d628c2f032efe56eaf6 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 6 Oct 2021 10:36:52 -0700 Subject: [PATCH 10/14] [FIX] delivery_gso: packaging type 15 --- delivery_gso/models/delivery_gso.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 04f55595..598c9138 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -150,7 +150,7 @@ class ProviderGSO(models.Model): if not package: package_type = self.gso_default_packaging_id else: - package_type = package.packaging_id + package_type = package.package_type_id length_uom = self.env['product.template']._get_length_uom_id_from_ir_config_parameter() if length_uom.name == 'ft': return {'Length': round(package_type.packaging_length / 12.0), 'Width': round(package_type.width / 12.0), 'Height': round(package_type.height / 12.0)} From 63be15eff63a60932d8c12f2b06c26f9aef55d5e Mon Sep 17 00:00:00 2001 From: Mishael De La Cruz Date: Tue, 2 Nov 2021 09:58:15 -0500 Subject: [PATCH 11/14] [I18N] multi: Initial Translations 15.0 --- delivery_gso/i18n/es.po | 190 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 delivery_gso/i18n/es.po diff --git a/delivery_gso/i18n/es.po b/delivery_gso/i18n/es.po new file mode 100644 index 00000000..a466c4f8 --- /dev/null +++ b/delivery_gso/i18n/es.po @@ -0,0 +1,190 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * delivery_gso +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-10-29 23:44+0000\n" +"PO-Revision-Date: 2021-10-29 23:44+0000\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_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__sam +msgid "AM Select (8A-12P) Delivery Window" +msgstr "Rango de Entrega: En la Mañana (8A - 12P)" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_stock_package_type__package_carrier_type +msgid "Carrier" +msgstr "Transportista" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_default_packaging_id +msgid "Default Package Type" +msgstr "Tipo de Paquete Predeterminado" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "Delivery Method not found in result" +msgstr "Método de envío no se encontro en la busqueda" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__eps +msgid "Early Priority Overnight" +msgstr "Entrega Temprana Prioritaria: Al día siguiente " + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__ess +msgid "Early Saturday Delivery" +msgstr "Entrega el Sábado Temprano" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__sev +msgid "Evening Select (4P-8P) Delivery Window" +msgstr "Ventana de Entrega: En la Noche (4P - 8P)" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__cps +msgid "GSO Ground" +msgstr "GSO Terrestre" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "GSO web service returned an error. " +msgstr "El servicio de web de GSO ha retornado un error" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "GSO web service returned an error." +msgstr "El servicio de web de GSO ha retornado un error" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_image_type +msgid "Image Type" +msgstr "Tipo de Imagen" + +#. module: delivery_gso +#: model:ir.model.fields,help:delivery_gso.field_delivery_carrier__gso_image_type +msgid "Image Type is the type of Label to use" +msgstr "El tipo de imagen es el tipo de etiqueta para utilizar" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_image_type__zpl_long_label +msgid "Long label" +msgstr "Etiqueta larga" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_image_type__no_label +msgid "No Label" +msgstr "Sin etiqueta" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__nps +msgid "Noon Priority Overnight" +msgstr "Entrega Prioritaria: Al Día Siguiente en la Tarde" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__spm +msgid "PM Select (12P-4P) Delivery Window" +msgstr "Ventana de Entrega: En la tarde (12P - 4P)" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_image_type__paper_label +msgid "Paper Label" +msgstr "Etiqueta de papel" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__pds +msgid "Priority Overnight" +msgstr "Entrega Prioritaria: Al Día Siguiente" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__delivery_type +msgid "Provider" +msgstr "Proveedor" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_service_type__sds +msgid "Saturday Delivery" +msgstr "Entrega el Sábado" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_service_type +msgid "Service Type" +msgstr "Tipo de Servicio" + +#. module: delivery_gso +#: model:ir.model.fields,help:delivery_gso.field_delivery_carrier__gso_service_type +msgid "Service Type determines speed of delivery" +msgstr "El tipo de servicio determina la velocidad de entrega" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "Shipment N° %s has been cancelled" +msgstr "El número de envío %s ha sido cancelado" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "Shipment created into GSO
Tracking Numbers: %s" +msgstr "" +"El envío ha sido creado en GSO
Números de Seguimiento: %s" + +#. module: delivery_gso +#: model:ir.model,name:delivery_gso.model_delivery_carrier +msgid "Shipping Methods" +msgstr "Métodos de Envío" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__gso_image_type__zpl_short_label +msgid "Short Label" +msgstr "Etiqueta corta" + +#. module: delivery_gso +#: model:ir.model,name:delivery_gso.model_stock_package_type +msgid "Stock package type" +msgstr "Tipo de Paquete de Stock" + +#. module: delivery_gso +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#: code:addons/delivery_gso/models/delivery_gso.py:0 +#, python-format +msgid "TotalCharge not found." +msgstr "El CostoTotal no se encontró" + +#. module: delivery_gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__delivery_carrier__delivery_type__gso +#: model:ir.model.fields.selection,name:delivery_gso.selection__stock_package_type__package_carrier_type__gso +msgid "gso.com" +msgstr "gso.com" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_account_number +msgid "gso.com Account Number" +msgstr "gso.com Número de Cuenta" + +#. module: delivery_gso +#: model_terms:ir.ui.view,arch_db:delivery_gso.view_delivery_carrier_form_with_provider_gso +msgid "gso.com Configuration" +msgstr "gso.com Configuración" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_password +msgid "gso.com Password" +msgstr "gso.com Clave" + +#. module: delivery_gso +#: model:ir.model.fields,field_description:delivery_gso.field_delivery_carrier__gso_username +msgid "gso.com Username" +msgstr "gso.com Usuario" From 8dcc67df8923acc867f1d901da7060ab2d7b0420 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 11 Jan 2022 12:54:14 -0800 Subject: [PATCH 12/14] [REF] multi: replace logging .warn( with .warning( --- delivery_gso/models/delivery_gso.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 598c9138..a242ff85 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -407,7 +407,7 @@ class ProviderGSO(models.Model): try: result = service.get_rates_and_transit_time(request_body) - # _logger.warn('GSO result:\n%s' % result) + # _logger.warning('GSO result:\n%s' % result) except HTTPError as e: _logger.error(e) return [{ From dc716a92de236ee653862668664e63cb77f6a4f3 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 9 Feb 2022 08:56:42 -0800 Subject: [PATCH 13/14] [IMP] delivery_gso: weight conversion, per-package insurance/sig.req --- delivery_gso/__manifest__.py | 2 +- delivery_gso/models/delivery_gso.py | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index e1923d56..26968b3a 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '15.0.1.0.0', + 'version': '15.0.1.0.1', 'author': "Hibou Corp.", 'category': 'Warehouse', 'license': 'OPL-1', diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index a242ff85..cc3a6965 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -196,14 +196,6 @@ class ProviderGSO(models.Model): request_body['Shipment'].update(self._gso_make_shipper_address(from_, company)) request_body['Shipment'].update(self._gso_make_ship_address(to)) - # Automatic insurance at $100.0 - insurance_value = sudoself.get_insurance_value(picking=picking) - if insurance_value: - request_body['Shipment']['SignatureCode'] = 'SIG_REQD' - if insurance_value > 100.0: - # Documentation says to set DeclaredValue ONLY if over $100.00 - request_body['Shipment']['DeclaredValue'] = insurance_value - cost = 0.0 labels = { 'thermal': [], @@ -218,6 +210,20 @@ class ProviderGSO(models.Model): if picking_packages: # Every package will be a transaction for package in picking_packages: + # Use Sale Order Number or fall back to Picking + shipment_ref = (picking.sale_id.name if picking.sale_id else picking.name) + '-' + package.name + insurance_value = sudoself.get_insurance_value(picking=picking, package=package) + if insurance_value > 100.0: + # Documentation says to set DeclaredValue ONLY if over $100.00 + request_body['Shipment']['DeclaredValue'] = insurance_value + elif 'DeclaredValue' in request_body['Shipment']: + del request_body['Shipment']['DeclaredValue'] + + if sudoself.get_signature_required(picking=picking, package=package): + request_body['Shipment']['SignatureCode'] = 'SIG_REQD' + else: + request_body['Shipment']['SignatureCode'] = 'SIG_NOT_REQD' + request_body['Shipment']['Weight'] = self._gso_convert_weight(package.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions(package)) request_body['Shipment']['ShipmentReference'] = package.name @@ -236,9 +242,10 @@ class ProviderGSO(models.Model): raise ValidationError(e) elif not package_carriers: # ship the whole picking + shipment_ref = picking.sale_id.name if picking.sale_id else picking.name request_body['Shipment']['Weight'] = self._gso_convert_weight(picking.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions()) - request_body['Shipment']['ShipmentReference'] = picking.name + request_body['Shipment']['ShipmentReference'] = shipment_ref request_body['Shipment']['TrackingNumber'] = self._gso_create_tracking_number(picking.name) try: response = service.post_shipment(request_body) @@ -393,7 +400,7 @@ class ProviderGSO(models.Model): elif not package: est_weight_value = self._gso_convert_weight(picking.shipping_weight) else: - est_weight_value = package.shipping_weight or package.weight + est_weight_value = self._gso_convert_weight(package.shipping_weight or package.weight) request_body = { 'AccountNumber': sudoself.gso_account_number, @@ -409,7 +416,7 @@ class ProviderGSO(models.Model): result = service.get_rates_and_transit_time(request_body) # _logger.warning('GSO result:\n%s' % result) except HTTPError as e: - _logger.error(e) + # _logger.error(e) return [{ 'success': False, 'price': 0.0, From fea1bc360e4599b0255ab77d699dec97bf8cb832 Mon Sep 17 00:00:00 2001 From: Leo Pinedo Date: Fri, 28 Oct 2022 23:10:23 +0000 Subject: [PATCH 14/14] [MIG] delivery_gso: to v16 --- delivery_gso/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index 26968b3a..5b89aa98 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '15.0.1.0.1', + 'version': '16.0.1.0.1', 'author': "Hibou Corp.", 'category': 'Warehouse', 'license': 'OPL-1',