Generating Business Partner data for your SAP S/4HANA mock server

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.