In this short blog post, I will share how you can use the Python Faker library to generate Business Partner data that you can use on your mock server.
A mock server is available as part of the Extending SAP S/4HANA book. The GitHub repository that’s part of the book contains the source code and instructions on how you can run the mock server – https://github.com/SAP/cloud-s4-sdk-book/tree/mock-server. Unfortunately, there aren’t many Business Partners included as part of the data, and I needed more Business Partner data for the SAP CodeJam (Connecting systems and services using SAP Integration Suite) I’ve been working on. Enter the Python Faker library.
From the PyPI website:
Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in your persistence to stress test it, or anonymize data taken from a production service, Faker is for you.
The script I include below uses the Business Partner data structure and generates Business Partner and address data using the Python Faker library. The script randomly generates Business Partners for the following countries: AU, BR, CA, CH, CL, CN, DE, ES, FR, GB, IN, IT, JP, KR, MX, NL, PT, US. The script will output a file that contains the generated Business Partners. You can copy the data and append it to the data included in the ./business-partner/business-partner-data.js file that’s used by the mock server.
Let’s start by installing the packages required to run the script:
$ pip install faker pytz
Copy the script below and save it locally, e.g. generate_bps.py
and run the following command: python generate_bps.py
.
import json
import random
from datetime import datetime as dt
import pytz as tz
from faker import Faker
COUNTRIES_LOCALE = {
"AU": ["en_AU"],
"BR": ["pt_BR"],
"CA": ["en_CA", "fr_CA"],
"CH": ["fr_CH", "it_CH"],
"CL": ["es_CL"],
"DE": ["de_DE"],
"ES": ["es_ES"],
"FR": ["fr_FR"],
"GB": ["en_GB"],
"IT": ["it_IT"],
"MX": ["es_MX"],
"NL": ["nl_NL"],
"PT": ["pt_PT"],
"US": ["en_US", "es"],
"KR": ["ko_KR"],
"CN": ["zh_CN"],
"JP": ["ja_JP"],
"IN": ["en_IN"],
}
FIRST_ID = 1003769
business_partners = []
for n in range(250):
bp_number = FIRST_ID + n
random.seed(bp_number)
country = random.choice(list(COUNTRIES_LOCALE.keys()))
print(country)
Faker.seed(bp_number)
fake = Faker(COUNTRIES_LOCALE[country])
bp_data = fake.profile()
full_name = bp_data['name']
first_name = full_name.split()[0]
last_name = full_name.split()[1] if len(full_name.split()) > 1 else ""
IS_MALE = bool(bp_data['s_ex'] == 'M')
job = bp_data['job']
person_number = fake.random_number(digits=5)
address_id = fake.random_number(digits=5)
city = fake.city()
# Select a random timezone for the country
country_timezone = random.choice(tz.country_timezones[country])
timezone = tz.timezone(country_timezone)
timezone_name = timezone.localize(dt.now(), is_dst=None).tzname()
new_bp = {
"__metadata": {
"id": f"https://{{host}}:{{port}}/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner('{bp_number}')",
"uri": f"https://{{host}}:{{port}}/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner('{bp_number}')",
"type": "API_BUSINESS_PARTNER.A_BusinessPartnerType"
},
"BusinessPartner": f"{bp_number}",
"Customer": "",
"Supplier": "",
"AcademicTitle": "",
"AuthorizationGroup": "",
"BusinessPartnerCategory": "1",
"BusinessPartnerFullName": f"{full_name}",
"BusinessPartnerGrouping": "BP02",
"BusinessPartnerName": f"{full_name}",
"BusinessPartnerUUID": f"{fake.uuid4(cast_to=str)}",
"CorrespondenceLanguage": "",
"CreatedByUser": "CC0000000002",
"CreationDate": "/Date(1518393600000)/",
"CreationTime": "PT17H49M05S",
"FirstName": f"{first_name}",
"FormOfAddress": "",
"Industry": "",
"InternationalLocationNumber1": "0",
"InternationalLocationNumber2": "0",
"IsFemale": not IS_MALE,
"IsMale": IS_MALE,
"IsNaturalPerson": "X",
"IsSexUnknown": False,
"Language": "",
"LastChangeDate": None,
"LastChangeTime": "PT00H00M00S",
"LastChangedByUser": "",
"LastName": f"{last_name}",
"LegalForm": "",
"OrganizationBPName1": "",
"OrganizationBPName2": "",
"OrganizationBPName3": "",
"OrganizationBPName4": "",
"OrganizationFoundationDate": None,
"OrganizationLiquidationDate": None,
"SearchTerm1": f"{job}",
"AdditionalLastName": "",
"BirthDate": None,
"BusinessPartnerIsBlocked": False,
"BusinessPartnerType": "",
"ETag": "CC000000000220180212174905",
"GroupBusinessPartnerName1": "",
"GroupBusinessPartnerName2": "",
"IndependentAddressID": "",
"InternationalLocationNumber3": "0",
"MiddleName": "",
"NameCountry": "",
"NameFormat": "",
"PersonFullName": "",
"PersonNumber": f"{person_number}",
"IsMarkedForArchiving": False,
"BusinessPartnerIDByExtSystem": "",
"YY1_AddrLastCheckedOn_bus": None,
"YY1_AddrLastCheckedBy_bus": "",
"to_BuPaIdentification": {"results": []},
"to_BusinessPartnerAddress": {
"results": [
{
"__metadata": {
"id": f"https://{{host}}:{{port}}/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartnerAddress(BusinessPartner='{bp_number}',AddressID='{address_id}')",
"uri": f"https://{{host}}:{{port}}/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartnerAddress(BusinessPartner='{bp_number}',AddressID='{address_id}')",
"type": "API_BUSINESS_PARTNER.A_BusinessPartnerAddressType"
},
"BusinessPartner": f"{bp_number}",
"AddressID": f"{address_id}",
"ValidityStartDate": "/Date(1518393600000+0000)/",
"ValidityEndDate": "/Date(253402300799000+0000)/",
"AuthorizationGroup": "",
"AddressUUID": f"{fake.uuid4(cast_to=str)}",
"AdditionalStreetPrefixName": "",
"AdditionalStreetSuffixName": "",
"AddressTimeZone": f"{timezone_name}",
"CareOfName": "",
"CityCode": "",
"CityName": f"{city}",
"CompanyPostalCode": "",
"Country": f"{country}",
"County": "",
"DeliveryServiceNumber": "",
"DeliveryServiceTypeCode": "",
"District": "",
"FormOfAddress": "",
"FullName": "",
"HomeCityName": f"{city}",
"HouseNumber": f"{fake.building_number()}",
"HouseNumberSupplementText": "",
"Language": "",
"POBox": "",
"POBoxDeviatingCityName": "",
"POBoxDeviatingCountry": "",
"POBoxDeviatingRegion": "",
"POBoxIsWithoutNumber": False,
"POBoxLobbyName": "",
"POBoxPostalCode": "",
"Person": f"{person_number}",
"PostalCode": f"{fake.postcode()}",
"PrfrdCommMediumType": "",
"Region": "",
"StreetName": f"{fake.street_address()}",
"StreetPrefixName": "",
"StreetSuffixName": "",
"TaxJurisdiction": "",
"TransportZone": "",
"AddressIDByExternalSystem": "",
"to_AddressUsage": {"results": []},
"to_EmailAddress": {"results": []},
"to_FaxNumber": {"results": []},
"to_MobilePhoneNumber": {"results": []},
"to_PhoneNumber": {"results": []},
"to_URLAddress": {"results": []}
}
]
},
"to_BusinessPartnerBank": {"results": []},
"to_BusinessPartnerContact": {"results": []},
"to_BusinessPartnerRole": {"results": []},
"to_BusinessPartnerTax": {"results": []},
"to_Customer": None,
"to_Supplier": None
}
business_partners.append(new_bp)
# the json file where the output must be stored
with open("./data/bp-data-generated.json", "w", encoding="UTF-8") as bp_generated_file:
json.dump(business_partners, bp_generated_file, indent=6)
There is a little word that I had to add an underscore in the script so that the blog post editor will allow me to publish it 😉.
This quick blog post can help you generate the data you might need in the future when developing/running tests and using the mock server.