def setUp(self): self.interface = CanadaPostAPI( customer_number=api_details.AUTH.customer_number, username=api_details.AUTH.username, password=api_details.AUTH.password, contract_number=None, dev=api_details.AUTH.dev)
class TestNonContractShipping(unittest.TestCase): """ Tests the Non-Contract Shipping use case as detailed on Canada Posts's Non-Contract Shipping documentation """ def setUp(self): self.interface = CanadaPostAPI( customer_number=api_details.AUTH.customer_number, username=api_details.AUTH.username, password=api_details.AUTH.password, contract_number=None, dev=api_details.AUTH.dev) #def test_interface_auth(self): # """ Test the CanadaPostAPI interface constructon with Auth object """ # interface = CanadaPostAPI(auth = api_details.AUTH) # self.assertEqual(interface.auth.username, api_details.AUTH.username) def test_interface_kwargs(self): """ Test the CanadaPostAPI interface constructor with key word args""" self.assertEqual(self.interface.auth.username, api_details.AUTH.username) def test_create_nc_shipment(self): """ The typical route used for shipping without a Canada Post contract: * Create Non-Contract Shipment * Get Artifact """ pass def test_get_nc_shipment_receipt(self): """ Test the Get Non-Contract Shipment receipt """ pass def test_get_nc_shipment_details(self): """ Tests Get Non-Contract Shipment Details """ def test_get_nc_shipments(self): """ Tests Get Non-Contract Shipments """ from_date = date(1960, 1, 1).strftime("%Y%m%d0000") self.interface.nc_get_shipments(from_date) def test_get_nc_shipment(self): """ Get Non-Contract Shipment """ pass
def create_shipments(self, request, id): from satchmo_store.shop.models import Config order_shipping = get_object_or_404(OrderShippingService, id=id) if request.method == 'GET': opts = self.model._meta title = _("Please confirm the parcels size and weight") object_name = unicode(opts.verbose_name) app_label = opts.app_label context = { "title": title, "object_name": object_name, "object": order_shipping, "opts": opts, "root_path": self.admin_site.root_path, "app_label": app_label, } return render(request, ("canada_post_dp_shipping/admin/" "confirm_shipments.html"), context) elif request.REQUEST.get('post', None) == "yes": # else method is POST shop_details = Config.objects.get_current() cpa_kwargs = canada_post_api_kwargs(self.settings) cpa = CanadaPostAPI(**cpa_kwargs) origin = get_origin(shop_details) destination = get_destination(order_shipping.order.contact) group = unicode(order_shipping.shipping_group()) cnt = 0 exs = 0 for parcel in (order_shipping.parceldescription_set .select_related().all()): try: if parcel.shipment: exs += 1 except Shipment.DoesNotExist: shipment = cpa.create_shipment( parcel=parcel.get_parcel(), origin=origin, destination=destination, service=order_shipping.get_service(), group=group) Shipment(shipment=shipment, parcel=parcel).save() cnt += 1 self.message_user(request, _("{count} shipments created for order " "{order}").format( count=cnt, order=order_shipping.order)) if exs > 0: messages.warning(request, _("{count} shipments already existed " "for {order}").format( count=exs, order=order_shipping.order)) else: messages.error(request, _("Unexpected error, please retry")) return HttpResponseRedirect("..")
def transmit_shipments(queryset=None, send_msg=None): log.info("transmit_shipments invoked") log.debug("queryset: %s", str(queryset)) if send_msg is None: send_msg = lambda x: x if queryset is None: queryset = OrderShippingService.objects.all() from satchmo_store.shop.models import Config shop_details = Config.objects.get_current() settings = config_get_group('canada_post_dp_shipping') cpa_kwargs = canada_post_api_kwargs(settings) cpa = CanadaPostAPI(**cpa_kwargs) origin = get_origin(shop_details) groups = [] order_shippings = [] for order_shipping in queryset.filter(transmitted=False): log.debug("processing order shipping: %s", order_shipping) if order_shipping.shipments_created(): log.debug("shipments created") group = unicode(order_shipping.shipping_group()) groups.append(group) order_shippings.append(order_shipping) else: log.debug("shipments not created") log.debug("using groups: %s", groups) if groups: log.info("transmitting shipments") links = time_f(cpa.transmit_shipments, 'canada-post-dp-shipping.transmit-shipments', origin, groups) log.debug("received manifests: %s", links) log.debug("marking order shippings as transmitted") for order_shipping in order_shippings: order_shipping.transmitted = True order_shipping.save() manifest_count = len(links) log.info("received %d manifests", manifest_count) send_msg( ungettext_lazy( "{count} manifest generated. It will be sent via email in a " "couple of minutes".format(count=manifest_count), "{count} manifests generated. They will be sent via email in a " "couple of minutes".format(count=manifest_count), manifest_count)) if USE_CELERY: get_manifests_async.apply_async(args=(links, ), cowntdown=1) else: get_manifests(links) group_count = len(groups) send_msg( ungettext_lazy( "Transmitted shipments for {count} group".format( count=group_count), "Transmitted shipments for {count} groups".format( count=group_count), group_count))
def get_rates(self, cart, contact): from satchmo_store.shop.models import Config error_ret = False, None, None shop_details = Config.objects.get_current() # always use production api keys for get_rates, you don't get charged # anyways cpa_kwargs = canada_post_api_kwargs(self.settings, production=True) cpa = CanadaPostAPI(**cpa_kwargs) # parcels is a list of (Parcel, pack(dimensions)) parcels, rest = self.make_parcels(cart) if rest: log.error("There's not boxes big enough for some of these " "products: {}".format(rest)) return error_ret log.debug("Calculated Parcels: [%s]", ",".join("({})".format(unicode(p)) for p in parcels)) origin = get_origin(shop_details) destination = get_destination(contact) services = [] for parcel, packs in parcels: # rates depend on dimensions + origin + destination only cache_key = "CP-GetRates-{W}-{l}x{w}x{h}-{fr}-{to}".format( W=parcel.weight, w=parcel.width, h=parcel.height, l=parcel.length, fr=origin.postal_code, to=destination.postal_code ) if cache.has_key(cache_key): parcel_services = cache.get(cache_key) else: try: parcel_services = cpa.get_rates(parcel, origin, destination) except CanadaPostError, e: if self.settings.RAISE_TOO_LARGE.value and e.code == 9111: raise ParcelTooLarge, e.message parcel_services = [] cache.set(cache_key, parcel_services) # so services is [(Service, parcel, [packs]),...] services.extend(product(filter(lambda s: s.code == self.service_code, parcel_services), [parcel], [packs]))
def void_shipments(self, request, queryset=None, id=-1): if queryset is None: if queryset is None: queryset = [get_object_or_404(OrderShippingService, id=id)] else: queryset = queryset.select_related() cpa_kwargs = canada_post_api_kwargs(self.settings) cpa = CanadaPostAPI(**cpa_kwargs) errcnt = 0 gdcnt = 0 dne = 0 for detail in queryset: for parcel in detail.parceldescription_set.all().select_related(): try: shipment = parcel.shipment cpa_shipment = shipment.get_shipment() if not cpa.void_shipment(cpa_shipment): errcnt += 1 self.message_user(request, _("Could not void shipment " "{shipment_id} for order " "{order_id}").format( shipment_id=shipment.id, order_id=detail.order.id)) else: gdcnt += 1 shipment.delete() except Shipment.DoesNotExist: dne += 1 if not errcnt: self.message_user(request, _("All shipments voided")) else: messages.warning(request, _("{good_count} shipments voided, " "{bad_count} problems").format( good_count=gdcnt, bad_count=errcnt)) if dne: self.message_user(request, _("{count} shipments didn't " "exist").format(count=dne)) if id >= 0: return HttpResponseRedirect("..")
def void_shipments(self, request, queryset=None, id=-1): log.info("void shipments %s", queryset or str(id)) if queryset is None: if queryset is None: queryset = [get_object_or_404(OrderShippingService, id=id)] else: queryset = queryset.select_related() cpa_kwargs = canada_post_api_kwargs(self.settings) cpa = CanadaPostAPI(**cpa_kwargs) errcnt = 0 gdcnt = 0 dne = 0 for detail in queryset: log.debug('Processing detail: %s', detail) for parcel in detail.parceldescription_set.all().select_related(): log.debug("Processing parcel: %s", parcel) try: shipment = parcel.shipment log.debug("Got shipment %s", shipment) cpa_shipment = shipment.get_shipment() if not time_f(cpa.void_shipment, 'canada-post-dp-shipping.void-shipment', cpa_shipment): log.warn("Problem voiding shipment: %s", cpa_shipment) errcnt += 1 self.message_user(request, _("Could not void shipment " "{shipment_id} for order " "{order_id}").format( shipment_id=shipment.id, order_id=detail.order.id)) else: log.debug("Shipment voided, deleting from DB") gdcnt += 1 shipment.delete() except Shipment.DoesNotExist: log.debug("Shipment does not exist!") dne += 1 if not errcnt: log.info("All shipments voided") self.message_user(request, _("All shipments voided")) else: log.warn("%d shipments voided, %d problems", gdcnt, errcnt) messages.warning(request, _("{good_count} shipments voided, " "{bad_count} problems").format( good_count=gdcnt, bad_count=errcnt)) if dne: log.debug("%d shipments didn't exist", dne) self.message_user(request, _("{count} shipments didn't " "exist").format(count=dne)) if id >= 0: return HttpResponseRedirect("..")
def get_manifests(links): log.info("Getting manifests from links: %s", links) settings = config_get_group('canada_post_dp_shipping') cpa_kwargs = canada_post_api_kwargs(settings) cpa = CanadaPostAPI(**cpa_kwargs) manifests = [] for link in links: log.debug("Getting manifest from %s", link['href']) try: cpa_manifest = time_f(cpa.get_manifest, 'canada-post-dp-shipping.get-manifest', link) manifest = Manifest(manifest=cpa_manifest) manifest_pdf = time_f(cpa.get_artifact, 'canada-post-dp-shipping.get-artifact', cpa_manifest) filename = os.path.basename(link['href'].rstrip('/')) if not filename.endswith('.pdf'): filename += '.pdf' manifest.artifact = File(manifest_pdf, filename) manifest.save() shipments = time_f( cpa.get_manifest_shipments, 'canada-post-dp-shipping.get-manifest-shipments', cpa_manifest) for shipment_id in shipments: log.info("Setting manifest for shipment %s", shipment_id) try: shipment = Shipment.objects.select_related().get( id=shipment_id) shipping_detail = shipment.parcel.shipping_detail shipping_detail.manifest = manifest shipping_detail.save() except Shipment.DoesNotExist: log.error("Requested shipment does not exist") manifests.append(manifest) except Exception, e: log.error("Error processing manifest: %s", e, exc_info=True)
def create_shipments(self, request, id): log.info("Creating shipments for %s", str(id)) from satchmo_store.shop.models import Config order_shipping = get_object_or_404(OrderShippingService, id=id) log.debug("Got OrderShippingService: %s", order_shipping) if request.method == 'GET': log.debug("GET. Ask for confirmation") opts = self.model._meta title = _("Please confirm the parcels size and weight") object_name = unicode(opts.verbose_name) app_label = opts.app_label context = { "title": title, "object_name": object_name, "object": order_shipping, "opts": opts, "root_path": self.admin_site.root_path, "app_label": app_label, } return render(request, ("canada_post_dp_shipping/admin/" "confirm_shipments.html"), context) elif request.REQUEST.get('post', None) == "yes": log.debug("POST with value=yes") # else method is POST shop_details = Config.objects.get_current() cpa_kwargs = canada_post_api_kwargs(self.settings) cpa = CanadaPostAPI(**cpa_kwargs) origin = get_origin(shop_details) destination = get_destination(order_shipping.order.contact) options = None if destination.country_code != 'CA': # TODO: make this selectable through website options = [Option(code='RASE')] group = unicode(order_shipping.shipping_group()) cnt = 0 exs = 0 for parcel in (order_shipping.parceldescription_set .select_related().all()): log.debug("Creating shipment for parcel %s", parcel) try: if parcel.shipment: log.warn("Shipment already existed in DB! %s", parcel.shipment) exs += 1 except Shipment.DoesNotExist: log.debug("Creating shipment") cpa_ship = time_f( cpa.create_shipment, 'canada-post-dp-shipping.create-shipping', parcel=parcel.get_parcel(), origin=origin, destination=destination, service=order_shipping.get_service(), group=group, options=options) shipment = Shipment(shipment=cpa_ship, parcel=parcel) shipment.save() log.debug("Shipment created: %s", shipment) if USE_CELERY: from canada_post_dp_shipping.tasks import get_label log.debug("Calling get_label celery task") get_label.apply_async(args=(shipment.id, cpa.auth.username, cpa.auth.password), # download labels in 3 minutes countdown=3*60) cnt += 1 log.info("%d shipments created for order %s", cnt, order_shipping.order) self.message_user(request, _(u"{count} shipments created for order " u"{order}").format( count=cnt, order=order_shipping.order)) if USE_CELERY: log.debug("Using celery. Task to download labels should run in " "3 minutes") self.message_user(request, _(u"Shipping labels will be " u"automatically downloaded in " u"three minutes")) if exs > 0: log.warn("%d shipments already existed for order %s", exs, order_shipping.order) messages.warning(request, _(u"{count} shipments already existed " u"for {order}").format( count=exs, order=order_shipping.order)) else: messages.error(request, _("Unexpected error, please retry")) return HttpResponseRedirect("..")