Avalara Tax Plugin - Tax Exemption?

9 months ago
RomanovM wrote:
Thanks. And one more request-response with type SalesInvoice, not SalesOrder as in your previous post.


I'm checking the source code now but the request/response I sent (with Type SalesOrder) is what is called when the Shopping Cart page is loaded.

I will get back to you with some more information ASAP. Thank you for your time, so far!
9 months ago
RomanovM wrote:
Thanks. And one more request-response with type SalesInvoice, not SalesOrder as in your previous post.


Yes, when I load the ShoppingCart page, this is the series of methods that are called:

1. Nop.Web.Factories.ShoppingCartModelFactory.cs > PrepareOrderTotalsModelAsync(cart, isEditable)
2. Nop.Services.Orders.OrderTotalCalculationService.cs > GetTaxTotalAsync(cart, usePaymentMethodAdditionalFee)
3. Nop.Services.Tax.TaxService.cs > GetTaxTotalAsync(cart, usePaymentMethodAdditionalFee)
4. Nop.Plugin.Tax.Avalara.AvalaraTaxProvider.cs > GetTaxTotalAsync(taxTotalRequest)
5. which calls the following code:


public async Task<TransactionModel> CreateTaxTotalTransactionAsync(TaxTotalRequest taxTotalRequest) {
    // ...
    // eventually, we prepare the model with DocumentType.SalesOrder below:
    // 👇👇👇👇
    var model = await PrepareTransactionModelAsync(address, customer.Id.ToString(), DocumentType.SalesOrder);
}


As you can see, this is the NopCommerce v4.4 code which calculates tax on the Shopping Cart page.

Are you suggesting that I either change that to DocumentType.SalesInvoice?
Or should I call
AvalaraTaxManager.CreateOrderTaxTransactionAsync(taxTotalRequest)
instead, since that one uses the DocumentType.SalesInvoice?
9 months ago
I suggest not modifying the plugin code unless necessary.
Type "SalesOrder" is used to pre-calculate taxes in the cart and during the checkout process, and such a request isn't saved in the transaction history. Type "SalesInvoice" is used for the final tax calculation when placing an order and is saved in the transaction history, you can see it in your AvaTax account.

I completed the request by our test account using your data from previous posts. Here is the result.
request:

{
  "lines": [
    {
      "quantity": 2.0,
      "amount": 118.1400,
      "itemCode": "11521",
      "exemptionCode": "",
      "discounted": false,
      "description": "Test T-Shirt"
    }
  ],
  "type": "SalesOrder",
  "companyCode": "APITrialCompany",
  "date": "2023-09-19T11:19:41.523822Z",
  "customerCode": "35700",
  "discount": 0.0,
  "exemptionNo": "Exempt-customer-#35700",
  "addresses": {
    "shipFrom": {
      "line1": "PO Box 123",
      "city": "Mequon",
      "region": "WI",
      "country": "US",
      "postalCode": "53097"
    },
    "shipTo": {
      "line1": "123 Main St",
      "city": "BUFFALO",
      "region": "WY",
      "country": "US",
      "postalCode": "82831-1234"
    }
  },
  "email": "<REDACTED>"
}

response:

{
  "id": 0,
  "code": "d3b3224a-c186-4b75-abb7-eb7b1b06995a",
  "companyId": "<REDACTED>",
  "date": "2023-09-19",
  "paymentDate": "2023-09-19",
  "status": "Temporary",
  "type": "SalesOrder",
  "batchCode": "",
  "currencyCode": "USD",
  "exchangeRateCurrencyCode": "USD",
  "customerUsageType": "",
  "entityUseCode": "",
  "customerVendorCode": "35700",
  "customerCode": "35700",
  "exemptNo": "Exempt-customer-#35700",
  "reconciled": false,
  "locationCode": "",
  "reportingLocationCode": "",
  "purchaseOrderNo": "",
  "referenceCode": "",
  "salespersonCode": "",
  "totalAmount": 118.14,
  "totalExempt": 118.14,
  "totalDiscount": 0.0,
  "totalTax": 0.0,
  "totalTaxable": 0.0,
  "totalTaxCalculated": 0.0,
  "adjustmentReason": "NotAdjusted",
  "locked": false,
  "version": 1,
  "exchangeRateEffectiveDate": "2023-09-19",
  "exchangeRate": 1.0,
  "email": "<REDACTED>",
  "modifiedDate": "2023-09-19T11:20:16.7601038Z",
  "modifiedUserId": 212348,
  "taxDate": "2023-09-19",
  "lines": [
    {
      "id": 0,
      "transactionId": 0,
      "lineNumber": "1",
      "customerUsageType": "",
      "entityUseCode": "",
      "description": "Test T-Shirt",
      "discountAmount": 0.0,
      "exemptAmount": 118.14,
      "exemptCertId": 0,
      "exemptNo": "",
      "isItemTaxable": false,
      "itemCode": "11521",
      "lineAmount": 118.14,
      "quantity": 2.0,
      "ref1": "",
      "ref2": "",
      "reportingDate": "2023-09-19",
      "tax": 0.0,
      "taxableAmount": 0.0,
      "taxCalculated": 0.0,
      "taxCode": "P0000000",
      "taxCodeId": 8087,
      "taxDate": "2023-09-19",
      "taxIncluded": false,
      "details": [
        {
          "id": 0,
          "transactionLineId": 0,
          "transactionId": 0,
          "country": "US",
          "region": "WY",
          "exemptAmount": 118.14,
          "jurisCode": "56",
          "jurisName": "WYOMING",
          "stateAssignedNo": "",
          "jurisType": "STA",
          "jurisdictionType": "State",
          "nonTaxableAmount": 0.0,
          "rate": 0.040000,
          "tax": 0.0,
          "taxableAmount": 0.0,
          "taxType": "Sales",
          "taxSubTypeId": "S",
          "taxName": "WY STATE TAX",
          "taxAuthorityTypeId": 45,
          "taxCalculated": 0.0,
          "rateType": "General",
          "rateTypeCode": "G",
          "unitOfBasis": "PerCurrencyUnit",
          "isNonPassThru": false,
          "isFee": false,
          "reportingTaxableUnits": 0.0,
          "reportingNonTaxableUnits": 0.0,
          "reportingExemptUnits": 118.14,
          "reportingTax": 0.0,
          "reportingTaxCalculated": 0.0,
          "liabilityType": "Seller",
          "chargedTo": "Buyer"
        },
        {
          "id": 0,
          "transactionLineId": 0,
          "transactionId": 0,
          "country": "US",
          "region": "WY",
          "exemptAmount": 118.14,
          "jurisCode": "019",
          "jurisName": "JOHNSON",
          "stateAssignedNo": "16",
          "jurisType": "CTY",
          "jurisdictionType": "County",
          "nonTaxableAmount": 0.0,
          "rate": 0.010000,
          "tax": 0.0,
          "taxableAmount": 0.0,
          "taxType": "Sales",
          "taxSubTypeId": "S",
          "taxName": "WY COUNTY TAX",
          "taxAuthorityTypeId": 45,
          "taxCalculated": 0.0,
          "rateType": "General",
          "rateTypeCode": "G",
          "unitOfBasis": "PerCurrencyUnit",
          "isNonPassThru": false,
          "isFee": false,
          "reportingTaxableUnits": 0.0,
          "reportingNonTaxableUnits": 0.0,
          "reportingExemptUnits": 118.14,
          "reportingTax": 0.0,
          "reportingTaxCalculated": 0.0,
          "liabilityType": "Seller",
          "chargedTo": "Buyer"
        }
      ],
      "nonPassthroughDetails": [],
      "hsCode": "",
      "costInsuranceFreight": 0.0,
      "vatCode": "",
      "vatNumberTypeId": 0
    }
  ],
  "addresses": [
    {
      "id": 0,
      "transactionId": 0,
      "boundaryLevel": "Address",
      "line1": "123 Main St",
      "line2": "",
      "line3": "",
      "city": "BUFFALO",
      "region": "WY",
      "postalCode": "82831-1234",
      "country": "US",
      "taxRegionId": 4005530,
      "latitude": "44.345528",
      "longitude": "-106.698155"
    },
    {
      "id": 0,
      "transactionId": 0,
      "boundaryLevel": "Zip5",
      "line1": "PO Box 123",
      "line2": "",
      "line3": "",
      "city": "Mequon",
      "region": "WI",
      "postalCode": "53097",
      "country": "US",
      "taxRegionId": 4006722,
      "latitude": "43.221791",
      "longitude": "-87.951726"
    }
  ],
  "summary": [
    {
      "country": "US",
      "region": "WY",
      "jurisType": "State",
      "jurisCode": "56",
      "jurisName": "WYOMING",
      "taxAuthorityType": 45,
      "stateAssignedNo": "",
      "taxType": "Sales",
      "taxSubType": "S",
      "taxName": "WY STATE TAX",
      "rateType": "General",
      "taxable": 0.0,
      "rate": 0.040000,
      "tax": 0.0,
      "taxCalculated": 0.0,
      "nonTaxable": 0.0,
      "exemption": 118.14
    },
    {
      "country": "US",
      "region": "WY",
      "jurisType": "County",
      "jurisCode": "019",
      "jurisName": "JOHNSON",
      "taxAuthorityType": 45,
      "stateAssignedNo": "16",
      "taxType": "Sales",
      "taxSubType": "S",
      "taxName": "WY COUNTY TAX",
      "rateType": "General",
      "taxable": 0.0,
      "rate": 0.010000,
      "tax": 0.0,
      "taxCalculated": 0.0,
      "nonTaxable": 0.0,
      "exemption": 118.14
    }
  ]
}


The text of the requests is almost the same, but as you can see the difference in the response is in the field "isItemTaxable", in my case it's "false", which leads to the correct calculation of taxes.

So the plugin works correctly. I recommend you place a test order (type "SalesInvoice", so that the transaction is saved in account history) and contact Avalara support with a reference to this transaction, perhaps a problem in your AvaTax account settings.
9 months ago
RomanovM wrote:
I suggest not modifying the plugin code unless necessary.
Type "SalesOrder" is used to pre-calculate taxes in the cart and during the checkout process, and such a request isn't saved in the transaction history. Type "SalesInvoice" is used for the final tax calculation when placing an order and is saved in the transaction history, you can see it in your AvaTax account.

I completed the request by our test account using your data from previous posts. Here is the result.
request:

{
  "lines": [
    {
      "quantity": 2.0,
      "amount": 118.1400,
      "itemCode": "11521",
      "exemptionCode": "",
      "discounted": false,
      "description": "Test T-Shirt"
    }
  ],
  "type": "SalesOrder",
  "companyCode": "APITrialCompany",
  "date": "2023-09-19T11:19:41.523822Z",
  "customerCode": "35700",
  "discount": 0.0,
  "exemptionNo": "Exempt-customer-#35700",
  "addresses": {
    "shipFrom": {
      "line1": "PO Box 123",
      "city": "Mequon",
      "region": "WI",
      "country": "US",
      "postalCode": "53097"
    },
    "shipTo": {
      "line1": "123 Main St",
      "city": "BUFFALO",
      "region": "WY",
      "country": "US",
      "postalCode": "82831-1234"
    }
  },
  "email": "<REDACTED>"
}

response:

{
  "id": 0,
  "code": "d3b3224a-c186-4b75-abb7-eb7b1b06995a",
  "companyId": "<REDACTED>",
  "date": "2023-09-19",
  "paymentDate": "2023-09-19",
  "status": "Temporary",
  "type": "SalesOrder",
  "batchCode": "",
  "currencyCode": "USD",
  "exchangeRateCurrencyCode": "USD",
  "customerUsageType": "",
  "entityUseCode": "",
  "customerVendorCode": "35700",
  "customerCode": "35700",
  "exemptNo": "Exempt-customer-#35700",
  "reconciled": false,
  "locationCode": "",
  "reportingLocationCode": "",
  "purchaseOrderNo": "",
  "referenceCode": "",
  "salespersonCode": "",
  "totalAmount": 118.14,
  "totalExempt": 118.14,
  "totalDiscount": 0.0,
  "totalTax": 0.0,
  "totalTaxable": 0.0,
  "totalTaxCalculated": 0.0,
  "adjustmentReason": "NotAdjusted",
  "locked": false,
  "version": 1,
  "exchangeRateEffectiveDate": "2023-09-19",
  "exchangeRate": 1.0,
  "email": "<REDACTED>",
  "modifiedDate": "2023-09-19T11:20:16.7601038Z",
  "modifiedUserId": 212348,
  "taxDate": "2023-09-19",
  "lines": [
    {
      "id": 0,
      "transactionId": 0,
      "lineNumber": "1",
      "customerUsageType": "",
      "entityUseCode": "",
      "description": "Test T-Shirt",
      "discountAmount": 0.0,
      "exemptAmount": 118.14,
      "exemptCertId": 0,
      "exemptNo": "",
      "isItemTaxable": false,
      "itemCode": "11521",
      "lineAmount": 118.14,
      "quantity": 2.0,
      "ref1": "",
      "ref2": "",
      "reportingDate": "2023-09-19",
      "tax": 0.0,
      "taxableAmount": 0.0,
      "taxCalculated": 0.0,
      "taxCode": "P0000000",
      "taxCodeId": 8087,
      "taxDate": "2023-09-19",
      "taxIncluded": false,
      "details": [
        {
          "id": 0,
          "transactionLineId": 0,
          "transactionId": 0,
          "country": "US",
          "region": "WY",
          "exemptAmount": 118.14,
          "jurisCode": "56",
          "jurisName": "WYOMING",
          "stateAssignedNo": "",
          "jurisType": "STA",
          "jurisdictionType": "State",
          "nonTaxableAmount": 0.0,
          "rate": 0.040000,
          "tax": 0.0,
          "taxableAmount": 0.0,
          "taxType": "Sales",
          "taxSubTypeId": "S",
          "taxName": "WY STATE TAX",
          "taxAuthorityTypeId": 45,
          "taxCalculated": 0.0,
          "rateType": "General",
          "rateTypeCode": "G",
          "unitOfBasis": "PerCurrencyUnit",
          "isNonPassThru": false,
          "isFee": false,
          "reportingTaxableUnits": 0.0,
          "reportingNonTaxableUnits": 0.0,
          "reportingExemptUnits": 118.14,
          "reportingTax": 0.0,
          "reportingTaxCalculated": 0.0,
          "liabilityType": "Seller",
          "chargedTo": "Buyer"
        },
        {
          "id": 0,
          "transactionLineId": 0,
          "transactionId": 0,
          "country": "US",
          "region": "WY",
          "exemptAmount": 118.14,
          "jurisCode": "019",
          "jurisName": "JOHNSON",
          "stateAssignedNo": "16",
          "jurisType": "CTY",
          "jurisdictionType": "County",
          "nonTaxableAmount": 0.0,
          "rate": 0.010000,
          "tax": 0.0,
          "taxableAmount": 0.0,
          "taxType": "Sales",
          "taxSubTypeId": "S",
          "taxName": "WY COUNTY TAX",
          "taxAuthorityTypeId": 45,
          "taxCalculated": 0.0,
          "rateType": "General",
          "rateTypeCode": "G",
          "unitOfBasis": "PerCurrencyUnit",
          "isNonPassThru": false,
          "isFee": false,
          "reportingTaxableUnits": 0.0,
          "reportingNonTaxableUnits": 0.0,
          "reportingExemptUnits": 118.14,
          "reportingTax": 0.0,
          "reportingTaxCalculated": 0.0,
          "liabilityType": "Seller",
          "chargedTo": "Buyer"
        }
      ],
      "nonPassthroughDetails": [],
      "hsCode": "",
      "costInsuranceFreight": 0.0,
      "vatCode": "",
      "vatNumberTypeId": 0
    }
  ],
  "addresses": [
    {
      "id": 0,
      "transactionId": 0,
      "boundaryLevel": "Address",
      "line1": "123 Main St",
      "line2": "",
      "line3": "",
      "city": "BUFFALO",
      "region": "WY",
      "postalCode": "82831-1234",
      "country": "US",
      "taxRegionId": 4005530,
      "latitude": "44.345528",
      "longitude": "-106.698155"
    },
    {
      "id": 0,
      "transactionId": 0,
      "boundaryLevel": "Zip5",
      "line1": "PO Box 123",
      "line2": "",
      "line3": "",
      "city": "Mequon",
      "region": "WI",
      "postalCode": "53097",
      "country": "US",
      "taxRegionId": 4006722,
      "latitude": "43.221791",
      "longitude": "-87.951726"
    }
  ],
  "summary": [
    {
      "country": "US",
      "region": "WY",
      "jurisType": "State",
      "jurisCode": "56",
      "jurisName": "WYOMING",
      "taxAuthorityType": 45,
      "stateAssignedNo": "",
      "taxType": "Sales",
      "taxSubType": "S",
      "taxName": "WY STATE TAX",
      "rateType": "General",
      "taxable": 0.0,
      "rate": 0.040000,
      "tax": 0.0,
      "taxCalculated": 0.0,
      "nonTaxable": 0.0,
      "exemption": 118.14
    },
    {
      "country": "US",
      "region": "WY",
      "jurisType": "County",
      "jurisCode": "019",
      "jurisName": "JOHNSON",
      "taxAuthorityType": 45,
      "stateAssignedNo": "16",
      "taxType": "Sales",
      "taxSubType": "S",
      "taxName": "WY COUNTY TAX",
      "rateType": "General",
      "taxable": 0.0,
      "rate": 0.010000,
      "tax": 0.0,
      "taxCalculated": 0.0,
      "nonTaxable": 0.0,
      "exemption": 118.14
    }
  ]
}


The text of the requests is almost the same, but as you can see the difference in the response is in the field "isItemTaxable", in my case it's "false", which leads to the correct calculation of taxes.

So the plugin works correctly. I recommend you place a test order (type "SalesInvoice", so that the transaction is saved in account history) and contact Avalara support with a reference to this transaction, perhaps a problem in your AvaTax account settings.


Thank you for the reply, but that is not correct.
The item IS taxable; the customer is tax-exempt. I can't change the product/item to not be taxable.  If you re-try the request with the "isItemTaxable" set to true, please let me know what you receive as a response because that is more accurate to my use-case.

The issue here is that both SalesOrder and SalesInvoice is returning tax for customers which are tax-exempt. I have not modified the AvaTax plugin code.
9 months ago
cleyva wrote:

I can't change the product/item to not be taxable.  If you re-try the request with the "isItemTaxable" set to true


This is not a request field, this is what the AvaTax service returns in the response, please look carefully. The item is not taxable because the customer is tax exempt. This analysis is performed by AvaTax.

cleyva wrote:

The issue here is that both SalesOrder and SalesInvoice is returning tax for customers which are tax-exempt.


"is returning tax" is the source of the problem. As you can see, for my test request tax is calculated and returned correctly, but for yours, it's not and this is not a plugin problem, contact Avalara support.
9 months ago
RomanovM wrote:

I can't change the product/item to not be taxable.  If you re-try the request with the "isItemTaxable" set to true


This is not a request field, this is what the AvaTax service returns in the response, please look carefully. The item is not taxable because the customer is tax exempt. This analysis is performed by AvaTax.


The issue here is that both SalesOrder and SalesInvoice is returning tax for customers which are tax-exempt.


"is returning tax" is the source of the problem. As you can see, for my test request tax is calculated and returned correctly, but for yours, it's not and this is not a plugin problem, contact Avalara support.


OK, I see. I have reached out to Avalara and they told me that Wisconsin is a Streamlined Sales Tax (SST) state and that for this customer I need to do some additional steps:  1. Add a customer in Avalara and 2. Add a certificate.

But this is not done by NopCommerce when a customer is set to be tax exempt?
❓ So, am I supposed to manually do this for each tax-exempt customer?

Also
The following are the settings for my Avatax plugin. Does anything stand out as wrong?


Thank you.
9 months ago
cleyva wrote:

But this is not done by NopCommerce when a customer is set to be tax exempt?


No. When a customer is marked as tax-exempt, the field "exemptionNo" is specified in the request, which is usually enough for AvaTax to identify the order items as not taxable.

Regarding exemption certificates, this feature was added into the plugin in version 2.50, you can download it from our marketplace.
9 months ago
RomanovM wrote:

But this is not done by NopCommerce when a customer is set to be tax exempt?


No. When a customer is marked as tax-exempt, the field "exemptionNo" is specified in the request, which is usually enough for AvaTax to identify the order items as not taxable.

Regarding exemption certificates, this feature was added into the plugin in version 2.50, you can download it from our marketplace.


OK, yes I noticed that the field "exemptionNo" is specified. In my case, I think it's not enough for AvaTax to identify the items as not taxable. That's what I've been trying to figure out.

Do you see anything wrong with my screenshot, in how I have my AvaTax settings configured?

And thank you, I will take a look at the updated plugin to see if I can upgrade. Hopefully I can.
9 months ago
There can be no wrong configuration, it's up to you what settings to use, and all of them have comprehensive hints. And these settings don't affect tax exemption.
9 months ago
RomanovM wrote:
There can be no wrong configuration, it's up to you what settings to use, and all of them have comprehensive hints. And these settings don't affect tax exemption.


OK! Thank you for all your help.
I think I figured out my issue.

So, in case others run into the same problem, here is the summary/conclusion for me:

* Problem: some "Tax-exempt" customers were being charged tax.
* It is NOT a NopCommerce plugin issue.
* In Avalara, we have 2 companies: our real one and then a Test one.
* This problem does not exist in our staging environment, using our Avalara Test company.
* The problem exists in production, using our actual Avalara company.
* Reason: The "tax-exempt" customers being charged tax are in SST states (about 23 states). In our Test company, we did not have any registered SST states, so "exemptionNo" was enough for tax-exemption. BUT, our real Avalara company had many SST states registered. So when a customer in an SST state is being charged tax, it's because they need 2 things created in Avalara: 1) a "customer" record and 2) a Certificate. (This was told to me by Avalara support).

I confirmed with one of my client's that they have plans to implement this process for their tax-exempt customers. The expectation is that these customers in SST states will no longer be charged tax once the appropriate requirements are met.

Thank you for your time and your help, @RomanovM