Skip to Content
Technical Articles
Author's profile photo Thiago de Castro Mendes

The guide: hybrid tax calculation for the SMB

In collaboration with: Murthy V, Rohit Acharya, Swati Singh and Anusha Prasad.

You will find here a guide on how to put the required components together to run an external application that calculates tax for the SAP Business ByDesign transactions. In this specific case we will focus on the outgoing documents, such as Sales Orders or Customer Invoices, but it would apply to incoming transactions as well, depending on how you set-up the tax event.

If you want to get a better understanding and background of the architecture we are talking here, please refer to this blog post. If you don’t care, and just want to get you hands dirty, this is what we are going to implement:

The goal of this sample is to skip the standard system’s tax calculation and let the partner’s application runs it based on their own code/rules.

The Business Add-In (BADI) is a key, powerful and main component in this architecture for two main reasons:

  • it enables us to write/change tax data of the ByD transactions, such as tax percentage and base amount; and
  • works as a bridge to the partner’s loosely-coupled application running in a cloud platform.

So go ahead, and learn a bit about it. Open up your SAP Cloud Applications Studio and take a look at the “Repository Explorer” for the “Enhancement Options”. There you are going to find several BADIs available. We are specially interested in the one called “CalculationProcedureForTaxes“, see below:

Select it and read the documentation that comes up on the right-hand side panel. It is worth reading this small piece of documentation carefully, because it tells you:

  • what filters are available to trigger your ABSL code;
  • what is the input data your ABSL code gets;
  • what output data it expects back; and
  • a sample implementation code for the ABSL logic.
    🤩 yes, I know you love sample code! 🤩

Ok, warm up session done. Time to build something.

⚠️Your attention please: as a pre-requisite, I expect you already have a solution created in your partner development tenant, therefore I’m going to show how to add the components on it. Good luck!

Enhancement Implementation

 

You are already familiar with the BADI for the tax calculation procedure, so let’s add it to your solution through the “Enhancement Implementation” component:

Select the following namespace and enhancement option:

Namespace: http://sap.com/xi/AP/FO/PriceAndTax/Global
Enhancement Option: CalculationProcedureForTaxes

Click “OK” – you are going to see now two components for the enhancement implementation:

  • the ABSL code, where we will implement the business logic to call the side-by-side tax engine service; and
  • the Filter, which consists of the conditions to trigger the ABSL logic:
    • the first condition required is the country code, in this case we are using Germany (DE); and
    • the second condition is the code of the tax calculation procedure. 

⚠️ Note: you have to inform both YOUR solution code + “_“+ the tax calculation procedure code itself. Total length of the “Filter for Tax calculation procedureMUST be 16 characters.

The “Tax calculation procedure” (in this case “YB80DZPJY_Z10000” – please replace my solution code by yours) is what you will assign to the Tax Event and the Tax Event to the Tax Type. Finally the Tax Type is used by ByD under certain conditions that we are going to configure, so it can run your code.

But wait! You still don’t have a tax calculation procedure created in your solution, right? So, how do you create it? You will need one BCSet per each of the required Tax Procedure, Tax Event, Tax Type and Tax Code. See it below, configure all of them, and then come back to your filter to inform the code of the tax procedure you have just created. Enjoy!

Tax Calculation Procedure

 

Add a new item and select the “Business Configuration Set“, give it a name and click “Add“. Then select “Use SAP Business Configuration Object“, and select the object named “TaxCalculationProcedure“:

Click “Next” and inform the code for your “Tax Calculation Procedure” followed by its “Description“.

⚠️ Note: as the length of the code used in the filter of the enhancement option has to be of 16 characters, you must create the calculation procedure with 6 characters:

Tax Calculation Procedure: Z10000
Description: Partners Tax Procedure

Now assign it to a “Country/Region“: in this case “Germany“:

Hit “next” and “finish“.

Tax Type

 

Let’s now create the “Tax Type”: add a new item and select the “Business Configuration Set“, give it a name and click “Add“. Then select “Use SAP Business Configuration Object“, and choose the object named “TaxType“:

Click “Next” and fill it as per the image below:

CountryCode: Germany
Code/Content: 1
TaxCategoryCode: Product Tax
Name/content: ZVATDE

Select the “Tax Rate Type” on the left panel and fill it accordingly:

CountryCode: Germany
TaxTypeCode/content: 1
Code/Content: 1

Select the “Tax Exemption Reason” on the left panel and fill it accordingly:

CountryCode: Germany
TaxTypeCode/content: 1
Code/Content: 1
ProductRelevant: true

Select the “Tax Exemption Reason Rate” on the left panel and fill it accordingly:

CountryCode: Germany
TaxTypeCode/content: 1
TaxExemptionReasonCode/content: 1

Make sure you hit “tab” on your keyboard or click out of the field you are filling before saving it. And don’t forget to hit next and finish.

Tax Event

 

You may now create the “Tax Event“, and assign the tax type to it. Go ahead and add a new item, select the “Business Configuration Set“, give it a name and click “Add“. Then select “Use SAP Business Configuration Object“, and select the object named “TaxEventType“:

Select the “Tax Event” on the left panel and fill it accordingly:

Country/Region: Germany
Tax Category: Product Tax
Tax Event: Z10
Valid From [YYYYMMDD]:20201109
Valid To [YYYYMMDD]:20991231
Tax Event Direction: Outgoing
Description: ZGermany Product Z10 Out

Select the “Tax Type Determination” on the left panel and fill it accordingly:

Country/Region: Germany
Tax Category: Product Tax
Tax Event: Z10
Tax Type: ZVATDE
Due Category: Payable

Select the “Tax Calculation Procedure Determination” on the left panel and fill it accordingly:

Country/Region: Germany
Tax Category: Product Tax
Tax Event: Z10
Valid From [YYYYMMDD]:20201109
Tax Calculation Procedure: Partners Tax Procedure

Make sure you hit “tab” on your keyboard or click out of the field you are filling before saving it. And don’t forget to hit next and finish.

Tax Codes

 

Let’s finally create one tax code and assign it to the tax type. Again, add a new item, select the “Business Configuration Set“, give it a name and click “Add“. Then select “Use SAP Business Configuration Object“, and select the object named “ProductTaxationCharacteristics“:

Select the “Tax Code” on the left panel and fill it accordingly:

CountryCode: Germany
Code/content: Z300
ProductTaxEventTypeCode/content: ZGermany Product Z10 Out
ValidityStartDate [YYYYMMDD]:20201109
ValidityEndDate [YYYYMMDD]:20991231
ProductTaxationCharacteristicsName/content: ZGermany Z300 Prod Z10 Out

Select the “Tax Code – Assign Tax Types” on the left panel and fill it accordingly:

CountryCode: Germany
ProductTaxationCharacteristicsCode/content: Z300
TaxTypeCode/content: ZVATDE
TaxRateTypeCode/content: 1

Make sure you hit “tab” on your keyboard or click out of the field you are filling before saving it. And don’t forget to hit next and finish.

Business Configuration

 

Let’s pack all those BCSets under a Business Configuration of type Business Option so the users can scope your solution and afterwards consume the Tax Event and Tax Type in the External Tax Calculation.

Add a new item to your solution; select the “BAC Elements”:

 

Then define the Scoping Question “Activate External tax engine?”, choose an anchor that would make sense, such as the Sales and Service Invoicing“, and hit “Next“:

You will see the BCSets assigned, just hit “Finish“:

⚠️Save and Activate all items; and Deploy the Business Configuration:

 

Back to the: Enhancement Implementation

 

Now that you have all of the required BCSets configured, go back to the BADI and inform the “Filter for Tax calculation procedure” accordingly:

⚠️ Note (yes, AGAIN – this is important): you have to inform both YOUR solution code + “_“+ the tax calculation procedure code itself. Total length of the “Filter for Tax calculation procedureMUST be 16 characters.

Time to add the ABSL code to our custom tax calculation.
Double click the “Calculate_TAX.absl” file on your solution:

Copy and paste the following code.

/*
	Add your SAP Business ByDesign scripting language implementation for:
		Enhancement Option: CalculationProcedureForTaxes
		Operation: CALCULATE_TAX

		Script file signature
		----------------------------
		Parameter: InputData of type PriceAndTaxItemCalculateTaxInbound
		Returns: PriceAndTaxItemCalculateTaxOutbound

	Note: 
	  - To use code completion, press CTRL+J.
*/

import ABSL;
import AP.Common.GDT;
import AP.PDI.Utilities;
import AP.FO.PriceAndTax.Global;

// variables for the input manipulation (InputData)
var caltab : collectionof TaxCalculationInput;
var calin : TaxCalculationInput; 

// variables for the output manipulation
var caltabout : collectionof TaxCalculationOutput;
var calinout : TaxCalculationOutput;

// variable for the actual badi's output values
var result : PriceAndTaxItemCalculateTaxOutbound;

// -- defines the variables to call the the loosely-coupled app running in the cloud
var ScenarioName = "TCMCSSCPTaxEngine";	// Communication Scenario			
var ServiceName = "SCPTaxEngine";		// Service of the Communication Scenario
var HttpMethod = "POST";
var HttpResource = ""; 
var URLParameter : collectionof NameAndValue;
var HeaderParameter : collectionof NameAndValue;
var ContentType = "application/json";
var Body = "";
var ws_result;

var resp_body;
var keys : collectionof LANGUAGEINDEPENDENT_Text;
var key;
var parsed_resp_body;
// -- 

caltab = InputData.TaxCalculationInput;	

foreach  (calin in caltab ){
	
	// -- defaults some data to the output in case there's no changes
	calinout.TaxCalculationKey = calin.TaxCalculationKey;
	calinout.TaxBaseAmount = calin.TaxBaseAmount;
	// -- 

	// -- sets the body with the badi's input tax data 
	// -- to call the the loosely-coupled app running in the cloud
	Body = "{" + 
				"\"inTaxEventTypeCode\":\"" + calin.TaxEventTypeCode.content + "\"," +
				"\"inTaxRateTypeCode\":\"" + calin.TaxRateTypeCode.content + "\"," +
				"\"inTaxBaseAmount\":" + calin.TaxBaseAmount.content.ToString() + "," +
				"\"inTaxPercent\":" + calin.TaxPercent.ToString() + "," +
				"\"inTaxDirectionCode\":\"" + calin.TaxDirectionCode.content + "\"," +
				"\"inTaxRegionCode\":\"" + calin.TaxRegionCode.content + "\"," +
				"\"inBaseQuantityTypeCode\":\"" + calin.BaseQuantityTypeCode.content + "\"," +
				"\"inBaseQuantity\":" + calin.BaseQuantity.content.ToString() + "," +
				"\"inTaxDate\":\"" + calin.TaxDate.ToString() + "\"," +
				"\"inItemUUID\":\"" + calin.TaxCalculationKey.ItemUUID.content.ToString() + "\"," +
				"\"inTaxDueCategoryCode\":\"" + calin.TaxCalculationKey.TaxDueCategoryCode + "\"," +
				"\"inTaxTypeCode\":\"" + calin.TaxCalculationKey.TaxTypeCode.content + "\"," +
				"\"inTaxLevelID\":\"" + calin.TaxCalculationKey.TaxLevelID.ToString() + "\"" +
				"}";
	// --

	
	// -- Executes the webservice call
	ws_result = WebServiceUtilities.ExecuteRESTServiceWithoutEncoding(	ScenarioName,
																			ServiceName,	
																			HttpMethod,		
																			HttpResource,	
																			URLParameter,	
																			HeaderParameter,
																			ContentType,	
																			Body);

	// -- the lines below are just to get a key/value from the json response ---
	resp_body = ws_result.Content;
	key = "newTaxRate";
	keys.Add(key);
	if (Json.IsValidJson(resp_body)) {
		parsed_resp_body = Json.ParseKeyValues(keys, resp_body);
		foreach(var res in parsed_resp_body.KeyValue)
		{
			calinout.TaxPercent = res.Value;
		}
		
	} else {
		calinout.TaxPercent = calin.TaxPercent;
	};
	// --
	
	// -- custom calc for the tax base amount
	calinout.TaxBaseAmount.content = 100 * calin.TaxCalculationKey.TaxLevelID;

	// -- adds the custom values to the output variable
	caltabout.Add(calinout);
}

// -- fills the actual badi's output parameter
result.PriceAndTaxItemCalculateTaxOutbound = caltabout;

// -- returns the result of custom tax calculation
return result;

Save and activate.

Notice that in the code above we are calling the loosely-coupled application (external web service) running on the SAP Cloud Platform. Before you can actually call that application, you need to deploy it. So go to this repository, follow the steps of the readme file, and come back here to configure the web service in the SAP Cloud Applications Studio.

Configuring the External Web Service Integration

 

Add a new item to your solution, and select the “External Web Service Integration“:

Choose “REST” for the “Web Service Type”:

Inform the URL of your loosely-coupled deployed web service:

Mark the check-box for “Create Communication Scenario” and give it a name:

Review your web service integration data, and finish the wizard:

Save and activate both Communication Scenario and the Web Service Integration.

Right-click the Communication Scenario and select “Manage Communication Arrangement“:

 

Search for your Communication Scenario and ensure it’s active.

Scoping the Solution

 

Login to SAP Business ByDesign and browse to the “Business Configuration” > “Implementation Projects, and choose “Edit Project Scope”:

Hit “Next” until you reach to the “Questions“, unfold “Sales” > “Customer Invoicing” and select “Sales and Service Invoicing” on the left-side menu structure. Then scope your solution by selecting the check-box “In Scope“:

Now unfold “Cash Flow Management” > “Tax Management” and select “Tax on Goods and Services” on the left-side menu structure. Then scope the “External Tax Determination” solution by selecting the check-box “In Scope” for the question “Do you want to do external tax determination on goods and services?”:

Hit “Next” and finish the flow.

Configuring the Custom Tax Code

 

Login to SAP Business ByDesign and browse to the “Business Configuration” > “Implementation Projects, select your implementation project and choose “Open Activity List”:

Search for the “External Tax Determination for Goods and Services“, and click on its name:

Here you have to inform the exact same data as you have configured on your Tax Event BCSet in the SAP Cloud Applications Studio:

 

Save and Close.

Configuring the Tax Type at the Item level

 

Let’s now set our custom tax type at the item level so we can do a very specific test to our development. Browser to the menu Product Portfolio > Products > By Materials. Filter it to an item you may test and click on its “Material ID“:

Click the button “View All“:

Select the tab “Taxes“:

And choose the “Country/Region“, “Tax Type” and “Tax Rate Type” accordingly:

Save and Close.

Testing the solution

 

If you reached this point, kudos to you! You must have now a solution running in the SAP Cloud Platform, a BADI running in the SAP Business ByDesign, and a full set of Business Configuration deployed to trigger your custom solution for tax calculation.

Time to test! Let’s create a Sales Order and add the recently configured item to it. It should trigger the BADI followed by the solution in the cloud.

Check it ou:

Hope you can make the most out of this sample.
Please leave you comment and feedback.

Stay tuned!!!

Assigned tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Murthy V
      Murthy V

      Hi Thiago,

      the blog is a gold dust for our partners 🙂

      very nice and detailed blog , which will help our partners and customer to easily integrate any 3rd party tax rate provider with SAP Business ByDesign .

      regards

      murthy

      Author's profile photo Fernando Alonso
      Fernando Alonso

      Is it possible to add a custom Tax Event via PDI solution for Spain?

       

      As you now, in ByD Configuration is not allowed to created new tax codes for Spain (Do not specify new tax codes or change the existing ones for Canada, India, Spain, or Mexico.)

       

      Thanks