def setUp(self): self.api = endicia.Endicia(EndiciaTestConfig, debug=True) self.shipper = Address('Adobe', "345 Park Avenue", 'San Jose', 'CA', 95110, 'US', phone='5122901212', email='*****@*****.**') self.recipient = Address('Apple', "1 Infinite Loop", 'Cupertino', 'CA', 95014, 'US', phone='5122901212', email='*****@*****.**') self.intl_recipient = Address('Apple Canada', "7495 Birchmount Road", 'Markham', 'ON', "L3R 5G2", 'CA', phone='9055135800', email='*****@*****.**') self.package = endicia.Package(endicia.Package.shipment_types[0], 3, endicia.Package.shapes[1], 10, 10, 10)
def TestEndiciaLabel(): package = endicia.Package(endicia.Package.shipment_types[0], 20, endicia.Package.shapes[1], 10, 10, 10) package_intl = endicia.Package(endicia.Package.international_shipment_types[0], 20, endicia.Package.shapes[3], 10, 10, 10) customs = [ endicia.Customs('hello', 1, 2, 100, 'Bermuda'), endicia.Customs('Thingy', 10, 16, 80, 'Bahamas') ] debug = True req0 = endicia.LabelRequest(EndiciaPartnerID, EndiciaAccountID, EndiciaPassphrase, package_intl, shipper, recipient_intl, contents_type='Merchandise', customs_info=customs, debug=debug) req1 = endicia.LabelRequest(EndiciaPartnerID, EndiciaAccountID, EndiciaPassphrase, package, shipper, recipient, debug=debug) req2 = endicia.LabelRequest(EndiciaPartnerID, EndiciaAccountID, EndiciaPassphrase, package, shipper, recipient, stealth=False, debug=debug) req3 = endicia.LabelRequest(EndiciaPartnerID, EndiciaAccountID, EndiciaPassphrase, package, shipper, recipient, insurance='ENDICIA', insurance_amount=1.0, debug=debug) req4 = endicia.LabelRequest(EndiciaPartnerID, EndiciaAccountID, EndiciaPassphrase, package, shipper, recipient, customs_form='Form2976A', customs_info=customs, contents_type='Merchandise', debug=debug) for request in [ req0, req1, req2, req3, req4 ]: response = request.send() print response if not isinstance(response, endicia.Error): _show_file(extension='.png', data=response.label) return response
def testIntlLabel(self): package_intl = endicia.Package( endicia.Package.international_shipment_types[0], 20, endicia.Package.shapes[3], 10, 10, 10) customs = [ endicia.Customs('Thing 1', 1, 2, 100, 'United States'), endicia.Customs('Thing 2', 10, 16, 80, 'Canada') ] label = self.api.label( package_intl, self.shipper, self.intl_recipient, contents_type='Merchandise', customs_info=customs, image_format="GIF" # Only GIF is valid for international labels. ) self.assertFalse(isinstance(label, endicia.Error), msg=label.message)
def generate_usps_tracking_no(self, picking, error=False): ''' This function is used to Generated USPS Shipping Label in Delivery order parameters: picking : (int) stock picking ID,(delivery order ID) ''' sale_id = self.env['sale.order'].search([('name', '=', picking.origin) ]) context = dict(self._context or {}) if not self.env['shipping.usps'].search([('active', '=', True)]): raise osv.except_osv(_('Error'), _('Default Endicia settings not defined')) ship_endicia = self.env['shipping.usps'].search([('active', '=', True) ]) context['usps_active'] = False #Endicia Quotes Selected stockpicking_obj = self.env['stock.picking'] if picking.service_type_usps.find('First') != -1: mail_class = 'First' elif picking.service_type_usps.find('Express') != -1: mail_class = 'Express' else: mail_class = picking.service_type_usps cust_address = ship_endicia.config_shipping_address_id shipper = Address( cust_address.name or '', cust_address.street, cust_address.street2 or '', cust_address.city, cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.phone or '', cust_address.email, (cust_address.name != cust_address.name) and cust_address.name or '') cust_address = picking.partner_id receipient = Address( cust_address.name or '', cust_address.street and cust_address.street.rstrip(','), cust_address.street2 and (cust_address.street != cust_address.street2) and cust_address.street2.rstrip(',') or '', cust_address.city and cust_address.city.rstrip(','), cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.phone or '', cust_address.email, (cust_address.name != cust_address.name) and cust_address.name or '') international_label = False if receipient.country_code.lower( ) != 'us' and receipient.country_code.lower( ) != 'usa' and receipient.country_code.lower() != 'pr': international_label = True if picking.service_type_usps.find('First') != -1: mail_class = 'FirstClassMailInternational' elif picking.service_type_usps.find('Express') != -1: mail_class = 'ExpressMailInternational' elif picking.service_type_usps.find('Priority') != -1: mail_class = 'PriorityMailInternational' package = endicia.Package( mail_class, int( round(picking.weight_package * 10 >= 1.0 and picking.weight_package * 10 or 1.0)), endicia.Package.shapes[picking.container_usps], picking.length_package, picking.width_package, picking.height_package, picking.name, sale_id.amount_total) customs = [] if international_label: for move_line in picking.move_lines: weight_net = move_line.product_id.product_tmpl_id.weight_net * 16 >= 1.0 and move_line.product_id.product_tmpl_id.weight_net * 16 * move_line.product_qty or 1.0 customs.append( endicia.Customs( move_line.product_id.default_code + '-' + move_line.product_id.name, int(move_line.product_qty), int(round(weight_net)), move_line.price_unit > 0.00 and move_line.price_unit or 39.00, shipper.country_code)) reference = '' reference2 = '' for move_line in picking.move_lines: reference += ' (' + str(int(move_line.product_qty)) + ')' if move_line.product_id.default_code: reference += str(move_line.product_id.default_code) + '+' reference = reference[:-1] reference = reference[20:] reference2 += ' ' + ship_endicia.config_shipping_address_id.name # try: include_postage = picking.include_postage_usps if picking.service_type_usps.find( 'International' ) != -1 or picking.container_usps == 'Letter' != -1: image_rotation = 'Rotate90' else: image_rotation = ship_endicia.image_rotation request = endicia.LabelRequest( ship_endicia.requester_id, ship_endicia.account_id, ship_endicia.passphrase, ship_endicia.label_type if not international_label else 'International', ship_endicia.label_size, ship_endicia.image_format, image_rotation, package, shipper, receipient, reference, reference2, include_postage, debug=ship_endicia.test, destination_confirm=True if picking.service_type_usps == 'First Class' and picking.container_usps == 'Letter' else False, customs_info=customs) response = request.send() if isinstance(response, (str)): log_data = picking.write({ 'error_for_faulty': str(response), 'is_faulty_deliv_order': True }) return True endicia_res = response._get_value() im_barcode = cStringIO.StringIO( endicia_res['label']) # constructs a StringIO holding the image img_barcode = Image.open(im_barcode) output = StringIO.StringIO() img_barcode.save(output, format='PNG') data = binascii.b2a_base64(output.getvalue()) f = open('/tmp/test.png', 'wb') f.write(output.getvalue()) f.close() c = canvas.Canvas("/tmp/picking_list.pdf") c.setPageSize((400, 650)) c.drawImage('/tmp/test.png', 10, 10, 380, 630) c.save() f = open('/tmp/picking_list.pdf', 'rb') attachment_pool = self.env['ir.attachment'] data_attach = { 'name': 'PackingList.pdf', 'datas': base64.b64encode(f.read()), 'description': 'Packing List', 'res_name': picking.name, 'res_model': 'stock.picking', 'res_id': picking.id, } attach_id = attachment_pool.search([('res_id', '=', picking.id), ('res_name', '=', picking.name)]) if not attach_id: attach_id = attachment_pool.create(data_attach) os.remove('/tmp/test.png') os.remove('/tmp/picking_list.pdf') else: attach_result = attachment_pool.write(cr, uid, attach_id, data_attach) attach_id = attach_id[0] context['attach_id'] = attach_id if endicia_res['tracking']: carrier_id = self.env['delivery.carrier'].search([ ('service_code', '=', picking.service_type_usps), ('container_usps', '=', picking.container_usps) ]) if len(carrier_id): carrier_id = carrier_id[0] cost = endicia_res['cost'] else: carrier_id = False cost = False vals = { 'carrier_tracking_ref': endicia_res['tracking'], 'carrier_id': carrier_id.id, 'shipping_rate': cost } picking.write(vals) context['track_success'] = True context['tracking_no'] = endicia_res['tracking'] return True
def endicia_send_shipping(self, pickings): res = [] for picking in pickings: # Sender international_label = False shipper_address = picking.company_id.partner_id if not shipper_address.name: raise ValidationError(_("You must enter Shipper Name.")) if not (shipper_address.street or shipper_address.street2): raise ValidationError(_("You must enter Shipper Street.")) if not shipper_address.city: raise ValidationError(_("You must enter Shipper City.")) if not shipper_address.state_id: raise ValidationError(_("You must enter Shipper State.")) if not shipper_address.state_id.code: raise ValidationError(_("You must enter Shipper State Code.")) if not shipper_address.zip: raise ValidationError(_("You must enter Shipper Zip.")) if not shipper_address.country_id.code: raise ValidationError(_("You must enter Shipper Country.")) if not shipper_address.email: raise ValidationError(_("You must enter Shipper email.")) # added handling because endicia api support zip5 format. if str(shipper_address.zip).find("-") != -1: zip_code = str(shipper_address.zip).split("-")[0] else: zip_code = str(shipper_address.zip) shipper = endicia.Address(shipper_address.name, shipper_address.street or shipper_address.street2, shipper_address.city, shipper_address.state_id and shipper_address.state_id.code or '', zip_code, shipper_address.country_id.code, shipper_address.street and shipper_address.street2 or '', shipper_address.phone or '', shipper_address.email, True, # shipper_address.name ) # Recipient cust_address = picking.partner_id if not cust_address.name: raise ValidationError(_("You must enter Recipient Name.")) if not (cust_address.street or cust_address.street2): raise ValidationError(_("You must enter Recipient Street.")) if not cust_address.city: raise ValidationError(_("You must enter Recipient City.")) if not cust_address.state_id: raise ValidationError(_("You must enter Recipient State.")) if not cust_address.state_id.code: raise ValidationError(_("You must enter Recipient State Code.")) if not cust_address.zip: raise ValidationError(_("You must enter Recipient Zip.")) if not cust_address.country_id.code: raise ValidationError(_("You must enter Recipient Country.")) # added handling because usps api support zip5 format. if str(cust_address.zip).find("-") != -1: zip_code = str(cust_address.zip).split("-")[0] else: zip_code = str(cust_address.zip) recipient = endicia.Address(cust_address.name or '', cust_address.street or cust_address.street2, cust_address.city, cust_address.state_id and cust_address.state_id.code or '', zip_code, cust_address.country_id and cust_address.country_id.code, cust_address.street and cust_address.street2 or '', cust_address.phone or '', cust_address.email, '' ) package_value = picking.sale_id.amount_total prod_weight = 0.0 weight = self._convert_weight(picking.weight_bulk*0.453592, self.endicia_weight_unit) #weight reversed back to kg since client decides put all product weights in pounds if self.endicia_weight_unit == 'LB': prod_weight = weight * 16 elif self.endicia_weight_unit == 'KG': prod_weight = weight * 35.274 elif self.endicia_weight_unit == 'OUNCE': prod_weight = weight else: prod_weight = weight package = endicia.Package(self.endicia_service_type, round(prod_weight or 1.0), endicia.Package.shapes[self.endicia_container], self.endicia_length, self.endicia_width, self.endicia_height, picking.name, package_value ) if recipient.country.lower() != 'us' and recipient.country.lower() != 'usa' and recipient.country.lower() != 'pr': if self.endicia_service_type not in ['FirstClassMailInternational', 'Priority Mail International']: raise ValidationError("Please select carrier First Class Mail or Priority Mail International for international delivery") # (self, mail_class, weight_in_ozs, shape, length, width, height, # description = '', value = 0, require_signature = False, # reference = u'') package = endicia.Package(self.endicia_service_type, int(round(prod_weight or 1.0)), endicia.Package.shapes[self.endicia_container], self.endicia_length, self.endicia_width, self.endicia_height, picking.name, package_value ) international_label = True customs = [] if international_label or self.endicia_label_type == 'Domestic': for move in picking.move_lines: # if not move.product_id.bom_ids: prod_weight = 0 prod_weight_unit = move.product_id.uom_po_id and move.product_id.uom_po_id.name or '' weight_net = move.product_id.weight * move.product_qty or 0.1 if prod_weight_unit == 'LB': prod_weight = weight_net * 16 elif prod_weight_unit == 'KG': prod_weight = weight_net * 35.274 elif prod_weight_unit == 'OUNCE': prod_weight = weight_net else: prod_weight = weight_net custom_value = move.product_id.list_price or 1.0 customs.append(endicia.Customs(move.product_id.name, int(move.product_qty), float(prod_weight) or 1.0, float(custom_value * move.product_qty) or 1.0, shipper_address.country_id.code )) # elif prod_info.get('subproducts', False): # for component in prod_info.get('subproducts', False): # prod_brw = product_obj.browse(cr, uid, component.get('product_id', False)) # prod_weight_unit = prod_brw.weight_unit # weight_net = prod_brw.product_tmpl_id.weight and prod_brw.product_tmpl_id.weight * int( # component['product_qty'] or 0) or 0.1 # if prod_weight_unit and prod_weight_unit == 'LB': # prod_weight = weight_net * 16 # elif prod_weight_unit and prod_weight_unit == 'KG': # prod_weight = weight_net * 35.274 # elif prod_weight_unit and prod_weight_unit == 'OUNCE': # prod_weight = weight_net # else: # prod_weight = weight_net # custome_value = float(prod_brw.list_price) or 1.0 # comp_qty = component.get('product_qty', 1) * move_line.product_qty # customs.append(endicia.Customs(str(component['name']), # int(comp_qty or 1), # float(prod_weight * comp_qty) or 1.0, # float(custome_value * comp_qty) or 1.0, # shipper_address.country_id.code # )) if self.endicia_label_type == 'DestinationConfirm' and not ( self.endicia_container in ['Flat', 'Letter'] and package.mail_class in ['First', 'FirstClassMailInternational', 'PriorityMailInternational', 'Priority Mail Express International']): raise ValidationError('Container should be "Flat or Letter" and Shipping Service should be \ "First-Class Mail", "First Class Mail International","Priority Mail International","Priority Mail \ Express International" for Label Type "Destination Confirm"!') if self.endicia_label_type == 'CertifiedMail' and not ( self.endicia_container in ['Flat', 'Letter', 'Parcel'] and package.mail_class in [ 'First', 'Priority', 'FirstClassMailInternational', 'PriorityMailInternational', 'Priority Mail Express International']): raise ValidationError('Container should be "Flat or Letter or Parcel" and supported Shipping' ' Service are "First-Class Mail","Priority Mail","Priority Mail International","Priority Mail\ Express International","First Class Mail International" for Label Type "Certified Mail"!') # sending request to endicia for label request = endicia.LabelRequest(self.endicia_requester_id, self.endicia_account_id, self.endicia_passphrase, self.endicia_label_type, self.endicia_label_size, self.endicia_image_format, self.endicia_image_rotation, package, shipper, recipient, debug=self.endicia_test_mode, destination_confirm=True if self.endicia_service_type == 'First-Class Mail' and self.endicia_container == 'Letter' else False, customs_info=customs) response = request.send() endicia_res = response._get_value() ## creating attachment for label # label_name = 'ShippingLabel' + picking.name + '.' + self.endicia_image_format carrier_tracking_ref = endicia_res.get('tracking', False) carrier_price = float(endicia_res.get('cost',0)) logmessage = (_("Shipment created into Endicia <br/> <b>Tracking Number : </b>%s") % (carrier_tracking_ref)) picking.message_post(body=logmessage, attachments=[('LabelEndicia-%s.%s' % (carrier_tracking_ref, self.endicia_image_format), str(endicia_res['label']))]) shipping_data = { 'exact_price': carrier_price, 'tracking_number': carrier_tracking_ref } res = res + [shipping_data] return res
def endicia_get_shipping_price_from_so(self, orders): res = [] for order in orders: if not order.order_line: raise ValidationError(_("Please provide at least one item to ship.")) if order.order_line.filtered( lambda line: not line.product_id.weight and not line.is_delivery and not line.product_id.type in [ 'service', 'digital']): raise ValidationError( _('The estimated price cannot be computed because the weight of your product is missing.')) # assume the weight in KG weight = sum([(line.product_id.weight * line.product_qty) for line in order.order_line])* 0.453592 #weight reversed back to kg since client decides put all product weights in pounds weight = self._convert_weight(weight, self.endicia_weight_unit) # weight_unit = saleorder.weight_unit if not weight: raise ValidationError(_('Package Weight Invalid!')) # added handling for maximum weight limitation. if self.endicia_weight_unit == 'KG' and weight > 31.75147: raise ValidationError(_('Package Weight should not exceed 31.75 kg!')) if self.endicia_weight_unit == 'LB' and weight > 70: raise ValidationError(_('Package Weight should not exceed 70 lb!')) if self.endicia_weight_unit == 'OUNCE' and weight > 1120: raise ValidationError(_('Package Weight should not exceed 1120 ounce!')) # added for weight conversion # Convert weight to ounce before creating package #1kg = 35.274 Ounce if self.endicia_weight_unit == 'KG': weight *= 35.274 #1lb = 16 Ounce if self.endicia_weight_unit == 'LB': weight *= 16 ### Sender shipper = order.company_id.partner_id if not shipper: raise ValidationError(_('Shop Address not defined!')) if str(shipper.zip).find("-") != -1: zip_code = str(shipper.zip).split("-")[0] else: zip_code = str(shipper.zip) shipper = endicia.Address( shipper.name, shipper.street, shipper.city, shipper.state_id and shipper.state_id.code, zip_code, shipper.country_id and shipper.country_id.code, shipper.street2, shipper.phone, shipper.email, shipper.name ) ### Recipient recipient = order.partner_shipping_id if str(recipient.zip).find("-") != -1: zip_code = str(recipient.zip).split("-")[0] else: zip_code = str(recipient.zip) recipient = endicia.Address(recipient.name, recipient.street and recipient.street.rstrip(','), recipient.city and recipient.city.rstrip(','), recipient.state_id and recipient.state_id.code, zip_code, recipient.country_id and recipient.country_id.code, recipient.street2 and (recipient.street != recipient.street2) and recipient.street2.rstrip(','), recipient.phone or '', recipient.email, recipient.name or '') credentials = { 'partner_id': self.endicia_requester_id, 'account_id': self.endicia_account_id, 'passphrase': self.endicia_passphrase } en = endicia.Endicia(credentials, self.endicia_test_mode) #creating packages packages = [endicia.Package(self.endicia_service_type, round(weight, 1), endicia.Package.shapes[self.endicia_container], self.endicia_length, self.endicia_width, self.endicia_height, value=1000) ] response = en.rate(packages, endicia.Package.shapes[self.endicia_container], shipper, recipient) if response['status'] == 0: for resp in response["info"]: if resp['service'] == self.endicia_service_type: res += [resp['cost']] return res or [0]