From fde596abfd49d6911dfdaf3fcd6eaa9c7e0fd850 Mon Sep 17 00:00:00 2001 From: Mayank Patel Date: Wed, 11 Sep 2024 05:45:33 +0000 Subject: [PATCH] [REM] delivery_stamps: available in professional H14528 --- delivery_stamps/__init__.py | 3 - delivery_stamps/__manifest__.py | 28 - delivery_stamps/i18n/es.po | 241 - delivery_stamps/models/__init__.py | 3 - delivery_stamps/models/api/LICENSE | 32 - delivery_stamps/models/api/__init__.py | 14 - delivery_stamps/models/api/config.py | 102 - delivery_stamps/models/api/services.py | 318 - delivery_stamps/models/api/tests.py | 149 - .../models/api/wsdls/stamps_v111.test.wsdl | 6039 ----------------- .../models/api/wsdls/stamps_v111.wsdl | 6039 ----------------- delivery_stamps/models/delivery_stamps.py | 571 -- .../views/delivery_stamps_view.xml | 41 - 13 files changed, 13580 deletions(-) delete mode 100644 delivery_stamps/__init__.py delete mode 100644 delivery_stamps/__manifest__.py delete mode 100644 delivery_stamps/i18n/es.po delete mode 100644 delivery_stamps/models/__init__.py delete mode 100755 delivery_stamps/models/api/LICENSE delete mode 100755 delivery_stamps/models/api/__init__.py delete mode 100755 delivery_stamps/models/api/config.py delete mode 100755 delivery_stamps/models/api/services.py delete mode 100755 delivery_stamps/models/api/tests.py delete mode 100644 delivery_stamps/models/api/wsdls/stamps_v111.test.wsdl delete mode 100644 delivery_stamps/models/api/wsdls/stamps_v111.wsdl delete mode 100644 delivery_stamps/models/delivery_stamps.py delete mode 100644 delivery_stamps/views/delivery_stamps_view.xml diff --git a/delivery_stamps/__init__.py b/delivery_stamps/__init__.py deleted file mode 100644 index 09434554..00000000 --- a/delivery_stamps/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from . import models diff --git a/delivery_stamps/__manifest__.py b/delivery_stamps/__manifest__.py deleted file mode 100644 index bfd9649e..00000000 --- a/delivery_stamps/__manifest__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -{ - 'name': 'Stamps.com (USPS) Shipping', - 'summary': 'Send your shippings through Stamps.com and track them online.', - 'version': '15.0.1.1.0', - 'author': "Hibou Corp.", - 'category': 'Warehouse', - 'license': 'OPL-1', - 'images': [], - 'website': "https://hibou.io", - 'description': """ -Stamps.com (USPS) Shipping -========================== - -Send your shippings through Stamps.com and track them online. - -""", - 'depends': [ - 'delivery_hibou', - ], - 'demo': [], - 'data': [ - 'views/delivery_stamps_view.xml', - ], - 'auto_install': False, - 'installable': True, -} diff --git a/delivery_stamps/i18n/es.po b/delivery_stamps/i18n/es.po deleted file mode 100644 index d7b4036a..00000000 --- a/delivery_stamps/i18n/es.po +++ /dev/null @@ -1,241 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * delivery_stamps -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 15.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-10-12 01:20+0000\n" -"PO-Revision-Date: 2021-10-12 01:20+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_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_service_type__us-emi -msgid " Priority Mail Express International" -msgstr "Servicio Postal Prioritario Express Internacional" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__azpl -msgid "AZPL" -msgstr "AZPL" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_addon_dc -msgid "Add Delivery Confirmation" -msgstr "Agregar Confirmación de Entrega" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_addon_hp -msgid "Add Hidden Postage" -msgstr "Agregar Franqueo Oculto" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_addon_sc -msgid "Add Signature Confirmation" -msgstr "Agregar Firma de Confirmación" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__auto -msgid "Auto" -msgstr "Automático" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__bzpl -msgid "BZPL" -msgstr "BZPL" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Cancelling due to error: " -msgstr "Cancelando debido a un error" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Cannot use customs without packing items to ship first." -msgstr "No se puede usar el servicio de aduana sin empacar los artículos para enviar primero." - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_stock_package_type__package_carrier_type -msgid "Carrier" -msgstr "Transportista" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_default_packaging_id -msgid "Default Package Type" -msgstr "Tipo de Paquete Predeterminado" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__epl -msgid "EPL" -msgstr "EPL" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__encryptedpngurl -msgid "Encrypted PNG URL" -msgstr "URL de PNG Encriptado" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Error Retrieving Response from Stamps.com" -msgstr "Error al recuperar una respuesta de Stamps.com" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Error on full shipment. Attempted to cancel any previously shipped." -msgstr "Error en el envío completo. Se intentó cancelar cualquier envío que se había enviado anteriormente" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Error on shipment. \"%s\"" -msgstr "Error en el envío. \"%s\"" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_service_type__us-fc -msgid "First-Class" -msgstr "Primera-Clase" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_service_type__us-fci -msgid "First-Class International" -msgstr "Primera Clase Internacional" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__gif -msgid "GIF" -msgstr "GIF" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_image_type -msgid "Image Type" -msgstr "Tipo de Imagen" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__jpg -msgid "JPG" -msgstr "JPG" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "No valid rates returned from Stamps.com" -msgstr "No se devolvieron tarifas válidas de Stamps.com" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__pdf -msgid "PDF" -msgstr "PDF" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__png -msgid "PNG" -msgstr "PNG" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Partner (%s) name must be more than 2 characters." -msgstr "El nombre del Socio (%s) debe tener más de dos caracteres" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__printoncepdf -msgid "Print Once PDF" -msgstr "Imprimir PDF Una Vez" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_service_type__us-pm -msgid "Priority" -msgstr "Prioridad" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_service_type__us-pmi -msgid "Priority Mail International" -msgstr "Servicio Postal Prioritaria Internacional" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__delivery_type -msgid "Provider" -msgstr "Proveedor" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_service_type -msgid "Service Type" -msgstr "Tipo de Servicio" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Shipment N° %s has been cancelled" -msgstr "Número de Envío %s ha sido cancelado" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "" -"Shipment created into Stamps.com
Tracking Number :
\"%s\" " -"
" -msgstr "El envío ha sido creado en Stamps.com
Número de Seguimiento :
\"%s\"
" - -#. module: delivery_stamps -#: model:ir.model,name:delivery_stamps.model_delivery_carrier -msgid "Shipping Methods" -msgstr "Métodos de Envío" - -#. module: delivery_stamps -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#: code:addons/delivery_stamps/models/delivery_stamps.py:0 -#, python-format -msgid "Stamps needs ZIP. From: \"%s\" To: \"%s\"" -msgstr "Stamps requiere un Código Postal. Desde: %s Hasta: %s" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__stock_package_type__package_carrier_type__stamps -msgid "Stamps.com" -msgstr "Stamps.com" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__delivery_type__stamps -msgid "Stamps.com (USPS)" -msgstr "Stamps.com (USPS)" - -#. module: delivery_stamps -#: model_terms:ir.ui.view,arch_db:delivery_stamps.view_delivery_carrier_form_with_provider_stamps -msgid "Stamps.com Configuration" -msgstr "Stamps.com Configuración" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_password -msgid "Stamps.com Password" -msgstr "Stamps.com Clave" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_stock_package_type__stamps_cubic_pricing -msgid "Stamps.com Use Cubic Pricing" -msgstr "Stamps.com Utilice el Precio Cúbicos" - -#. module: delivery_stamps -#: model:ir.model.fields,field_description:delivery_stamps.field_delivery_carrier__stamps_username -msgid "Stamps.com Username" -msgstr "Stamps.com Usuario" - -#. module: delivery_stamps -#: model:ir.model,name:delivery_stamps.model_stock_package_type -msgid "Stock package type" -msgstr "Tipo de Paquete de Stock" - -#. module: delivery_stamps -#: model:ir.model.fields.selection,name:delivery_stamps.selection__delivery_carrier__stamps_image_type__zpl -msgid "ZPL" -msgstr "ZPL" diff --git a/delivery_stamps/models/__init__.py b/delivery_stamps/models/__init__.py deleted file mode 100644 index 1f944aa8..00000000 --- a/delivery_stamps/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from . import delivery_stamps diff --git a/delivery_stamps/models/api/LICENSE b/delivery_stamps/models/api/LICENSE deleted file mode 100755 index b699676b..00000000 --- a/delivery_stamps/models/api/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (c) 2019 by Hibou Corp. -Copyright (c) 2014 by Jonathan Zempel. - -Some rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -* The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/delivery_stamps/models/api/__init__.py b/delivery_stamps/models/api/__init__.py deleted file mode 100755 index 0654679c..00000000 --- a/delivery_stamps/models/api/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -""" - stamps - ~~~~~~ - - Stamps.com API. - - :copyright: 2014 by Jonathan Zempel. - :license: BSD, see LICENSE for more details. -""" - -__author__ = "Jonathan Zempel" -__license__ = "BSD" -__version__ = "0.9.1" diff --git a/delivery_stamps/models/api/config.py b/delivery_stamps/models/api/config.py deleted file mode 100755 index 937ef6b7..00000000 --- a/delivery_stamps/models/api/config.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- -""" - stamps.config - ~~~~~~~~~~~~~ - - Stamps.com configuration. - - :copyright: 2014 by Jonathan Zempel. - :license: BSD, see LICENSE for more details. -""" - -from configparser import NoOptionError, NoSectionError, SafeConfigParser -from urllib.request import pathname2url -from urllib.parse import urljoin -import os - - -VERSION = 111 - - -class StampsConfiguration(object): - """Stamps service configuration. The service configuration may be provided - directly via parameter values, or it can be read from a configuration file. - If no parameters are given, the configuration will attempt to read from a - ``'.stamps.cfg'`` file in the user's HOME directory. Alternately, a - configuration filename can be passed to the constructor. - - Here is a sample configuration (by default the constructor reads from a - ``'default'`` section):: - - [default] - integration_id = XXXXXXXX-1111-2222-3333-YYYYYYYYYYYY - username = stampy - password = secret - - :param integration_id: Default `None`. Unique ID, provided by Stamps.com, - that represents your application. - :param username: Default `None`. Stamps.com account username. - :param password: Default `None`. Stamps.com password. - :param wsdl: Default `None`. WSDL URI. Use ``'testing'`` to use the test - server WSDL. - :param port: Default `None`. The name of the WSDL port to use. - :param file_name: Default `None`. Optional configuration file name. - :param section: Default ``'default'``. The configuration section to use. - """ - - def __init__(self, integration_id=None, username=None, password=None, - wsdl=None, port=None, file_name=None, section="default"): - parser = SafeConfigParser() - - if file_name: - parser.read([file_name]) - else: - parser.read([os.path.expanduser("~/.stamps.cfg")]) - - self.integration_id = self.__get(parser, section, "integration_id", - integration_id) - self.username = self.__get(parser, section, "username", username) - self.password = self.__get(parser, section, "password", password) - self.wsdl = self.__get(parser, section, "wsdl", wsdl) - self.port = self.__get(parser, section, "port", port) - - if self.wsdl is None or wsdl == "testing": - file_path = os.path.abspath(__file__) - directory_path = os.path.dirname(file_path) - - if wsdl == "testing": - file_name = "stamps_v{0}.test.wsdl".format(VERSION) - else: - file_name = "stamps_v{0}.wsdl".format(VERSION) - - wsdl = os.path.join(directory_path, "wsdls", file_name) - self.wsdl = urljoin("file:", pathname2url(wsdl)) - - if self.port is None: - self.port = "SwsimV{0}Soap12".format(VERSION) - - assert self.integration_id - assert self.username - assert self.password - assert self.wsdl - assert self.port - - @staticmethod - def __get(parser, section, name, default): - """Get a configuration value for the named section. - - :param parser: The configuration parser. - :param section: The section for the given name. - :param name: The name of the value to retrieve. - """ - if default: - vars = {name: default} - else: - vars = None - - try: - ret_val = parser.get(section, name, vars=vars) - except (NoSectionError, NoOptionError): - ret_val = default - - return ret_val diff --git a/delivery_stamps/models/api/services.py b/delivery_stamps/models/api/services.py deleted file mode 100755 index a53aaea9..00000000 --- a/delivery_stamps/models/api/services.py +++ /dev/null @@ -1,318 +0,0 @@ -# -*- coding: utf-8 -*- -""" - stamps.services - ~~~~~~~~~~~~~~~ - - Stamps.com services. - - :copyright: 2014 by Jonathan Zempel. - :license: BSD, see LICENSE for more details. -""" - -from decimal import Decimal -from logging import getLogger -from re import compile -from suds import WebFault -from suds.bindings.document import Document -from suds.client import Client -from suds.plugin import MessagePlugin -from suds.sax.element import Element -from suds.sudsobject import asdict -from suds.xsd.sxbase import XBuiltin -from suds.xsd.sxbuiltin import Factory - - -PATTERN_HEX = r"[0-9a-fA-F]" -PATTERN_ID = r"{hex}{{8}}-{hex}{{4}}-{hex}{{4}}-{hex}{{4}}-{hex}{{12}}".format( - hex=PATTERN_HEX) -RE_TRANSACTION_ID = compile(PATTERN_ID) - - -# class LogPlugin(MessagePlugin): -# def __init__(self): -# self.logger = getLogger('stamps2') -# self.last_sent_raw = None -# self.last_received_raw = None -# -# def sending(self, context): -# self.last_sent_raw = str(context.envelope) -# self.logger.warning(self.last_sent_raw) -# -# def received(self, context): -# self.last_received_raw = str(context.reply) -# self.logger.warning(self.last_received_raw) - - -class AuthenticatorPlugin(MessagePlugin): - """Handle message authentication. - - :param credentials: Stamps API credentials. - :param wsdl: Configured service client. - """ - - def __init__(self, credentials, client): - self.credentials = credentials - self.client = client - self.authenticator = None - - def marshalled(self, context): - """Add an authenticator token to the document before it is sent. - - :param context: The current message context. - """ - body = context.envelope.getChild("Body") - operation = body[0] - - if operation.name in ("AuthenticateUser", "RegisterAccount"): - pass - elif self.authenticator: - namespace = operation.namespace() - element = Element("Authenticator", ns=namespace) - element.setText(self.authenticator) - operation.insert(element) - else: - document = Document(self.client.wsdl) - method = self.client.service.AuthenticateUser.method - parameter = document.param_defs(method)[0] - element = document.mkparam(method, parameter, self.credentials) - operation.insert(element) - - def unmarshalled(self, context): - """Store the authenticator token for the next call. - - :param context: The current message context. - """ - if hasattr(context.reply, "Authenticator"): - self.authenticator = context.reply.Authenticator - del context.reply.Authenticator - else: - self.authenticator = None - - return context - - -class BaseService(object): - """Base service. - - :param configuration: API configuration. - """ - - def __init__(self, configuration): - Factory.maptag("decimal", XDecimal) - self.client = Client(configuration.wsdl) - credentials = self.create("Credentials") - credentials.IntegrationID = configuration.integration_id - credentials.Username = configuration.username - credentials.Password = configuration.password - self.plugin = AuthenticatorPlugin(credentials, self.client) - # put in plugins=[] as well - # self.logplugin = LogPlugin() - self.client.set_options(plugins=[self.plugin], port=configuration.port) - self.logger = getLogger("stamps") - - def call(self, method, **kwargs): - """Call the given web service method. - - :param method: The name of the web service operation to call. - :param kwargs: Method keyword-argument parameters. - """ - self.logger.debug("%s(%s)", method, kwargs) - instance = getattr(self.client.service, method) - - try: - ret_val = instance(**kwargs) - except WebFault as error: - self.logger.warning("Retry %s", method, exc_info=True) - self.plugin.authenticator = None - - try: # retry with a re-authenticated user. - ret_val = instance(**kwargs) - except WebFault as error: - self.logger.exception("%s retry failed", method) - self.plugin.authenticator = None - raise error - - return ret_val - - def create(self, wsdl_type): - """Create an object of the given WSDL type. - - :param wsdl_type: The WSDL type to create an object for. - """ - return self.client.factory.create(wsdl_type) - - -class StampsService(BaseService): - """Stamps.com service. - """ - - def add_postage(self, amount, transaction_id=None): - """Add postage to the account. - - :param amount: The amount of postage to purchase. - :param transaction_id: Default `None`. ID that may be used to retry the - purchase of this postage. - """ - account = self.get_account() - control = account.AccountInfo.PostageBalance.ControlTotal - - return self.call("PurchasePostage", PurchaseAmount=amount, - ControlTotal=control, IntegratorTxID=transaction_id) - - def create_add_on(self): - """Create a new add-on object. - """ - return self.create("AddOnV17") - - def create_customs(self): - """Create a new customs object. - """ - return self.create("CustomsV7") - - def create_array_of_customs_lines(self): - """Create a new array of customs objects. - """ - return self.create("ArrayOfCustomsLine") - - def create_customs_lines(self): - """Create new customs lines. - """ - return self.create("CustomsLine") - - def create_address(self): - """Create a new address object. - """ - return self.create("Address") - - def create_purchase_status(self): - """Create a new purchase status object. - """ - return self.create("PurchaseStatus") - - def create_registration(self): - """Create a new registration object. - """ - ret_val = self.create("RegisterAccount") - ret_val.IntegrationID = self.plugin.credentials.IntegrationID - ret_val.UserName = self.plugin.credentials.Username - ret_val.Password = self.plugin.credentials.Password - - return ret_val - - def create_extended_postage_info(self): - return self.create("ExtendedPostageInfoV1") - - def create_shipping(self): - """Create a new shipping object. - """ - return self.create("RateV40") - - def get_address(self, address): - """Get a shipping address. - - :param address: Address instance to get a clean shipping address for. - """ - return self.call("CleanseAddress", Address=address) - - def get_account(self): - """Get account information. - """ - return self.call("GetAccountInfo") - - def get_label(self, rate, transaction_id, image_type=None, - customs=None, sample=False, extended_postage_info=False): - """Get a shipping label. - - :param from_address: The shipping 'from' address. - :param to_address: The shipping 'to' address. - :param rate: A rate instance for the shipment. - :param transaction_id: ID that may be used to retry/rollback the - purchase of this label. - :param customs: A customs instance for international shipments. - :param sample: Default ``False``. Get a sample label without postage. - """ - return self.call("CreateIndicium", IntegratorTxID=transaction_id, - Rate=rate, ImageType=image_type, Customs=customs, - SampleOnly=sample, ExtendedPostageInfo=extended_postage_info) - - def get_postage_status(self, transaction_id): - """Get postage purchase status. - - :param transaction_id: The transaction ID returned by - :meth:`add_postage`. - """ - return self.call("GetPurchaseStatus", TransactionID=transaction_id) - - def get_rates(self, shipping): - """Get shipping rates. - - :param shipping: Shipping instance to get rates for. - """ - rates = self.call("GetRates", Rate=shipping) - - if rates.Rates: - ret_val = [rate for rate in rates.Rates.Rate] - else: - ret_val = [] - - return ret_val - - def get_tracking(self, transaction_id): - """Get tracking events for a shipment. - - :param transaction_id: The transaction ID (or tracking number) returned - by :meth:`get_label`. - """ - if RE_TRANSACTION_ID.match(transaction_id): - arguments = dict(StampsTxID=transaction_id) - else: - arguments = dict(TrackingNumber=transaction_id) - - return self.call("TrackShipment", **arguments) - - def register_account(self, registration): - """Register a new account. - - :param registration: Registration instance. - """ - arguments = asdict(registration) - - return self.call("RegisterAccount", **arguments) - - def remove_label(self, transaction_id): - """Cancel a shipping label. - - :param transaction_id: The transaction ID (or tracking number) returned - by :meth:`get_label`. - """ - if RE_TRANSACTION_ID.match(transaction_id): - arguments = dict(StampsTxID=transaction_id) - else: - arguments = dict(TrackingNumber=transaction_id) - - return self.call("CancelIndicium", **arguments) - - -class XDecimal(XBuiltin): - """Represents an XSD decimal type. - """ - - def translate(self, value, topython=True): - """Translate between string and decimal values. - - :param value: The value to translate. - :param topython: Default `True`. Determine whether to translate the - value for python. - """ - if topython: - if isinstance(value, str) and len(value): - ret_val = Decimal(value) - else: - ret_val = None - else: - if isinstance(value, (int, float, Decimal)): - ret_val = str(value) - else: - ret_val = value - - return ret_val diff --git a/delivery_stamps/models/api/tests.py b/delivery_stamps/models/api/tests.py deleted file mode 100755 index 5f5669e9..00000000 --- a/delivery_stamps/models/api/tests.py +++ /dev/null @@ -1,149 +0,0 @@ -# -*- coding: utf-8 -*- -""" - stamps.tests - ~~~~~~~~~~~~ - - Stamps.com API tests. - - :copyright: 2014 by Jonathan Zempel. - :license: BSD, see LICENSE for more details. -""" - -from .config import StampsConfiguration -from .services import StampsService -from datetime import date, datetime -from time import sleep -from unittest import TestCase -import logging -import os - - -logging.basicConfig() -logging.getLogger("suds.client").setLevel(logging.DEBUG) -file_path = os.path.abspath(__file__) -directory_path = os.path.dirname(file_path) -file_name = os.path.join(directory_path, "tests.cfg") -CONFIGURATION = StampsConfiguration(wsdl="testing", file_name=file_name) - - -def get_rate(service): - """Get a test rate. - - :param service: Instance of the stamps service. - """ - ret_val = service.create_shipping() - ret_val.ShipDate = date.today().isoformat() - ret_val.FromZIPCode = "94107" - ret_val.ToZIPCode = "20500" - ret_val.PackageType = "Package" - rate = service.get_rates(ret_val)[0] - ret_val.Amount = rate.Amount - ret_val.ServiceType = rate.ServiceType - ret_val.DeliverDays = rate.DeliverDays - ret_val.DimWeighting = rate.DimWeighting - ret_val.Zone = rate.Zone - ret_val.RateCategory = rate.RateCategory - ret_val.ToState = rate.ToState - add_on = service.create_add_on() - add_on.AddOnType = "US-A-DC" - ret_val.AddOns.AddOnV15.append(add_on) - - return ret_val - - -def get_from_address(service): - """Get a test 'from' address. - - :param service: Instance of the stamps service. - """ - address = service.create_address() - address.FullName = "Pickwick & Weller" - address.Address1 = "300 Brannan St." - address.Address2 = "Suite 405" - address.City = "San Francisco" - address.State = "CA" - - return service.get_address(address).Address - - -def get_to_address(service): - """Get a test 'to' address. - - :param service: Instance of the stamps service. - """ - address = service.create_address() - address.FullName = "POTUS" - address.Address1 = "1600 Pennsylvania Avenue NW" - address.City = "Washington" - address.State = "DC" - - return service.get_address(address).Address - - -class StampsTestCase(TestCase): - - initialized = False - - def setUp(self): - if not StampsTestCase.initialized: - self.service = StampsService(CONFIGURATION) - StampsTestCase.initalized = True - - def _test_0(self): - """Test account registration. - """ - registration = self.service.create_registration() - type = self.service.create("CodewordType") - registration.Codeword1Type = type.Last4SocialSecurityNumber - registration.Codeword1 = 1234 - registration.Codeword2Type = type.Last4DriversLicense - registration.Codeword2 = 1234 - registration.PhysicalAddress = get_from_address(self.service) - registration.MachineInfo.IPAddress = "127.0.0.1" - registration.Email = "sws-support@stamps.com" - type = self.service.create("AccountType") - registration.AccountType = type.OfficeBasedBusiness - result = self.service.register_account(registration) - print result - - def _test_1(self): - """Test postage purchase. - """ - transaction_id = datetime.now().isoformat() - result = self.service.add_postage(10, transaction_id=transaction_id) - transaction_id = result.TransactionID - status = self.service.create_purchase_status() - seconds = 4 - - while result.PurchaseStatus in (status.Pending, status.Processing): - seconds = 32 if seconds * 2 >= 32 else seconds * 2 - print "Waiting {0:d} seconds to get status...".format(seconds) - sleep(seconds) - result = self.service.get_postage_status(transaction_id) - - print result - - def test_2(self): - """Test label generation. - """ - self.service = StampsService(CONFIGURATION) - rate = get_rate(self.service) - from_address = get_from_address(self.service) - to_address = get_to_address(self.service) - transaction_id = datetime.now().isoformat() - label = self.service.get_label(from_address, to_address, rate, - transaction_id=transaction_id) - self.service.get_tracking(label.StampsTxID) - self.service.get_tracking(label.TrackingNumber) - self.service.remove_label(label.StampsTxID) - print label - - def test_3(self): - """Test authentication retry. - """ - self.service.get_account() - authenticator = self.service.plugin.authenticator - self.service.get_account() - self.service.plugin.authenticator = authenticator - result = self.service.get_account() - print result diff --git a/delivery_stamps/models/api/wsdls/stamps_v111.test.wsdl b/delivery_stamps/models/api/wsdls/stamps_v111.test.wsdl deleted file mode 100644 index ad1a2011..00000000 --- a/delivery_stamps/models/api/wsdls/stamps_v111.test.wsdl +++ /dev/null @@ -1,6039 +0,0 @@ - - - Stamps.com Web Services for Individual Meters (SWS/IM) Version 111 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Generate an indicium. - - - - - Calculate a rate or a list of rates. - - - - - Generate an envelope indicium. - - - - - Generate a mailing label sheet. - - - - - Generate NetStamps indicia. - - - - - Get URL for a Stamps.com web page. - - - - - Register a new Stamps.com account. - - - - - Add the image uploaded by the user. - - - - - Create Branding. - - - - - Get Branding. - - - - - Modify Branding. - - - - - Delete Branding. - - - - - Schedule carrier pickup. - - - - - Modify existing carrier pickup request. - - - - - Cancel existing carrier pickup request. - - - - - Begin Reprint Indicium - - - - - Add carrier. - - - - - Delete carrier. - - - - - Get tracking events for shipment. - - - - - Check carrier pickup availability for an address. - - - - - Creates a Parcel Guard insurance claim. - - - - - Get list of shipments. - - - - - Generate a Carrier Shipment Manifest. - - - - - Start account verification for phone. - - - - - Finish account verification for phone. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Recover Username. - - - - - Purchase additional postage. - - - - - Authenticate Bridge Authenticator - - - - - Get the images uploaded by the user. - - - - - Delete an image uploaded by the user. - - - - - Get the existing carrier pickup requests. - - - - - Cancel an Account. - - - - - Cleanse an address. - - - - - Price Store Orders. - - - - - Place Store Orders. - - - - - Get list of shipments. - - - - - Change Plan. - - - - - Get list of transactions. - - - - - Get list of transactions. - - - - - Cancel a previously issued indicium. - - - - - Set CodeWord information - - - - - Set auto-buy settings - - - - - Return the list of available CodeWord types. - - - - - Get list of supported countries. - - - - - Change Password. - - - - - Get NetStamps Images. - - - - - Get status of plan change. - - - - - Resubmit Purchase. - - - - - Get list of NetStamps layouts. - - - - - Get list of cost codes. - - - - - Authenticate with transfer authenticator. - - - - - Start a password reset by sending a temporary password to the e-mail address on file. - - - - - Finish a password reset, setting the permanent password to a new password. - - - - - Retrieve codeword questions for user for starting password reset. - - - - - Initial authentication. - - - - - Get account information, including postage balance. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Stamps.com Web Services for Individual Meters (SWS/IM) Version 111 - - - - - - - - \ No newline at end of file diff --git a/delivery_stamps/models/api/wsdls/stamps_v111.wsdl b/delivery_stamps/models/api/wsdls/stamps_v111.wsdl deleted file mode 100644 index 78de10ee..00000000 --- a/delivery_stamps/models/api/wsdls/stamps_v111.wsdl +++ /dev/null @@ -1,6039 +0,0 @@ - - - Stamps.com Web Services for Individual Meters (SWS/IM) Version 111 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Generate an indicium. - - - - - Calculate a rate or a list of rates. - - - - - Generate an envelope indicium. - - - - - Generate a mailing label sheet. - - - - - Generate NetStamps indicia. - - - - - Get URL for a Stamps.com web page. - - - - - Register a new Stamps.com account. - - - - - Add the image uploaded by the user. - - - - - Create Branding. - - - - - Get Branding. - - - - - Modify Branding. - - - - - Delete Branding. - - - - - Schedule carrier pickup. - - - - - Modify existing carrier pickup request. - - - - - Cancel existing carrier pickup request. - - - - - Begin Reprint Indicium - - - - - Add carrier. - - - - - Delete carrier. - - - - - Get tracking events for shipment. - - - - - Check carrier pickup availability for an address. - - - - - Creates a Parcel Guard insurance claim. - - - - - Get list of shipments. - - - - - Generate a Carrier Shipment Manifest. - - - - - Start account verification for phone. - - - - - Finish account verification for phone. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Add a payment method for the user. - - - - - Recover Username. - - - - - Purchase additional postage. - - - - - Authenticate Bridge Authenticator - - - - - Get the images uploaded by the user. - - - - - Delete an image uploaded by the user. - - - - - Get the existing carrier pickup requests. - - - - - Cancel an Account. - - - - - Cleanse an address. - - - - - Price Store Orders. - - - - - Place Store Orders. - - - - - Get list of shipments. - - - - - Change Plan. - - - - - Get list of transactions. - - - - - Get list of transactions. - - - - - Cancel a previously issued indicium. - - - - - Set CodeWord information - - - - - Set auto-buy settings - - - - - Return the list of available CodeWord types. - - - - - Get list of supported countries. - - - - - Change Password. - - - - - Get NetStamps Images. - - - - - Get status of plan change. - - - - - Resubmit Purchase. - - - - - Get list of NetStamps layouts. - - - - - Get list of cost codes. - - - - - Authenticate with transfer authenticator. - - - - - Start a password reset by sending a temporary password to the e-mail address on file. - - - - - Finish a password reset, setting the permanent password to a new password. - - - - - Retrieve codeword questions for user for starting password reset. - - - - - Initial authentication. - - - - - Get account information, including postage balance. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Stamps.com Web Services for Individual Meters (SWS/IM) Version 111 - - - - - - - - \ No newline at end of file diff --git a/delivery_stamps/models/delivery_stamps.py b/delivery_stamps/models/delivery_stamps.py deleted file mode 100644 index dee8aec8..00000000 --- a/delivery_stamps/models/delivery_stamps.py +++ /dev/null @@ -1,571 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -import hashlib -from datetime import date -from logging import getLogger -from urllib.request import urlopen -from suds import WebFault - -from odoo import api, fields, models, _ -from odoo.exceptions import UserError, ValidationError - -from .api.config import StampsConfiguration -from .api.services import StampsService - -_logger = getLogger(__name__) - -STAMPS_US_APO_FPO_STATE_CODES = ( - 'AE', - 'AP', - 'AA', -) - -STAMPS_PACKAGE_TYPES = [ - 'Unknown', - 'Postcard', - 'Letter', - 'Large Envelope or Flat', - 'Thick Envelope', - 'Package', - 'Flat Rate Box', - 'Small Flat Rate Box', - 'Large Flat Rate Box', - 'Flat Rate Envelope', - 'Flat Rate Padded Envelope', - 'Large Package', - 'Oversized Package', - 'Regional Rate Box A', - 'Regional Rate Box B', - 'Legal Flat Rate Envelope', - 'Regional Rate Box C', -] - -STAMPS_CONTENT_TYPES = { - 'Letter': 'Document', - 'Postcard': 'Document', -} - -STAMPS_INTEGRATION_ID = 'f62cb4f0-aa07-4701-a1dd-f0e7c853ed3c' - - -class StockPackageType(models.Model): - _inherit = 'stock.package.type' - - package_carrier_type = fields.Selection(selection_add=[('stamps', 'Stamps.com')]) - stamps_cubic_pricing = fields.Boolean(string="Stamps.com Use Cubic Pricing") - - -class ProviderStamps(models.Model): - _inherit = 'delivery.carrier' - - delivery_type = fields.Selection(selection_add=[('stamps', 'Stamps.com')], - ondelete={'stamps': 'set default'}) - - 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_service_type = fields.Selection([('US-FC', 'USPS First-Class'), - ('US-PM', 'USPS Priority'), - ('US-XM', 'USPS Express'), - ('US-MM', 'USPS Media Mail'), - ('US-FCI', 'USPS First-Class International'), - ('US-PMI', 'USPS Priority International'), - ('US-EMI', 'USPS Express International'), - ('SC-GPE', 'GlobalPost Economy'), - ('SC-GPP', 'GlobalPost Standard'), - ('SC-GPESS', 'GlobalPost SmartSaver Economy'), - ('SC-GPPSS', 'GlobalPost SmartSaver Standard'), - ], - required=True, string="Service Type", default="US-PM") - stamps_default_packaging_id = fields.Many2one('stock.package.type', string='Default Package Type') - - stamps_image_type = fields.Selection([('Auto', 'Auto'), - ('Png', 'PNG'), - ('Gif', 'GIF'), - ('Pdf', 'PDF'), - ('Epl', 'EPL'), - ('Jpg', 'JPG'), - ('PrintOncePdf', 'Print Once PDF'), - ('EncryptedPngUrl', 'Encrypted PNG URL'), - ('Zpl', 'ZPL'), - ('AZpl', 'AZPL'), - ('BZpl', 'BZPL'), - ], - required=True, string="Image Type", default="Pdf", - help='Generally PDF or ZPL are the great options.') - 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): - if not package: - return self.stamps_default_packaging_id.shipper_package_code - return package.package_type_id.shipper_package_code if package.package_type_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): - if not package: - return self.stamps_default_packaging_id.stamps_cubic_pricing - return package.package_type_id.stamps_cubic_pricing - - def _stamps_package_dimensions(self, package=None): - if not package: - package_type = self.stamps_default_packaging_id - else: - 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 round(package_type.packaging_length / 12.0), round(package_type.width / 12.0), round(package_type.height / 12.0) - elif length_uom.name == 'mm': - return round(package_type.packaging_length * 0.0393701), round(package_type.width * 0.0393701), round(package_type.height * 0.0393701) - return package_type.packaging_length, package_type.width, package_type.height - - def _get_stamps_service(self): - sudoself = self.sudo() - config = StampsConfiguration(integration_id=STAMPS_INTEGRATION_ID, - username=sudoself.stamps_username, - password=sudoself.stamps_password, - wsdl=('testing' if not sudoself.prod_environment else None)) - return StampsService(configuration=config) - - def _stamps_convert_weight(self, weight): - """ weight always expressed in database units (KG/LBS) """ - weight_uom = self.env['product.template']._get_weight_uom_id_from_ir_config_parameter() - if weight_uom.name == 'kg': - weight_in_pounds = weight * 2.20462 - else: - weight_in_pounds = weight - return weight_in_pounds - - def _get_stamps_shipping_for_order(self, service, order, date_planned): - weight = sum([(line.product_id.weight * line.product_qty) for line in order.order_line]) or 0.0 - weight = self._stamps_convert_weight(weight) - - if not all((order.warehouse_id.partner_id.zip, order.partner_shipping_id.zip)): - raise ValidationError(_('Stamps needs ZIP. From: "%s" To: "%s"', - order.warehouse_id.partner_id.zip, - order.partner_shipping_id.zip)) - - ret_val = service.create_shipping() - ret_val.ShipDate = date_planned.strftime('%Y-%m-%d') if date_planned else date.today().isoformat() - shipper_partner = self.get_shipper_warehouse(order=order) - 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.ServiceType = self.stamps_service_type - ret_val.WeightLb = weight - ret_val.ContentType = self._stamps_content_type() - return ret_val - - def _get_stamps_shipping_multi(self, service, date_planned, order=False, picking=False, package=False): - if order: - weight = sum([(line.product_id.weight * line.product_qty) for line in order.order_line]) or 0.0 - elif not package: - weight = picking.shipping_weight - else: - weight = package.shipping_weight or package.weight - weight = self._stamps_convert_weight(weight) - - shipper = self.get_shipper_warehouse(order=order, picking=picking) - recipient = self.get_recipient(order=order, picking=picking) - - if not all((shipper.zip, recipient.zip)): - raise ValidationError(_('Stamps needs ZIP. From: "%s" To: "%s"', - shipper.zip, - recipient.zip)) - - ret_val = service.create_shipping() - ret_val.ShipDate = date_planned.strftime('%Y-%m-%d') if date_planned else date.today().isoformat() - ret_val.From = self._stamps_address(service, shipper) - ret_val.To = self._stamps_address(service, recipient) - ret_val.PackageType = self._stamps_package_type(package=package) - ret_val.WeightLb = weight - ret_val.ContentType = 'Merchandise' - return ret_val - - def _stamps_get_addresses_for_picking(self, picking): - company = self.get_shipper_company(picking=picking) - from_ = self.get_shipper_warehouse(picking=picking) - to = self.get_recipient(picking=picking) - 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): - ret = [] - company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking) - if not all((from_partner.zip, to_partner.zip)): - raise ValidationError(_('Stamps needs ZIP. From: "%s" To: "%s"', - from_partner.zip, - to_partner.zip)) - - 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) - - for package in picking_packages: - weight = self._stamps_convert_weight(package.shipping_weight) - l, w, h = self._stamps_package_dimensions(package=package) - - ret_val = service.create_shipping() - ret_val.ShipDate = date.today().isoformat() - ret_val.From = self._stamps_address(service, from_partner) - ret_val.To = self._stamps_address(service, to_partner) - ret_val.PackageType = self._stamps_package_type(package=package) - ret_val.CubicPricing = self._stamps_package_is_cubic_pricing(package=package) - ret_val.Length = l - ret_val.Width = w - ret_val.Height = h - ret_val.ServiceType = self.stamps_service_type - ret_val.WeightLb = weight - ret_val.ContentType = self._stamps_content_type(package=package) - ret.append((package.name + ret_val.ShipDate + str(ret_val.WeightLb) + self._stamps_hash_partner(to_partner), ret_val)) - if not ret and not package_carriers: - weight = self._stamps_convert_weight(picking.shipping_weight) - l, w, h = self._stamps_package_dimensions() - - ret_val = service.create_shipping() - ret_val.ShipDate = date.today().isoformat() - ret_val.From = self._stamps_address(service, from_partner) - ret_val.To = self._stamps_address(service, to_partner) - ret_val.PackageType = self._stamps_package_type() - ret_val.CubicPricing = self._stamps_package_is_cubic_pricing() - ret_val.Length = l - ret_val.Width = w - ret_val.Height = h - ret_val.ServiceType = self.stamps_service_type - ret_val.WeightLb = weight - ret_val.ContentType = self._stamps_content_type() - ret.append((picking.name + ret_val.ShipDate + str(ret_val.WeightLb) + self._stamps_hash_partner(to_partner), ret_val)) - - return ret - - def stamps_get_shipping_price_from_so(self, orders): - res = self.stamps_get_shipping_price_for_plan(orders, date.today().isoformat()) - return map(lambda r: r[0] if r else 0.0, res) - - def stamps_get_shipping_price_for_plan(self, orders, date_planned): - res = [] - service = self._get_stamps_service() - - for order in orders: - shipping = self._get_stamps_shipping_for_order(service, order, date_planned) - rates = service.get_rates(shipping) - if rates and len(rates) >= 1: - rate = rates[0] - price = float(rate.Amount) - - if order.currency_id.name != 'USD': - quote_currency = self.env['res.currency'].search([('name', '=', 'USD')], limit=1) - price = quote_currency.compute(rate.Amount, order.currency_id) - - delivery_days = rate.DeliverDays - if delivery_days.find('-') >= 0: - delivery_days = delivery_days.split('-') - transit_days = int(delivery_days[-1]) - else: - transit_days = int(delivery_days) - date_delivered = None - if date_planned and transit_days > 0: - date_delivered = self.calculate_date_delivered(date_planned, transit_days) - - res = res + [(price, transit_days, date_delivered)] - continue - res = res + [(0.0, 0, None)] - return res - - def stamps_rate_shipment(self, order): - self.ensure_one() - result = { - 'success': False, - 'price': 0.0, - 'error_message': _('Error Retrieving Response from Stamps.com'), - 'warning_message': False - } - date_planned = None - if self.env.context.get('date_planned'): - date_planned = self.env.context.get('date_planned') - rate = self.stamps_get_shipping_price_for_plan(order, date_planned) - if rate: - price, transit_time, date_delivered = rate[0] - result.update({ - 'success': True, - 'price': price, - 'error_message': False, - 'transit_time': transit_time, - 'date_delivered': date_delivered, - }) - return result - return result - - def _stamps_needs_customs(self, from_partner, to_partner, picking=None): - return from_partner.country_id.code != to_partner.country_id.code or \ - (to_partner.country_id.code == 'US' and to_partner.state_id.code in STAMPS_US_APO_FPO_STATE_CODES) - - def stamps_send_shipping(self, pickings): - res = [] - service = self._get_stamps_service() - had_customs = False - - for picking in pickings: - package_labels = [] - - shippings = self._stamps_get_shippings_for_picking(service, picking) - if not shippings: - continue - company, from_partner, to_partner = self._stamps_get_addresses_for_picking(picking) - - customs = None - if self._stamps_needs_customs(from_partner, to_partner, picking=picking): - customs = service.create_customs() - had_customs = bool(had_customs or customs) - - try: - for txn_id, shipping in shippings: - rates = service.get_rates(shipping) - if rates and len(rates) >= 1: - rate = rates[0] - shipping.Amount = rate.Amount - shipping.ServiceType = rate.ServiceType - shipping.DeliverDays = rate.DeliverDays - if hasattr(rate, 'DimWeighting'): - shipping.DimWeighting = rate.DimWeighting - shipping.RateCategory = rate.RateCategory - # shipping.ToState = rate.ToState - addons = [] - if self.stamps_addon_sc: - add_on = service.create_add_on() - add_on.AddOnType = 'US-A-SC' - 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() - if self.is_amazon(picking=picking): - extended_postage_info.bridgeProfileType = 'Amazon MWS' - - 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, - 'weight': 0.0, - } - product_values[product]['quantity'] += quantity - product_values[product]['value'] += price * quantity - product_values[product]['weight'] += self._stamps_convert_weight(product.weight * quantity) # not rounded so we can sum better.... - - # Note that Stamps must match customs weight to the shipment itself - # IF we just take the weight from the products, then we're wrong by the difference between shipping weight - # IF INSTEAD we want the shipping weight to be accurate, we can ratio the weights of the customs lines. - # e.g. shipping_weight = 5, customs_weight (2 items at 1lb and 3lb) = 4 - # to get to a shipping_weight of 5, the weights we will send will be (5/4) * 1lb and (5/4) * 3lb = 5 - shipment_weight = shipping.WeightLb - customs_total_weight = sum(round(v['weight'], 2) for k, v in product_values.items()) - if not all((shipment_weight, customs_total_weight)): - raise UserError(_('Must have a shipment and customs weight to proceed. (shipment_weight %s, customs_weight %s') % (shipment_weight, customs_total_weight)) - customs_lines = [] - new_total_weight = 0.0 - for product, values in product_values.items(): - line_weight_ratio = shipment_weight / customs_total_weight - 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']) * line_weight_ratio, 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) - # still set it, but it should be much closer to the original weight - shipping.WeightLb = round(new_total_weight, 2) - - label = service.get_label(shipping, - transaction_id=txn_id, image_type=self.stamps_image_type, - extended_postage_info=extended_postage_info, - customs=customs) - package_labels.append((txn_id, label)) - except WebFault as e: - _logger.warning(e) - if package_labels: - for name, label in package_labels: - body = _(u'Cancelling due to error: ', label.TrackingNumber) - try: - service.remove_label(label.TrackingNumber) - except WebFault as e: - raise ValidationError(e) - else: - picking.message_post(body=body) - raise ValidationError(_('Error on full shipment. Attempted to cancel any previously shipped.')) - raise ValidationError(_('Error on shipment. "%s"', e)) - else: - carrier_price = 0.0 - tracking_numbers = [] - for name, label in package_labels: - body = _(u'Shipment created into Stamps.com
Tracking Number :
"%s"
', label.TrackingNumber) - tracking_numbers.append(label.TrackingNumber) - carrier_price += float(label.Rate.Amount) - url = label.URL - - url_spaces = url.split(' ') - attachments = [] - for i, url in enumerate(url_spaces, 1): - response = urlopen(url) - attachment = response.read() - # Stamps.com sends labels that set the print rate (print speed) to 8 Inches per Second - # this is too fast for international/customs forms that have fine detail - # set it to the general minimum of 2IPS - if had_customs: - attachment = attachment.replace(b'^PR8,8,8\r\n', b'^PR2\r\n') - 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)} - res = res + [shipping_data] - return res - - def stamps_get_tracking_link(self, pickings): - res = [] - for picking in pickings: - ref = picking.carrier_tracking_ref - res = res + ['https://tools.usps.com/go/TrackConfirmAction_input?qtc_tLabels1=%s' % ref] - return res - - def stamps_cancel_shipment(self, picking): - service = self._get_stamps_service() - try: - 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.write({'carrier_tracking_ref': '', - 'carrier_price': 0.0}) - except WebFault as e: - raise ValidationError(e) - - def stamps_rate_shipment_multi(self, order=None, picking=None, packages=None): - if not packages: - return self._stamps_rate_shipment_multi_package(order=order, picking=picking) - else: - rates = [] - for package in packages: - rates += self._stamps_rate_shipment_multi_package(order=order, picking=picking, package=package) - return rates - - def _stamps_rate_shipment_multi_package(self, order=None, picking=None, package=None): - self.ensure_one() - date_planned = fields.Datetime.now() - if self.env.context.get('date_planned'): - date_planned = self.env.context.get('date_planned') - res = [] - service = self._get_stamps_service() - shipping = self._get_stamps_shipping_multi(service, date_planned, order=order, picking=picking, package=package) - rates = service.get_rates(shipping) - for rate in rates: - price = float(rate.Amount) - if order: - currency = order.currency_id - else: - currency = picking.sale_id.currency_id if picking.sale_id else picking.company_id.currency_id - if currency.name != 'USD': - quote_currency = self.env['res.currency'].search([('name', '=', 'USD')], limit=1) - price = quote_currency.compute(rate.Amount, currency) - - delivery_days = rate.DeliverDays - if delivery_days.find('-') >= 0: - delivery_days = delivery_days.split('-') - transit_days = int(delivery_days[-1]) - else: - transit_days = int(delivery_days) - date_delivered = None - if transit_days > 0: - date_delivered = self.calculate_date_delivered(date_planned, transit_days) - service_code = rate.ServiceType - carrier = self.stamps_find_delivery_carrier_for_service(service_code) - if carrier: - res.append({ - 'carrier': carrier, - 'package': package or self.env['stock.quant.package'].browse(), - 'success': True, - 'price': price, - 'error_message': False, - 'warning_message': False, - 'transit_days': transit_days, - 'date_delivered': date_delivered, - 'date_planned': date_planned, - 'service_code': service_code, - }) - if not res: - res.append({ - 'success': False, - 'price': 0.0, - 'error_message': _('No valid rates returned from Stamps.com'), - 'warning_message': False - }) - return res - - def stamps_find_delivery_carrier_for_service(self, service_code): - if self.stamps_service_type == service_code: - return self - # arbitrary decision, lets find the same user name - carrier = self.search([('stamps_username', '=', self.stamps_username), - ('stamps_service_type', '=', service_code) - ], limit=1) - return carrier diff --git a/delivery_stamps/views/delivery_stamps_view.xml b/delivery_stamps/views/delivery_stamps_view.xml deleted file mode 100644 index 90dcc20a..00000000 --- a/delivery_stamps/views/delivery_stamps_view.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - delivery.carrier.form.provider.stamps - delivery.carrier - - - - - - - - - - - - - - - - - - - - - - - - - stamps.stock.package.type.form.delivery - stock.package.type - - - - - - - - -