def get_rates(self, cart, contact): from satchmo_store.shop.models import Config error_ret = False, 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: from django.contrib.sites.models import Site site = Site.objects.get_current() error_message = (u"There's not boxes big enough for some of these " u"products: ({})").format(u", ".join( u"Package({})".format(unicode(p)) for p in rest)) subject = u"There's not boxes big enough for some products" send_store_mail(subject, context={ 'site': site, 'product_list': rest }, template=("canada_post_dp_shipping/admin/mail/" "add_boxes.txt"), send_to_store=True) raise ParcelDimensionError, error_message log.debug(u"Calculated Parcels: [%s]", u",".join(u"({},[{}])".format( pr, u",".join(unicode(pk) for pk in pks)) for pr, pks 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 ) parcel_services = cache.get(cache_key) if parcel_services is None: try: parcel_services = time_f( cpa.get_rates, 'canada-post-dp-shipping.get-rates', parcel, origin, destination) except CanadaPostError, e: if self.settings.RAISE_TOO_LARGE.value and e.code == 9111: raise ParcelDimensionError, e.message else: log.error(u"Canada Post returned with error: %s|%s", e.code, 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 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 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 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("..")