question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Update of delivery methods

See original GitHub issue

Hi I have a delivery method, which is only valid if a customer is living in a certain area in which she/he lives in.

 class ClimateNeutralShippingModifier(ShippingModifier):
     identifier = 'climate-neutral-shipping'

     def get_choice(self):
         return (self.identifier, _("Climate neutral shipping"))

     def is_disabled(self, cart):
         # geolocate address of customer
         if cart.shipping_address:
             postal_code = cart.shipping_address.postal_code
             city = cart.shipping_address.city
             country = cart.shipping_address.country
             distance = checkdistance(postal_code, city, country)
             if distance > settings.SHIPPING_DISTANCE:
                 return True
         return False

     def add_extra_cart_row(self, cart, request):
         if not self.is_active(cart.extra.get('shipping_modifier')) and len(cart_modifiers_pool.get_shipping_modifiers()) > 1:
             return
         amount = Money(settings.BIKING_PRICE)
         instance = {'label': _("Shipping costs"), 'amount': amount}
         cart.extra_rows[self.identifier] = ExtraCartRow(instance)
         cart.total += amount

     def ship_the_goods(self, delivery):
         super().ship_the_goods(delivery)

But somehow it will not be disabled, if distance is greater than my configured shipping distance. And now in my production instance I am getting errors like: Bildschirmfoto 2020-11-18 um 20 58 18 But it should not even be a possibilty to select anyways… This error always occurs for the first shipping. After that this error does not occur anymore. I guess it has to do something with saving shipping address to a customer… but I do not really get any other error than WARNING: Forbidden: /shop/api/shipping_address/add

Any suggestions how to either adapt the error message or check for distance in another way?

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
ay0000commented, Mar 5, 2021

So I think that I have a workaround for at least changing the page display…you may be able to use it in order to just hide the limited delivery option that you’re trying to implement…it’s a little messy and it sometimes loses synchronization but bear with me.

In each one of my modifiers, I made and instantiated an handler class with a getService() function that I can call using AJAX from the clicking the NEXT button or numbered steps at the top of the page that contains the service name.

class AjaxHandler():
    def __init__(self):
        self.friendlyService=''

    def updateService(self,name):
        print(self.friendlyService)
        self.friendlyService=name
        return

    def getService(self,request):
        print((dir(request.POST)),flush=True)
        print((request.POST['tag'][0]),flush=True)
        print(self.friendlyService)
        data={request.POST['tag']:self.friendlyService}
        return JsonResponse(data)

Then I overrode the pre_process_cart() function that it inherits from BaseModifier. Unfortunately that function will run on every single step of the checkout process, even before any address info has been entered, instead of just at the point where the modifier is activated (i.e. after the address has been entered and on the payment/shipping page). This requires some checking in order to ensure that you’re not trying to do anything with address information before it’s even available…which’ll crash the checkout process. This is also the reason for the default values at the top of the class (i.e. shippingCost, postCode, etc.,)

class CanadaPostExpeditedShippingModifier(ShippingModifier):
    """
    This is just a demo on how to implement a shipping modifier, which when selected
    by the customer, adds an additional charge to the cart.
    """
    identifier = 'canpost-expedited'
    service_friendlyName=''
    shippingCost='15'
    postCode=''
    ajaxHandler=AjaxHandler()
    service=0

    currentCountry=None
    currentZip=None

    def pre_process_cart(self, cart, request, raise_exception=False):
        if (hasattr(cart, "shipping_address")):
            if (hasattr(cart.shipping_address, "country")):
                print(cart.shipping_address.country)
                if (self.currentCountry == None or cart.shipping_address.country != self.currentCountry):
                    if(cart.shipping_address.country=='CA' or cart.shipping_address.country=='US'):
                        if(cart.shipping_address.zip_code!=self.currentZip):
                            print("Zip Changed")
                            print(self.shippingCost)
                            self.service_friendlyName, self.shippingCost = cpcOps.getShippingCost(
                                (cart.shipping_address.country,
                                 cart.shipping_address.zip_code),
                                service=self.service)
                            self.ajaxHandler.friendlyService = "{}-{}".format(self.service_friendlyName,
                                                                              self.shippingCost)
                            self.currentZip = cart.shipping_address.zip_code
                            print(self.ajaxHandler.friendlyService)
                    else:
                        print("Country Changed")
                        print(self.shippingCost)
                        self.service_friendlyName, self.shippingCost = cpcOps.getShippingCost(
                            (cart.shipping_address.country,
                             cart.shipping_address.zip_code),
                            service=self.service)
                        self.ajaxHandler.updateService("{}-{}".format(self.service_friendlyName, self.shippingCost))
                        self.currentCountry = cart.shipping_address.country
                        print(self.ajaxHandler.friendlyService)
                else:
                    print("No location change detected")
        return

From there, you can create a checkout folder in your templates folder and copy and paste the shipping-method-form.html, next-step-button.html, process-bar.html, etc., and modify them to your liking. For instance, I needed to break out each individual option that I had so I got rid of the {{shipping_modifier.as_div}} and replaced it with a modified version of the template that it generates.

<script>
function nextAjax() {

		var labelUrlDict={'canpost-regular': '{% url "updateRegShip" %}',
						'canpost-priority': '{% url "updatePriShip" %}',
						'canpost-expedited': '{% url "updateExpShip" %}',
						'canpost-xpressPost': '{% url "updateXprShip" %}'
		}
		var labelTagDict={'canpost-regular': 'label_shipping_method_form-shipping_modifier_2',
						'canpost-priority': 'label_shipping_method_form-shipping_modifier_1',
						'canpost-expedited': 'label_shipping_method_form-shipping_modifier_0',
						'canpost-xpressPost': 'label_shipping_method_form-shipping_modifier_3'
		}


		for(var serviceId in labelUrlDict){
			$.ajax({
			url: labelUrlDict[serviceId],
			type: "POST",
			dataType: 'json',
			data:{'csrfmiddlewaretoken':'{{ csrf_token }}','tag':labelTagDict[serviceId]},
			beforeSend: function() {
    			$('#loader').show();
    			console.log("AJAX Started");
  			},
  			complete: function(){
    			 $('#loader').hide();
    			 console.log("AJAX Done");
  			},
			success: function (data) {
			  if (data) {

				console.log(Object.entries(data));
				$("span[name="+Object.entries(data)[0][0]+"]").text(Object.entries(data)[0][1]);
			  }
			}
		  });

	  	}

}
</script>
{% endaddtoblock %}

...

<form shop-method-form djng-endpoint="{% url 'shop:checkout-upload' %}" name="{{ shipping_method_form.form_name }}" class="mt-3" novalidate>
{% if shipping_method_form.has_choices %}
<div class="djng-line-spreader">
	<ul ng-show="shipping_method_form.$pristine" class="djng-form-errors" ng-cloak>
		<li ng-show="shipping_method_form.$error.rejected && shipping_method_form.$message" class="invalid" ng-bind="shipping_method_form.$message"></li>
	</ul>
</div>
<div class="form-group has-feedback djng-field-required">
	<div id="shipping_method_form-shipping_modifier">
	{% for choice in shipping_method_form.shipping_modifier %}
	<div class="radio">
		<label>
			{{choice.tag}}
			<span class="label" name="label_shipping_method_form-shipping_modifier_{{ forloop.counter0 }}">
				{{choice.choice_label}}
			</span>
		</label>
	</div>
	{% endfor %}
	</div>
	<ul ng-show="shipping_method_form['shipping_modifier'].$dirty && !shipping_method_form['shipping_modifier'].$untouched" class="djng-form-control-feedback djng-field-errors" ng-cloak>
		<li ng-show="shipping_method_form['shipping_modifier'].$error.required" class="invalid">At least one radio button has to be selected.</li>
		<li ng-show="shipping_method_form['shipping_modifier'].$valid" class="valid"></li>
	</ul>
	<ul ng-show="shipping_method_form['shipping_modifier'].$pristine" class="djng-form-control-feedback djng-field-errors" ng-cloak>
		<li ng-show="shipping_method_form['shipping_modifier'].$valid" class="valid"></li>
		<li ng-show="shipping_method_form['shipping_modifier'].$error.rejected && shipping_method_form['shipping_modifier'].$message" class="invalid" ng-bind="shipping_method_form['shipping_modifier'].$message"></li>
	</ul>
	<input type="hidden" name="plugin_id" value="1043" ng-model="shipping_method['plugin_id']" class="form-control" id="shipping_method_form-plugin_id">
	<input type="hidden" name="plugin_order" value="5" ng-model="shipping_method['plugin_order']" class="form-control" id="shipping_method_form-plugin_order">
</div>
	{% if show_additional_charge %}
	<ul class="additional-charge">
		{% for choice, label in shipping_method_form.shipping_modifier.field.choices %}
		<li ng-repeat="extra_row in cart.extra_rows|filter:{modifier:'{{ choice }}'}">{% trans "Additional charge: {{ extra_row.amount }}" context "checkout" %}</li>
		{% endfor %}
		{% if shipping_modifiers.initial_row %}
		<li ng-if="!cart.extra_rows">{% blocktrans with amount=shipping_modifiers.initial_row.amount context "checkout" %}Additional charge: {{ amount }}{% endblocktrans %}</li>
		{% endif %}
	</ul>
	{% endif %}
{% else %}
	<input name="__force_invalidation__" style="display: none;" required />
	<p class="bg-danger">{% trans "No shipping method available" context "checkout" %}</p>
{% endif %}
</form>

I also modified the next-step-button.html file to run the nextAjax() on every click in order to make sure that the information being provided to/by the Python AJAX handler is current.

<button **onclick="nextAjax()"** ng-click="do(prepare()).then(update()).then(showOK()).then(emit('shop.checkout.digest')).then(delay(333)).then(nextStep).catch(scrollToRejected()).finally(restore())

I’m not sure if any of this helps you but you may be able to use the AJAX call to just outright hide the shipping modifier from view instead of changing its name. Let me know what you think.

0reactions
markusmocommented, Mar 7, 2021

Thanks for the extensive research. I wil have a look at it, and will come back to you. It looks promising.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Update Your Delivery Method Component - Salesforce Help
When a buyer makes a purchase, we changed the way delivery methods are updated in your buyer user profiles. If you previously cloned...
Read more >
Editing the delivery methods - IBM
Editing the delivery methods. You can change the delivery method, update the pickup store, and edit or add a new shipping address for...
Read more >
Manage transfers - Western Union
Update delivery method. You can make your cash transfer even more convenient by having it deposited directly into your receiver's bank account.
Read more >
Move Update Data Delivery Method - Official Mail Guide (OMG)
Postage Meter Changes: New Intelligent Mail Indicia (IMI) Mandated In 2024. WASHINGTON, DC — The U.S. Postal Service is moving to a new...
Read more >
Edit the delivery method for an active transfer | Remitly Help
Update your recipient's delivery method on Remitly.com · Navigate to Remitly.com and sign in to your account · Click Transfer History in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found