benzkji
benzkji

Reputation: 1867

Access basket/shipping address in django oscar pricing strategy

What would be the best practice to get the shipping address in a pricing strategy? Based on the country selected, I would like to apply tax, or not.

I have an instance of CheckoutSessionData in my Selector, and the Selector inherits from CheckoutSessionMixin. But, CheckoutSessionMixin needs a basket for many operations, especially for getting a shipping address. And, the BasketMiddleware gets it's strategy first, and only then sets the basket on the current request.

So, how to get the shipping address, before? Any best practices?

oscar version is 1.6.3

Upvotes: 1

Views: 624

Answers (2)

benzkji
benzkji

Reputation: 1867

for now, I'm using this solution, enabling me to apply tax or not throughout my complete site, where SwissStrategy includes taxes, and InternationalStrategy not. Glad for any feedback.

class Selector(CheckoutSessionMixin):
    """
    Responsible for returning the appropriate strategy class for a given
    user/session.

    This can be called in three ways:

    #) Passing a request and user.  This is for determining
       prices/availability for a normal user browsing the site.

    #) Passing just the user.  This is for offline processes that don't
       have a request instance but do know which user to determine prices for.

    #) Passing nothing.  This is for offline processes that don't
       correspond to a specific user.  Eg, determining a price to store in
       a search index.

    """

    def strategy(self, request=None, user=None, **kwargs):

        # TODO: if request, decide based on location/geoip,
        # if to use swiss or international strategy
        country_id = request.session.get(
            'checkout_data', {}).get('shipping', {}).get('new_address_fields', {}).get('country_id', None)
        try:
            country = Country.objects.get(iso_3166_1_a2=country_id)
        except ObjectDoesNotExist:
            country = None
        if not country or country.iso_3166_1_a2 == 'CH':
            return SwissStrategy(request)
        else:
            return InternationalStrategy(request)

Upvotes: 1

solarissmoke
solarissmoke

Reputation: 31474

I think your issue is addressed in this part of the documentation - how to address US taxes. You basically need to:

  1. Use a DeferredTax strategy that returns prices without taxes applied.

  2. Override and adjust the checkout views to apply taxes once they are known:

    def build_submission(self, **kwargs):
       submission = super().build_submission(**kwargs)
    
        if submission['shipping_address'] and submission['shipping_method']:
            tax.apply_to(submission)
    
            # Recalculate order total to ensure we have a tax-inclusive total
            submission['order_total'] = self.get_order_totals(
                submission['basket'],
                submission['shipping_charge'])
    
        return submission
    

Where tax.apply_to is a function that you define, that determines the appropriate tax for the country of delivery (there's an example in the documentation).

Upvotes: 2

Related Questions