If you implement your 3rd party tax service as an implementation of ITaxCalculator, and then use IOrderRepository.Save, the taxes should be calculated and saved. not sure how they are set them now?
Hi Quan,
Below is how the code is ran currently (modified to pass in the parameters differently as the old custom implementation didn't work, and also for content of the code)
public class TaxRateOrderActivity
{
public Guid OrderActivityId { get; set; }
private static class OperationTypes
{
public static string Post = "post";
public static string Get = "get";
}
public bool ProcessActivity(OrderGroup orderGroup, string accountNumber, string licenseKey, string serviceUrl, string companyCode, string operation, string docType, string defaultTaxCode)
{
// Pre-condition information
OrderGroupHelper orderGroupHelper = new OrderGroupHelper((OrderGroup)orderGroup);
OrderAddress shippingAddress = orderGroupHelper.GetOrderShippingAddress();
List<LineItem> lineItems = orderGroupHelper.GetLineItems();
// Check if enough information to process
if (shippingAddress == null || lineItems == null || lineItems.Count() == 0)
return false;
// Tax Service Client
TaxSvc taxSvc = new TaxSvc();
// Header Level Parameters
// Required Header Parameters
// Set required values for taxSvc
// Optional Header Parameters
// Set optional values for taxSvc
// Base Request Info
GetTaxRequest getTaxRequest = new GetTaxRequest();
getTaxRequest.DocDate = DateTime.Now;
getTaxRequest.CompanyCode = companyCode;
getTaxRequest.DetailLevel = DetailLevel.Tax;
getTaxRequest.Commit = operation == OperationTypes.Post;
getTaxRequest.DocType = (DocumentType)Enum.Parse(typeof(DocumentType), docType);
getTaxRequest.CustomerUsageType = "";
// Order Currency
getTaxRequest.CurrencyCode = orderGroupHelper.orderGroup.BillingCurrency;
// Default Origin
IWarehouse primaryWarehouse = WarehouseHelper.ListAllWarehouses().FirstOrDefault(w => w.IsPrimary);
getTaxRequest.OriginAddress = primaryWarehouse.ContactInformation.ToAvalaraAddress();
// Default Destination
Address shipToAddress = shippingAddress.ToAvalaraAddress();
getTaxRequest.DestinationAddress = shipToAddress;
// Customer Info
CustomerContact customerContact = CustomerContext.Current.GetContactById(orderGroup.CustomerId);
getTaxRequest.CustomerCode = customerContact.Email;
if (customerContact.ContactOrganization != null && !string.IsNullOrEmpty(customerContact.ContactOrganization.Name))
{
getTaxRequest.CustomerCode = customerContact.ContactOrganization.Name;
}
// Get taxes by shipment
decimal orderTaxTotal = new decimal(0);
foreach (OrderForm orderForm in orderGroup.OrderForms)
{
decimal orderFormTaxTotal = new decimal(0);
foreach (Shipment shipment in orderForm.Shipments)
{
// If no shipping method, then not ready for tax
if (string.IsNullOrEmpty(shipment.ShippingMethodName))
continue;
// Post options
if (operation == OperationTypes.Post && orderGroupHelper.orderGroup is PurchaseOrder)
{
getTaxRequest.PaymentDate = ((PurchaseOrder)orderGroupHelper.orderGroup).Created;
getTaxRequest.PurchaseOrderNo = string.Format("{0}-{1}", ((PurchaseOrder)orderGroupHelper.orderGroup).TrackingNumber, shipment.ShipmentId);
}
// Line Data
getTaxRequest.Lines.Clear();
foreach (LineItem lineItem in ShipmentHelper.GetShipmentLineItems(shipment))
{
// Updating CatalogEntryId to Code
CatalogEntry catEntry = CatalogEntry.Create(lineItem.Code);
Line taxLineItem = new Line();
taxLineItem.No = lineItem.LineItemId.ToString();
// Updating CatalogEntryId to Code
taxLineItem.ItemCode = lineItem.Code;
taxLineItem.Qty = Convert.ToDouble(lineItem.Quantity);
taxLineItem.Amount = lineItem.ExtendedPrice;
// if warehouse code is set, then use, else primary
IWarehouse warehouse = primaryWarehouse;
if (lineItem.WarehouseCode.Trim().Length > 0)
{
warehouse = WarehouseHelper.GetWarehouse(lineItem.WarehouseCode);
}
// Source/Destination address
taxLineItem.OriginAddress = warehouse.ContactInformation.ToAvalaraAddress();
taxLineItem.DestinationAddress = shipToAddress;
// Description
taxLineItem.Description = catEntry.GetDisplayName();
// Product tax code
string taxCode = catEntry.GetTaxCode();
// Is always null
if (string.IsNullOrEmpty(taxCode))
{
taxCode = defaultTaxCode;
}
taxLineItem.TaxCode = taxCode;
getTaxRequest.Lines.Add(taxLineItem);
}
// Add line
Line taxLineItem = new Line();
// Set taxLineItem values
getTaxRequest.Lines.Add(taxLineItem);
// Get Taxes
GetTaxResult getTaxResult = taxSvc.GetTax(getTaxRequest);
// Log result/messages in order group notes
string resultMessages = string.Format("Result Code: {0}", getTaxResult.ResultCode.ToString());
foreach (Message message in getTaxResult.Messages)
{
resultMessages += string.Format("{0}: {1}; ", message.Name, message.Summary);
}
orderGroupHelper.AddNote("Tax", "/orderactivity/tax/log", string.Format("{0} : {1}", shipment.ShipmentId.ToString(), shipment.ShippingMethodName), resultMessages);
// Check for failure
if (getTaxResult.ResultCode != SeverityLevel.Success)
{
return false;
}
// Total Tax and save to shipment
decimal shipmentTaxTotal = new decimal(0.0);
foreach (TaxLine taxLine in getTaxResult.TaxLines)
{
shipmentTaxTotal += taxLine.Tax;
}
shipment.SetShipmentTaxStatus(getTaxRequest.ExemptionNo);
shipment.SetShipmentTax(shipmentTaxTotal);
shipment.SetTaxDocCode(getTaxResult.DocCode);
shipment.SetShipmentTaxStatus(taxExemptStatus);
shipment.AcceptChanges();
orderFormTaxTotal += shipmentTaxTotal;
}
// Tax and total order form
orderForm.TaxTotal = orderFormTaxTotal;
orderForm.Total = orderForm.SubTotal + orderForm.ShippingTotal + orderForm.HandlingTotal + orderForm.TaxTotal;
orderForm.AcceptChanges();
orderTaxTotal += orderFormTaxTotal;
}
// Tax and total order
orderGroup.TaxTotal = orderTaxTotal;
orderGroup.Total = orderGroup.SubTotal + orderGroup.ShippingTotal + orderGroup.HandlingTotal + orderGroup.TaxTotal;
orderGroup.AcceptChanges();
return true;
}
}
The ProcessActivity is called after a user selects their shipping method and moves to the next step.
I don't completely understand what you mean by implementing the ITaxCalculator? I tried inheriting the ITaxCalculator, but then had to implement some interface members that I'm guessing would have to have the code from the ProcessActivity worked into them? Apologies for not understanding.
Thank you,
Kevin Larsen
Hello,
Any additional feedback or information? I'm stuck on this at the moment.
Thank you!
Kevin Larsen
https://world.episerver.com/documentation/developer-guides/commerce/orders/calculating-orders-intro/calculating-orders-tax-calculator/
Hi,
I overrode the CalculateTaxTotal and can return a value in the step of our checkout process. The problem now is that I want to be able to save that value in the Order Group/Order Form to be able to pull it again in the next steps or if the user leaves the checkout and comes back later. The service we use charges a small fee each time it's hit, so I wouldn't want to call this each time the tax value is needed to be displayed to the user.
I looked at the Quicksilver site, but the order information (which has the tax total) is saved in a cookie and not in the Order Group/Order Form.
Is there a way to save the tax total to the Order Group/Order Form before the order is placed? I saw similar questions that led to this question being asked but never answered.
Thank you,
Kevin Larsen
I would store the request and resposne serialized as JSON or xml to IOderForm.Properties["TaxRequest"] or ILineItem.Properties["TaxRequest"] andIOderForm.Properties["TaxResponse"] or ILineItem.Properties["TaxResponse"] If the json or xml of the request is the same then use the saved response to caculate the tax or just return the tax total already calculated.
Hello,
We use a thrid party service to calculate the taxes for our orders on our site. I've been in the process of moving over to using the new order system and have ran into a problem with saving the tax value that is returned back from the service. (CMS 11.9.1 and Commerce 11.8.5)
Below is what we used to use to save the tax that we received.
Order Form
Order Group
I converted from an IOrderGroup to an OrderGroup and went through the process and saw that it hit everything correctly, but when I got to the next step in our checkout process I saw that it wasn't displaying the tax and the tax values were not saved in the database. I made changes to use the IOrderGroup instead of the OrderGroup and when I got to the point of changing the above code I didn't see a way to save the tax value.
Is there a way of saving Tax this way?
Thank you,
Kevin Larsen