def label(self, package, shipper, recipient, customs=None, image_format="PNG"): shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) shipment = self._prepare_request(FedexProcessShipmentRequest(self.config), shipper, recipient, package) shipment.RequestedShipment.ServiceType = package.mail_class shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = self.config.account_number # Specifies the label type to be returned. # LABEL_DATA_ONLY or COMMON2D shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D' # Specifies which format the label file will be sent to you in. # DPL, EPL2, PDF, PNG, ZPLII shipment.RequestedShipment.LabelSpecification.ImageType = image_format shipment.RequestedShipment.LabelSpecification.LabelStockType = 'STOCK_4X6' if image_format == 'EPL2' else 'PAPER_4X6' shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' if customs: customs_label = shipment.create_wsdl_object_of_type('AdditionalLabelsDetail') customs_label.Type = 'CUSTOMS' customs_label.Count = 1 shipment.AdditionalLabels.append(customs_label) wsdl_customs = shipment.create_wsdl_object_of_type('CustomsClearanceDetail') wsdl_customs.CustomsValue = shipment.create_wsdl_object_of_type('Money') wsdl_customs.CustomsValue.Currency = 'USD' wsdl_customs.CustomsValue.Amount = package.value for item in sorted(customs.items, key=lambda i: i.value, reverse=True): wsdl_item = shipment.create_wsdl_object_of_type('Commodity') wsdl_item.CustomsValue = shipment.create_wsdl_object_of_type('Money') wsdl_item.CustomsValue.Amount = item.value wsdl_item.CustomsValue.Currency = 'USD' wsdl_item.NumberOfPieces = item.quantity wsdl_item.CountryOfManufacture = item.country_of_origin wsdl_item.Description = item.description wsdl_item.Weight = round(item.weight, 2) wsdl_customs.Commodities.append(wsdl_item) shipment.CustomsClearanceDetail = wsdl_customs try: shipment.send_request() except Exception as e: return {"error": str(e)} tracking = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber net_cost = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].PackageRating.PackageRateDetails[0].NetCharge.Amount return Label( postage=net_cost, tracking=tracking, format=[image_format], label=[base64.b64decode(shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].Label.Parts[0].Image)] )
def rate(self, package, shipper, recipient, insurance='OFF', insurance_amount=0, delivery_confirmation=False, signature_confirmation=False): response = {'info': []} # Play nice with the other function signatures, which expect to take lists of packages. if not isinstance(package, Package): # But not too nice. if len(package) > 1: raise Exception("Can only take one Package at a time!") package = package[0] shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) rate_request = FedexRateServiceRequest(self.config) rate_request = self._prepare_request(rate_request, shipper, recipient, package) rate_request.RequestedShipment.ServiceType = None rate_request.RequestedShipment.EdtRequestType = 'NONE' rate_request.RequestedShipment.PackageDetail = 'INDIVIDUAL_PACKAGES' rate_request.RequestedShipment.ShippingChargesPayment.Payor.AccountNumber = self.config.account_number seen_quotes = [] try: rate_request.send_request() for service in rate_request.response.RateReplyDetails: for detail in service.RatedShipmentDetails: response['info'].append({ 'service': service.ServiceType, 'package': service.PackagingType, 'delivery_day': '', 'cost': float(detail.ShipmentRateDetail.TotalNetFedExCharge. Amount) }) except Exception as e: raise FedExError(e) return response
def rate(self, package, shipper, recipient, insurance='OFF', insurance_amount=0, delivery_confirmation=False, signature_confirmation=False): services = dict(SERVICES) # Play nice with the other function signatures, which expect to take lists of packages. if not isinstance(package, Package): # But not too nice. if len(package) > 1: raise Exception("Can only take one Package at a time!") package = package[0] shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) data = self.templates.get_template("RatingServiceSelectionRequest.mko").render( credentials=self.credentials, shipper=shipper, recipient=recipient, package=package ) try: httpresq = urllib2.Request(url=self.endpoints["rate"], data=data.encode('utf_8'), headers={'Content-Type': 'application/x-www-form-urlencoded'}) reply = etree.fromstring(urllib2.urlopen(httpresq).read()) response = { 'status': reply.find('Response/ResponseStatusDescription').text, 'info': list() } error = reply.find('Response/Error') if error is not None: #error_location = error.find("ErrorLocation") #error_xpath = error.find("ErrorLocationElementName") response["error"] = error.find("ErrorDescription").text #if error_location: # response["error_location"] = error_location.text #if error_xpath: # response["error_xpath"] = error_xpath.text raise UPSError(response["error"]) for details in reply.findall('RatedShipment'): service_code = details.find('Service/Code').text response['info'].append({ 'service': services.get(service_code, service_code), 'package': package.shape.name, 'delivery_day': '', 'cost': float(details.find('TotalCharges/MonetaryValue').text) }) return response except urllib2.URLError as e: raise UPSError(e)
def _add_address(self, address, type, root): info = dict() info['Company'] = address.company_name info['Name'] = address.name info['Address1'] = address.address1 info['City'] = address.city info['State'] = address.state info['PostalCode'] = address.zip info['CountryCode'] = get_country_code(address.country.upper()) if address.phone: info['Phone'] = re.sub( r'[^\d]+', '', address.phone) # Strip all non-digit characters. if address.address2: info['Address2'] = address.address2 for key, value in info.items(): # Endicia expects ReturnAddressX instead of FromAddressX if type == 'From' and 'Address' in key: element_key = 'Return%s' % key else: element_key = '%s%s' % (type, key) etree.SubElement(root, element_key).text = value
def rate(self, package, shipper, recipient, insurance='OFF', insurance_amount=0, delivery_confirmation=False, signature_confirmation=False): # Play nice with the other function signatures, which expect to take lists of packages. if not isinstance(package, Package): # But not too nice. if len(package) > 1: raise Exception("Can only take one Package at a time!") package = package[0] to_country_code = get_country_code(recipient.country) request = self.client.factory.create('PostageRatesRequest') request.RequesterID = self.credentials['partner_id'] request.CertifiedIntermediary.AccountID = self.credentials['account_id'] request.CertifiedIntermediary.PassPhrase = self.credentials['passphrase'] if package.shape: request.MailpieceShape = package.shape request.MailClass = 'Domestic' if to_country_code.upper() == 'US' else 'International' request.WeightOz = package.weight_in_ozs request.MailpieceDimensions.Length = package.length request.MailpieceDimensions.Width = package.width request.MailpieceDimensions.Height = package.height request.FromPostalCode = shipper.zip request.ToPostalCode = recipient.zip request.ToCountryCode = to_country_code request.CODAmount = 0 request.InsuredValue = insurance_amount request.RegisteredMailValue = package.value request.Services._InsuredMail = insurance if delivery_confirmation: request.Services._DeliveryConfirmation = 'ON' if signature_confirmation: request.Services._SignatureConfirmation = 'ON' try: reply = self.client.service.CalculatePostageRates(request) if reply.Status != 0: raise EndiciaError(reply.ErrorMessage) logger.debug(reply) response = { 'status': reply.Status, 'info': list() } for details in reply.PostagePrice: response['info'].append({ 'service': details.Postage.MailService, 'package': details.MailClass, 'delivery_day': '', 'cost': details._TotalAmount }) return response except suds.WebFault as e: raise EndiciaWebError(e.fault, e.document)
def rate(self, package, shipper, recipient, insurance='OFF', insurance_amount=0, delivery_confirmation=False, signature_confirmation=False): response = {'info': []} # Play nice with the other function signatures, which expect to take lists of packages. if not isinstance(package, Package): # But not too nice. if len(package) > 1: raise Exception("Can only take one Package at a time!") package = package[0] shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) rate_request = FedexRateServiceRequest(self.config) rate_request = self._prepare_request(rate_request, shipper, recipient, package) rate_request.RequestedShipment.ServiceType = None rate_request.RequestedShipment.EdtRequestType = 'NONE' rate_request.RequestedShipment.PackageDetail = 'INDIVIDUAL_PACKAGES' rate_request.RequestedShipment.ShippingChargesPayment.Payor.AccountNumber = self.config.account_number seen_quotes = [] try: rate_request.send_request() for service in rate_request.response.RateReplyDetails: for detail in service.RatedShipmentDetails: response['info'].append({ 'service': service.ServiceType, 'package': service.PackagingType, 'delivery_day': '', 'cost': float(detail.ShipmentRateDetail.TotalNetFedExCharge.Amount) }) except Exception as e: raise FedExError(e) return response
def _add_address(self, address, type, root): info = dict() info['Company'] = address.company_name info['Name'] = address.name info['Address1'] = address.address1 info['City'] = address.city info['State'] = address.state info['PostalCode'] = address.zip info['CountryCode'] = get_country_code(address.country.upper()) if address.phone: info['Phone'] = re.sub(r'[^\d]+', '', address.phone) # Strip all non-digit characters. if address.address2: info['Address2'] = address.address2 for key, value in info.items(): # Endicia expects ReturnAddressX instead of FromAddressX if type == 'From' and 'Address' in key: element_key = 'Return%s' % key else: element_key = '%s%s' % (type, key) etree.SubElement(root, element_key).text = value
def _get_xml(self): root = etree.Element('LabelRequest') root.set('LabelType', self.label_type) root.set('LabelSize', self.label_size) root.set('ImageFormat', self.image_format) if self.debug: root.set('Test', 'YES') etree.SubElement(root, u'RequesterID').text = self.partner_id etree.SubElement(root, u'AccountID').text = self.account_id etree.SubElement(root, u'PassPhrase').text = self.passphrase etree.SubElement(root, u'MailClass').text = self.package.mail_class etree.SubElement(root, u'WeightOz').text = self.package.weight_oz etree.SubElement(root, u'MailpieceShape').text = self.package.shape etree.SubElement(root, u'Stealth').text = self.stealth etree.SubElement(root, u'Value').text = self.package.value etree.SubElement(root, u'Description').text = self.package.description etree.SubElement(root, u'PartnerCustomerID').text = 'SomeCustomerID' etree.SubElement(root, u'PartnerTransactionID').text = 'SomeTransactionID' etree.SubElement(root, u'ResponseOptions').set('PostagePrice', 'TRUE') self._add_address(self.shipper, 'From', root) self._add_address(self.recipient, 'To', root) etree.SubElement(root, u'Stealth').text = self.stealth etree.SubElement(root, u'Value').text = str(self.value) etree.SubElement(root, u'InsuredValue').text = str(self.insurance_amount) etree.SubElement(root, u'DateAdvance').text = str(self.date_advance) services = etree.SubElement(root, u'Services') services.set(u'DeliveryConfirmation', self.delivery_confirmation) services.set(u'SignatureConfirmation', self.signature_confirmation) services.set(u'InsuredMail', self.insurance) if self.return_services: services.set(u'ReturnReceipt', "YES") dimensions = etree.SubElement(root, u'MailpieceDimensions') etree.SubElement(dimensions, u'Length').text = str(self.package.length) etree.SubElement(dimensions, u'Width').text = str(self.package.width) etree.SubElement(dimensions, u'Height').text = str(self.package.height) # Add customs info, including items. if self.customs: # Root-level customs fields. root.set('LabelSubtype', "Integrated") etree.SubElement( root, u'IntegratedFormType').text = self.customs.form_type etree.SubElement( root, u'CustomsSendersCopy' ).text = "TRUE" if self.customs.senders_copy else "FALSE" etree.SubElement( root, u'NonDeliveryOption').text = self.customs.undeliverable # CustomsInfo-level customs fields customs_info = etree.SubElement(root, u'CustomsInfo') etree.SubElement(customs_info, u'ContentsType').text = self.customs.contents_type etree.SubElement(customs_info, u'ContentsExplanation' ).text = self.customs.contents_explanation etree.SubElement(customs_info, u'NonDeliveryOption' ).text = self.customs.undeliverable or "Return" if self.customs.eel_pfc: etree.SubElement(customs_info, u'EelPfc').text = self.customs.eel_pfc if self.customs.restriction: etree.SubElement( customs_info, u'RestrictionType').text = self.customs.restriction etree.SubElement(customs_info, u'RestrictionComments' ).text = self.customs.restriction_comments # CustomsItems customs_items = etree.SubElement(customs_info, u'CustomsItems') for item in self.customs.items: customs_item = etree.SubElement(customs_items, u'CustomsItem') etree.SubElement(customs_item, u'Description').text = item.description etree.SubElement(customs_item, u'Quantity').text = item.quantity etree.SubElement(customs_item, u'Weight').text = item.weight etree.SubElement(customs_item, u'Value').text = item.value if hasattr(item, "country_of_origin") and item.country_of_origin: etree.SubElement( customs_item, u'CountryOfOrigin').text = get_country_code( item.country_of_origin) # Customs signature if self.customs and self.customs.signature: etree.SubElement(root, u'CustomsCertify').text = 'TRUE' etree.SubElement(root, u'CustomsSigner').text = self.customs.signature #from shipping import debug_print_tree #debug_print_tree(root) return root
def rate(self, package, shipper, recipient, insurance='OFF', insurance_amount=0, delivery_confirmation=False, signature_confirmation=False): # Play nice with the other function signatures, which expect to take lists of packages. if not isinstance(package, Package): # But not too nice. if len(package) > 1: raise Exception("Can only take one Package at a time!") package = package[0] to_country_code = get_country_code(recipient.country) request = self.client.factory.create('PostageRatesRequest') request.RequesterID = self.credentials['partner_id'] request.CertifiedIntermediary.AccountID = self.credentials[ 'account_id'] request.CertifiedIntermediary.PassPhrase = self.credentials[ 'passphrase'] if package.shape: request.MailpieceShape = package.shape request.MailClass = 'Domestic' if to_country_code.upper( ) == 'US' else 'International' request.WeightOz = package.weight_in_ozs request.MailpieceDimensions.Length = package.length request.MailpieceDimensions.Width = package.width request.MailpieceDimensions.Height = package.height request.FromPostalCode = shipper.zip request.ToPostalCode = recipient.zip request.ToCountryCode = to_country_code request.CODAmount = 0 request.InsuredValue = insurance_amount request.RegisteredMailValue = package.value request.Services._InsuredMail = insurance if delivery_confirmation: request.Services._DeliveryConfirmation = 'ON' if signature_confirmation: request.Services._SignatureConfirmation = 'ON' try: reply = self.client.service.CalculatePostageRates(request) if reply.Status != 0: raise EndiciaError(reply.ErrorMessage) logger.debug(reply) response = {'status': reply.Status, 'info': list()} for details in reply.PostagePrice: response['info'].append({ 'service': details.Postage.MailService, 'package': details.MailClass, 'delivery_day': '', 'cost': details._TotalAmount }) return response except suds.WebFault as e: raise EndiciaWebError(e.fault, e.document)
def _get_xml(self): root = etree.Element('LabelRequest') root.set('LabelType', self.label_type) root.set('LabelSize', self.label_size) root.set('ImageFormat', self.image_format) if self.debug: root.set('Test', 'YES') etree.SubElement(root, u'RequesterID').text = self.partner_id etree.SubElement(root, u'AccountID').text = self.account_id etree.SubElement(root, u'PassPhrase').text = self.passphrase etree.SubElement(root, u'MailClass').text = self.package.mail_class etree.SubElement(root, u'WeightOz').text = self.package.weight_oz etree.SubElement(root, u'MailpieceShape').text = self.package.shape etree.SubElement(root, u'Stealth').text = self.stealth etree.SubElement(root, u'Value').text = self.package.value etree.SubElement(root, u'Description').text = self.package.description etree.SubElement(root, u'PartnerCustomerID').text = 'SomeCustomerID' etree.SubElement(root, u'PartnerTransactionID').text = 'SomeTransactionID' etree.SubElement(root, u'ResponseOptions').set('PostagePrice', 'TRUE') self._add_address(self.shipper, 'From', root) self._add_address(self.recipient, 'To', root) etree.SubElement(root, u'Stealth').text = self.stealth etree.SubElement(root, u'Value').text = str(self.value) etree.SubElement(root, u'InsuredValue').text = str(self.insurance_amount) etree.SubElement(root, u'DateAdvance').text = str(self.date_advance) services = etree.SubElement(root, u'Services') services.set(u'DeliveryConfirmation', self.delivery_confirmation) services.set(u'SignatureConfirmation', self.signature_confirmation) services.set(u'InsuredMail', self.insurance) if self.return_services: services.set(u'ReturnReceipt', "YES") dimensions = etree.SubElement(root, u'MailpieceDimensions') etree.SubElement(dimensions, u'Length').text = str(self.package.length) etree.SubElement(dimensions, u'Width').text = str(self.package.width) etree.SubElement(dimensions, u'Height').text = str(self.package.height) # Add customs info, including items. if self.customs: # Root-level customs fields. root.set('LabelSubtype', "Integrated") etree.SubElement(root, u'IntegratedFormType').text = self.customs.form_type etree.SubElement(root, u'CustomsSendersCopy').text = "TRUE" if self.customs.senders_copy else "FALSE" etree.SubElement(root, u'NonDeliveryOption').text = self.customs.undeliverable # CustomsInfo-level customs fields customs_info = etree.SubElement(root, u'CustomsInfo') etree.SubElement(customs_info, u'ContentsType').text = self.customs.contents_type etree.SubElement(customs_info, u'ContentsExplanation').text = self.customs.contents_explanation etree.SubElement(customs_info, u'NonDeliveryOption').text = self.customs.undeliverable or "Return" if self.customs.eel_pfc: etree.SubElement(customs_info, u'EelPfc').text = self.customs.eel_pfc if self.customs.restriction: etree.SubElement(customs_info, u'RestrictionType').text = self.customs.restriction etree.SubElement(customs_info, u'RestrictionComments').text = self.customs.restriction_comments # CustomsItems customs_items = etree.SubElement(customs_info, u'CustomsItems') for item in self.customs.items: customs_item = etree.SubElement(customs_items, u'CustomsItem') etree.SubElement(customs_item, u'Description').text = item.description etree.SubElement(customs_item, u'Quantity').text = item.quantity etree.SubElement(customs_item, u'Weight').text = item.weight etree.SubElement(customs_item, u'Value').text = item.value if hasattr(item, "country_of_origin") and item.country_of_origin: etree.SubElement(customs_item, u'CountryOfOrigin').text = get_country_code(item.country_of_origin) # Customs signature if self.customs and self.customs.signature: etree.SubElement(root, u'CustomsCertify').text = 'TRUE' etree.SubElement(root, u'CustomsSigner').text = self.customs.signature #from shipping import debug_print_tree #debug_print_tree(root) return root
def label(self, package, shipper, recipient, customs=None, image_format="PNG"): shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) shipment = self._prepare_request( FedexProcessShipmentRequest(self.config), shipper, recipient, package) shipment.RequestedShipment.ServiceType = package.mail_class shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = self.config.account_number # Specifies the label type to be returned. # LABEL_DATA_ONLY or COMMON2D shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D' # Specifies which format the label file will be sent to you in. # DPL, EPL2, PDF, PNG, ZPLII shipment.RequestedShipment.LabelSpecification.ImageType = image_format shipment.RequestedShipment.LabelSpecification.LabelStockType = 'STOCK_4X6' if image_format == 'EPL2' else 'PAPER_4X6' shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' if customs: customs_label = shipment.create_wsdl_object_of_type( 'AdditionalLabelsDetail') customs_label.Type = 'CUSTOMS' customs_label.Count = 1 shipment.AdditionalLabels.append(customs_label) wsdl_customs = shipment.create_wsdl_object_of_type( 'CustomsClearanceDetail') wsdl_customs.CustomsValue = shipment.create_wsdl_object_of_type( 'Money') wsdl_customs.CustomsValue.Currency = 'USD' wsdl_customs.CustomsValue.Amount = package.value for item in sorted(customs.items, key=lambda i: i.value, reverse=True): wsdl_item = shipment.create_wsdl_object_of_type('Commodity') wsdl_item.CustomsValue = shipment.create_wsdl_object_of_type( 'Money') wsdl_item.CustomsValue.Amount = item.value wsdl_item.CustomsValue.Currency = 'USD' wsdl_item.NumberOfPieces = item.quantity wsdl_item.CountryOfManufacture = item.country_of_origin wsdl_item.Description = item.description wsdl_item.Weight = round(item.weight, 2) wsdl_customs.Commodities.append(wsdl_item) shipment.CustomsClearanceDetail = wsdl_customs try: shipment.send_request() except Exception as e: return {"error": str(e)} tracking = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0].TrackingIds[0].TrackingNumber net_cost = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0].PackageRating.PackageRateDetails[0].NetCharge.Amount return Label(postage=net_cost, tracking=tracking, format=[image_format], label=[ base64.b64decode( shipment.response.CompletedShipmentDetail. CompletedPackageDetails[0].Label.Parts[0].Image) ])
def __init__(self, description, quantity, weight, value, country): self._description = description self._quantity = quantity self._weight = weight self._value = value self._country = get_country_code(country)
def label(self, package, shipper, recipient, customs=None, image_format="EPL2"): shipper.country_code = get_country_code(shipper.country) recipient.country_code = get_country_code(recipient.country) invoice_date = datetime.date.today().strftime('%Y%m%d') data = self.templates.get_template("ShipmentConfirmRequest.mko").render( credentials=self.credentials, shipper=shipper, recipient=recipient, package=package, invoice_date=invoice_date, customs=customs, image_format=image_format ) httpresq = urllib2.Request(url=self.endpoints["confirm"], data=data.encode('utf_8'), headers={'Content-Type': 'application/x-www-form-urlencoded'}) reply = etree.fromstring(urllib2.urlopen(httpresq).read()) response = { 'status': reply.find('Response/ResponseStatusDescription').text, 'info': list() } error = reply.find('Response/Error') if error: error_location = error.find("ErrorLocation") error_xpath = error_location.find("ErrorLocationElementName") if error_location else error.find("ErrorLocationElementName") response["error"] = error.find("ErrorDescription").text if error_location: response["error_location"] = error_location.text if error_xpath: response["error_xpath"] = error_xpath.text return response data = self.templates.get_template("ShipmentAcceptRequest.mko").render( credentials=self.credentials, digest=reply.find('ShipmentDigest').text ) httpresq = urllib2.Request(url=self.endpoints["accept"], data=data.encode('utf_8'), headers={'Content-Type': 'application/x-www-form-urlencoded'}) reply = etree.fromstring(urllib2.urlopen(httpresq).read()) error = reply.find('Response/Error') if error: response = {} error_location = error.find("ErrorLocation") error_xpath = error.find("ErrorLocationElementName") response["error"] = error.find("ErrorDescription").text if error_location: response["error_location"] = error_location.text if error_xpath: response["error_xpath"] = error_xpath.text return response shipment = reply.find("ShipmentResults") label = Label( postage=shipment.find("ShipmentCharges/TotalCharges/MonetaryValue").text, shipment_id=shipment.find("ShipmentIdentificationNumber").text, tracking=shipment.find("PackageResults/TrackingNumber").text, label=[base64.b64decode(shipment.find("PackageResults/LabelImage/GraphicImage").text)], format=[shipment.find("PackageResults/LabelImage/LabelImageFormat/Code").text] ) # UPS truncates EPL2 to EPL. if label.format == "EPL": label.format = "EPL2" return label