def create_shipment_service(self, credentials, from_address_doc, to_address_doc, \ from_country_doc, to_country_doc, transporter_doc, contact_doc): from fedex.services.ship_service import FedexProcessShipmentRequest customer_transaction_id = self.name # Optional transaction_id shipment = FedexProcessShipmentRequest(credentials, \ customer_transaction_id=customer_transaction_id) self.set_shipment_details(shipment, credentials, transporter_doc) shipper_details = self.set_shipper_info(shipment, from_address_doc, credentials) recipient_details = self.set_recipient_info(shipment, to_address_doc, credentials) self.set_fedex_label_info(shipment) self.set_commodities_info(self, shipment) self.set_commercial_invoice_info(shipment) #self.set_email_notification(shipment, from_address_doc, to_address_doc, contact_doc) pkg_count = self.total_handling_units for index, pkg in enumerate(self.shipment_package_details): pkg_doc = frappe.get_doc("Shipment Package", pkg.shipment_package) if index: shipment.RequestedShipment.MasterTrackingId.TrackingNumber = self.awb_number shipment.RequestedShipment.MasterTrackingId.TrackingIdType.value = \ transporter_doc.type_of_service self.set_package_data(pkg, pkg_doc, shipment, index + 1) else: shipment.RequestedShipment.TotalWeight.Units = self.uom_mapper.get( self.weight_uom) shipment.RequestedShipment.TotalWeight.Value = self.total_weight self.set_package_data(pkg, pkg_doc, shipment, index + 1) shipment.send_validation_request() shipment.send_request() self.validate_fedex_shipping_response(shipment, pkg.idx) tracking_id = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0].TrackingIds[0].TrackingNumber if index == 0: self.awb_number = tracking_id self.status = "Booked" self.set_package_details(pkg, cstr(shipment.response), tracking_id) self.store_label(self, shipment, tracking_id, self.doctype, self.name) self.save() return shipment
def create_shipment_service(self, credentials, from_address_doc, to_address_doc, \ from_country_doc, to_country_doc, transporter_doc, contact_doc): from fedex.services.ship_service import FedexProcessShipmentRequest customer_transaction_id = self.name # Optional transaction_id shipment = FedexProcessShipmentRequest(credentials, \ customer_transaction_id=customer_transaction_id) self.set_shipment_details(shipment, credentials, transporter_doc) shipper_details = self.set_shipper_info(shipment, from_address_doc, credentials) recipient_details = self.set_recipient_info(shipment, to_address_doc, credentials) self.set_fedex_label_info(shipment) self.set_commodities_info(self, shipment) self.set_commercial_invoice_info(shipment) #self.set_email_notification(shipment, from_address_doc, to_address_doc, contact_doc) pkg_count = self.total_handling_units for index, pkg in enumerate(self.shipment_package_details): pkg_doc = frappe.get_doc("Shipment Package", pkg.shipment_package) if index: shipment.RequestedShipment.MasterTrackingId.TrackingNumber = self.awb_number shipment.RequestedShipment.MasterTrackingId.TrackingIdType.value = \ transporter_doc.type_of_service self.set_package_data(pkg, pkg_doc, shipment, index + 1) else: shipment.RequestedShipment.TotalWeight.Units = self.uom_mapper.get(self.weight_uom) shipment.RequestedShipment.TotalWeight.Value = self.total_weight self.set_package_data(pkg, pkg_doc, shipment, index + 1) shipment.send_validation_request() shipment.send_request() self.validate_fedex_shipping_response(shipment, pkg.idx) tracking_id = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber if index == 0: self.awb_number = tracking_id self.status = "Booked" self.set_package_details(pkg, cstr(shipment.response), tracking_id) self.store_label(self, shipment, tracking_id, self.doctype, self.name) self.save() return shipment
def process_ship(self,cr, uid, ids, context=None): do = self.browse(cr, uid, type(ids)==type([]) and ids[0] or ids, context=context) user = self.pool.get('res.users').browse(cr, uid, uid, context=context) print do.ship_company_code if do.ship_company_code != 'fedex': return super(stock_picking, self).process_ship(cr, uid, ids, context=context) if not (do.logis_company and do.logis_company.ship_company_code=='fedex'): return super(stock_picking, self).process_ship(cr, uid, ids, context=context) from fedex.config import FedexConfig config_obj = FedexConfig(key=do.logis_company.fedex_key, password=do.logis_company.fedex_password, account_number=do.logis_company.fedex_account_number, meter_number=do.logis_company.fedex_meter_number, use_test_server=do.logis_company.test_mode) from fedex.services.ship_service import FedexProcessShipmentRequest #=============================================================================== # shipment = FedexProcessShipmentRequest(config_obj) # # # # shipment.RequestedShipment.DropoffType = do.fedex_dropoff_type # shipment.RequestedShipment.ServiceType = do.fedex_service_type # shipment.RequestedShipment.PackagingType = do.fedex_packaging_type # shipment.RequestedShipment.PackageDetail= do.fedex_package_detail # # # Shipper contact info. # shipment.RequestedShipment.Shipper.Contact.PersonName = user.name # #@todo: check the which module add the company to do and add module dependancy # shipment.RequestedShipment.Shipper.Contact.CompanyName = do.company_id.name # shipment.RequestedShipment.Shipper.Contact.PhoneNumber = user.address_id and user.address_id.phone or '' # # # Shipper address. # #@todo: check the address should have value and type is browse object # address = do.company_id.partner_id.address and do.company_id.partner_id.address[0] or '' # # shipment.RequestedShipment.Shipper.Address.StreetLines = [address.street, address.street2] # shipment.RequestedShipment.Shipper.Address.City = address.city # shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = address.state_id and address.state_id.code or '' # # #@tod : check which module added zip_id and add module dependancy # # #shipment.RequestedShipment.Shipper.Address.PostalCode = address.zip # shipment.RequestedShipment.Shipper.Address.PostalCode = address.zip_id and address.zip_id.zipcode # shipment.RequestedShipment.Shipper.Address.CountryCode = address.country_id and address.country_id.code or '' # shipment.RequestedShipment.Shipper.Address.Residential = True # # # #@todo: Confirm address should have value, else raise error # address=do.address_id # # Recipient contact info. # shipment.RequestedShipment.Recipient.Contact.PersonName = address.partner_id and address.partner_id.name or '' # shipment.RequestedShipment.Recipient.Contact.CompanyName = address.partner_id and address.partner_id.name or '' # shipment.RequestedShipment.Recipient.Contact.PhoneNumber = address.phone or address.mobile or '' # # # Recipient address # shipment.RequestedShipment.Recipient.Address.StreetLines = [address.street, address.street2] # shipment.RequestedShipment.Recipient.Address.City = address.city # shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = address.state_id and address.state_id.code or '' # # #@todo : zip_id and zip : # shipment.RequestedShipment.Recipient.Address.PostalCode = address.zip_id and address.zip_id.zipcode # shipment.RequestedShipment.Recipient.Address.CountryCode = address.country_id and address.country_id.code or '' # # This is needed to ensure an accurate rate quote with the response. # shipment.RequestedShipment.Recipient.Address.Residential = True # # # Who pays for the shipment? # # RECIPIENT, SENDER or THIRD_PARTY # shipment.RequestedShipment.ShippingChargesPayment.PaymentType = do.fedex_payment_type # # # 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 = 'PNG' # # # To use doctab stocks, you must change ImageType above to one of the # # label printer formats (ZPLII, EPL2, DPL). # # See documentation for paper types, there quite a few. # shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_4X6' # # # This indicates if the top or bottom of the label comes out of the # # printer first. # # BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST # shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' # # #=============================================================================== if do.packages_ids: str_error = '' ship_message = '' for pack in do.packages_ids: #@todo: If package already have Tracking no then don't process. shipment = FedexProcessShipmentRequest(config_obj) shipment.RequestedShipment.DropoffType = do.fedex_dropoff_type #@todo: Depending upon the Service type some of shipment.RequestedShipment.ServiceType = do.fedex_service_type shipment.RequestedShipment.PackagingType = do.fedex_packaging_type shipment.RequestedShipment.PackageDetail= do.fedex_package_detail # Shipper contact info. shipment.RequestedShipment.Shipper.Contact.PersonName = user.name #@todo: check the which module add the company to do and add module dependancy shipment.RequestedShipment.Shipper.Contact.CompanyName = do.company_id.name shipment.RequestedShipment.Shipper.Contact.PhoneNumber = user.address_id and user.address_id.phone or '' # Shipper address. #@todo: check the address should have value and type is browse object address = do.company_id.partner_id.address and do.company_id.partner_id.address[0] or '' shipment.RequestedShipment.Shipper.Address.StreetLines = [address.street or '', address.street2 or ''] shipment.RequestedShipment.Shipper.Address.City = address.city or '' shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = address.state_id and address.state_id.code or '' #@tod : check which module added zip_id and add module dependancy #shipment.RequestedShipment.Shipper.Address.PostalCode = address.zip shipment.RequestedShipment.Shipper.Address.PostalCode = address.zip_id and address.zip_id.zipcode shipment.RequestedShipment.Shipper.Address.CountryCode = address.country_id and address.country_id.code or '' shipment.RequestedShipment.Shipper.Address.Residential = False #@todo: Confirm address should have value, else raise error address=do.address_id # Recipient contact info. shipment.RequestedShipment.Recipient.Contact.PersonName = address.name or '' shipment.RequestedShipment.Recipient.Contact.CompanyName = address.partner_id and address.partner_id.name or '' shipment.RequestedShipment.Recipient.Contact.PhoneNumber = address.phone or address.mobile or '' # Recipient address shipment.RequestedShipment.Recipient.Address.StreetLines = [address.street or '', address.street2 or ''] shipment.RequestedShipment.Recipient.Address.City = address.city or '' shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = address.state_id and address.state_id.code or '' #@todo : zip_id and zip : shipment.RequestedShipment.Recipient.Address.PostalCode = address.zip_id and address.zip_id.zipcode or '' shipment.RequestedShipment.Recipient.Address.CountryCode = address.country_id and address.country_id.code or '' # This is needed to ensure an accurate rate quote with the response. shipment.RequestedShipment.Recipient.Address.Residential = False # Who pays for the shipment? # RECIPIENT, SENDER or THIRD_PARTY shipment.RequestedShipment.ShippingChargesPayment.PaymentType = do.fedex_payment_type # 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 = 'PNG' # To use doctab stocks, you must change ImageType above to one of the # label printer formats (ZPLII, EPL2, DPL). # See documentation for paper types, there quite a few. shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_4X8' # This indicates if the top or bottom of the label comes out of the # printer first. # BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' package_weight = shipment.create_wsdl_object_of_type('Weight') # Weight, in pounds. package_weight.Value = pack.weight package_weight.Units = "LB" package = shipment.create_wsdl_object_of_type('RequestedPackageLineItem') package.Weight = package_weight shipment.add_package(package) #Create package #Call Print Labels #print "Shipment SEND VALIDATIOIN REQUEST : ", shipment.send_validation_request() #x try: #print "Shipment : " #print shipment.RequestedShipment shipment.send_request() shipment.response.HighestSeverity print "Shipment Response" print shipment.response # Getting the tracking number from the new shipment. tracking_no = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber # Net shipping costs. ascii_label_data = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].Label.Parts[0].Image logo = binascii.b2a_base64(str(b64decode(ascii_label_data))) #@todo : if payment type is not SENDER ( may if Recipeint or THIRD PARTY ) the PackageRating will not present in response, so the next line will be error shipping_cost = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].PackageRating.PackageRateDetails[0].NetCharge.Amount #@todo: There is a lot of dfferent rates will present in response, need to clarify it. self.pool.get('stock.packages').write(cr, uid, pack.id, { 'logo': logo, 'negotiated_rates' : shipping_cost, 'tracking_no' : tracking_no, 'ship_message' : shipment.response.HighestSeverity }, context=context) except Exception, e: print "ERROR : ", e str_error = str_error + str(e) #raise osv.except_osv(_('Error'), _('%s' % (e))) if str_error: #@todo : if some package lines are process successfully and some other failed then now the status will show error. # it need cancell all other succeeded shipment and show error msg. # or show appropriate msg for each and every packages . #@attention: Must cancel other entris or should check the Tracking no befor doing the process, instead of creating new at everytime. self.write(cr, uid, do.id, {'ship_message': str_error}, context=context) else : self.write(cr, uid, do.id, {'ship_state':'ready_pick','ship_message': 'Shipment has been processed.'}, context=context) return { 'type': 'ir.actions.report.xml', 'report_name':'multiple.label.print', 'datas': { 'model':'stock.picking', 'id': ids and ids[0] or False, 'ids': ids and ids or [], 'report_type': 'pdf' }, 'nodestroy': True }
def test_create_delete_shipment(self): shipment = FedexProcessShipmentRequest(CONFIG_OBJ) shipment.RequestedShipment.DropoffType = 'REGULAR_PICKUP' shipment.RequestedShipment.ServiceType = 'FEDEX_GROUND' shipment.RequestedShipment.PackagingType = 'YOUR_PACKAGING' shipment.RequestedShipment.Shipper.Contact.PersonName = 'Sender Name' shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '9012638716' shipment.RequestedShipment.Shipper.Address.StreetLines = [ 'Address Line 1' ] shipment.RequestedShipment.Shipper.Address.City = 'Herndon' shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = 'VA' shipment.RequestedShipment.Shipper.Address.PostalCode = '20171' shipment.RequestedShipment.Shipper.Address.CountryCode = 'US' shipment.RequestedShipment.Recipient.Contact.PersonName = 'Recipient Name' shipment.RequestedShipment.Recipient.Contact.PhoneNumber = '9012637906' shipment.RequestedShipment.Recipient.Address.StreetLines = [ 'Address Line 1' ] shipment.RequestedShipment.Recipient.Address.City = 'Herndon' shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'VA' shipment.RequestedShipment.Recipient.Address.PostalCode = '20171' shipment.RequestedShipment.Recipient.Address.CountryCode = 'US' shipment.RequestedShipment.EdtRequestType = 'NONE' shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber \ = CONFIG_OBJ.account_number shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER' shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D' shipment.RequestedShipment.LabelSpecification.ImageType = 'PNG' shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_7X4.75' shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' # Use order if setting multiple labels or delete del shipment.RequestedShipment.LabelSpecification.LabelOrder package1_weight = shipment.create_wsdl_object_of_type('Weight') package1_weight.Value = 2.0 package1_weight.Units = "LB" package1 = shipment.create_wsdl_object_of_type( 'RequestedPackageLineItem') package1.PhysicalPackaging = 'ENVELOPE' package1.Weight = package1_weight shipment.add_package(package1) shipment.send_validation_request() shipment.send_request() assert shipment.response assert shipment.response.HighestSeverity in ['SUCCESS', 'WARNING'] track_id = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0].TrackingIds[0].TrackingNumber assert track_id del_shipment = FedexDeleteShipmentRequest(CONFIG_OBJ) del_shipment.DeletionControlType = "DELETE_ALL_PACKAGES" del_shipment.TrackingId.TrackingNumber = track_id del_shipment.TrackingId.TrackingIdType = 'EXPRESS' del_shipment.send_request() assert del_shipment.response
# Senders account information shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number # Label config. transfer_config_dict(shipment.RequestedShipment.LabelSpecification, LABEL_SPECIFICATION) package1_weight = shipment.create_wsdl_object_of_type('Weight') package1_weight.Value = 1.0 package1_weight.Units = "LB" package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem') package1.Weight = package1_weight shipment.add_package(package1) if __name__ == "__main__": shipment.send_request() device = LabelPrinterClass(shipment) device.print_label() shipment.RequestedShipment.Recipient.Address.StreetLines = ['456 Peach St'] shipment.RequestedShipment.Recipient.Address.City = 'Atlanta' shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'GA' shipment.RequestedShipment.Recipient.Address.PostalCode = '30303' shipment.RequestedShipment.Recipient.Address.CountryCode = 'US' shipment.send_request() device = LabelPrinterClass(shipment) device.print_label() shipment.RequestedShipment.Recipient.Address.StreetLines = ['987 Main St'] shipment.RequestedShipment.Recipient.Address.City = 'Boston'
def fedex_get_label(self, picking, data): GENERATE_IMAGE_TYPE = 'PDF' CONFIG_OBJ = FedexConfig(key=self.fedex_developer_key, password=self.fedex_developer_password, account_number=self.fedex_account_number, meter_number=self.fedex_meter_number, use_test_server=True if self.fedex_environment == 'test' else False) shipment = FedexProcessShipmentRequest( CONFIG_OBJ, customer_transaction_id="Label for %s" % picking.name) # REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER or STATION shipment.RequestedShipment.DropoffType = 'REGULAR_PICKUP' # See page 355 in WS_ShipService.pdf for a full list. Here are the common ones: # STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, FEDEX_EXPRESS_SAVER, # FEDEX_2_DAY, INTERNATIONAL_PRIORITY, SAME_DAY, INTERNATIONAL_ECONOMY # shipment.RequestedShipment.ServiceType = data['serviceCode'].upper() # TODO mapping SS and FedEx shipment.RequestedShipment.ServiceType = data['fedex_code'] # FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, FEDEX_ENVELOPE shipment.RequestedShipment.PackagingType = 'YOUR_PACKAGING' # Shipper contact info. # shipment.RequestedShipment.Shipper.Contact.PersonName = 'Sender Name' shipment.RequestedShipment.Shipper.Contact.CompanyName = 'Vertical4' shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '3136408402' # Shipper address. shipment.RequestedShipment.Shipper.Address.StreetLines = '15004 3rd Ave' shipment.RequestedShipment.Shipper.Address.City = 'Highland Park' shipment.RequestedShipment.Shipper.Address.PostalCode = '48203-3718' shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = 'MI' shipment.RequestedShipment.Shipper.Address.CountryCode = 'US' # Recipient contact info. shipment.RequestedShipment.Recipient.Contact.PersonName = data[ 'shipTo']['name'] # shipment.RequestedShipment.Recipient.Contact.CompanyName = shipment.RequestedShipment.Recipient.Contact.PhoneNumber = data[ 'shipTo']['phone'] # Recipient address shipment.RequestedShipment.Recipient.Address.StreetLines = picking.partner_id.street shipment.RequestedShipment.Recipient.Address.City = data['shipTo'][ 'city'] shipment.RequestedShipment.Recipient.Address.PostalCode = data[ 'shipTo']['postalCode'] shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = data[ 'shipTo']['state'] shipment.RequestedShipment.Recipient.Address.CountryCode = data[ 'shipTo']['country'] shipment.RequestedShipment.Recipient.Address.Residential = picking.residential # shipment.RequestedShipment.Recipient.Address.Residential = False # This is needed to ensure an accurate rate quote with the response. Use AddressValidation to get ResidentialStatus # shipment.RequestedShipment.Recipient.Address.Residential = True shipment.RequestedShipment.EdtRequestType = 'NONE' # Senders account information shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number # Who pays for the shipment? # RECIPIENT, SENDER or THIRD_PARTY shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER' # 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 = GENERATE_IMAGE_TYPE # To use doctab stocks, you must change ImageType above to one of the # label printer formats (ZPLII, EPL2, DPL). # See documentation for paper types, there quite a few. shipment.RequestedShipment.LabelSpecification.LabelStockType = 'STOCK_4X6' # This indicates if the top or bottom of the label comes out of the # printer first. # BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST # Timestamp in YYYY-MM-DDThh:mm:ss format, e.g. 2002-05-30T09:00:00 shipment.RequestedShipment.ShipTimestamp = datetime.now().replace( microsecond=0).isoformat() # BOTTOM_EDGE_OF_TEXT_FIRST, TOP_EDGE_OF_TEXT_FIRST shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'TOP_EDGE_OF_TEXT_FIRST' # Delete the flags we don't want. # Can be SHIPPING_LABEL_FIRST, SHIPPING_LABEL_LAST or delete if hasattr(shipment.RequestedShipment.LabelSpecification, 'LabelOrder'): del shipment.RequestedShipment.LabelSpecification.LabelOrder # Delete, not using. package1_weight = shipment.create_wsdl_object_of_type('Weight') package1_weight.Value = int(data['weight']['value']) package1_weight.Units = "LB" package1_dimensions = shipment.create_wsdl_object_of_type('Dimensions') package1_dimensions.Length = int(data['dimensions']['length']) package1_dimensions.Width = int(data['dimensions']['width']) package1_dimensions.Height = int(data['dimensions']['height']) package1_dimensions.Units = 'IN' package1 = shipment.create_wsdl_object_of_type( 'RequestedPackageLineItem') package1.Weight = package1_weight package1.Dimensions = package1_dimensions package1.PhysicalPackaging = 'BOX' package1.GroupPackageCount = 1 customer_reference = shipment.create_wsdl_object_of_type( 'CustomerReference') customer_reference.CustomerReferenceType = 'CUSTOMER_REFERENCE' customer_reference.Value = picking.origin package1.CustomerReferences.append(customer_reference) # Add a signature option for the package using SpecialServicesRequested or comment out. # SpecialServiceTypes can be APPOINTMENT_DELIVERY, COD, DANGEROUS_GOODS, DRY_ICE, SIGNATURE_OPTION etc.. # package1.SpecialServicesRequested.SpecialServiceTypes = 'SIGNATURE_OPTION' # SignatureOptionType can be ADULT, DIRECT, INDIRECT, NO_SIGNATURE_REQUIRED, SERVICE_DEFAULT # package1.SpecialServicesRequested.SignatureOptionDetail.OptionType = 'SERVICE_DEFAULT' shipment.add_package(package1) shipment.send_request() # This will convert the response to a python dict object. To # make it easier to work with. Also see basic_sobject_to_dict, it's faster but lacks options. response_dict = sobject_to_dict(shipment.response) response_dict['CompletedShipmentDetail']['CompletedPackageDetails'][0][ 'Label']['Parts'][0]['Image'] = '' print(response_dict) # Image is empty string for display purposes. # Here is the overall end result of the query. print("HighestSeverity: {}".format(shipment.response.HighestSeverity)) # Getting the tracking number from the new shipment. print("Tracking #: {}" "".format( shipment.response.CompletedShipmentDetail. CompletedPackageDetails[0].TrackingIds[0].TrackingNumber)) # Net shipping costs. Only show if available. Sometimes sandbox will not include this in the response. CompletedPackageDetails = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0] if hasattr(CompletedPackageDetails, 'PackageRating'): print("Net Shipping Cost (US$): {}" "".format(CompletedPackageDetails.PackageRating. PackageRateDetails[0].NetCharge.Amount)) else: print('WARNING: Unable to get shipping rate.') ascii_label_data = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0].Label.Parts[0].Image label_binary_data = binascii.a2b_base64(ascii_label_data) out_path = '/var/tmp/example_shipment_label.%s' % GENERATE_IMAGE_TYPE.lower( ) print("Writing to file {}".format(out_path)) out_file = open(out_path, 'wb') out_file.write(label_binary_data) out_file.close() result = { 'trackingNumber': shipment.response.CompletedShipmentDetail. CompletedPackageDetails[0].TrackingIds[0].TrackingNumber, 'voided': False, 'shipmentId': '', 'labelData': ascii_label_data } return result
def fedex_send_shipping(self, pickings): try: result = { 'exact_price': 0, 'weight': 0, 'date_delivery': None, 'tracking_number': '', 'attachments': [] } packaging_ids = self.wk_group_by_packaging(pickings=pickings) MasterTrackingIds = dict() product_uom_obj = self.env['uom.uom'] currency_id = pickings.sale_id.currency_id and pickings.sale_id.currency_id or pickings.company_id.currency_id total_package = 0 for packaging_id, package_ids in packaging_ids.items(): self.wk_validate_data(pickings=pickings) number_of_packages = len(package_ids) total_package += number_of_packages for index, package_id in enumerate(package_ids, 1): # _logger.info( # "WK %r [%r/%r] %r : %r kg", # packaging_id, # number_of_packages, # total_package,package_id.name, # package_id.shipping_weight # ) shipment = FedexProcessShipmentRequest(self.config_fedex()) if number_of_packages > 1: shipment.RequestedShipment.PackageCount = number_of_packages - 1 shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D' shipment.RequestedShipment.LabelSpecification.ImageType = 'PNG' shipment.RequestedShipment.LabelSpecification.LabelStockType = self.fedex_label_stock_type shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' ##################################### if packaging_id.fedex_edt_request_type == 'ALL': shipment.RequestedShipment.SpecialServicesRequested.SpecialServiceTypes = "ELECTRONIC_TRADE_DOCUMENTS" shipment.RequestedShipment.SpecialServicesRequested.EtdDetail.RequestedDocumentCopies = "COMMERCIAL_INVOICE" spec = shipment.create_wsdl_object_of_type( 'ShippingDocumentSpecification') spec.ShippingDocumentTypes = 'COMMERCIAL_INVOICE' spec_format = shipment.create_wsdl_object_of_type( 'ShippingDocumentFormat') spec_format.ImageType = 'PDF' spec_format.StockType = 'PAPER_LETTER' spec.CommercialInvoiceDetail.Format = spec_format shipment.RequestedShipment.ShippingDocumentSpecification = spec ##################################### shipment = self.fedex_preprocessing(shipment, packaging_id, pickings=pickings, package_id=package_id) weight = self._get_api_weight(package_id.shipping_weight) weight = weight and weight or self.default_product_weight package = self.get_fedex_package(shipment, weight, packaging_id.length, packaging_id.width, packaging_id.height, packaging_id) package.ItemDescription = package_id.description package.SequenceNumber = index if index == 1: if package_id.cover_amount: package.InsuredValue.Amount = package_id.cover_amount package.InsuredValue.Currency = currency_id.name shipment.add_package(package) shipment.send_request() CompletedPackageDetails = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0] MasterTrackingIds[ packaging_id] = CompletedPackageDetails.TrackingIds[ 0].TrackingNumber else: if number_of_packages > 1: shipment.RequestedShipment.MasterTrackingId.TrackingIdType = self.fedex_trackingid_type shipment.RequestedShipment.MasterTrackingId.TrackingNumber = MasterTrackingIds.get( packaging_id) shipment.add_package(package) shipment.send_request() CompletedPackageDetails = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[ 0] TrackingNumber = CompletedPackageDetails.TrackingIds[ 0].TrackingNumber image = CompletedPackageDetails.Label.Parts[0].Image result['attachments'].append( ('FedEx' + str(TrackingNumber) + '.png', binascii.a2b_base64(str(image)))) result['tracking_number'] += ',' + TrackingNumber result['weight'] += weight Amount = hasattr( CompletedPackageDetails, 'PackageRating' ) and CompletedPackageDetails.PackageRating.PackageRateDetails[ 0].NetCharge.Amount or 0 if Amount: CurrencyCode = CompletedPackageDetails.PackageRating.PackageRateDetails[ 0].NetCharge.Currency if currency_id.name == CurrencyCode: result['exact_price'] += Amount else: currency = currency_id.search( [('name', '=', CurrencyCode)], limit=1) result['exact_price'] += currency.compute( Amount, currency_id) pickings.number_of_packages = total_package return result except (FedexError, FedexFailure, SchemaValidationError) as f_err: pickings.message_post(body=f_err.value, subject="FedEx Error:") _logger.warning( "#1 FEDEX SEND SHIPMENT ERROR-------%r---------------", f_err.value) raise ValidationError(f_err.value) except Exception as e: pickings.message_post(body=e, subject="FedEx Error:") _logger.warning('#2 FEDEX SEND SHIPMENT ERROR--%r', e) raise ValidationError(e)
class FedexLabelHelper: mCommodities = [] def __init__(self): pass # ---------------------------------------------------- # set overall shipment configuration def setShipmentConfig( self, CONFIG_OBJ, invoice_info, cust_tran_id="*** ShipService Request v17 using Python ***", dropoffType="BUSINESS_SERVICE_CENTER", shippingPaymentType="SENDER", labelFormatType="COMMON2D", labelSpecificationImageType="PDF", labelSpecificationStockType="PAPER_7X4.75", labelPrintingOrientation="TOP_EDGE_OF_TEXT_FIRST", LabelOrder="SHIPPING_LABEL_FIRST", ): self.invoice_info = invoice_info self.dropoffType = dropoffType self.serviceType = "INTERNATIONAL_PRIORITY" if invoice_info[ "ShippingExpress"] == True else "INTERNATIONAL_ECONOMY" self.mCommodities.clear() self.CONFIG_OBJ = CONFIG_OBJ self.shipment = FedexProcessShipmentRequest( CONFIG_OBJ, customer_transaction_id=cust_tran_id) self.shipment.RequestedShipment.DropoffType = dropoffType self.shipment.RequestedShipment.ServiceType = self.serviceType self.shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number self.shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Address.CountryCode = "DK" self.shipment.RequestedShipment.ShippingChargesPayment.PaymentType = shippingPaymentType labelSpecification = self.shipment.create_wsdl_object_of_type( "LabelSpecification") labelSpecification.LabelFormatType = labelFormatType labelSpecification.LabelStockType = labelSpecificationStockType labelSpecification.ImageType = labelSpecificationImageType labelSpecification.LabelOrder = LabelOrder labelSpecification.LabelPrintingOrientation = labelPrintingOrientation self.shipment.RequestedShipment.LabelSpecification = labelSpecification # ---------------------------------------------------- # set sender information def setSenderInfo(self, sender): self.shipment.RequestedShipment.Shipper.Contact.PersonName = sender[ "Name"] self.shipment.RequestedShipment.Shipper.Contact.CompanyName = sender[ "Company"] self.shipment.RequestedShipment.Shipper.Contact.PhoneNumber = sender[ "Phone"] self.shipment.RequestedShipment.Shipper.Contact.EMailAddress = sender[ "Email"] self.shipment.RequestedShipment.Shipper.Address.StreetLines = sender[ "Address"] self.shipment.RequestedShipment.Shipper.Address.City = sender["City"] self.shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = sender[ "Region"] self.shipment.RequestedShipment.Shipper.Address.PostalCode = sender[ "Zip"] self.shipment.RequestedShipment.Shipper.Address.CountryCode = sender[ "CountryCode"] self.shipment.RequestedShipment.Shipper.Address.Residential = sender[ "Residential"] ti = self.shipment.create_wsdl_object_of_type("TaxpayerIdentification") ti.Number = sender["VAT"] ti.TinType = "BUSINESS_NATIONAL" self.shipment.RequestedShipment.Shipper.Tins = ti # ---------------------------------------------------- # upload all documents (invoice and product information) def upload_all_documents(self): doc_ids = [] doc_ids.append( self.upload_document(self.invoice_info["InvoicePath"], "COMMERCIAL_INVOICE")) for pdf in self.invoice_info["Pdfs"]: doc_ids.append(self.upload_document(pdf, "OTHER")) return doc_ids # ---------------------------------------------------- # function for uploading documents as electronic trade documents and getting the response doc IDs def upload_document(self, path, type): from fedex.services.document_service import FedexDocumentServiceRequest # specify prefix for use in attachment naming if type == "COMMERCIAL_INVOICE": prefix = "invoice_" else: prefix = "product_description_" uploadRequest = FedexDocumentServiceRequest(self.CONFIG_OBJ) uploadRequest.OriginCountryCode = "DK" uploadRequest.DestinationCountryCode = self.shipment.RequestedShipment.Recipient.Address.CountryCode uploadRequest.Usage = "ELECTRONIC_TRADE_DOCUMENTS" clientdetails = uploadRequest.create_wsdl_object_of_type( "ClientDetail") clientdetails.AccountNumber = self.CONFIG_OBJ.account_number clientdetails.MeterNumber = self.CONFIG_OBJ.meter_number uploadRequest.ClientDetail = clientdetails webAuthDetails = uploadRequest.create_wsdl_object_of_type( "WebAuthenticationDetail") webAuthDetails.ParentCredential.Key = self.CONFIG_OBJ.key webAuthDetails.ParentCredential.Password = self.CONFIG_OBJ.password webAuthDetails.UserCredential.Key = self.CONFIG_OBJ.key webAuthDetails.UserCredential.Password = self.CONFIG_OBJ.password uploadRequest.WebAuthenticationDetail = webAuthDetails docdetails = uploadRequest.create_wsdl_object_of_type( "UploadDocumentDetail") docdetails.LineNumber = 1 docdetails.DocumentType = type docdetails.FileName = prefix + path fileContent = open(path, "rb").read() fileBase64 = binascii.b2a_base64(fileContent) docdetails.DocumentContent = fileBase64.decode("cp1250") uploadRequest.Documents = docdetails uploadRequest.send_request() doc_id = uploadRequest.response.DocumentStatuses[0].DocumentId return doc_id # ---------------------------------------------------- # set recipient information def setRecipientInfo(self, recipient): self.shipment.RequestedShipment.Recipient.Contact.PersonName = recipient[ "Name"] self.shipment.RequestedShipment.Recipient.Contact.CompanyName = recipient[ "Company"] self.shipment.RequestedShipment.Recipient.Contact.PhoneNumber = recipient[ "Phone"] self.shipment.RequestedShipment.Recipient.Contact.EMailAddress = recipient[ "Email"] self.shipment.RequestedShipment.Recipient.Address.StreetLines = recipient[ "Address"] self.shipment.RequestedShipment.Recipient.Address.City = recipient[ "City"] self.shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = recipient[ "Region"] self.shipment.RequestedShipment.Recipient.Address.PostalCode = recipient[ "Zip"] self.shipment.RequestedShipment.Recipient.Address.CountryCode = recipient[ "CountryCode"] self.shipment.RequestedShipment.Recipient.Address.Residential = recipient[ "Residential"] ti = self.shipment.create_wsdl_object_of_type("TaxpayerIdentification") ti.Number = recipient["VAT"] ti.TinType = "BUSINESS_NATIONAL" self.shipment.RequestedShipment.Recipient.Tins = ti # ---------------------------------------------------- # add "commercial invoice" reference as the only commodity def add_ci_commodity(self): self.addCommodity( cCustomsValueAmnt=self.invoice_info["Value"], cCustomsValueCurrency=self.invoice_info["Currency"], cWeightValue=self.invoice_info["Weight"], cDescription="See attached commercial invoice", cQuantity=self.invoice_info["Quantity"], cExportLicenseNumber=self.shipment.RequestedShipment.Shipper.Tins. Number, cPartNumber=1, ) # ---------------------------------------------------- # add commodity to shipment (for now, just add 1 commodity to refer to attached CI) def addCommodity( self, cCustomsValueAmnt, cCustomsValueCurrency, cWeightValue, cDescription, cQuantity, cExportLicenseNumber, cPartNumber, ): commodity = self.shipment.create_wsdl_object_of_type("Commodity") commodity.NumberOfPieces = str(cQuantity) commodity.Description = cDescription commodity.Quantity = cQuantity commodity.QuantityUnits = "EA" commodity.ExportLicenseNumber = cExportLicenseNumber commodity.PartNumber = cPartNumber commodity.CountryOfManufacture = "DK" mCustomsValue = self.shipment.create_wsdl_object_of_type("Money") mCustomsValue.Amount = cCustomsValueAmnt mCustomsValue.Currency = cCustomsValueCurrency commodity.CustomsValue = mCustomsValue commodity_weight = self.shipment.create_wsdl_object_of_type("Weight") commodity_weight.Value = cWeightValue commodity_weight.Units = "KG" commodity.Weight = commodity_weight munitPrice = self.shipment.create_wsdl_object_of_type("Money") munitPrice.Amount = float(round((cCustomsValueAmnt / cQuantity), 2)) munitPrice.Currency = cCustomsValueCurrency commodity.UnitPrice = munitPrice self.mCommodities.append(commodity) # ---------------------------------------------------- # add package to shipment def set_packaging_info(self): weight = self.invoice_info["Weight"] type = "BOX" if weight > 0.5 else "ENVELOPE" weight_final = float(round(weight + 0.2, 2)) if weight > 0.5 else 0.4 self.addShippingPackage(packageWeight=weight_final, physicalPackagingType=type, packagingType=f"FEDEX_{type}") # ---------------------------------------------------- # add package to shipment def addShippingPackage(self, packageWeight, physicalPackagingType, packagingType, packageWeightUnit="KG"): package_weight = self.shipment.create_wsdl_object_of_type("Weight") package_weight.Value = packageWeight package_weight.Units = packageWeightUnit package = self.shipment.create_wsdl_object_of_type( "RequestedPackageLineItem") package.PhysicalPackaging = physicalPackagingType package.Weight = package_weight self.shipment.add_package(package) self.shipment.RequestedShipment.TotalWeight = package_weight self.shipment.RequestedShipment.PackagingType = packagingType # ---------------------------------------------------- # add information on duties def setDutiesPaymentInfo(self): mPayment = self.shipment.create_wsdl_object_of_type("Payment") mPayment.PaymentType = "RECIPIENT" # change if sender should pay duties mCustomsValue = self.shipment.create_wsdl_object_of_type("Money") mCustomsValue.Amount = self.invoice_info["Value"] mCustomsValue.Currency = self.invoice_info["Currency"] ccd = self.shipment.create_wsdl_object_of_type( "CustomsClearanceDetail") ccd.Commodities = self.mCommodities ccd.CustomsValue = mCustomsValue ccd.DutiesPayment = mPayment self.shipment.RequestedShipment.CustomsClearanceDetail = ccd # ---------------------------------------------------- # Set ETD (electronic trade documents) settings def setSpecialServices(self, doc_ids): # construct objects ssr = self.shipment.create_wsdl_object_of_type( "ShipmentSpecialServicesRequested") ssr.SpecialServiceTypes.append("ELECTRONIC_TRADE_DOCUMENTS") ssr.SpecialServiceTypes.append("EVENT_NOTIFICATION") # set up ETD details etd = self.shipment.create_wsdl_object_of_type("EtdDetail") etd.RequestedDocumentCopies = "COMMERCIAL INVOICE" for i, doc_id in enumerate(doc_ids, start=0): udrd = self.shipment.create_wsdl_object_of_type( "UploadDocumentReferenceDetail") udrd.DocumentType = "COMMERCIAL_INVOICE" if i == 0 else "OTHER" udrd.DocumentId = doc_id udrd.Description = "Commercial_Invoice" if i == 0 else "Product_Description" udrd.DocumentIdProducer = "CUSTOMER" ssr.EtdDetail.DocumentReferences.append(udrd) self.shipment.RequestedShipment.SpecialServicesRequested = ssr # set Event Notification details send = self.shipment.create_wsdl_object_of_type( "ShipmentEventNotificationDetail") send.AggregationType = "PER_SHIPMENT" sens = self.shipment.create_wsdl_object_of_type( "ShipmentEventNotificationSpecification") sens.NotificationDetail.NotificationType = "EMAIL" sens.NotificationDetail.EmailDetail.EmailAddress = self.shipment.RequestedShipment.Recipient.Contact.EMailAddress sens.NotificationDetail.EmailDetail.Name = self.shipment.RequestedShipment.Recipient.Contact.PersonName sens.NotificationDetail.Localization.LanguageCode = "EN" sens.Role = "SHIPPER" sens.Events.append("ON_SHIPMENT") sens.Events.append("ON_EXCEPTION") sens.Events.append("ON_DELIVERY") sens.FormatSpecification.Type = "HTML" send.EventNotifications = sens self.shipment.RequestedShipment.SpecialServicesRequested.EventNotificationDetail = send # ---------------------------------------------------- # process the shipment def processInternationalShipment(self): from shutil import copyfile self.shipment.RequestedShipment.ShipTimestamp = datetime.datetime.now( ).replace(microsecond=0).isoformat() # print(" ---- **** DETAILS ---- ****") # print(self.shipment.RequestedShipment) # print(self.shipment.ClientDetail) # print(self.shipment.TransactionDetail) # print("REQUESTED SHIPMENT\n\n", self.shipment.RequestedShipment) self.shipment.send_request() # print("RESPONSE\n\n", self.shipment.response) status = self.shipment.response.HighestSeverity if status == "SUCCESS" and "CompletedShipmentDetail" in self.shipment.response: shipment_details = self.shipment.response.CompletedShipmentDetail package_details = shipment_details.CompletedPackageDetails[0] tracking_id = package_details.TrackingIds[0].TrackingNumber email = self.shipment.RequestedShipment.Recipient.Contact.EMailAddress fedex_cost = "N/A" if hasattr(package_details, "PackageRating"): fedex_cost = package_details.PackageRating.PackageRateDetails[ 0].NetCharge.Amount # create the shipping PDF label ascii_label_data = package_details.Label.Parts[0].Image label_binary_data = binascii.a2b_base64(ascii_label_data) out_path = self.invoice_info[ "InvoiceId"] + f"_shipment_label_{tracking_id}.pdf" out_file = open(out_path, "wb") out_file.write(label_binary_data) out_file.close() # print output information print( f"- SUCCESS: Created FedEx label for invoice {self.invoice_info['InvoiceId']}\n tracking ID: {tracking_id}\n email: {email}\n FedEx cost: {fedex_cost}\n Customs value: {self.invoice_info['Value']} {self.invoice_info['Currency']}\n Weight: {self.invoice_info['Weight']}\n output path: {out_path}" )
def test_create_delete_shipment(self): shipment = FedexProcessShipmentRequest(CONFIG_OBJ) shipment.RequestedShipment.DropoffType = 'REGULAR_PICKUP' shipment.RequestedShipment.ServiceType = 'FEDEX_GROUND' shipment.RequestedShipment.PackagingType = 'YOUR_PACKAGING' shipment.RequestedShipment.Shipper.Contact.PersonName = 'Sender Name' shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '9012638716' shipment.RequestedShipment.Shipper.Address.StreetLines = ['Address Line 1'] shipment.RequestedShipment.Shipper.Address.City = 'Herndon' shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = 'VA' shipment.RequestedShipment.Shipper.Address.PostalCode = '20171' shipment.RequestedShipment.Shipper.Address.CountryCode = 'US' shipment.RequestedShipment.Recipient.Contact.PersonName = 'Recipient Name' shipment.RequestedShipment.Recipient.Contact.PhoneNumber = '9012637906' shipment.RequestedShipment.Recipient.Address.StreetLines = ['Address Line 1'] shipment.RequestedShipment.Recipient.Address.City = 'Herndon' shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'VA' shipment.RequestedShipment.Recipient.Address.PostalCode = '20171' shipment.RequestedShipment.Recipient.Address.CountryCode = 'US' shipment.RequestedShipment.EdtRequestType = 'NONE' shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber \ = CONFIG_OBJ.account_number shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER' shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D' shipment.RequestedShipment.LabelSpecification.ImageType = 'PNG' shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_7X4.75' shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' del shipment.RequestedShipment.LabelSpecification.LabelOrder package1_weight = shipment.create_wsdl_object_of_type('Weight') package1_weight.Value = 2.0 package1_weight.Units = "LB" package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem') package1.PhysicalPackaging = 'ENVELOPE' package1.Weight = package1_weight shipment.add_package(package1) shipment.send_request() assert shipment.response assert shipment.response.HighestSeverity == 'SUCCESS' track_id = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber assert track_id del_shipment = FedexDeleteShipmentRequest(CONFIG_OBJ) del_shipment.DeletionControlType = "DELETE_ALL_PACKAGES" del_shipment.TrackingId.TrackingNumber = track_id del_shipment.TrackingId.TrackingIdType = 'EXPRESS' del_shipment.send_request() assert del_shipment.response
def do_partial(self, cr, uid, ids, context=None): if context is None: context = {} assert len(ids) == 1, 'Partial picking processing may only be done one at a time.' stock_picking = self.pool.get('stock.picking') stock_move = self.pool.get('stock.move') uom_obj = self.pool.get('product.uom') partial = self.browse(cr, uid, ids[0], context=context) partial_data = { 'delivery_date' : partial.date } picking_type = partial.picking_id.type for wizard_line in partial.move_ids: line_uom = wizard_line.product_uom move_id = wizard_line.move_id.id #Quantiny must be Positive if wizard_line.quantity < 0: raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.')) #Compute the quantity for respective wizard_line in the line uom (this jsut do the rounding if necessary) qty_in_line_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, line_uom.id) if line_uom.factor and line_uom.factor <> 0: if float_compare(qty_in_line_uom, wizard_line.quantity, precision_rounding=line_uom.rounding) != 0: raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only rounding of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.quantity, line_uom.name, line_uom.rounding, line_uom.name)) if move_id: #Check rounding Quantity.ex. #picking: 1kg, uom kg rounding = 0.01 (rounding to 10g), #partial delivery: 253g #=> result= refused, as the qty left on picking would be 0.747kg and only 0.75 is accepted by the uom. initial_uom = wizard_line.move_id.product_uom #Compute the quantity for respective wizard_line in the initial uom qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, initial_uom.id) without_rounding_qty = (wizard_line.quantity / line_uom.factor) * initial_uom.factor if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0: raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only rounding of "%s %s" is accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name)) else: seq_obj_name = 'stock.picking.' + picking_type move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name), 'product_id': wizard_line.product_id.id, 'product_qty': wizard_line.quantity, 'product_uom': wizard_line.product_uom.id, 'prodlot_id': wizard_line.prodlot_id.id, 'location_id' : wizard_line.location_id.id, 'location_dest_id' : wizard_line.location_dest_id.id, 'picking_id': partial.picking_id.id },context=context) stock_move.action_confirm(cr, uid, [move_id], context) partial_data['move%s' % (move_id)] = { 'product_id': wizard_line.product_id.id, 'product_qty': wizard_line.quantity, 'product_uom': wizard_line.product_uom.id, 'prodlot_id': wizard_line.prodlot_id.id, } if (picking_type == 'in') and (wizard_line.product_id.cost_method == 'average'): partial_data['move%s' % (wizard_line.move_id.id)].update(product_price=wizard_line.cost, product_currency=wizard_line.currency.id) # Do the partial delivery and open the picking that was delivered # We don't need to find which view is required, stock.picking does it. done = stock_picking.do_partial( cr, uid, [partial.picking_id.id], partial_data, context=context) picking = self.pool.get('stock.picking.out').read(cr, uid, done[partial.picking_id.id]['delivered_picking'], ['origin', 'name'], context) so = picking['origin'] # Set this to the INFO level to see the response from Fedex printed in stdout. logging.basicConfig(level=logging.INFO) # This is the object that will be handling our tracking request. # We're using the FedexConfig object from example_config.py in this dir. shipment = FedexProcessShipmentRequest(CONFIG_OBJ, customer_transaction_id='ProcessShipmentRequest_v15') # This is very generalized, top-level information. # REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER or STATION shipment.RequestedShipment.DropoffType = 'REGULAR_PICKUP' # See page 355 in WS_ShipService.pdf for a full list. Here are the common ones: # STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, FEDEX_EXPRESS_SAVER shipment.RequestedShipment.ServiceType = 'FEDEX_GROUND' # What kind of package this will be shipped in. # FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING shipment.RequestedShipment.PackagingType = 'YOUR_PACKAGING' shipment.RequestedShipment.PreferredCurrency = 'USD' # Shipper contact info. shipment.RequestedShipment.Shipper.Contact.PersonName = 'Sam' shipment.RequestedShipment.Shipper.Contact.CompanyName = 'Cute Shoe' shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '9012638716' shipment.RequestedShipment.Shipper.Contact.EMailAddress = '*****@*****.**' # Shipper address. shipment.RequestedShipment.Shipper.Address.StreetLines = ['2000 Freight LTL Testing', 'Do Not Delete - Test Account'] shipment.RequestedShipment.Shipper.Address.City = 'Harrison' shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = 'AR' shipment.RequestedShipment.Shipper.Address.PostalCode = '72601' shipment.RequestedShipment.Shipper.Address.CountryCode = 'US' #shipment.RequestedShipment.Shipper.Address.Residential = True # Recipient contact info. shipment.RequestedShipment.Recipient.Contact.PersonName = 'Jack' shipment.RequestedShipment.Recipient.Contact.CompanyName = 'Taobao' shipment.RequestedShipment.Recipient.Contact.PhoneNumber = '9012637906' shipment.RequestedShipment.Recipient.Contact.EMailAddress = '*****@*****.**' # Recipient address shipment.RequestedShipment.Recipient.Address.StreetLines = ['1202 Chalet Ln', 'Do Not Delete - Test Account'] shipment.RequestedShipment.Recipient.Address.City = 'Harrison' shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'AR' shipment.RequestedShipment.Recipient.Address.PostalCode = '72601' shipment.RequestedShipment.Recipient.Address.CountryCode = 'US' # This is needed to ensure an accurate rate quote with the response. #shipment.RequestedShipment.Recipient.Address.Residential = True shipment.RequestedShipment.EdtRequestType = 'NONE' #shipment.RequestedShipment.CustomsClearanceDetail.ClearanceBrokerage = 'BROKER_UNASSIGNED' #shipment.RequestedShipment.CustomsClearanceDetail.DocumentContent = 'DOCUMENTS_ONLY' #shipment.RequestedShipment.CustomsClearanceDetail.CustomsValue.Currency = 'USD' #shipment.RequestedShipment.CustomsClearanceDetail.CustomsValue.Amount = 100 #shipment.RequestedShipment.CustomsClearanceDetail.FreightOnValue = 'CARRIER_RISK' shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber = CONFIG_OBJ.account_number shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Tins = [{'TinType': 'BUSINESS_STATE', 'Number': '353'}] shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.Contact = [{'ContactId': '12345', 'PersonName': 'jack'}] # Who pays for the shipment? # RECIPIENT, SENDER or THIRD_PARTY shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER' # 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 = 'PNG' # To use doctab stocks, you must change ImageType above to one of the # label printer formats (ZPLII, EPL2, DPL). # See documentation for paper types, there quite a few. shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_4X6' # This indicates if the top or bottom of the label comes out of the # printer first. # BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST' shipment.RequestedShipment.LabelSpecification.LabelOrder = 'SHIPPING_LABEL_FIRST' package1_weight = shipment.create_wsdl_object_of_type('Weight') # Weight, in pounds. package1_weight.Value = 1.0 package1_weight.Units = "LB" package1_dim = shipment.create_wsdl_object_of_type('Dimensions') package1_dim.Length = 12 package1_dim.Width = 12 package1_dim.Height = 12 package1_dim.Units = 'IN' package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem') package1.PhysicalPackaging = 'BOX' package1.Weight = package1_weight package1.SequenceNumber = 1 package1.Dimensions = package1_dim package1.CustomerReferences = [{'CustomerReferenceType': 'CUSTOMER_REFERENCE', 'Value': so}] # Un-comment this to see the other variables you may set on a package. #print package1 # This adds the RequestedPackageLineItem WSDL object to the shipment. It # increments the package count and total weight of the shipment for you. shipment.client.wsdl.services[0].setlocation('https://wsbeta.fedex.com:443/web-services/ship') logging.basicConfig(level=logging.INFO) logging.getLogger('suds.client').setLevel(logging.DEBUG) logging.getLogger('suds.transport').setLevel(logging.DEBUG) logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG) logging.getLogger('suds.wsdl').setLevel(logging.DEBUG) shipment.add_package(package1) # If you'd like to see some documentation on the ship service WSDL, un-comment # this line. (Spammy). #print shipment.client # Un-comment this to see your complete, ready-to-send request as it stands # before it is actually sent. This is useful for seeing what values you can # change. #print shipment.RequestedShipment # If you want to make sure that all of your entered details are valid, you # can call this and parse it just like you would via send_request(). If # shipment.response.HighestSeverity == "SUCCESS", your shipment is valid. #shipment.send_validation_request() # Fires off the request, sets the 'response' attribute on the object. shipment.send_request() # This will show the reply to your shipment being sent. You can access the # attributes through the response attribute on the request object. This is # good to un-comment to see the variables returned by the Fedex reply. print shipment.response # Here is the overall end result of the query. print "HighestSeverity:", shipment.response.HighestSeverity # Getting the tracking number from the new shipment. print "Tracking #:", shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber # Net shipping costs. print "Net Shipping Cost (US$):", shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].PackageRating.PackageRateDetails[0].NetCharge.Amount # Get the label image in ASCII format from the reply. Note the list indices # we're using. You'll need to adjust or iterate through these if your shipment # has multiple packages. ascii_label_data = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].Label.Parts[0].Image # Convert the ASCII data to binary. label_binary_data = binascii.a2b_base64(ascii_label_data) """ This is an example of how to dump a label to a PNG file. """ # This will be the file we write the label out to. png_file = open(os.path.dirname(os.path.abspath(__file__)) + '/static/' + picking['name'].replace('/', '') + '.png', 'wb') png_file.write(label_binary_data) png_file.close() # label = open(os.path.dirname(os.path.abspath(__file__)) + '/' + picking['name'].replace('/', '') + '.png', 'rU') # label_data = label.read() # label_binary_data = base64.b64encode(label_data) vals = { 'courier_label': '/ida_wms_app/static/' + picking['name'].replace('/', '') + '.png' } self.pool.get('stock.picking.out').write(cr, uid, done[partial.picking_id.id]['delivered_picking'], vals, context) """ This is an example of how to print the label to a serial printer. This will not work for all label printers, consult your printer's documentation for more details on what formats it can accept. """ # Pipe the binary directly to the label printer. Works under Linux # without requiring PySerial. This WILL NOT work on other platforms. #label_printer = open("/dev/ttyS0", "w") #label_printer.write(label_binary_data) #label_printer.close() """ This is a potential cross-platform solution using pySerial. This has not been tested in a long time and may or may not work. For Windows, Mac, and other platforms, you may want to go this route. """ #import serial #label_printer = serial.Serial(0) #print "SELECTED SERIAL PORT: "+ label_printer.portstr #label_printer.write(label_binary_data) #label_printer.close() if done[partial.picking_id.id]['delivered_picking'] == partial.picking_id.id: return {'type': 'ir.actions.act_window_close'} return { 'type': 'ir.actions.act_window', 'res_model': context.get('active_model', 'stock.picking'), 'name': _('Partial Delivery'), 'res_id': done[partial.picking_id.id]['delivered_picking'], 'view_type': 'form', 'view_mode': 'form,tree,calendar', 'context': context, }