mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[IMP] delivery_stamps: international and latest wsdl
This commit is contained in:
@@ -1 +1,3 @@
|
|||||||
|
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Stamps.com (USPS) Shipping',
|
'name': 'Stamps.com (USPS) Shipping',
|
||||||
'summary': 'Send your shippings through Stamps.com and track them online.',
|
'summary': 'Send your shippings through Stamps.com and track them online.',
|
||||||
'version': '11.0.2.0.0',
|
'version': '11.0.2.1.1',
|
||||||
'author': "Hibou Corp.",
|
'author': "Hibou Corp.",
|
||||||
'category': 'Warehouse',
|
'category': 'Warehouse',
|
||||||
'license': 'OPL-1',
|
'license': 'OPL-1',
|
||||||
@@ -15,7 +17,6 @@ Send your shippings through Stamps.com and track them online.
|
|||||||
|
|
||||||
""",
|
""",
|
||||||
'depends': [
|
'depends': [
|
||||||
'delivery',
|
|
||||||
'delivery_hibou',
|
'delivery_hibou',
|
||||||
],
|
],
|
||||||
'demo': [],
|
'demo': [],
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
|
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||||
|
|
||||||
from . import delivery_stamps
|
from . import delivery_stamps
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
Copyright (c) 2019 by Hibou Corp.
|
||||||
Copyright (c) 2014 by Jonathan Zempel.
|
Copyright (c) 2014 by Jonathan Zempel.
|
||||||
|
|
||||||
Some rights reserved.
|
Some rights reserved.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from urllib.parse import urljoin
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
VERSION = 84
|
VERSION = 111
|
||||||
|
|
||||||
|
|
||||||
class StampsConfiguration(object):
|
class StampsConfiguration(object):
|
||||||
|
|||||||
@@ -145,12 +145,12 @@ class StampsService(BaseService):
|
|||||||
def create_add_on(self):
|
def create_add_on(self):
|
||||||
"""Create a new add-on object.
|
"""Create a new add-on object.
|
||||||
"""
|
"""
|
||||||
return self.create("AddOnV15")
|
return self.create("AddOnV17")
|
||||||
|
|
||||||
def create_customs(self):
|
def create_customs(self):
|
||||||
"""Create a new customs object.
|
"""Create a new customs object.
|
||||||
"""
|
"""
|
||||||
return self.create("CustomsV3")
|
return self.create("CustomsV7")
|
||||||
|
|
||||||
def create_array_of_customs_lines(self):
|
def create_array_of_customs_lines(self):
|
||||||
"""Create a new array of customs objects.
|
"""Create a new array of customs objects.
|
||||||
@@ -188,7 +188,7 @@ class StampsService(BaseService):
|
|||||||
def create_shipping(self):
|
def create_shipping(self):
|
||||||
"""Create a new shipping object.
|
"""Create a new shipping object.
|
||||||
"""
|
"""
|
||||||
return self.create("RateV31")
|
return self.create("RateV40")
|
||||||
|
|
||||||
def get_address(self, address):
|
def get_address(self, address):
|
||||||
"""Get a shipping address.
|
"""Get a shipping address.
|
||||||
@@ -202,7 +202,7 @@ class StampsService(BaseService):
|
|||||||
"""
|
"""
|
||||||
return self.call("GetAccountInfo")
|
return self.call("GetAccountInfo")
|
||||||
|
|
||||||
def get_label(self, from_address, to_address, rate, transaction_id, image_type=None,
|
def get_label(self, rate, transaction_id, image_type=None,
|
||||||
customs=None, sample=False, extended_postage_info=False):
|
customs=None, sample=False, extended_postage_info=False):
|
||||||
"""Get a shipping label.
|
"""Get a shipping label.
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ class StampsService(BaseService):
|
|||||||
:param sample: Default ``False``. Get a sample label without postage.
|
:param sample: Default ``False``. Get a sample label without postage.
|
||||||
"""
|
"""
|
||||||
return self.call("CreateIndicium", IntegratorTxID=transaction_id,
|
return self.call("CreateIndicium", IntegratorTxID=transaction_id,
|
||||||
Rate=rate, From=from_address, To=to_address, ImageType=image_type, Customs=customs,
|
Rate=rate, ImageType=image_type, Customs=customs,
|
||||||
SampleOnly=sample, ExtendedPostageInfo=extended_postage_info)
|
SampleOnly=sample, ExtendedPostageInfo=extended_postage_info)
|
||||||
|
|
||||||
def get_postage_status(self, transaction_id):
|
def get_postage_status(self, transaction_id):
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,6 @@
|
|||||||
|
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||||
|
|
||||||
|
import hashlib
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
@@ -31,6 +34,13 @@ STAMPS_PACKAGE_TYPES = [
|
|||||||
'Regional Rate Box C',
|
'Regional Rate Box C',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
STAMPS_CONTENT_TYPES = {
|
||||||
|
'Letter': 'Document',
|
||||||
|
'Postcard': 'Document',
|
||||||
|
}
|
||||||
|
|
||||||
|
STAMPS_INTEGRATION_ID = 'f62cb4f0-aa07-4701-a1dd-f0e7c853ed3c'
|
||||||
|
|
||||||
|
|
||||||
class ProductPackaging(models.Model):
|
class ProductPackaging(models.Model):
|
||||||
_inherit = 'product.packaging'
|
_inherit = 'product.packaging'
|
||||||
@@ -44,12 +54,14 @@ class ProviderStamps(models.Model):
|
|||||||
|
|
||||||
delivery_type = fields.Selection(selection_add=[('stamps', 'Stamps.com (USPS)')])
|
delivery_type = fields.Selection(selection_add=[('stamps', 'Stamps.com (USPS)')])
|
||||||
|
|
||||||
stamps_integration_id = fields.Char(string='Stamps.com Integration ID', groups='base.group_system')
|
|
||||||
stamps_username = fields.Char(string='Stamps.com Username', groups='base.group_system')
|
stamps_username = fields.Char(string='Stamps.com Username', groups='base.group_system')
|
||||||
stamps_password = fields.Char(string='Stamps.com Password', groups='base.group_system')
|
stamps_password = fields.Char(string='Stamps.com Password', groups='base.group_system')
|
||||||
|
|
||||||
stamps_service_type = fields.Selection([('US-FC', 'First-Class'),
|
stamps_service_type = fields.Selection([('US-FC', 'First-Class'),
|
||||||
|
('US-FCI', 'First-Class International'),
|
||||||
('US-PM', 'Priority'),
|
('US-PM', 'Priority'),
|
||||||
|
('US-PMI', 'Priority Mail International'),
|
||||||
|
('US-EMI', ' Priority Mail Express International'),
|
||||||
],
|
],
|
||||||
required=True, string="Service Type", default="US-PM")
|
required=True, string="Service Type", default="US-PM")
|
||||||
stamps_default_packaging_id = fields.Many2one('product.packaging', string='Default Package Type')
|
stamps_default_packaging_id = fields.Many2one('product.packaging', string='Default Package Type')
|
||||||
@@ -67,12 +79,21 @@ class ProviderStamps(models.Model):
|
|||||||
('BZpl', 'BZPL'),
|
('BZpl', 'BZPL'),
|
||||||
],
|
],
|
||||||
required=True, string="Image Type", default="Pdf")
|
required=True, string="Image Type", default="Pdf")
|
||||||
|
stamps_addon_sc = fields.Boolean(string='Add Signature Confirmation')
|
||||||
|
stamps_addon_dc = fields.Boolean(string='Add Delivery Confirmation')
|
||||||
|
stamps_addon_hp = fields.Boolean(string='Add Hidden Postage')
|
||||||
|
|
||||||
def _stamps_package_type(self, package=None):
|
def _stamps_package_type(self, package=None):
|
||||||
if not package:
|
if not package:
|
||||||
return self.stamps_default_packaging_id.shipper_package_code
|
return self.stamps_default_packaging_id.shipper_package_code
|
||||||
return package.packaging_id.shipper_package_code if package.packaging_id.shipper_package_code in STAMPS_PACKAGE_TYPES else 'Package'
|
return package.packaging_id.shipper_package_code if package.packaging_id.shipper_package_code in STAMPS_PACKAGE_TYPES else 'Package'
|
||||||
|
|
||||||
|
def _stamps_content_type(self, package=None):
|
||||||
|
package_type = self._stamps_package_type(package=package)
|
||||||
|
if package_type in STAMPS_CONTENT_TYPES:
|
||||||
|
return STAMPS_CONTENT_TYPES[package_type]
|
||||||
|
return 'Merchandise'
|
||||||
|
|
||||||
def _stamps_package_is_cubic_pricing(self, package=None):
|
def _stamps_package_is_cubic_pricing(self, package=None):
|
||||||
if not package:
|
if not package:
|
||||||
return self.stamps_default_packaging_id.stamps_cubic_pricing
|
return self.stamps_default_packaging_id.stamps_cubic_pricing
|
||||||
@@ -87,15 +108,21 @@ class ProviderStamps(models.Model):
|
|||||||
|
|
||||||
def _get_stamps_service(self):
|
def _get_stamps_service(self):
|
||||||
sudoself = self.sudo()
|
sudoself = self.sudo()
|
||||||
config = StampsConfiguration(integration_id=sudoself.stamps_integration_id,
|
config = StampsConfiguration(integration_id=STAMPS_INTEGRATION_ID,
|
||||||
username=sudoself.stamps_username,
|
username=sudoself.stamps_username,
|
||||||
password=sudoself.stamps_password)
|
password=sudoself.stamps_password,
|
||||||
|
wsdl=('testing' if not sudoself.prod_environment else None))
|
||||||
return StampsService(configuration=config)
|
return StampsService(configuration=config)
|
||||||
|
|
||||||
def _stamps_convert_weight(self, weight):
|
def _stamps_convert_weight(self, weight):
|
||||||
""" weight always expressed in KG """
|
""" weight always expressed in database units (KG/LBS) """
|
||||||
if self.stamps_default_packaging_id.max_weight and self.stamps_default_packaging_id.max_weight < weight:
|
if self.stamps_default_packaging_id.max_weight and self.stamps_default_packaging_id.max_weight < weight:
|
||||||
raise ValidationError('Stamps cannot ship for weight: ' + str(weight) + 'kgs.')
|
raise ValidationError('Stamps cannot ship for weight: ' + str(weight) + ' kgs/lbs.')
|
||||||
|
|
||||||
|
get_param = self.env['ir.config_parameter'].sudo().get_param
|
||||||
|
product_weight_in_lbs_param = get_param('product.weight_in_lbs')
|
||||||
|
if product_weight_in_lbs_param == '1':
|
||||||
|
return weight
|
||||||
|
|
||||||
weight_in_pounds = weight * 2.20462
|
weight_in_pounds = weight * 2.20462
|
||||||
return weight_in_pounds
|
return weight_in_pounds
|
||||||
@@ -108,9 +135,10 @@ class ProviderStamps(models.Model):
|
|||||||
raise ValidationError('Stamps needs ZIP. From: ' + str(order.warehouse_id.partner_id.zip) + ' To: ' + str(order.partner_shipping_id.zip))
|
raise ValidationError('Stamps needs ZIP. From: ' + str(order.warehouse_id.partner_id.zip) + ' To: ' + str(order.partner_shipping_id.zip))
|
||||||
|
|
||||||
ret_val = service.create_shipping()
|
ret_val = service.create_shipping()
|
||||||
ret_val.ShipDate = date_planned.split()[0] if date_planned else date.today().isoformat()
|
ret_val.ShipDate = date_planned.split(' ')[0] if date_planned else date.today().isoformat()
|
||||||
ret_val.FromZIPCode = self.get_shipper_warehouse(order=order).zip.split('-')[0]
|
shipper_partner = self.get_shipper_warehouse(order=order)
|
||||||
ret_val.ToZIPCode = order.partner_shipping_id.zip.split('-')[0]
|
ret_val.From = self._stamps_address(service, shipper_partner)
|
||||||
|
ret_val.To = self._stamps_address(service, order.partner_shipping_id)
|
||||||
ret_val.PackageType = self._stamps_package_type()
|
ret_val.PackageType = self._stamps_package_type()
|
||||||
ret_val.ServiceType = self.stamps_service_type
|
ret_val.ServiceType = self.stamps_service_type
|
||||||
ret_val.WeightLb = weight
|
ret_val.WeightLb = weight
|
||||||
@@ -133,12 +161,12 @@ class ProviderStamps(models.Model):
|
|||||||
raise ValidationError('Stamps needs ZIP. From: ' + str(shipper.zip) + ' To: ' + str(recipient.zip))
|
raise ValidationError('Stamps needs ZIP. From: ' + str(shipper.zip) + ' To: ' + str(recipient.zip))
|
||||||
|
|
||||||
ret_val = service.create_shipping()
|
ret_val = service.create_shipping()
|
||||||
ret_val.ShipDate = date_planned.strftime('%Y-%m-%d') if date_planned else date.today().isoformat()
|
ret_val.ShipDate = date_planned.split(' ')[0] if date_planned else date.today().isoformat()
|
||||||
ret_val.From = self._stamps_address(service, shipper)
|
ret_val.From = self._stamps_address(service, shipper)
|
||||||
ret_val.To = self._stamps_address(service, recipient)
|
ret_val.To = self._stamps_address(service, recipient)
|
||||||
ret_val.PackageType = self._stamps_package_type(package=package)
|
ret_val.PackageType = self._stamps_package_type(package=package)
|
||||||
ret_val.WeightLb = weight
|
ret_val.WeightLb = weight
|
||||||
ret_val.ContentType = self._stamps_content_type()
|
ret_val.ContentType = 'Merchandise'
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def _stamps_get_addresses_for_picking(self, picking):
|
def _stamps_get_addresses_for_picking(self, picking):
|
||||||
@@ -147,11 +175,36 @@ class ProviderStamps(models.Model):
|
|||||||
to = self.get_recipient(picking=picking)
|
to = self.get_recipient(picking=picking)
|
||||||
return company, from_, to
|
return company, from_, to
|
||||||
|
|
||||||
|
def _stamps_address(self, service, partner):
|
||||||
|
address = service.create_address()
|
||||||
|
if not partner.name or len(partner.name) < 2:
|
||||||
|
raise ValidationError('Partner (%s) name must be more than 2 characters.' % (partner, ))
|
||||||
|
address.FullName = partner.name
|
||||||
|
address.Address1 = partner.street
|
||||||
|
if partner.street2:
|
||||||
|
address.Address2 = partner.street2
|
||||||
|
address.City = partner.city
|
||||||
|
address.State = partner.state_id.code
|
||||||
|
if partner.country_id.code == 'US':
|
||||||
|
zip_pieces = partner.zip.split('-')
|
||||||
|
address.ZIPCode = zip_pieces[0]
|
||||||
|
if len(zip_pieces) >= 2:
|
||||||
|
address.ZIPCodeAddOn = zip_pieces[1]
|
||||||
|
else:
|
||||||
|
address.PostalCode = partner.zip or ''
|
||||||
|
address.Country = partner.country_id.code
|
||||||
|
res = service.get_address(address).Address
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _stamps_hash_partner(self, partner):
|
||||||
|
to_hash = ''.join(f[1] if isinstance(f, tuple) else str(f) for f in partner.read(['name', 'street', 'street2', 'city', 'country_id', 'state_id', 'zip', 'phone', 'email'])[0].values())
|
||||||
|
return hashlib.sha1(to_hash.encode()).hexdigest()
|
||||||
|
|
||||||
def _stamps_get_shippings_for_picking(self, service, picking):
|
def _stamps_get_shippings_for_picking(self, service, picking):
|
||||||
ret = []
|
ret = []
|
||||||
company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking)
|
company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking)
|
||||||
if not all((from_partner.zip, to_partner.zip)):
|
if not all((from_partner.zip, to_partner.zip)):
|
||||||
raise ValidationError('Stamps needs ZIP. From: ' + str(from_partner.zip) + ' To: ' + str(to_partner.zip))
|
raise ValidationError('Stamps needs ZIP/PostalCode. From: ' + str(from_partner.zip) + ' To: ' + str(to_partner.zip))
|
||||||
|
|
||||||
picking_packages = picking.package_ids
|
picking_packages = picking.package_ids
|
||||||
package_carriers = picking_packages.mapped('carrier_id')
|
package_carriers = picking_packages.mapped('carrier_id')
|
||||||
@@ -165,8 +218,8 @@ class ProviderStamps(models.Model):
|
|||||||
|
|
||||||
ret_val = service.create_shipping()
|
ret_val = service.create_shipping()
|
||||||
ret_val.ShipDate = date.today().isoformat()
|
ret_val.ShipDate = date.today().isoformat()
|
||||||
ret_val.FromZIPCode = from_partner.zip.split('-')[0]
|
ret_val.From = self._stamps_address(service, from_partner)
|
||||||
ret_val.ToZIPCode = to_partner.zip.split('-')[0]
|
ret_val.To = self._stamps_address(service, to_partner)
|
||||||
ret_val.PackageType = self._stamps_package_type(package=package)
|
ret_val.PackageType = self._stamps_package_type(package=package)
|
||||||
ret_val.CubicPricing = self._stamps_package_is_cubic_pricing(package=package)
|
ret_val.CubicPricing = self._stamps_package_is_cubic_pricing(package=package)
|
||||||
ret_val.Length = l
|
ret_val.Length = l
|
||||||
@@ -182,8 +235,8 @@ class ProviderStamps(models.Model):
|
|||||||
|
|
||||||
ret_val = service.create_shipping()
|
ret_val = service.create_shipping()
|
||||||
ret_val.ShipDate = date.today().isoformat()
|
ret_val.ShipDate = date.today().isoformat()
|
||||||
ret_val.FromZIPCode = from_partner.zip.split('-')[0]
|
ret_val.From = self._stamps_address(service, from_partner)
|
||||||
ret_val.ToZIPCode = to_partner.zip.split('-')[0]
|
ret_val.To = self._stamps_address(service, to_partner)
|
||||||
ret_val.PackageType = self._stamps_package_type()
|
ret_val.PackageType = self._stamps_package_type()
|
||||||
ret_val.CubicPricing = self._stamps_package_is_cubic_pricing()
|
ret_val.CubicPricing = self._stamps_package_is_cubic_pricing()
|
||||||
ret_val.Length = l
|
ret_val.Length = l
|
||||||
@@ -191,8 +244,8 @@ class ProviderStamps(models.Model):
|
|||||||
ret_val.Height = h
|
ret_val.Height = h
|
||||||
ret_val.ServiceType = self.stamps_service_type
|
ret_val.ServiceType = self.stamps_service_type
|
||||||
ret_val.WeightLb = weight
|
ret_val.WeightLb = weight
|
||||||
ret_val.ContentType = 'Merchandise'
|
ret_val.ContentType = self._stamps_content_type()
|
||||||
ret.append((picking.name + ret_val.ShipDate + str(ret_val.WeightLb), ret_val))
|
ret.append((picking.name + ret_val.ShipDate + str(ret_val.WeightLb) + self._stamps_hash_partner(to_partner), ret_val))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@@ -254,6 +307,9 @@ class ProviderStamps(models.Model):
|
|||||||
return result
|
return result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _stamps_needs_customs(self, from_partner, to_partner):
|
||||||
|
return from_partner.country_id.code != to_partner.country_id.code
|
||||||
|
|
||||||
def stamps_send_shipping(self, pickings):
|
def stamps_send_shipping(self, pickings):
|
||||||
res = []
|
res = []
|
||||||
service = self._get_stamps_service()
|
service = self._get_stamps_service()
|
||||||
@@ -266,31 +322,9 @@ class ProviderStamps(models.Model):
|
|||||||
continue
|
continue
|
||||||
company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking)
|
company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking)
|
||||||
|
|
||||||
from_address = service.create_address()
|
customs = None
|
||||||
from_address.FullName = company.name
|
if self._stamps_needs_customs(from_partner, to_partner):
|
||||||
from_address.Address1 = from_partner.street
|
customs = service.create_customs()
|
||||||
if from_partner.street2:
|
|
||||||
from_address.Address2 = from_partner.street2
|
|
||||||
from_address.City = from_partner.city
|
|
||||||
from_address.State = from_partner.state_id.code
|
|
||||||
from_zip_pieces = from_partner.zip.split('-')
|
|
||||||
from_address.ZIPCode = from_zip_pieces[0]
|
|
||||||
if len(from_zip_pieces) >= 2:
|
|
||||||
from_address.ZIPCodeAddOn = from_zip_pieces[1]
|
|
||||||
from_address = service.get_address(from_address).Address
|
|
||||||
|
|
||||||
to_address = service.create_address()
|
|
||||||
to_address.FullName = to_partner.name
|
|
||||||
to_address.Address1 = to_partner.street
|
|
||||||
if to_partner.street2:
|
|
||||||
to_address.Address2 = to_partner.street2
|
|
||||||
to_address.City = to_partner.city
|
|
||||||
to_address.State = to_partner.state_id.code
|
|
||||||
to_zip_pieces = to_partner.zip.split('-')
|
|
||||||
to_address.ZIPCode = to_zip_pieces[0]
|
|
||||||
if len(to_zip_pieces) >= 2:
|
|
||||||
to_address.ZIPCodeAddOn = to_zip_pieces[1]
|
|
||||||
to_address = service.get_address(to_address).Address
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for txn_id, shipping in shippings:
|
for txn_id, shipping in shippings:
|
||||||
@@ -302,20 +336,78 @@ class ProviderStamps(models.Model):
|
|||||||
shipping.DeliverDays = rate.DeliverDays
|
shipping.DeliverDays = rate.DeliverDays
|
||||||
if hasattr(rate, 'DimWeighting'):
|
if hasattr(rate, 'DimWeighting'):
|
||||||
shipping.DimWeighting = rate.DimWeighting
|
shipping.DimWeighting = rate.DimWeighting
|
||||||
shipping.Zone = rate.Zone
|
|
||||||
shipping.RateCategory = rate.RateCategory
|
shipping.RateCategory = rate.RateCategory
|
||||||
shipping.ToState = rate.ToState
|
# shipping.ToState = rate.ToState
|
||||||
add_on = service.create_add_on()
|
addons = []
|
||||||
add_on.AddOnType = 'US-A-DC'
|
if self.stamps_addon_sc:
|
||||||
add_on2 = service.create_add_on()
|
add_on = service.create_add_on()
|
||||||
add_on2.AddOnType = 'SC-A-HP'
|
add_on.AddOnType = 'US-A-SC'
|
||||||
shipping.AddOns.AddOnV15 = [add_on, add_on2]
|
addons.append(add_on)
|
||||||
|
if self.stamps_addon_dc:
|
||||||
|
add_on = service.create_add_on()
|
||||||
|
add_on.AddOnType = 'US-A-DC'
|
||||||
|
addons.append(add_on)
|
||||||
|
if self.stamps_addon_hp:
|
||||||
|
add_on = service.create_add_on()
|
||||||
|
add_on.AddOnType = 'SC-A-HP'
|
||||||
|
addons.append(add_on)
|
||||||
|
shipping.AddOns.AddOnV17 = addons
|
||||||
|
|
||||||
extended_postage_info = service.create_extended_postage_info()
|
extended_postage_info = service.create_extended_postage_info()
|
||||||
if self.is_amazon(picking=picking):
|
if self.is_amazon(picking=picking):
|
||||||
extended_postage_info.bridgeProfileType = 'Amazon MWS'
|
extended_postage_info.bridgeProfileType = 'Amazon MWS'
|
||||||
label = service.get_label(from_address, to_address, shipping,
|
|
||||||
|
if customs:
|
||||||
|
customs.ContentType = shipping.ContentType
|
||||||
|
if not picking.package_ids:
|
||||||
|
raise ValidationError('Cannot use customs without packing items to ship first.')
|
||||||
|
customs_total = 0.0
|
||||||
|
product_values = {}
|
||||||
|
# Note multiple packages will result in all product being on customs form.
|
||||||
|
# Recommended to ship one customs international package at a time.
|
||||||
|
for quant in picking.mapped('package_ids.quant_ids'):
|
||||||
|
# Customs should have the price for the destination but we may not be able
|
||||||
|
# to rely on the price from the SO (e.g. kit BoM)
|
||||||
|
product = quant.product_id
|
||||||
|
quantity = quant.quantity
|
||||||
|
price = product.lst_price
|
||||||
|
if to_partner.property_product_pricelist:
|
||||||
|
# Note the quantity is used for the price, but it is per unit
|
||||||
|
price = to_partner.property_product_pricelist.get_product_price(product, quantity, to_partner)
|
||||||
|
if product not in product_values:
|
||||||
|
product_values[product] = {
|
||||||
|
'quantity': 0.0,
|
||||||
|
'value': 0.0,
|
||||||
|
}
|
||||||
|
product_values[product]['quantity'] += quantity
|
||||||
|
product_values[product]['value'] += price * quantity
|
||||||
|
|
||||||
|
# Note that Stamps will not allow you to use the scale weight if it is not equal
|
||||||
|
# to the sum of the customs lines.
|
||||||
|
# Thus we sum the line
|
||||||
|
new_total_weight = 0.0
|
||||||
|
customs_lines = []
|
||||||
|
for product, values in product_values.items():
|
||||||
|
customs_line = service.create_customs_lines()
|
||||||
|
customs_line.Description = product.name
|
||||||
|
customs_line.Quantity = values['quantity']
|
||||||
|
customs_total += round(values['value'], 2)
|
||||||
|
customs_line.Value = round(values['value'], 2)
|
||||||
|
line_weight = round(self._stamps_convert_weight(product.weight * values['quantity']), 2)
|
||||||
|
customs_line.WeightLb = line_weight
|
||||||
|
new_total_weight += line_weight
|
||||||
|
customs_line.HSTariffNumber = product.hs_code or ''
|
||||||
|
# customs_line.CountryOfOrigin =
|
||||||
|
customs_line.sku = product.default_code or ''
|
||||||
|
customs_lines.append(customs_line)
|
||||||
|
customs.CustomsLines.CustomsLine = customs_lines
|
||||||
|
shipping.DeclaredValue = round(customs_total, 2)
|
||||||
|
shipping.WeightLb = round(new_total_weight, 2)
|
||||||
|
|
||||||
|
label = service.get_label(shipping,
|
||||||
transaction_id=txn_id, image_type=self.stamps_image_type,
|
transaction_id=txn_id, image_type=self.stamps_image_type,
|
||||||
extended_postage_info=extended_postage_info)
|
extended_postage_info=extended_postage_info,
|
||||||
|
customs=customs)
|
||||||
package_labels.append((txn_id, label))
|
package_labels.append((txn_id, label))
|
||||||
except WebFault as e:
|
except WebFault as e:
|
||||||
_logger.warn(e)
|
_logger.warn(e)
|
||||||
@@ -339,9 +431,13 @@ class ProviderStamps(models.Model):
|
|||||||
carrier_price += float(label.Rate.Amount)
|
carrier_price += float(label.Rate.Amount)
|
||||||
url = label.URL
|
url = label.URL
|
||||||
|
|
||||||
response = urlopen(url)
|
url_spaces = url.split(' ')
|
||||||
attachment = response.read()
|
attachments = []
|
||||||
picking.message_post(body=body, attachments=[('LabelStamps-%s.%s' % (label.TrackingNumber, self.stamps_image_type), attachment)])
|
for i, url in enumerate(url_spaces, 1):
|
||||||
|
response = urlopen(url)
|
||||||
|
attachment = response.read()
|
||||||
|
attachments.append(('LabelStamps-%s-%s.%s' % (label.TrackingNumber, i, self.stamps_image_type), attachment))
|
||||||
|
picking.message_post(body=body, attachments=attachments)
|
||||||
shipping_data = {'exact_price': carrier_price, 'tracking_number': ','.join(tracking_numbers)}
|
shipping_data = {'exact_price': carrier_price, 'tracking_number': ','.join(tracking_numbers)}
|
||||||
res = res + [shipping_data]
|
res = res + [shipping_data]
|
||||||
return res
|
return res
|
||||||
@@ -356,7 +452,9 @@ class ProviderStamps(models.Model):
|
|||||||
def stamps_cancel_shipment(self, picking):
|
def stamps_cancel_shipment(self, picking):
|
||||||
service = self._get_stamps_service()
|
service = self._get_stamps_service()
|
||||||
try:
|
try:
|
||||||
service.remove_label(picking.carrier_tracking_ref)
|
all_tracking = picking.carrier_tracking_ref
|
||||||
|
for tracking in all_tracking.split(','):
|
||||||
|
service.remove_label(tracking.strip())
|
||||||
picking.message_post(body=_(u'Shipment N° %s has been cancelled' % picking.carrier_tracking_ref))
|
picking.message_post(body=_(u'Shipment N° %s has been cancelled' % picking.carrier_tracking_ref))
|
||||||
picking.write({'carrier_tracking_ref': '',
|
picking.write({'carrier_tracking_ref': '',
|
||||||
'carrier_price': 0.0})
|
'carrier_price': 0.0})
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
<page string="Stamps.com Configuration" attrs="{'invisible': [('delivery_type', '!=', 'stamps')]}">
|
<page string="Stamps.com Configuration" attrs="{'invisible': [('delivery_type', '!=', 'stamps')]}">
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="stamps_integration_id" attrs="{'required': [('delivery_type', '=', 'stamps')]}" />
|
|
||||||
<field name="stamps_username" attrs="{'required': [('delivery_type', '=', 'stamps')]}" />
|
<field name="stamps_username" attrs="{'required': [('delivery_type', '=', 'stamps')]}" />
|
||||||
<field name="stamps_password" attrs="{'required': [('delivery_type', '=', 'stamps')]}" password="True"/>
|
<field name="stamps_password" attrs="{'required': [('delivery_type', '=', 'stamps')]}" password="True"/>
|
||||||
</group>
|
</group>
|
||||||
@@ -18,6 +17,9 @@
|
|||||||
<field name="stamps_service_type" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
<field name="stamps_service_type" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
||||||
<field name="stamps_default_packaging_id" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
<field name="stamps_default_packaging_id" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
||||||
<field name="stamps_image_type" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
<field name="stamps_image_type" attrs="{'required': [('delivery_type', '==', 'stamps')]}"/>
|
||||||
|
<field name="stamps_addon_sc"/>
|
||||||
|
<field name="stamps_addon_dc"/>
|
||||||
|
<field name="stamps_addon_hp"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
|
|||||||
Reference in New Issue
Block a user