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"])}
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 }