def test0040_account_status_request(self): get_account_status_request_api = AccountStatusAPI( request_id='098765', requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) print get_account_status_request_api.to_xml() response = get_account_status_request_api.send_request() print objectify_response(response)
def test0050_refund_request(self): refund_request = RefundRequestAPI( pic_numbers=[pic_number], requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test='Y', ) print refund_request.to_xml() response = refund_request.send_request() print objectify_response(response)
def test0060_scan_form(self): scan_request = SCANFormAPI( pic_number=pic_number, requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test='Y', ) print scan_request.to_xml() response = scan_request.send_request() print objectify_response(response)
def test0050_refund_request(self): refund_request = RefundRequestAPI( pic_number=pic_number, requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test='Y', ) print refund_request.to_xml() response = refund_request.send_request() print objectify_response(response)
def test0060_scan_form(self): scan_request = SCANFormAPI( pic_numbers=[pic_number], requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test='Y', ) print scan_request.to_xml() response = scan_request.send_request() print objectify_response(response)
def test0020_change_passphrase_request(self): change_passphrase_request_api = ChangingPassPhraseAPI( request_id='098765', new_pass_phrase='my new password', requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) print change_passphrase_request_api.to_xml() response = change_passphrase_request_api.send_request() print objectify_response(response)
def test0010_recredit_request(self): recredit_request_api = BuyingPostageAPI( request_id='098765', recredit_amount=500.00, requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) print recredit_request_api.to_xml() response = recredit_request_api.send_request() print objectify_response(response)
def test0030_calculating_postage_request(self): calculate_postage_request = CalculatingPostageAPI( mailclass='First', weightoz=10.00, from_postal_code="83702", to_postal_code="84301", to_country_code="US", requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) print calculate_postage_request.to_xml() response = calculate_postage_request.send_request() print objectify_response(response)
def get_endicia_shipping_cost(self): """Returns the calculated shipping cost as sent by endicia :returns: The shipping cost in USD """ endicia_credentials = self.company.get_endicia_credentials() if not self.endicia_mailclass: self.raise_user_error('mailclass_missing') calculate_postage_request = CalculatingPostageAPI( mailclass=self.endicia_mailclass.value, weightoz=sum( map(lambda move: move.get_weight_for_endicia(), self.outgoing_moves)), from_postal_code=self.warehouse.address.zip, to_postal_code=self.delivery_address.zip, to_country_code=self.delivery_address.country.code, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.usps_test, ) response = calculate_postage_request.send_request() return Decimal( objectify_response(response).PostagePrice.get('TotalAmount'))
def _buy_postage(self, data): """ Generate the SCAN Form for the current shipment record """ res = data['form'] company_obj = self.pool.get('company.company') # Getting the api credentials to be used in refund request generation # endicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) endicia_credentials = company_obj.get_endicia_credentials() buy_postage_api = BuyingPostageAPI( request_id = Transaction().user, recredit_amount = res['amount'], requesterid = endicia_credentials.requester_id, accountid = endicia_credentials.account_id, passphrase = endicia_credentials.passphrase, test = endicia_credentials.usps_test, ) response = buy_postage_api.send_request() result = objectify_response(response) res['response'] = str(result.ErrorMessage) \ if hasattr(result, 'ErrorMessage') else 'Success' return res
def _request_refund(self, data): """Requests the refund for the current shipment record and returns the response. """ res = data['form'] company_obj = self.pool.get('company.company') shipment_record_obj = self.pool.get('shipment.record') shipment_record = shipment_record_obj.browse(data['id']) # Getting the api credentials to be used in refund request generation # endicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) endicia_credentials = company_obj.get_endicia_credentials() pic_number = shipment_record.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' refund_request = RefundRequestAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = refund_request.send_request() result = objectify_response(response) if str(result.RefundList.PICNumber.IsApproved) == 'YES': refund_approved = True # If refund is approved, then set the state of record # as cancel/refund shipment_record_obj.write(data['id'], {'state': 'cancel'}) else: refund_approved = False res['refund_status'] = str(result.RefundList.PICNumber.ErrorMsg) res['refund_approved'] = refund_approved return res
def make_scanform(self): """ Generate the SCAN Form for bag """ Attachment = Pool().get('ir.attachment') if not self.shipments: self.raise_user_error('bag_empty') pic_numbers = [shipment.tracking_number for shipment in self.shipments] test = self.carrier.endicia_is_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_numbers=pic_numbers, accountid=self.carrier.endicia_account_id, requesterid=self.carrier.endicia_requester_id, passphrase=self.carrier.endicia_passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): self.raise_user_error( 'error_scanform', error_args=(result.ErrorMsg,) ) else: self.submission_id = str(result.SubmissionID) self.save() Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': '%s,%s' % (self.__name__, self.id) }])
def make_scanform(self): """ Generate the SCAN Form for bag """ Attachment = Pool().get('ir.attachment') if not self.shipments: self.raise_user_error('bag_empty') pic_numbers = [shipment.tracking_number for shipment in self.shipments] test = self.carrier.endicia_is_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_numbers=pic_numbers, accountid=self.carrier.endicia_account_id, requesterid=self.carrier.endicia_requester_id, passphrase=self.carrier.endicia_passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): self.raise_user_error('error_scanform', error_args=(result.ErrorMsg, )) else: self.submission_id = str(result.SubmissionID) self.save() Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': '%s,%s' % (self.__name__, self.id) }])
def get_endicia_shipping_cost(self): """Returns the calculated shipping cost as sent by endicia :returns: The shipping cost in USD """ endicia_credentials = self.company.get_endicia_credentials() if not self.endicia_mailclass: self.raise_user_error('mailclass_missing') calculate_postage_request = CalculatingPostageAPI( mailclass=self.endicia_mailclass.value, weightoz=sum(map( lambda move: move.get_weight_for_endicia(), self.outgoing_moves )), from_postal_code=self.warehouse.address.zip, to_postal_code=self.delivery_address.zip, to_country_code=self.delivery_address.country.code, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.usps_test, ) response = calculate_postage_request.send_request() return Decimal( objectify_response(response).PostagePrice.get('TotalAmount') )
def get_shipping_rate(self, carrier, carrier_service=None, silent=False): """ Call the rates service and get possible quotes for shipment for eligible mail classes """ Currency = Pool().get('currency.currency') UOM = Pool().get('product.uom') ModelData = Pool().get('ir.model.data') if carrier.carrier_cost_method != "endicia": return super(Sale, self).get_shipping_rate( carrier, carrier_service, silent ) from_address = self._get_ship_from_address() if self.shipment_address.country.code == "US": mailclass_type = "Domestic" else: mailclass_type = "International" uom_oz = UOM.search([('symbol', '=', 'oz')])[0] # Endicia only support 1 decimal place in weight weight_oz = "%.1f" % UOM.compute_qty( self.weight_uom, self.weight, uom_oz ) to_zip = self.shipment_address.zip if mailclass_type == 'Domestic': to_zip = to_zip and to_zip[:5] else: # International to_zip = to_zip and to_zip[:15] postage_rates_request = PostageRatesAPI( mailclass=mailclass_type, weightoz=weight_oz, from_postal_code=from_address.zip[:5], to_postal_code=to_zip, to_country_code=self.shipment_address.country.code, accountid=carrier.endicia_account_id, requesterid=carrier.endicia_requester_id, passphrase=carrier.endicia_passphrase, test=carrier.endicia_is_test, ) # Logging. logger.debug( 'Making Postage Rates Request for shipping rates of' 'Sale ID: {0} and Carrier ID: {1}' .format(self.id, carrier.id) ) logger.debug('--------POSTAGE RATES REQUEST--------') logger.debug(str(postage_rates_request.to_xml())) logger.debug('--------END REQUEST--------') try: response_xml = postage_rates_request.send_request() response = objectify_response(response_xml) except RequestError, e: self.raise_user_error(unicode(e))
def get_endicia_shipping_rates(self, silent=True): """ Call the rates service and get possible quotes for shipment for eligible mail classes """ Carrier = Pool().get('carrier') UOM = Pool().get('product.uom') EndiciaConfiguration = Pool().get('endicia.configuration') endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() carrier, = Carrier.search(['carrier_cost_method', '=', 'endicia']) from_address = self._get_ship_from_address() mailclass_type = "Domestic" if self.shipment_address.country.code == 'US' \ else "International" uom_oz = UOM.search([('symbol', '=', 'oz')])[0] # Endicia only support 1 decimal place in weight weight_oz = self._get_package_weight(uom_oz).quantize( Decimal('.1'), rounding=ROUND_UP ) to_zip = self.shipment_address.zip if mailclass_type == 'Domestic': to_zip = to_zip and to_zip[:5] else: # International to_zip = to_zip and to_zip[:15] postage_rates_request = PostageRatesAPI( mailclass=mailclass_type, weightoz=weight_oz, from_postal_code=from_address.zip[:5], to_postal_code=to_zip, to_country_code=self.shipment_address.country.code, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.is_test, ) # Logging. logger.debug( 'Making Postage Rates Request for shipping rates of' 'Sale ID: {0} and Carrier ID: {1}' .format(self.id, carrier.id) ) logger.debug('--------POSTAGE RATES REQUEST--------') logger.debug(str(postage_rates_request.to_xml())) logger.debug('--------END REQUEST--------') try: response_xml = postage_rates_request.send_request() response = objectify_response(response_xml) except RequestError, e: self.raise_user_error(unicode(e))
def default_request_refund(self, data): """Requests the refund for the current shipment record and returns the response. """ Shipment = Pool().get('stock.shipment.out') Company = Pool().get('company.company') # Getting the api credentials to be used in refund request generation # endicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) company = Transaction().context.get('company') endicia_credentials = Company(company).get_endicia_credentials() try: shipment, = Shipment.browse(Transaction().context['active_ids']) except ValueError: self.raise_user_error( 'This wizard can be called for only one shipment at a time' ) if not shipment.carrier.carrier_cost_method == 'endicia': self.raise_user_error('wrong_carrier') # PICNumber is the argument name expected by endicia in API, # so its better to use the same name here for better understanding pic_number = shipment.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' refund_request = RefundRequestAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = refund_request.send_request() result = objectify_response(response) if str(result.RefundList.PICNumber.IsApproved) == 'YES': refund_approved = True # If refund is approved, then set the state of record # as cancel/refund shipment.__class__.write( [shipment], {'endicia_refunded': True} ) else: refund_approved = False default = { 'refund_status': unicode(result.RefundList.PICNumber.ErrorMsg), 'refund_approved': refund_approved } return default
def get_endicia_shipping_rates(self, silent=True): """ Call the rates service and get possible quotes for shipment for eligible mail classes """ Carrier = Pool().get('carrier') UOM = Pool().get('product.uom') EndiciaConfiguration = Pool().get('endicia.configuration') endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() carrier, = Carrier.search(['carrier_cost_method', '=', 'endicia']) from_address = self._get_ship_from_address() mailclass_type = "Domestic" if self.shipment_address.country.code == 'US' \ else "International" uom_oz = UOM.search([('symbol', '=', 'oz')])[0] # Endicia only support 1 decimal place in weight weight_oz = "%.1f" % self._get_package_weight(uom_oz) to_zip = self.shipment_address.zip if mailclass_type == 'Domestic': to_zip = to_zip and to_zip[:5] else: # International to_zip = to_zip and to_zip[:15] postage_rates_request = PostageRatesAPI( mailclass=mailclass_type, weightoz=weight_oz, from_postal_code=from_address.zip[:5], to_postal_code=to_zip, to_country_code=self.shipment_address.country.code, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.is_test, ) # Logging. logger.debug('Making Postage Rates Request for shipping rates of' 'Sale ID: {0} and Carrier ID: {1}'.format( self.id, carrier.id)) logger.debug('--------POSTAGE RATES REQUEST--------') logger.debug(str(postage_rates_request.to_xml())) logger.debug('--------END REQUEST--------') try: response_xml = postage_rates_request.send_request() response = objectify_response(response_xml) except RequestError, e: self.raise_user_error(unicode(e))
def test0005_label_request(self): label_request = LabelRequest() shipping_label_api = ShippingLabelAPI( label_request=label_request, weight_oz=10, partner_customer_id=1, partner_transaction_id=1020, requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) shipping_label_api.to_xml() # # Now try to fetch label # self.assertRaises(RequestError, shipping_label_api.send_request) print "Excpected Error: %s" % shipping_label_api.error from_address = FromAddress( FromName="John Doe", ReturnAddress1="123 Main Street", FromCity="Boise", FromState="ID", FromPostalCode="83702", FromZIP4="7261", FromPhone="8005551212" ) to_address = ToAddress( ToName="Amine Khechfe", ToCompany="Endicia", ToAddress1="247 High Street", ToCity="Palo Alto", ToState="CA", ToPostalCode="84301", ToZIP4="0000", ToDeliveryPoint="00", ToPhone="8005763279" ) shipping_label_api.add_data(from_address.data) shipping_label_api.add_data(to_address.data) response = shipping_label_api.send_request() print shipping_label_api.to_xml() assert shipping_label_api.success == True res = objectify_response(response) pic_number = res.TrackingNumber filename = '/tmp/' + str(res.TrackingNumber) + '.gif' f = open(filename, 'wb') f.write(base64.decodestring(str(res.Base64LabelImage))) f.close() print "New Label at: %s" % filename
def default_make_scanform(self, data): """ Generate the SCAN Form for the current shipment record """ Shipment = Pool().get('stock.shipment.out') Company = Pool().get('company.company') Attachment = Pool().get('ir.attachment') # Getting the api credentials to be used in refund request generation # endget_weight_for_endiciaicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) company = Transaction().context.get('company') endicia_credentials = Company(company).get_endicia_credentials() default = {} try: shipment, = Shipment.browse(Transaction().context['active_ids']) except ValueError: self.raise_user_error( 'This wizard can be called for only one shipment at a time') if not shipment.carrier.carrier_cost_method == 'endicia': self.raise_user_error('wrong_carrier') pic_number = shipment.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): default['response'] = result.ErrorMsg else: Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': 'stock.shipment.out,%s' % shipment.id }]) default['response'] = 'SCAN' + str(result.SubmissionID) return default
def default_request_refund(self, data): """Requests the refund for the current shipment record and returns the response. """ Shipment = Pool().get('stock.shipment.out') Company = Pool().get('company.company') # Getting the api credentials to be used in refund request generation # endicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) company = Transaction().context.get('company') endicia_credentials = Company(company).get_endicia_credentials() try: shipment, = Shipment.browse(Transaction().context['active_ids']) except ValueError: self.raise_user_error( 'This wizard can be called for only one shipment at a time') if not shipment.carrier.carrier_cost_method == 'endicia': self.raise_user_error('wrong_carrier') # PICNumber is the argument name expected by endicia in API, # so its better to use the same name here for better understanding pic_number = shipment.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' refund_request = RefundRequestAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = refund_request.send_request() result = objectify_response(response) if str(result.RefundList.PICNumber.IsApproved) == 'YES': refund_approved = True # If refund is approved, then set the state of record # as cancel/refund shipment.__class__.write([shipment], {'endicia_refunded': True}) else: refund_approved = False default = { 'refund_status': unicode(result.RefundList.PICNumber.ErrorMsg), 'refund_approved': refund_approved } return default
def default_make_scanform(self, data): """ Generate the SCAN Form for the current shipment record """ Shipment = Pool().get('stock.shipment.out') Company = Pool().get('company.company') Attachment = Pool().get('ir.attachment') # Getting the api credentials to be used in refund request generation # endget_weight_for_endiciaicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) company = Transaction().context.get('company') endicia_credentials = Company(company).get_endicia_credentials() default = {} try: shipment, = Shipment.browse(Transaction().context['active_ids']) except ValueError: self.raise_user_error( 'This wizard can be called for only one shipment at a time' ) if not shipment.carrier.carrier_cost_method == 'endicia': self.raise_user_error('wrong_carrier') pic_number = shipment.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): default['response'] = result.ErrorMsg else: Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': 'stock.shipment.out,%s' % shipment.id }]) default['response'] = 'SCAN' + str(result.SubmissionID) return default
def test0035_calculating_postage_rates_request(self): calculate_postage_request = PostageRatesAPI( mailclass='Domestic', weightoz=10.00, from_postal_code="83702", to_postal_code="84301", to_country_code="US", requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) print calculate_postage_request.to_xml() response = calculate_postage_request.send_request() rv_obj = objectify_response(response) print rv_obj self.assertTrue(len(rv_obj.PostagePrice) > 1)
def test0005_label_request(self): label_request = LabelRequest() shipping_label_api = ShippingLabelAPI( label_request=label_request, weight_oz=10, partner_customer_id=1, partner_transaction_id=1020, requesterid=REQUESTER_ID, accountid=ACCOUNT_ID, passphrase=PASSPHRASE, test=True, ) shipping_label_api.to_xml() # # Now try to fetch label # self.assertRaises(RequestError, shipping_label_api.send_request) print "Excpected Error: %s" % shipping_label_api.error from_address = FromAddress(FromName="John Doe", ReturnAddress1="123 Main Street", FromCity="Boise", FromState="ID", FromPostalCode="83702", FromZIP4="7261", FromPhone="8005551212") to_address = ToAddress(ToName="Amine Khechfe", ToCompany="Endicia", ToAddress1="247 High Street", ToCity="Palo Alto", ToState="CA", ToPostalCode="84301", ToZIP4="0000", ToDeliveryPoint="00", ToPhone="8005763279") shipping_label_api.add_data(from_address.data) shipping_label_api.add_data(to_address.data) response = shipping_label_api.send_request() print shipping_label_api.to_xml() assert shipping_label_api.success == True res = objectify_response(response) pic_number = res.TrackingNumber filename = '/tmp/' + str(res.TrackingNumber) + '.gif' f = open(filename, 'wb') f.write(base64.decodestring(str(res.Base64LabelImage))) f.close() print "New Label at: %s" % filename
class BuyPostageWizard(Wizard): """Buy Postage Wizard """ __name__ = 'buy.postage.wizard' start = StateView('buy.postage.wizard.view', 'shipping_endicia.endicia_buy_postage_wizard_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Buy Postage', 'buy_postage', 'tryton-ok'), ]) buy_postage = StateView( 'buy.postage.wizard.view', 'shipping_endicia.endicia_buy_postage_wizard_view_form', [ Button('OK', 'end', 'tryton-ok'), ]) def default_buy_postage(self, data): """ Generate the SCAN Form for the current shipment record """ EndiciaConfiguration = Pool().get('endicia.configuration') default = {} endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() buy_postage_api = BuyingPostageAPI( request_id=Transaction().user, recredit_amount=self.start.amount, requesterid=endicia_credentials.requester_id, accountid=endicia_credentials.account_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.is_test, ) try: response = buy_postage_api.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error, )) result = objectify_response(response) default['company'] = self.start.company default['amount'] = self.start.amount default['response'] = str(result.ErrorMessage) \ if hasattr(result, 'ErrorMessage') else 'Success' return default
def make_scanform(self): """ Generate the SCAN Form for bag """ EndiciaConfiguration = Pool().get('endicia.configuration') Attachment = Pool().get('ir.attachment') # Getting the api credentials to be used in refund request generation # endget_weight_for_endiciaicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() if not self.shipments: self.raise_user_error('bag_empty') pic_numbers = [shipment.tracking_number for shipment in self.shipments] test = endicia_credentials.is_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_numbers=pic_numbers, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): self.raise_user_error('error_scanform', error_args=(result.ErrorMsg, )) else: self.submission_id = str(result.SubmissionID) self.save() Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': '%s,%s' % (self.__name__, self.id) }])
def close(cls, manifests): """ Generate the SCAN Form for manifest """ Attachment = Pool().get('ir.attachment') super(ShippingManifest, cls).close(manifests) for manifest in manifests: if not manifest.shipments: manifest.raise_user_error('manifest_empty') if manifest.carrier_cost_method != 'endicia': continue pic_numbers = [ shipment.tracking_number.tracking_number for shipment in manifest.shipments if shipment.tracking_number ] test = manifest.carrier.endicia_is_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_numbers=pic_numbers, accountid=manifest.carrier.endicia_account_id, requesterid=manifest.carrier.endicia_requester_id, passphrase=manifest.carrier.endicia_passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): manifest.raise_user_error( 'error_scanform', error_args=(result.ErrorMsg,) ) else: Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': '%s,%s' % (manifest.__name__, manifest.id) }])
def make_scanform(self): """ Generate the SCAN Form for bag """ EndiciaConfiguration = Pool().get('endicia.configuration') Attachment = Pool().get('ir.attachment') # Getting the api credentials to be used in refund request generation # endget_weight_for_endiciaicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() if not self.shipments: self.raise_user_error('bag_empty') pic_numbers = [shipment.tracking_number for shipment in self.shipments] test = endicia_credentials.is_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_numbers=pic_numbers, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): self.raise_user_error( 'error_scanform', error_args=(result.ErrorMsg,) ) else: self.submission_id = str(result.SubmissionID) self.save() Attachment.create([{ 'name': 'SCAN%s.png' % str(result.SubmissionID), 'data': buffer(base64.decodestring(result.SCANForm.pyval)), 'resource': '%s,%s' % (self.__name__, self.id) }])
def get_sale_price(self, carrier): """Estimates the shipment rate for the provided shipment """ company_obj = self.pool.get('company.company') shipment_obj = self.pool.get('stock.shipment.out') if carrier.carrier_cost_method != 'endicia-usps': return super(CarrierUSPS, self).get_sale_price(carrier) # Getting the api credentials to be used in shipping label generation # endicia credentials are in the format : # EndiciaSettings(account_id, requester_id, passphrase, is_test) endicia_credentials = company_obj.get_endicia_credentials() shipment_id = Transaction().context['id'] if shipment_id: shipment = shipment_obj.browse(shipment_id) #From location is the warehouse location. So it must be filled. location = shipment.warehouse.address if not location: self.raise_user_error('location_required') line_weights = shipment_obj.get_move_line_weights(shipment_id, 'oz') calculate_postage_request = CalculatingPostageAPI( mailclass = carrier.carrier_product.code, weightoz = sum(line_weights.values()), from_postal_code = location.zip, to_postal_code = shipment.delivery_address.zip, to_country_code = shipment.delivery_address.country.code, accountid = endicia_credentials.account_id, requesterid = endicia_credentials.requester_id, passphrase = endicia_credentials.passphrase, test = endicia_credentials.usps_test, ) response = calculate_postage_request.send_request() return objectify_response(response).PostagePrice.\ get('TotalAmount'), False else: return 0, False
def default_buy_postage(self, data): """ Generate the SCAN Form for the current shipment record """ default = {} company = self.start.company endicia_credentials = company.get_endicia_credentials() buy_postage_api = BuyingPostageAPI( request_id=Transaction().user, recredit_amount=self.start.amount, requesterid=endicia_credentials.requester_id, accountid=endicia_credentials.account_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.usps_test, ) response = buy_postage_api.send_request() result = objectify_response(response) default['company'] = self.start.company default['amount'] = self.start.amount default['response'] = str(result.ErrorMessage) \ if hasattr(result, 'ErrorMessage') else 'Success' return default
def _make_scanform(self, data): """ Generate the SCAN Form for the current shipment record """ res = data['form'] company_obj = self.pool.get('company.company') attachment_obj = self.pool.get('ir.attachment') shipment_record_obj = self.pool.get('shipment.record') shipment_record = shipment_record_obj.browse(data['id']) # Getting the api credentials to be used in refund request generation # endicia credentials are in the format : # (account_id, requester_id, passphrase, is_test) endicia_credentials = company_obj.get_endicia_credentials() # tracking_no is same as PICNumber pic_number = shipment_record.tracking_number test = endicia_credentials.usps_test and 'Y' or 'N' scan_request = SCANFormAPI( pic_number=pic_number, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=test, ) response = scan_request.send_request() result = objectify_response(response) if not hasattr(result, 'SCANForm'): res['response'] = result.ErrorMsg else: attachment_obj.create({ 'name': 'SCAN' + str(result.SubmissionID), 'data': str(result.SCANForm), 'resource': 'shipment.record,%s' % data['id']}) res['response'] = 'SCAN' + str(result.SubmissionID) return res
ToCompany="Endicia", ToAddress1="247 High Street", ToCity="Palo Alto", ToState="CA", ToPostalCode="84301", ToZIP4="0000", ToDeliveryPoint="00", ToPhone="8005763279" ) shipping_label_api.add_data(from_address.data) shipping_label_api.add_data(to_address.data) print shipping_label_api.to_xml() response = shipping_label_api.send_request() objectify_response(response) """ A more complicated example """ customs_item1 = [ Element('Description','My Beautiful Shoes'), Element('Quantity', 1), Element('Weight', 10), Element('Value', 50), ] customs_item2 = [ Element('Description','My Beautiful Dress'), Element('Quantity', 1), Element('Weight', 10), Element('Value', 50), ]
if self.endicia_label_subtype != 'None': # Integrated form type needs to be sent for international shipments shipping_label_request.add_data({ 'IntegratedFormType': self.endicia_integrated_form_type, }) self._update_endicia_item_details(shipping_label_request) try: response = shipping_label_request.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error, )) else: result = objectify_response(response) tracking_number = result.TrackingNumber.pyval self.__class__.write( [self], { 'tracking_number': unicode(result.TrackingNumber.pyval), 'cost': Decimal(str(result.FinalPostage.pyval)), }) # Save images as attachments images = get_images(result) for (id, label) in images: Attachment.create([{ 'name': "%s_%s_USPS-Endicia.png" % (tracking_number, id), 'data':
self._update_endicia_item_details(shipping_label_request) # Logging. logger.debug('Making Shipping Label Request for' 'Shipment ID: {0} and Carrier ID: {1}'.format( self.id, self.carrier.id)) logger.debug('--------SHIPPING LABEL REQUEST--------') logger.debug(str(shipping_label_request.to_xml())) logger.debug('--------END REQUEST--------') try: response = shipping_label_request.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error, )) else: result = objectify_response(response) # Logging. logger.debug('--------SHIPPING LABEL RESPONSE--------') logger.debug(str(response)) logger.debug('--------END RESPONSE--------') tracking_number = result.TrackingNumber.pyval self.__class__.write( [self], { 'tracking_number': unicode(result.TrackingNumber.pyval), 'cost': Decimal(str(result.FinalPostage.pyval)), }) # Save images as attachments images = get_images(result)
class EndiciaRefundRequestWizard(Wizard): """A wizard to cancel the current shipment and refund the cost """ __name__ = 'endicia.refund.wizard' start = StateView( 'endicia.refund.wizard.view', 'shipping_endicia.endicia_refund_wizard_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button( 'Request Refund', 'request_refund', 'tryton-ok', default=True), ]) request_refund = StateView( 'endicia.refund.wizard.view', 'shipping_endicia.endicia_refund_wizard_view_form', [ Button('OK', 'end', 'tryton-ok', default=True), ]) @classmethod def __setup__(self): super(EndiciaRefundRequestWizard, self).__setup__() self._error_messages.update( {'wrong_carrier': 'Carrier for selected shipment is not Endicia'}) def default_request_refund(self, data): """Requests the refund for the current shipment record and returns the response. """ Shipment = Pool().get('stock.shipment.out') shipments = Shipment.browse(Transaction().context['active_ids']) # PICNumber is the argument name expected by endicia in API, # so its better to use the same name here for better understanding pic_numbers = [] for shipment in shipments: if not (shipment.carrier and shipment.carrier.carrier_cost_method == 'endicia'): self.raise_user_error('wrong_carrier') pic_numbers.append(shipment.tracking_number) test = shipment.carrier.endicia_is_test and 'Y' or 'N' refund_request = RefundRequestAPI( pic_numbers=pic_numbers, accountid=shipment.carrier.endicia_account_id, requesterid=shipment.carrier.endicia_requester_id, passphrase=shipment.carrier.endicia_passphrase, test=test, ) try: response = refund_request.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error, )) result = objectify_response(response) if str(result.RefundList.PICNumber.IsApproved) == 'YES': refund_approved = True # If refund is approved, then set the state of record # as cancel/refund shipment.__class__.write([shipment], {'endicia_refunded': True}) else: refund_approved = False default = { 'refund_status': unicode(result.RefundList.PICNumber.ErrorMsg), 'refund_approved': refund_approved } return default
class Sale: "Sale" __name__ = 'sale.sale' endicia_mailclass = fields.Many2One( 'endicia.mailclass', 'MailClass', states={ 'readonly': ~Eval('state').in_(['draft', 'quotation']), }, depends=['state']) endicia_mailpiece_shape = fields.Selection( MAILPIECE_SHAPES, 'Endicia MailPiece Shape', states={ 'readonly': ~Eval('state').in_(['draft', 'quotation']), }, depends=['state']) is_endicia_shipping = fields.Function( fields.Boolean('Is Endicia Shipping?', readonly=True), 'get_is_endicia_shipping') @classmethod def view_attributes(cls): return super(Sale, cls).view_attributes() + [ ('//page[@id="endicia"]', 'states', { 'invisible': ~Bool(Eval('is_endicia_shipping')) }) ] def _get_weight_uom(self): """ Returns uom for endicia """ UOM = Pool().get('product.uom') if self.is_endicia_shipping: # Endicia by default uses this uom return UOM.search([('symbol', '=', 'oz')])[0] return super(Sale, self)._get_weight_uom() @staticmethod def default_endicia_mailclass(): Config = Pool().get('sale.configuration') config = Config(1) return config.endicia_mailclass and config.endicia_mailclass.id or None @classmethod def __setup__(cls): super(Sale, cls).__setup__() cls._error_messages.update({ 'mailclass_missing': 'Select a mailclass to ship using Endicia [USPS].' }) cls._buttons.update({ 'update_endicia_shipment_cost': { 'invisible': Eval('state') != 'quotation' } }) @fields.depends('is_endicia_shipping', 'carrier') def on_change_carrier(self): super(Sale, self).on_change_carrier() self.is_endicia_shipping = self.carrier and \ self.carrier.carrier_cost_method == 'endicia' or None def _get_carrier_context(self): "Pass sale in the context" context = super(Sale, self)._get_carrier_context() if not self.carrier.carrier_cost_method == 'endicia': return context context = context.copy() context['sale'] = self.id return context def on_change_lines(self): """Pass a flag in context which indicates the get_sale_price method of endicia carrier not to calculate cost on each line change """ with Transaction().set_context({'ignore_carrier_computation': True}): return super(Sale, self).on_change_lines() def apply_endicia_shipping(self): "Add a shipping line to sale for endicia" Currency = Pool().get('currency.currency') if self.carrier and self.carrier.carrier_cost_method == 'endicia': if not self.endicia_mailclass: self.raise_user_error('mailclass_missing') with Transaction().set_context(self._get_carrier_context()): shipment_cost_usd = self.carrier.get_sale_price() if not shipment_cost_usd[0]: return # Convert the shipping cost to sale currency from USD usd, = Currency.search([('code', '=', 'USD')]) shipment_cost = Currency.compute(usd, shipment_cost_usd[0], self.currency) self.add_shipping_line( shipment_cost, '%s - %s' % (self.carrier.party.name, self.endicia_mailclass.name)) @classmethod def quote(cls, sales): res = super(Sale, cls).quote(sales) cls.update_endicia_shipment_cost(sales) return res @classmethod @ModelView.button def update_endicia_shipment_cost(cls, sales): "Updates the shipping line with new value if any" for sale in sales: sale.apply_endicia_shipping() def create_shipment(self, shipment_type): Shipment = Pool().get('stock.shipment.out') with Transaction().set_context(ignore_carrier_computation=True): # disable `carrier cost computation`(default behaviour) as cost # should only be computed after updating mailclass else error may # occur, with improper mailclass. shipments = super(Sale, self).create_shipment(shipment_type) if shipment_type == 'out' and shipments and self.carrier and \ self.carrier.carrier_cost_method == 'endicia': Shipment.write( shipments, { 'endicia_mailclass': self.endicia_mailclass.id, 'endicia_mailpiece_shape': self.endicia_mailpiece_shape, 'is_endicia_shipping': self.is_endicia_shipping, }) return shipments def get_endicia_shipping_cost(self, mailclass=None): """Returns the calculated shipping cost as sent by endicia :param mailclass: endicia mailclass for which cost to be fetched :returns: The shipping cost in USD """ Carrier = Pool().get('carrier') EndiciaConfiguration = Pool().get('endicia.configuration') endicia_credentials = EndiciaConfiguration(1).get_endicia_credentials() carrier, = Carrier.search(['carrier_cost_method', '=', 'endicia']) if not mailclass and not self.endicia_mailclass: self.raise_user_error('mailclass_missing') from_address = self._get_ship_from_address() to_address = self.shipment_address to_zip = to_address.zip if to_address.country and to_address.country.code == 'US': # Domestic to_zip = to_zip and to_zip[:5] else: # International to_zip = to_zip and to_zip[:15] # Endicia only support 1 decimal place in weight weight_oz = "%.1f" % self.package_weight calculate_postage_request = CalculatingPostageAPI( mailclass=mailclass or self.endicia_mailclass.value, MailpieceShape=self.endicia_mailpiece_shape, weightoz=weight_oz, from_postal_code=from_address.zip and from_address.zip[:5], to_postal_code=to_zip, to_country_code=to_address.country and to_address.country.code, accountid=endicia_credentials.account_id, requesterid=endicia_credentials.requester_id, passphrase=endicia_credentials.passphrase, test=endicia_credentials.is_test, ) # Logging. logger.debug('Making Postage Request for shipping cost of' 'Sale ID: {0} and Carrier ID: {1}'.format( self.id, carrier.id)) logger.debug('--------POSTAGE REQUEST--------') logger.debug(str(calculate_postage_request.to_xml())) logger.debug('--------END REQUEST--------') try: response = calculate_postage_request.send_request() except RequestError, e: self.raise_user_error(unicode(e)) # Logging. logger.debug('--------POSTAGE RESPONSE--------') logger.debug(str(response)) logger.debug('--------END RESPONSE--------') return self.fetch_endicia_postage_rate( objectify_response(response).PostagePrice)
def _make_label(self, carrier, shipment, options): """ Create a label for given shipment and return the response as such :param carrier: Browse Record of shipment method :param shipment: Browse Record of outgoing shipment :param options: Dictionary of values """ address_obj = self.pool.get('party.address') company_obj = self.pool.get('company.company') shipment_obj = self.pool.get('stock.shipment.out') line_weights = shipment_obj.get_move_line_weights(shipment.id, 'oz') # Getting the api credentials to be used in shipping label generation # endicia credentials are in the format : # EndiciaSettings(account_id, requester_id, passphrase, is_test) endicia_credentials = company_obj.get_endicia_credentials() mailclass = carrier.carrier_product.code or \ 'FirstClassMailInternational' label_request = LabelRequest( Test=endicia_credentials.usps_test and 'YES' or 'NO', LabelType= ('International' in mailclass) and 'International' \ or 'Default', # this size and dpi combi works only for FirstClassInternational ImageFormat="PNG", LabelSize="6x4", ImageResolution="203", ImageRotation="Rotate270", ) delivery_address = shipment.delivery_address shipping_label_api = ShippingLabelAPI( label_request=label_request, weight_oz=sum(line_weights.values()), partner_customer_id=delivery_address.id, partner_transaction_id=shipment.id, mail_class=mailclass, accountid = endicia_credentials.account_id, requesterid = endicia_credentials.requester_id, passphrase = endicia_credentials.passphrase, test = endicia_credentials.usps_test, ) #From location is the warehouse location. So it must be filled. location = shipment.warehouse.address if not location: self.raise_user_error('location_required') from_address = address_obj.address_to_endicia_from_address(location.id) to_address = address_obj.address_to_endicia_to_address( delivery_address.id) shipping_label_api.add_data(from_address.data) shipping_label_api.add_data(to_address.data) shipping_label_api.add_data({ 'LabelSubtype': options['label_sub_type'], 'IncludePostage': options['include_postage'] and 'TRUE' or 'FALSE', }) if options['label_sub_type'] != 'None': shipping_label_api.add_data({ 'IntegratedFormType': options['integrated_form_type'], }) #Comment this line if not required shipping_label_api = self._add_items_from_moves(shipping_label_api, shipment.inventory_moves, line_weights) response = shipping_label_api.send_request() return objectify_response(response)
# Logging. logger.debug( 'Making Shipping Label Request for' 'Shipment ID: {0} and Carrier ID: {1}' .format(self.id, self.carrier.id) ) logger.debug('--------SHIPPING LABEL REQUEST--------') logger.debug(str(shipping_label_request.to_xml())) logger.debug('--------END REQUEST--------') try: response = shipping_label_request.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error.message,)) else: result = objectify_response(response) # Logging. logger.debug('--------SHIPPING LABEL RESPONSE--------') logger.debug(str(response)) logger.debug('--------END RESPONSE--------') tracking_number = unicode(result.TrackingNumber.pyval) stock_package = self.packages[0] tracking, = Tracking.create([{ 'carrier': self.carrier, 'tracking_number': tracking_number, 'origin': '%s,%d' % ( stock_package.__name__, stock_package.id ), }])
# Logging. logger.debug( 'Making Shipping Label Request for' 'Shipment ID: {0} and Carrier ID: {1}' .format(self.id, self.carrier.id) ) logger.debug('--------SHIPPING LABEL REQUEST--------') logger.debug(str(shipping_label_request.to_xml())) logger.debug('--------END REQUEST--------') try: response = shipping_label_request.send_request() except RequestError, error: self.raise_user_error('error_label', error_args=(error,)) else: result = objectify_response(response) # Logging. logger.debug('--------SHIPPING LABEL RESPONSE--------') logger.debug(str(response)) logger.debug('--------END RESPONSE--------') tracking_number = result.TrackingNumber.pyval self.__class__.write([self], { 'tracking_number': unicode(result.TrackingNumber.pyval), 'cost': Decimal(str(result.FinalPostage.pyval)), }) # Save images as attachments images = get_images(result) for (id, label) in images: