Example #1
0
    def get_quotes(self, cr, uid, pkg, sale_id=None, from_address=None, to_address=None, test=None, context=None):
        '''Returns a list of all shipping options'''

        # Return immediately if we're just checking endpoints.
        if test:
            return {
                'quotes': [{
                    "company": "USPS",
                    "service": "Dummy Service",
                    "price": 1.0
                }]
            }

        # Convert kilograms to pounds?
        if pkg['scale']['unit'] == "kilogram":
            pkg['scale']['weight'] = float(Decimal(pkg['scale']['weight']) * Decimal("2.2046"))
            pkg['scale']['unit'] = "pound"

        # Wrap our package dictionary so we can pass it safely to the USPS API.
        pkg = PackageWrapper(
            round(Decimal(pkg["scale"]["weight"])*16, 1), pkg["length"], pkg["width"], pkg["height"], pkg.get("value")
        )

        if sale_id:
            sale = self.pool.get("sale.order").browse(cr, uid, sale_id)
            usps_config = usps_api.get_config(cr, uid, sale=sale, context=context)
            ups_config = ups_api.get_config(cr, uid, sale=sale, context=context)
            fedex_config = fedex_api.get_config(cr, uid, sale=sale, context=context)
        else:
            sale = None
            usps_config = usps_api.get_config(cr, uid, context=context)
            ups_config = ups_api.get_config(cr, uid, context=context)
            fedex_config = fedex_api.get_config(cr, uid, sale=sale, context=context)

        if from_address:
            from_address = AddressWrapper(
                from_address['name'], from_address['street'], from_address['street2'],
                from_address['city'], from_address['state'], from_address['zip'], from_address['country'],
                from_address.get("phone")
            )
            
        if to_address:
            to_address = AddressWrapper(
                to_address['name'], to_address['street'], to_address['street2'],
                to_address['city'], to_address['state'], to_address['zip'], to_address['country'],
                to_address.get("phone")
            )

        try:
            company_id = self.pool.get("res.users").browse(cr, uid, uid).company_id.id
            logis_pool = self.pool.get("logistic.company")
            available_services = [company.ship_company_code.lower() for company in
                logis_pool.browse(cr, uid, logis_pool.search(cr, uid, [
                    '|', ("company_id", "=", company_id), ("company_id", "=", None)
                ]))]

            ups_quotes = [] if 'ups' not in available_services else ups_api.get_quotes(
                ups_config, pkg, sale=sale, from_address=from_address, to_address=to_address, test=test
            )

            usps_quotes = [] if 'usps' not in available_services else usps_api.get_quotes(
                usps_config, pkg, sale=sale, from_address=from_address, to_address=to_address, test=test
            )

            seen_fedex_quotes = []
            filtered_fedex_quotes = []

            fedex_quotes = [] if 'fedex' not in available_services else fedex_api.get_quotes(
                fedex_config, pkg, sale=sale, from_address=from_address, to_address=to_address, test=test
            )

            for fedex_quote in fedex_quotes:
                fedex_quote_key = '%s:%s' % (fedex_quote['service'], fedex_quote['price'])

                if fedex_quote_key in seen_fedex_quotes:
                    continue

                seen_fedex_quotes.append(fedex_quote_key)
                filtered_fedex_quotes.append(fedex_quote)

            for i, fedex_quote in enumerate(filtered_fedex_quotes):
                filtered_fedex_quotes[i]['service'] = ' '.join([
                    w[0].upper() + w[1:].lower() for w in filtered_fedex_quotes[i]['service'].split('_')
                ])

        except UPSError as e:
            return {"success": False, "error": "UPS: " + str(e)}

        except EndiciaError as e:
            return {"success": False, "error": "Endicia: " + str(e)}

        except FedExError as e:
            return {"success": False, "error": "FedEx: " + str(e)}

        except urllib2.URLError as e:
            raise e
            return {
                "success": False,
                "error": "Could not connect to Endicia!" + (" (%s)" % str(e) if str(e) else '')
            }

        return {'quotes': sorted(usps_quotes + ups_quotes + filtered_fedex_quotes, key=lambda x: x["price"])}
Example #2
0
    def get_label(self, cr, uid, package=None, package_id=None, from_address=None, to_address=None, shipping=None,
                  customs=None, test=None, context=None):
        '''Returns a base64-encoded EPL2 label'''

        # Return immediately if we're just checking endpoints.
        if test:
            return {'label': base64.b64encode("dummy label data")}

        if not package and not package_id:
            return {"error": "Cannot create label without a package!"}

        elif package:
            if package['scale']['unit'] == "kilogram":
                package['scale']['weight'] = float(
                    (Decimal(package['scale']['weight']) * Decimal("2.2046")).quantize(Decimal("1.00"))
                )
                package['scale']['unit'] = "pound"

            package = PackageWrapper(round(float(package["scale"]["weight"])*16, 1), package["length"],
                                 package["width"], package["height"], package.get("value"))
            picking = None

        elif package_id:
            package = self.pool.get("stock.packages").browse(cr, uid, package_id)
            picking = package.pick_id

        if from_address:
            from_address = AddressWrapper(
                from_address['name'], from_address['street'], from_address['street2'],
                from_address['city'], from_address['state'], from_address['zip'], from_address['country'],
                from_address.get("phone")
            )

        if to_address:
            to_address = AddressWrapper(
                to_address['name'], to_address['street'], to_address['street2'],
                to_address['city'], to_address['state'], to_address['zip'], to_address['country'],
                to_address.get("phone")
            )

         # Get the shipper and recipient addresses if all we have is the picking.
        if picking and not from_address:
            from_address = picking.company_id.partner_id
            from_address.state = from_address.state_id.code
            from_address.country = from_address.country_id.name
            from_address.zip = from_address.zip

        if picking and not to_address:
            to_address = picking.sale_id.partner_shipping_id or ''
            to_address.state = to_address.state_id.code
            to_address.country = to_address.country_id.name
            to_address.zip = to_address.zip
            to_address.is_residence = False

        # Grab customs info.
        customs_obj = None
        image_format = "EPL2"

        if to_address.country != from_address.country:
            if not customs:
                customs = {}

            company = self.pool.get("res.users").browse(cr, uid, uid).company_id

            if "items" not in customs:
                customs["items"] = [{
                    "description": company.customs_description,
                    "quantity": "1",
                    "weight": str(package.weight_in_ozs),
                    "value": str(package.value) or (str(package.decl_val) if hasattr(package, "decl_val") else None)
                }]

            customs_items = [CustomsItem(
                description=item.get("description") or company.customs_description,
                quantity=str(item.get("quantity") or "1"),
                weight=str(item.get("weight") or package.weight_in_ozs),
                value=str(item.get("value") or package.value) or (str(package.decl_val) if hasattr(package, "decl_val") else None),
                country_of_origin=get_country_code(item.get("country_of_origin") or from_address.country)
            ) for item in customs["items"]]

            customs_obj = Customs(
                signature=customs.get("signature") or company.customs_signature,
                contents_type=customs.get("contents_type") or company.customs_contents_type,
                contents_explanation=customs.get("explanation") or company.customs_explanation,
                commodity_code=customs.get("commodity_code") or company.customs_commodity_code,
                restriction=customs.get("restriction") or company.customs_restriction,
                restriction_comments=customs.get("restriction_comments") or company.customs_restriction_comments,
                undeliverable=customs.get("undeliverable") or company.customs_undeliverable,
                eel_pfc=customs.get("eel_pfc") or company.customs_eel_pfc,
                senders_copy=customs.get("senders_copy") or company.customs_senders_copy,
                items=customs_items
            )

        # Grab config info
        if shipping["company"] == "USPS":
            if customs_obj:
                image_format = "PNGMONOCHROME"

            if picking:
                usps_config = usps_api.get_config(cr, uid, sale=picking.sale_id, context=context)
            else:
                usps_config = usps_api.get_config(cr, uid, context=context)

            label = usps_api.get_label(usps_config, package, shipping["service"].replace(" ", ""),
                                       from_address=from_address, to_address=to_address, customs=customs_obj,
                                       test=test, image_format=image_format)

        elif shipping["company"] == "UPS":
            if picking:
                ups_config = ups_api.get_config(cr, uid, sale=picking.sale_id, context=context)
            else:
                ups_config = ups_api.get_config(cr, uid, context=context)

            services_dict = dict([(name, code) for (code, name) in UPS_SERVICES])
            label = ups_api.get_label(ups_config, package, services_dict.get(shipping["service"]),
                                      from_address=from_address, to_address=to_address, customs=customs_obj,
                                      test=test, image_format=image_format)

        elif shipping["company"] == "FedEx":
            image_format = "PNG"

            if picking:
                fedex_config = fedex_api.get_config(cr, uid, sale=picking.sale_id, context=context, test=test)
            else:
                fedex_config = fedex_api.get_config(cr, uid, context=context, test=test)

            #services_dict = dict([(name, code) for (code, name) in FEDEX_SERVICES])
            label = fedex_api.get_label(
                fedex_config, package, '_'.join([w.upper() for w in shipping["service"].split(' ')]),
                from_address=from_address, to_address=to_address, customs=customs_obj,
                test=test, image_format=image_format)

        else:
            return {"error": "Shipping company '%s' not recognized." % shipping['company']}

        if hasattr(label, "get") and label.get("error"):
            return {"error": label["error"]}

        if package_id:
            logis_pool = self.pool.get("logistic.company")
            company = self.pool.get("res.users").browse(cr, uid, uid).company_id
            shipping_company = logis_pool.browse(cr, uid, logis_pool.search(cr, uid, [
                ('ship_company_code', '=', shipping.get("company", "").lower()),
                '|', ("company_id", "=", company.id), ("company_id", "=", None)
            ]))

            if shipping_company and not hasattr(shipping_company, 'id') and len(shipping_company) == 1:
                shipping_company = shipping_company[0]

            if not shipping_company:
                return {"error": "Could not find logistic company!"}

            package_update = {
                "tracking_no": label.tracking, "shipping_company": shipping_company.id,
                "shipping_company_name": shipping.get("company"), "shipping_method": shipping["service"]
            }

            if hasattr(label, "shipment_id") and label.shipment_id:
                package_update['shipment_identific_no'] = label.shipment_id

            self.pool.get("stock.packages").write(cr, uid, package_id, package_update)


        # If we got something besides EPL2 data, convert it to EPL2 format before sending it client-side.
        if image_format != "EPL2":
            label = Label(
                label=image_to_epl2(label.label[0]), # Only interested in the first label right now.
                postage_balance=label.postage_balance if hasattr(label, "postage_balance") else label.postage
            )
        else:
            label = Label(
                label=label.label[0],
                postage_balance=label.postage_balance if hasattr(label, "postage_balance") else label.postage
            )

        return {
            'label': base64.b64encode(label.label),
            'format': "EPL2",
            'postage_balance': label.postage_balance
        }