Source code for royal_mail_rest_api.tools

import datetime
from royal_mail_rest_api.errors import *

[docs]class RoyalMailBody: service_formats = { 'inland_large_letter': 'F', 'inland_letter': 'L', 'inland_format_not_applicable': 'N', 'inland_parcel': 'P', 'international_parcel': 'E', 'international_large_letter': 'G', 'international_format_not_applicable': 'N', 'international_letter': 'P' } service_types = { 'royal_mail_24': '1', 'Royal Mail 48': '2', 'special_delivery': 'D', 'BFPO': 'H', 'international': 'I', 'tracked_returns': 'R', 'royal_mail_tracked': 'T' } service_offerings = { "royal_mail_24_48": "CRL", "intl_bus_parcels_zero_sort_hi_vol_priority_i": "DE1", "intl_bus_parcels_zero_sort_hi_vol_economy_": "DE3", "intl_bus_parcels_zero_srt_lo_vol_priority_": "DE4", "intl_bus_parcels_zero_srt_lo_vol_economy_": "DE6", "intl_bus_mail_l_ltr_ctry_srt_hi_vol_priority_": "DG1", "intl_bus_mail_l_ltr_ctry_srt_hi_vol_economy_": "DG3", "intl_bus_mail_l_ltr_ctry_srt_lo_vol_priority_": "DG4", "intl_bus_mail_l_ltr_ctry_srt_lo_vol_economy_": "DG6", "royal_mail_24_sort8_ll_flat_rate": "FS1", "royal_mail_48_sort8_ll_flat_rate": "FS2", "intl_bus_parcels_zone_sort_priority_": "IE1", "intl_bus_parcels_zone_sort_economy": "IE3", "intl_bus_mail_lrg_ltr_zone_sort_pri": "IG1", "intl_bus_mail_lrg_ltr_zone_sort_economy": "IG3", "intl_bus_mail_lrg_ltr_zone_srt_pri_mch": "IG4", "intl_bus_mail_l_ltr_zone_srt_economy_mch_": "IG6", "intl_bus_parcels_print_direct_priority": "MB1", "intl_bus_parcels_print_direct_standard": "MB2", "intl_bus_parcels_print_direct_economy": "MB3", "intl_bus_parcels_signed_extra_comp_ctry": "MP0", "intl_bus_parcels_tracked": "MP1", "intl_bus_parcels_tracked_extra_comp": "MP4", "intl_bus_parcels_signed": "MP5", "intl_bus_parcels_signed_extra_comp": "MP6", "intl_bus_parcels_tracked_country_priced": "MP7", "intl_bus_parcels_tracked_extra_comp_ctry": "MP8", "intl_bus_parcels_signed_country_priced": "MP9", "intl_bus_parcels_tracked_and_signed": "MTA", "intl_bus_parcels_tracked_signed_xtr_comp": "MTB", "intl_bus_mail_tracked_and_signed": "MTC", "intl_bus_mail_tracked_and_signed_xtr_comp": "MTD", "intl_bus_parcels_tracked_and_signed__ctry": "MTE", "intl_bus_parcel_track&sign_xtr_cmp_ctry": "MTF", "intl_bus_mail_tracked_and_signed_country": "MTG", "intl_bus_mail_track_and_sign_xtr_comp_ctry": "MTH", "intl_bus_mail_tracked": "MTI", "intl_bus_mail_tracked_extra_comp": "MTJ", "intl_bus_mail_tracked_country_priced": "MTK", "intl_bus_mail_tracked_extra_comp_ctry": "MTL", "intl_bus_mail_signed": "MTM", "intl_bus_mail_signed_extra_comp": "MTN", "intl_bus_mail_signed_country_priced": "MTO", "intl_bus_mail_signed_extra_comp_country": "MTP", "intl_bus_parcels_zone_sort_plus_priority": "MTQ", "intl_bus_parcels_zone_srt_plus_economy": "MTS", "intl_standard_on_account": "OLA", "intl_economy_on_account": "OLS", "international_signed_on_account": "OSA", "intl_signed_on_account_extra_comp": "OSB", "international_tracked_on_account": "OTA", "intl_tracked_on_account_extra_comp": "OTB", "international_tracked_and_signed_on_acct": "OTC", "intl_tracked_and_signed_on_acct_extra_comp": "OTD", "intl_bus_mail_mixed_zone_sort_priority": "OZ1", "intl_bus_mail_mixed_zone_sort_economy": "OZ3", "intl_bus_mail_mixed_zone_sort_pri_mch": "OZ4", "intl_bus_mail_mixed_zone_srt_economy_mch": "OZ6", "royal_mail_48_ll_flat_rate": "PK0", "royal_mail_24_sort8_p_flat_rate": "PK1", "royal_mail_48_sort8_p_flat_rate": "PK2", "royal_mail_24_sort8_llp_daily_rate": "PK3", "royal_mail_48_sort8_llp_daily_rate": "PK4", "royal_mail_24_ll_flat_rate": "PK9", "royal_mail_24_48_p_flat_rate": "PPF", "intl_bus_parcels_max_sort_economy": "PS0", "intl_bus_parcels_max_sort_standard": "PSC", "intl_bus_parcels_max_sort_priority": "PS9", "intl_bus_mail_lrg_ltr_max_sort_economy": "PS8", "intl_bus_mail_lrg_ltr_max_sort_standard": "PSB", "intl_bus_mail_lrg_ltr_max_sort_priority": "PS7", "royal_mail_48_sort8_p_daily_rate": "RM0", "royal_mail_24_ll_daily_rate": "RM1", "royal_mail_24_p_daily_rate": "RM2", "royal_mail_48_ll_daily_rate": "RM3", "royal_mail_48_p_daily_rate": "RM4", "royal_mail_24_p_flat_rate": "RM5", "royal_mail_48_p_flat_rate": "RM6", "royal_mail_24_sort8_ll_daily_rate": "RM7", "royal_mail_24_sort8_p_daily_rate": "RM8", "royal_mail_48_sort8_ll_daily_rate": "RM9", "sd_guaranteed_by_1pm": "SD1", "sd_guaranteed_by_1pm_1000": "SD2", "sd_guaranteed_by_1pm_2500": "SD3", "sd_guaranteed_by_9am": "SD4", "sd_guaranteed_by_9am_1000": "SD5", "sd_guaranteed_by_9am_2500": "SD6", "1st_and_2nd_class_account_mail": "STL", "royal_mail_tracked_48_hv": "TPL", "royal_mail_tracked_24_hv": "TPM", "royal_mail_tracked_24": "TPN", "royal_mail_tracked_48": "TPS", "royal_mail_tracked_48_lbt_hv": "TRL", "royal_mail_tracked_24_lbt_hv": "TRM", "royal_mail_tracked_24_lbt": "TRN", "royal_mail_tracked_48_lbt": "TRS", "royal_mail_tracked_returns_24": "TSN", "royal_mail_tracked_returns_48": "TSS", "intl_bus_parcels_zero_sort_priority": "WE1", "intl_bus_parcels_zero_sort_economy": "WE3", "intl_bus_mail_lrg_ltr_zero_srt_priority": "WG1", "intl_bus_mail_lrg_ltr_zero_sort_economy": "WG3", "intl_bus_mail_lrg_ltr_zero_srt_pri_mch": "WG4", "intl_bus_mail_l_ltr_zero_srt_economy_mch": "WG6", "intl_bus_mail_mixed_zero_sort_priority": "WW1", "intl_bus_mail_mixed_zero_sort_economy": "WW3", "intl_bus_mail_mixed_zero_sort_pri_mch": "WW4", "intl_bus_mail_mixd_zero_srt_economy_mch": "WW6", "intl_bus_mail_mixed_zero_sort_premium": "ZC1", } service_enhancements = { "loss_1000": "1", "loss_2500": "2", "loss_5000": "3", "loss_7500": "4", "loss_10000": "5", "recorded": "6", "loss_750": "11", "signature": "12", "sms_notification": "13", "e-mail_notification": "14", "safeplace": "15", "sms_and_e-mail_notification": "16", "local_collect": "22", "saturday_guaranteed": "24", } def __init__(self, shipment_type): self.receipient = None self.address = None self.service = None self.shipping_date = None self._check_ship_type(shipment_type) self.sender_reference = None self.department_reference = None self.customer_reference = None self.items = [] self.item_count = len(self.items) self.safe_place = None self.enhancements = []
[docs] def return_domestic_body(self): """ build domestic body from items :return: """ domestic_body = { 'shipmentType': self.shipment_type, 'service': self._add_service(), 'shippingDate': self.shipping_date, 'items': self.items, 'recipientContact': self.receipient, 'recipientAddress': self.address, 'senderReference': self.sender_reference, 'departmentReference': self.department_reference, 'customerReference': self.customer_reference, 'safePlace': self.safe_place } return domestic_body
[docs] def return_domestic_update_boy(self): """ build domestic body from items :return: """ domestic_body = { 'service': self.service, 'shippingDate': self.shipping_date, 'recipientContact': self.receipient, 'recipientAddress': self.address, 'senderReference': self.sender_reference, 'departmentReference': self.department_reference, 'customerReference': self.customer_reference, 'safePlace': self.safe_place } return domestic_body
[docs] @staticmethod def remove_none_values(iterable): """ take out values of None by removing the key :param iterable: :return: dictionary """ new_dict = {k: v for k, v in iterable.items() if v is not None} return new_dict
def _check_ship_type(self, shipment_type): """ Check that the shipment type is valid (currently only delivery) :param shipment_type: :return: """ if shipment_type.lower() != 'delivery': # TODO: Find out the other options here! raise ValueError('Sorry, only delivery supported at the moment') else: self.shipment_type = shipment_type.lower()
[docs] def add_ship_date(self, date_obj=None): """ take a datetime object and format it to royal mails Y-m-d format :param date_obj: :return: """ if date_obj is None: date_obj = datetime.datetime.today() if isinstance(date_obj, datetime.datetime): self.shipping_date = datetime.datetime.strftime(date_obj, '%Y-%m-%d') else: raise(TypeError('Sorry, need a datetime object'))
def _add_service(self): """ create our service block from already added inputs :return: """ service = { "format": self.service_format, "occurrence": self.service_occurence, "offering": self.service_offering, "type": self.service_type, "signature": self.signature, "enhancements": self.enhancements } return service
[docs] def add_service_format(self, format=None): """ add a valid service format using our friendly names :param format: :return: """ if format is None: raise(ValueError('No service format selected')) if format not in self.service_formats: raise(KeyError('Invalid service format')) self.service_format = self.service_formats[format]
[docs] def add_service_type(self, service_type=None): """ add a valid service type using our friendly names :param service_type: :return: """ if service_type is None: raise(ValueError('no service type selected')) if service_type not in self.service_types: raise(KeyError('Invalid service type')) self.service_type = self.service_types[service_type]
[docs] def add_service_offering(self, service_offering=None): """ add a valid service offering using our friendly names :param service_offering: :return: """ if service_offering is None: raise(ValueError('No service type selected')) if service_offering not in self.service_offerings: raise(KeyError('Invalid service type')) self.service_offering = self.service_offerings[service_offering]
[docs] def add_service_occurence(self): # TODO - what is this, can't find anything in the docs self.service_occurence = 1
[docs] def add_signature(self, signature=False): """ Do we want a signature on delivery :param signature: :return: """ if isinstance(signature, bool): self.signature = signature else: raise(TypeError('Must be a boolean, True or False'))
[docs] def add_service_enhancements(self, enhancement): """ add a single service enhancement, can be called multiple times to append required items :param enhancement: :return: """ if enhancement is None: raise(ValueError('No Enhancement Selected')) if enhancement not in self.service_enhancements: raise(KeyError('Not in service_enhancements')) self.enhancements.append(self.service_enhancements[enhancement])
[docs] def add_receipient_contact(self, name, email, complementary_name=None, telephone=None): """ Add the name and contact of who this is being sent to :param name: :param email: :param complementary_name: :param telephone: :return: """ receipient = { "name": name, "complementaryName": complementary_name, "telephoneNumber": telephone, "email": email } # receipient = self.remove_none_values(receipient) self.receipient = receipient
[docs] def add_items(self, number, weight, unit_of_measure): """ Add items- currently only a single item :param number: :param weight: :param unit_of_measure: :return: """ items = [{ "count": number, "weight": { "unitOfMeasure": unit_of_measure, "value": weight }, }] self.items = items
[docs] def add_receipient_address(self, address_line1, post_town, county, postcode, country, building_name=None, building_number=None, address_line2=None, address_line3=None): """ Add address of receipient :param address_line1: :param post_town: :param county: :param postcode: :param country: :param building_name: :param building_number: :param address_line2: :param address_line3: :return: """ address = { "buildingName": building_name, "buildingNumber": building_number, "addressLine1": address_line1, "addressLine2": address_line2, "addressLine3": address_line3, "postTown": post_town, "county": county, "postCode": postcode, "country": country } # address = self.remove_none_values(address) self.address = address