Oracle Applications (EBS R12) Site level Tax Profile API

No, there are no documented APIs are available for this requirement, or that is what claimed by Oracle community MOSC support on different discussions. So what happens when the country where you live and work decides to implement Tax (example, Middle East countries) and you were using Oracle applications(EBS) over a decade already without Tax setup? Are you going to open up each and every other customer/supplier account and setup the Tax profile? We are using Multi-organization structure and we have 8 companies under the same business group. We’ve 13,000 unique parties in our database and most of them are linked to all these organizations! It didn’t look good for us, I am sure it doesn’t look good for anyone else either!

Then I came across a poorly constructed sample for an API “zx_registrations_pkg.insert_row” that is “not well documented” by Oracle. This means, Oracle doesn’t categorize this API as public & they will not support the customer if something goes wrong while using this API. Hence, make sure that you are going to use an API that could turn stuffs into a nightmare.

Let’s see how to use this API now. Some technical details for better understanding where to look for some mandatory elements. Every time a new site created for customer or supplier, the TAX profile table (ZX_PARTY_TAX_PROFILE) is inserted with a new row, bearing the PARTY_ID column populated with newly created Site’s id (PARTY_SITE_ID) value. Given example below, I am setting up Tax profiles for customers and suppliers that were created for a new organization bearing organization id “285”

For the purpose, I created a new view comprise of both customer and supplier sites details. Please judge me because I am using “A” and “B” for aliases ;)

CREATE VIEW XXKCC_VAT_TABLE_V AS SELECT
hcas.org_id, ac.customer_id party_id, ac.customer_number party_number, ac.customer_name party_name,ac.customer_type party_type, hcas.party_site_id, 'CUSTOMER' as party_classification
FROM
hz_cust_acct_sites_all hcas
inner join ar_customers ac on ac.customer_id= hcas.cust_account_id
where
1=1
and hcas.status='A'
AND ac.status ='A'
AND NVL(ac.customer_type,'R') ='R'--Account type is empty for maximum bahrain customers
AND hcas.org_id=285
UNION ALL
select b.org_id, b.vendor_id party_id, A.segment1 party_number, a.vendor_name,NULL party_type, b.party_site_id, 'SUPPLIER' as party_classification
from AP_SUPPLIERS A
inner join AP_SUPPLIER_SITES_ALL B ON B.VENDOR_ID = A.VENDOR_ID
where B.ORG_ID = 285
/

I am using two different staging tables with VAT/TRN numbers & aliased as “B” in the following PL/SQL blocks. I executed the same script twice, once for customer and other time for supplier. Please note, I have hard coded many parameters, including TAX_AUTHORITY_ID. Make sure that you change such information to suit your environment. Although, we applied this solution to PRODUCTION, I would recommend everyone to practice caution, make backups.

DECLARE
CURSOR CUSTOMER_RECORD IS
SELECT B.VAT_TRN_NUMBER vat_registration_num,'VAT' REGISTRATION_TYPE_CODE, 'UP' ROUNDING_RULE_CODE,'TAX BH JURISDICTION' TAX_JURISDICTION_CODE,
'REGISTERED' REGISTRATION_STATUS_CODE, 'TAX BAHRAIN' TAX, 'TAX REGIME BAHRAIN' TAX_REGIME_CODE,5379228 TAX_AUTHORITY_ID,'N' SELF_ASSESS_FLAG,'IMPLICIT' REGISTRATION_SOURCE_CODE,
'N' INCLUSIVE_TAX_FLAG,'USER_DEFINED' RECORD_TYPE_CODE,
A.* FROM XXKCC_VAT_TABLE_V A
INNER JOIN XX_BAH_CUSTOMER_T B ON B.ERP_CUSTOMER_ID = A.PARTY_ID
WHERE
1=1
AND A.PARTY_CLASSIFICATION='CUSTOMER'
AND B.VAT_TRN_NUMBER IS NOT NULL;
--AND A.PARTY_SITE_ID=3702712;
g_return_status varchar2(1);
l_party_tax_profile_id NUMBER;
BEGIN
for i in CUSTOMER_RECORD loop
BEGIN
Select PARTY_TAX_PROFILE_ID into l_party_tax_profile_id from
ZX_PARTY_TAX_PROFILE
where party_id = i.party_site_id;
EXCEPTION
when no_data_found then
l_party_tax_profile_id:=NULL;
END;
IF l_party_tax_profile_id IS NOT NULL THEN
zx_registrations_pkg.insert_row(
p_request_id => NULL
,p_attribute1 => NULL
,p_attribute2 => NULL
,p_attribute3 => NULL
,p_attribute4 => NULL
,p_attribute5 => NULL
,p_attribute6 => NULL
,p_rounding_rule_code => i.ROUNDING_RULE_CODE
,p_validation_rule => NULL
,p_tax_jurisdiction_code => i.TAX_JURISDICTION_CODE
,p_self_assess_flag => i.SELF_ASSESS_FLAG
,p_registration_status_code => i.REGISTRATION_STATUS_CODE
,p_registration_source_code => i.REGISTRATION_SOURCE_CODE
,p_registration_reason_code => NULL
,p_tax => i.TAX
,p_tax_regime_code => i.TAX_REGIME_CODE
,p_inclusive_tax_flag => i.INCLUSIVE_TAX_FLAG
,p_effective_from => SYSDATE
,p_effective_to => NULL
,p_rep_party_tax_name => NULL
,p_default_registration_flag => NULL
,p_bank_account_num => NULL
,p_record_type_code => i.RECORD_TYPE_CODE
,p_legal_location_id => NULL
,p_tax_authority_id => i.TAX_AUTHORITY_ID
,p_rep_tax_authority_id => NULL
,p_coll_tax_authority_id => NULL
,p_registration_type_code => i.REGISTRATION_TYPE_CODE
,p_registration_number => i.vat_registration_num
,p_party_tax_profile_id => l_party_tax_profile_id
,p_legal_registration_id => NULL
,p_bank_id => NULL
,p_bank_branch_id => NULL
,p_account_site_id => NULL
,p_attribute14 => NULL
,p_attribute15 => NULL
,p_attribute_category => NULL
,p_program_login_id => NULL
,p_account_id => NULL
,p_tax_classification_code => NULL
,p_attribute7 => NULL
,p_attribute8 => NULL
,p_attribute9 => NULL
,p_attribute10 => NULL
,p_attribute11 => NULL
,p_attribute12 => NULL
,p_attribute13 => NULL
,x_return_status => g_return_status
);
END IF;
DBMS_OUTPUT.PUT_LINE(i.PARTY_NUMBER||', '||i.party_name||' Process status : '||g_return_status);
--"S" for success, any other means trouble ;)
END loop;
--COMMIT;
END;
/

That’s all folks. Have questions? Use the comments section to let me know.

Purger | File shredder project for Windows

One of the major benefits of getting exposed to Linux was coming across some fabulous tools for managing and manipulating files. Let it be a simple utility that could replace strings within hundreds of files within a path or find and delete files matching patterns, age etcetera was out of the box available on most of the Linux distributions. Windows Operating System lacks such tools out of the box & next possibility is to write own scripts, which is not very possible for many users.

“Purger” is a file shredding project that I devised few years ago, while we were still hosting our Oracle 11g R2 version on Windows for multiple custom business applications, that generated multiple log files. Today I am sharing a working version of the software with you!

Download Purger

This software can, recursively scan and list files that match the age specified by the user & delete them from the file system. I’ve a minimalistic help file (PDF) under the help section of the software, please make sure that you will read it before using the software.

I’ve tried my level best to ensure that the software doesn’t give the user surprises. Regardless, observe caution when you are using the same as the software is expected to “delete” or “purge” files from your system permanently. If you are not using the “Send to Recyclebin” option, you might end up using tools like Recuva to recover the files deleted!

Do let me know if you have comments.

Microsoft Exchange | empty ECP OWA pages

Recently we switched to wildcard SSL certificate & our on premise exchange services were configured to use the new certificate from ECP. Then, we upgraded our Antivirus software on the Exchange server and needed a reboot.

Once after the physical reboot, Exchange services completely looked toasted. Although the users were able to logon to OWA, after authentication it was just blank, empty pages. We are using Microsoft Exchange 2013 and a quick search landed us on this page.

As per instructions provided by Microsoft, we found out that the IIS “Exchange Back End” site didn’t have the SSL certificate assigned. Once after assigning the new wildcard certificate, we restarted IIS and all services came online immediately after that.

Oracle 19c | Install sample schemas

Updated on 3rd June 2025

After a fresh installation of Oracle 19c and patch update to 25, I couldn’t get the mksample.sql to work as explained below. The 12th parameter for connect string “localhost:1521/SCT” started throwing many errors like listed below:

SQL*Loader: Release 19.0.0.0.0 - Production on Tue Jun 3 13:47:18 2025
Version 19.25.0.0.0

Copyright (c) 1982, 2024, Oracle and/or its affiliates.  All rights reserved.

SQL*Loader-704: Internal error: ulconnect: OCIServerAttach [0]
ORA-12154: TNS:could not resolve the connect identifier specified

I checked tnsnames.ora and listener.ora files to ensure that the necessary entries were available for the PDB so that I can connect to the PDB directly from .Net applications. I couldn’t figure out what was going wrong, and decided to give it a try by connecting to the the PDB directly and executing the mksample.sql script. This also didn’t work as the script failed to connect to the connection string.

For a curiosity purpose, I decided to enter only the connect string name during the next attempt and the script executed without any troubles. If you are facing the same issue, make sure that the current CMD is completely closed and you will execute the script from a new command window. Let us see how it work.

SCT is my PDB and I am connecting to it as sys & executing the script mksample.sql

That’s it!

End of update 3rd June 2025

Oracle 19c comes with a single sample schema HR. For other sample schemas, we have to download the installation media from github repositories. Today we will see how to install the sample schemas on a pluggable database. We’ll be installing Oracle 19.2 sample schemas and please remember, there are possibilities that the sample schema scripts differ for different releases. you can download the 19.2 sample scripts from here

Now comes the difficult part. Once you extract the archive, it creates a folder “db-sample-schemas-19.2”, unless you modified the extract location. I’ve discussed about this on my other post about the Windows software that I made for replacing strings recursively

Basically, Oracle scripts for sample schemas refer to a path, that has to be changed within all the nested SQL and DAT files being referred by the installer script. This is not going to be an easy task for anyone if manually attempted, prompting me to develop the above discussed small utility. Another approach is to write a batch or Powershell script. I opted the latter. Save the below as PowerShell script. Make sure that you configured the environment to run remote signed scripts.

<# run once for *.sql and again for *.dat #>

$count = 0;
Get-ChildItem 'D:\db-sample-schemas-19.2\*.sql' -Recurse | ForEach {
$count = (get-content $_ | select-string -pattern '__SUB__CWD__').length
if ($count -gt 0) {
Write-Host $_ " has $count matches & a backup file $_.bak will be created."
Copy-Item -Path $_ -Destination $_".bak"
(Get-Content $_ | ForEach { $_ -replace '__SUB__CWD__', 'D:/db-sample-schemas-19.2' }) | Set-Content $_
}
}

The above script should be run twice, to iterate through two different types of files. First time for “.sql” and second time for “.dat”

Once the scripts are modified with the correct path, we can proceed with setting up sample schemas. We will use the script “mksample.sql”. Start sqlplus from the script root, eg: D:\db-sample-schemas-19.2. Don’t forget to alter session to your PDB prior executing the script! Please ensure that you have created a new a tablespace “EXAMPLE” if it doesn’t exist (You can use another existing tablespace for the purpose, however not recommended)

Usually the script completes generating few errors. You can check the log files for detailed information about what went wrong, that are insignificant as long as you are only looking at tables/views and indexes.

Hope this helps!