19 Jan 2023 by Karol Kielecki

Saleor 3.8 & 3.9: simple taxes, tax exemption API, and GraphiQL

This article summarizes the 3.8 and 3.9 releases of Saleor. We introduced simple taxes along with a tax exemption API, GraphiQL V2, and more.


Saleor 3.8: GraphiQL 2 and tax exemption API

GraphiQL 2

We have switched to the long-awaited GraphiQL 2 which adds many enhancements compared to the previous playground. Notable improvements are:

  • improved user interface
  • query history
  • merge fragments into query
  • plugin system to create sharable playgrounds - see the video below:

playgif small.gif

Tax exemption API

Delivering the tax exemption API is another leap in our new tax approach. We’ve added a new permission to manage this API - MANAGE TAXES.

This feature may be useful in situations when a customer provides a VAT number in B2B checkouts, even though they intend to pay excluding VAT.

You can use the following mutation to disable taxes from a specific checkout - you can also set a tax exemption for orders. You need to provide a checkout ID, or order ID, and set the flag to false.

mutation {
  taxExemptionManage(id: "checkout-id", taxExemption: false) {
    taxableObject {
      __typename
      ... on Checkout {
        token
      }
    }
  }
}

Check our documentation to learn more about tax exemption API.

Filtering by slugs

You can now filter through a slug in the following objects:

  • Attribute
  • Category
  • Collection
  • Menu
  • Page
  • Product
  • ProductType
  • Warehouse

New product filters

You can use the following new product filters:

  • isAvailable
  • publishedFrom
  • availableFrom
  • isVisibleInListings

Datagrid

Now you can manage product data with a spreadsheet interface directly in the dashboard, bulk updates, copy-paste from external sources, and more 🚀

datagrid4.gif

All summarized pull requests that have been merged are available in the following Saleor 3.8 Changelog.


Saleor 3.9: new tax calculation API

Introduction to tax improvements

With v3.9, we introduced the complete rework of the tax calculation engine. The new tax API allows defining tax rates per country and tax class. What’s more, you can also customize taxes per channel. The following concept introduces tax configuration (a channel configuration) and tax classes (tax for specific countries). We’ve also decided to drop the Vatlayer plugin because our new engine covers a major part of its logic.

Tax configuration

The tax configuration object defines different configuration options for a channel, such as tax calculation method, whether to charge taxes in this channel or whether prices are entered, including tax. The tax configuration object is created automatically for each sales channel. In the API, it is represented by the TaxConfiguration object. See the API reference for descriptions of all properties.

Below are some common examples of getting and managing the tax configuration.

Fetching tax configurations

To fetch a list of tax configurations with their properties, use the following query:

query TaxConfigurations {
  taxConfigurations(first: 10) {
    edges {
      node {
        id
        channel {
          slug
        }
        chargeTaxes
        displayGrossPrices
        pricesEnteredWithTax
        taxCalculationStrategy
      }
    }
  }
}

To query a specific tax configuration by ID, use the query below (in this case, we’re only asking for the taxCalculationStrategy field):

query TaxConfiguration {
  taxConfiguration(id: "VGF4Q29uZmlndXJhdGlvbjox") {
    taxCalculationStrategy
  }
}

Updating the tax configuration

The taxConfigurationUpdate mutation allows you to update a specific tax configuration. The example below shows how to set the tax calculation strategy to dynamic taxes (in API represented as the TAX_APP option):

mutation {
  taxConfigurationUpdate(
    id: "VGF4Q29uZmlndXJhdGlvbjox"
    input: {taxCalculationStrategy: TAX_APP}
  ) {
    errors {
      field
      message
    }
    taxConfiguration {
      taxCalculationStrategy
    }
  }
}

Overriding tax configuration per country

You can override channel-specific tax configurations for different countries. Let’s consider the following example: there is a single sales channel that uses flat rates for EU countries, but for the US, it uses the Avalara integration. To represent such a scenario in Saleor, we need to set the flat rates as the channel’s default tax calculation strategy and override the configuration for the US to use dynamic taxes:

mutation {
  taxConfigurationUpdate(
    id: "VGF4Q29uZmlndXJhdGlvbjox"
    input: {
      taxCalculationStrategy: FLAT_RATES,
      updateCountriesConfiguration: [
        {
          countryCode: US,
          taxCalculationStrategy: TAX_APP,
          displayGrossPrices: false,
          chargeTaxes: true
        }
      ]}
  ) {
    errors {
      field
      message
    }
    taxConfiguration {
      taxCalculationStrategy
      countries {
        country {
          code
        }
        chargeTaxes
        taxCalculationStrategy
        displayGrossPrices
      }
    }
  }
}

Flat tax rates

Flat tax rates are the default tax calculation strategy that is enabled for any new sales channel. With this method, you can configure static tax rates and associate them with products, product types, or shipping methods. Tax rates can be defined either as default country rates or can be overridden for specific products with tax classes. During checkout, Saleor uses either default country rates or overridden values from tax classes.

Enabling flat rates for a channel

To enable flat rates, use the following mutation:

mutation {
  taxConfigurationUpdate(
    id: "VGF4Q29uZmlndXJhdGlvbjox"
    input: {taxCalculationStrategy: FLAT_RATES}
  ) {
    errors {
      field
      message
    }
    taxConfiguration {
      taxCalculationStrategy
    }
  }
}

Creating a default national tax rate

The default national tax rate is used for products and shipping methods when there is no other tax class assigned to them. In the following mutation, we used the Polish default tax rate (23%):

mutation {
  taxCountryConfigurationUpdate(
    countryCode: PL
    updateTaxClassRates: [{rate: 23}]
  ) {
    taxCountryConfiguration {
      country {
        code
      }
      taxClassCountryRates {
        rate
      }
    }
    errors {
      field
      message
    }
  }
}

Assigning a specific tax rate to a product

To create a tax rate that would be used only for specific products, you must create a tax class and assign it to the product. The example below shows a tax class “Healthcare products” with an 8% tax rate for Poland:

mutation {
  taxClassCreate(
    input: {
      name: "Healthcare products",
      createCountryRates: [{countryCode: PL, rate: 8}]}
  ) {
    errors {
      field
      message
    }
    taxClass {
      id
      countries {
        rate
      }
    }
  }
}

To assign a tax class to a product, use the following mutation:

mutation {
  productUpdate(id: "UHJvZHVjdDox", input: {taxClass: "VGF4Q2xhc3M6Mg=="}) {
    errors {
      field
      message
    }
    product {
      taxClass {
        name
      }
    }
  }
}

Setting flat tax rates via dashboard

You can also see how to manage simple taxes via your dashboard in the video below. As you have probably already noticed, we have introduced a new, fresh look to the Saleor Dashboard.

Saleor simple taxes

A flat tax rate is not the only change delivered. Please check the Saleor 3.9 changelog to read more about all improvements.


Thank you!

In this blog post, we highlighted some of the key changes and improvements in Saleor 3.8 and 3.9. Follow our Twitter and sign up for our newsletter to stay up to date with the latest info about Saleor!

Cheers!

– The Saleor Team

— Share

You can also read

View all